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