xref: /netbsd-src/lib/libm/arch/vax/n_atan2.S (revision daf6c4152fcddc27c445489775ed1f66ab4ea9a9)
1/*	$NetBSD: n_atan2.S,v 1.8 2008/03/20 18:49:39 mhitch Exp $	*/
2/*
3 * Copyright (c) 1985, 1993
4 *	The Regents of the University of California.  All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the University nor the names of its contributors
15 *    may be used to endorse or promote products derived from this software
16 *    without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 *	@(#)atan2.s	8.1 (Berkeley) 6/4/93
31 */
32
33#include <machine/asm.h>
34
35/*
36 * ATAN2(Y,X)
37 * RETURN ARG (X+iY)
38 * VAX D FORMAT (56 BITS PRECISION)
39 * CODED IN VAX ASSEMBLY LANGUAGE BY K.C. NG, 4/16/85;
40 *
41 *
42 * Method :
43 *	1. Reduce y to positive by atan2(y,x)=-atan2(-y,x).
44 *	2. Reduce x to positive by (if x and y are unexceptional):
45 *		ARG (x+iy) = arctan(y/x)   	   ... if x > 0,
46 *		ARG (x+iy) = pi - arctan[y/(-x)]   ... if x < 0,
47 *	3. According to the integer k=4t+0.25 truncated , t=y/x, the argument
48 *	   is further reduced to one of the following intervals and the
49 *	   arctangent of y/x is evaluated by the corresponding formula:
50 *
51 *          [0,7/16]	   atan(y/x) = t - t^3*(a1+t^2*(a2+...(a10+t^2*a11)...)
52 *	   [7/16,11/16]    atan(y/x) = atan(1/2) + atan( (y-x/2)/(x+y/2) )
53 *	   [11/16.19/16]   atan(y/x) = atan( 1 ) + atan( (y-x)/(x+y) )
54 *	   [19/16,39/16]   atan(y/x) = atan(3/2) + atan( (y-1.5x)/(x+1.5y) )
55 *	   [39/16,INF]     atan(y/x) = atan(INF) + atan( -x/y )
56 *
57 * Special cases:
58 * Notations: atan2(y,x) == ARG (x+iy) == ARG(x,y).
59 *
60 *	ARG( NAN , (anything) ) is NaN;
61 *	ARG( (anything), NaN ) is NaN;
62 *	ARG(+(anything but NaN), +-0) is +-0  ;
63 *	ARG(-(anything but NaN), +-0) is +-PI ;
64 *	ARG( 0, +-(anything but 0 and NaN) ) is +-PI/2;
65 *	ARG( +INF,+-(anything but INF and NaN) ) is +-0 ;
66 *	ARG( -INF,+-(anything but INF and NaN) ) is +-PI;
67 *	ARG( +INF,+-INF ) is +-PI/4 ;
68 *	ARG( -INF,+-INF ) is +-3PI/4;
69 *	ARG( (anything but,0,NaN, and INF),+-INF ) is +-PI/2;
70 *
71 * Accuracy:
72 *	atan2(y,x) returns the exact ARG(x+iy) nearly rounded.
73 */
74
75#ifdef WEAK_ALIAS
76WEAK_ALIAS(atan2f, _atan2f)
77#endif
78
79ENTRY(_atan2f, 0)
80	cvtfd	4(%ap),-(%sp)
81	calls	$2,_C_LABEL(_atan2)
82	cvtdf	%r0,%r0
83	ret
84
85#ifdef WEAK_ALIAS
86WEAK_ALIAS(atan2, _atan2)
87#endif
88
89ENTRY(_atan2, 0x0fc0)
90	movq	4(%ap),%r2		# %r2 = y
91	movq	12(%ap),%r4		# %r4 = x
92	bicw3	$0x7f,%r2,%r0
93	bicw3	$0x7f,%r4,%r1
94	cmpw	%r0,$0x8000		# y is the reserved operand
95	jeql	resop
96	cmpw	%r1,$0x8000		# x is the reserved operand
97	jeql	resop
98	subl2	$8,%sp
99	bicw3	$0x7fff,%r2,-4(%fp)	# copy y sign bit to -4(%fp)
100	bicw3	$0x7fff,%r4,-8(%fp)	# copy x sign bit to -8(%fp)
101	cmpd	%r4,$0x4080		# x = 1.0 ?
102	bneq	xnot1
103	movq	%r2,%r0
104	bicw2	$0x8000,%r0		# t = |y|
105	movq	%r0,%r2			# y = |y|
106	jbr	begin
107xnot1:
108	bicw3	$0x807f,%r2,%r11		# yexp
109	jeql	yeq0			# if y=0 goto yeq0
110	bicw3	$0x807f,%r4,%r10		# xexp
111	jeql	pio2			# if x=0 goto pio2
112	subw2	%r10,%r11			# k = yexp - xexp
113	cmpw	%r11,$0x2000		# k >= 64 (exp) ?
114	jgeq	pio2			# atan2 = +-pi/2
115	divd3	%r4,%r2,%r0		# t = y/x  never overflow
116	bicw2	$0x8000,%r0		# t > 0
117	bicw2	$0xff80,%r2		# clear the exponent of y
118	bicw2	$0xff80,%r4		# clear the exponent of x
119	bisw2	$0x4080,%r2		# normalize y to [1,2)
120	bisw2	$0x4080,%r4		# normalize x to [1,2)
121	subw2	%r11,%r4			# scale x so that yexp-xexp=k
122begin:
123	cmpw	%r0,$0x411c		# t : 39/16
124	jgeq	L50
125	addl3	$0x180,%r0,%r10		# 8*t
126	cvtrfl	%r10,%r10			# [8*t] rounded to int
127	ashl	$-1,%r10,%r10		# [8*t]/2
128	casel	%r10,$0,$4
129L1:
130	.word	L20-L1
131	.word	L20-L1
132	.word	L30-L1
133	.word	L40-L1
134	.word	L40-L1
135L10:
136	movq	$0xb4d9940f985e407b,%r6	# Hi=.98279372324732906796d0
137	movq	$0x21b1879a3bc2a2fc,%r8	# Lo=-.17092002525602665777d-17
138	subd3	%r4,%r2,%r0		# y-x
139	addw2	$0x80,%r0		# 2(y-x)
140	subd2	%r4,%r0			# 2(y-x)-x
141	addw2	$0x80,%r4		# 2x
142	movq	%r2,%r10
143	addw2	$0x80,%r10		# 2y
144	addd2	%r10,%r2			# 3y
145	addd2	%r4,%r2			# 3y+2x
146	divd2	%r2,%r0			# (2y-3x)/(2x+3y)
147	jbr	L60
148L20:
149	cmpw	%r0,$0x3280		# t : 2**(-28)
150	jlss	L80
151	clrq	%r6			# Hi=%r6=0, Lo=%r8=0
152	clrq	%r8
153	jbr	L60
154L30:
155	movq	$0xda7b2b0d63383fed,%r6	# Hi=.46364760900080611433d0
156	movq	$0xf0ea17b2bf912295,%r8	# Lo=.10147340032515978826d-17
157	movq	%r2,%r0
158	addw2	$0x80,%r0		# 2y
159	subd2	%r4,%r0			# 2y-x
160	addw2	$0x80,%r4		# 2x
161	addd2	%r2,%r4			# 2x+y
162	divd2	%r4,%r0 			# (2y-x)/(2x+y)
163	jbr	L60
164L50:
165	movq	$0x68c2a2210fda40c9,%r6	# Hi=1.5707963267948966135d1
166	movq	$0x06e0145c26332326,%r8	# Lo=.22517417741562176079d-17
167	cmpw	%r0,$0x5100		# y : 2**57
168	bgeq	L90
169	divd3	%r2,%r4,%r0
170	bisw2	$0x8000,%r0 		# -x/y
171	jbr	L60
172L40:
173	movq	$0x68c2a2210fda4049,%r6	# Hi=.78539816339744830676d0
174	movq	$0x06e0145c263322a6,%r8	# Lo=.11258708870781088040d-17
175	subd3	%r4,%r2,%r0		# y-x
176	addd2	%r4,%r2			# y+x
177	divd2	%r2,%r0			# (y-x)/(y+x)
178L60:
179	movq	%r0,%r10
180	muld2	%r0,%r0
181	polyd	%r0,$12,ptable
182	muld2	%r10,%r0
183	subd2	%r0,%r8
184	addd3	%r8,%r10,%r0
185	addd2	%r6,%r0
186L80:
187	movw	-8(%fp),%r2
188	bneq	pim
189	bisw2	-4(%fp),%r0		# return sign(y)*%r0
190	ret
191L90:					# x >= 2**25
192	movq	%r6,%r0
193	jbr	L80
194pim:
195	subd3	%r0,$0x68c2a2210fda4149,%r0	# pi-t
196	bisw2	-4(%fp),%r0
197	ret
198yeq0:
199	movw	-8(%fp),%r2
200	beql	zero			# if sign(x)=1 return pi
201	movq	$0x68c2a2210fda4149,%r0	# pi=3.1415926535897932270d1
202	ret
203zero:
204	clrq	%r0			# return 0
205	ret
206pio2:
207	movq	$0x68c2a2210fda40c9,%r0	# pi/2=1.5707963267948966135d1
208	bisw2	-4(%fp),%r0		# return sign(y)*pi/2
209	ret
210resop:
211	movq	$0x8000,%r0		# propagate the reserved operand
212	ret
213
214	_ALIGN_TEXT
215ptable:
216	.quad	0xb50f5ce96e7abd60
217	.quad	0x51e44a42c1073e02
218	.quad	0x3487e3289643be35
219	.quad	0xdb62066dffba3e54
220	.quad	0xcf8e2d5199abbe70
221	.quad	0x26f39cb884883e88
222	.quad	0x135117d18998be9d
223	.quad	0x602ce9742e883eba
224	.quad	0xa35ad0be8e38bee3
225	.quad	0xffac922249243f12
226	.quad	0x7f14ccccccccbf4c
227	.quad	0xaa8faaaaaaaa3faa
228	.quad	0x0000000000000000
229