n_atan2.S revision 1.6 1 /* $NetBSD: n_atan2.S,v 1.6 2003/08/07 16:44:44 agc 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 ENTRY(atan2, 0x0fc0)
76 movq 4(%ap),%r2 # %r2 = y
77 movq 12(%ap),%r4 # %r4 = x
78 bicw3 $0x7f,%r2,%r0
79 bicw3 $0x7f,%r4,%r1
80 cmpw %r0,$0x8000 # y is the reserved operand
81 jeql resop
82 cmpw %r1,$0x8000 # x is the reserved operand
83 jeql resop
84 subl2 $8,%sp
85 bicw3 $0x7fff,%r2,-4(%fp) # copy y sign bit to -4(%fp)
86 bicw3 $0x7fff,%r4,-8(%fp) # copy x sign bit to -8(%fp)
87 cmpd %r4,$0x4080 # x = 1.0 ?
88 bneq xnot1
89 movq %r2,%r0
90 bicw2 $0x8000,%r0 # t = |y|
91 movq %r0,%r2 # y = |y|
92 jbr begin
93 xnot1:
94 bicw3 $0x807f,%r2,%r11 # yexp
95 jeql yeq0 # if y=0 goto yeq0
96 bicw3 $0x807f,%r4,%r10 # xexp
97 jeql pio2 # if x=0 goto pio2
98 subw2 %r10,%r11 # k = yexp - xexp
99 cmpw %r11,$0x2000 # k >= 64 (exp) ?
100 jgeq pio2 # atan2 = +-pi/2
101 divd3 %r4,%r2,%r0 # t = y/x never overflow
102 bicw2 $0x8000,%r0 # t > 0
103 bicw2 $0xff80,%r2 # clear the exponent of y
104 bicw2 $0xff80,%r4 # clear the exponent of x
105 bisw2 $0x4080,%r2 # normalize y to [1,2)
106 bisw2 $0x4080,%r4 # normalize x to [1,2)
107 subw2 %r11,%r4 # scale x so that yexp-xexp=k
108 begin:
109 cmpw %r0,$0x411c # t : 39/16
110 jgeq L50
111 addl3 $0x180,%r0,%r10 # 8*t
112 cvtrfl %r10,%r10 # [8*t] rounded to int
113 ashl $-1,%r10,%r10 # [8*t]/2
114 casel %r10,$0,$4
115 L1:
116 .word L20-L1
117 .word L20-L1
118 .word L30-L1
119 .word L40-L1
120 .word L40-L1
121 L10:
122 movq $0xb4d9940f985e407b,%r6 # Hi=.98279372324732906796d0
123 movq $0x21b1879a3bc2a2fc,%r8 # Lo=-.17092002525602665777d-17
124 subd3 %r4,%r2,%r0 # y-x
125 addw2 $0x80,%r0 # 2(y-x)
126 subd2 %r4,%r0 # 2(y-x)-x
127 addw2 $0x80,%r4 # 2x
128 movq %r2,%r10
129 addw2 $0x80,%r10 # 2y
130 addd2 %r10,%r2 # 3y
131 addd2 %r4,%r2 # 3y+2x
132 divd2 %r2,%r0 # (2y-3x)/(2x+3y)
133 jbr L60
134 L20:
135 cmpw %r0,$0x3280 # t : 2**(-28)
136 jlss L80
137 clrq %r6 # Hi=%r6=0, Lo=%r8=0
138 clrq %r8
139 jbr L60
140 L30:
141 movq $0xda7b2b0d63383fed,%r6 # Hi=.46364760900080611433d0
142 movq $0xf0ea17b2bf912295,%r8 # Lo=.10147340032515978826d-17
143 movq %r2,%r0
144 addw2 $0x80,%r0 # 2y
145 subd2 %r4,%r0 # 2y-x
146 addw2 $0x80,%r4 # 2x
147 addd2 %r2,%r4 # 2x+y
148 divd2 %r4,%r0 # (2y-x)/(2x+y)
149 jbr L60
150 L50:
151 movq $0x68c2a2210fda40c9,%r6 # Hi=1.5707963267948966135d1
152 movq $0x06e0145c26332326,%r8 # Lo=.22517417741562176079d-17
153 cmpw %r0,$0x5100 # y : 2**57
154 bgeq L90
155 divd3 %r2,%r4,%r0
156 bisw2 $0x8000,%r0 # -x/y
157 jbr L60
158 L40:
159 movq $0x68c2a2210fda4049,%r6 # Hi=.78539816339744830676d0
160 movq $0x06e0145c263322a6,%r8 # Lo=.11258708870781088040d-17
161 subd3 %r4,%r2,%r0 # y-x
162 addd2 %r4,%r2 # y+x
163 divd2 %r2,%r0 # (y-x)/(y+x)
164 L60:
165 movq %r0,%r10
166 muld2 %r0,%r0
167 polyd %r0,$12,ptable
168 muld2 %r10,%r0
169 subd2 %r0,%r8
170 addd3 %r8,%r10,%r0
171 addd2 %r6,%r0
172 L80:
173 movw -8(%fp),%r2
174 bneq pim
175 bisw2 -4(%fp),%r0 # return sign(y)*%r0
176 ret
177 L90: # x >= 2**25
178 movq %r6,%r0
179 jbr L80
180 pim:
181 subd3 %r0,$0x68c2a2210fda4149,%r0 # pi-t
182 bisw2 -4(%fp),%r0
183 ret
184 yeq0:
185 movw -8(%fp),%r2
186 beql zero # if sign(x)=1 return pi
187 movq $0x68c2a2210fda4149,%r0 # pi=3.1415926535897932270d1
188 ret
189 zero:
190 clrq %r0 # return 0
191 ret
192 pio2:
193 movq $0x68c2a2210fda40c9,%r0 # pi/2=1.5707963267948966135d1
194 bisw2 -4(%fp),%r0 # return sign(y)*pi/2
195 ret
196 resop:
197 movq $0x8000,%r0 # propagate the reserved operand
198 ret
199
200 _ALIGN_TEXT
201 ptable:
202 .quad 0xb50f5ce96e7abd60
203 .quad 0x51e44a42c1073e02
204 .quad 0x3487e3289643be35
205 .quad 0xdb62066dffba3e54
206 .quad 0xcf8e2d5199abbe70
207 .quad 0x26f39cb884883e88
208 .quad 0x135117d18998be9d
209 .quad 0x602ce9742e883eba
210 .quad 0xa35ad0be8e38bee3
211 .quad 0xffac922249243f12
212 .quad 0x7f14ccccccccbf4c
213 .quad 0xaa8faaaaaaaa3faa
214 .quad 0x0000000000000000
215