1*61318Sbostic# Copyright (c) 1985, 1993 2*61318Sbostic# The Regents of the University of California. All rights reserved. 324566Szliu# 445308Sbostic# %sccs.include.redist.sh% 534125Sbostic# 6*61318Sbostic# @(#)atan2.s 8.1 (Berkeley) 06/04/93 734125Sbostic# 824729Selefunt .data 924729Selefunt .align 2 1024729Selefunt_sccsid: 11*61318Sbostic.asciz "@(#)atan2.s 1.2 (Berkeley) 8/21/85; 8.1 (ucb.elefunt) 06/04/93" 1224566Szliu 1324566Szliu# ATAN2(Y,X) 1424566Szliu# RETURN ARG (X+iY) 1524566Szliu# VAX D FORMAT (56 BITS PRECISION) 1624566Szliu# CODED IN VAX ASSEMBLY LANGUAGE BY K.C. NG, 4/16/85; 1724566Szliu# 1824566Szliu# 1924566Szliu# Method : 2024566Szliu# 1. Reduce y to positive by atan2(y,x)=-atan2(-y,x). 2124566Szliu# 2. Reduce x to positive by (if x and y are unexceptional): 2224566Szliu# ARG (x+iy) = arctan(y/x) ... if x > 0, 2324566Szliu# ARG (x+iy) = pi - arctan[y/(-x)] ... if x < 0, 2424566Szliu# 3. According to the integer k=4t+0.25 truncated , t=y/x, the argument 2524566Szliu# is further reduced to one of the following intervals and the 2624566Szliu# arctangent of y/x is evaluated by the corresponding formula: 2724566Szliu# 2824566Szliu# [0,7/16] atan(y/x) = t - t^3*(a1+t^2*(a2+...(a10+t^2*a11)...) 2924566Szliu# [7/16,11/16] atan(y/x) = atan(1/2) + atan( (y-x/2)/(x+y/2) ) 3024566Szliu# [11/16.19/16] atan(y/x) = atan( 1 ) + atan( (y-x)/(x+y) ) 3124566Szliu# [19/16,39/16] atan(y/x) = atan(3/2) + atan( (y-1.5x)/(x+1.5y) ) 3224566Szliu# [39/16,INF] atan(y/x) = atan(INF) + atan( -x/y ) 3324566Szliu# 3424566Szliu# Special cases: 3524566Szliu# Notations: atan2(y,x) == ARG (x+iy) == ARG(x,y). 3624566Szliu# 3724566Szliu# ARG( NAN , (anything) ) is NaN; 3824566Szliu# ARG( (anything), NaN ) is NaN; 3924566Szliu# ARG(+(anything but NaN), +-0) is +-0 ; 4024566Szliu# ARG(-(anything but NaN), +-0) is +-PI ; 4124566Szliu# ARG( 0, +-(anything but 0 and NaN) ) is +-PI/2; 4224566Szliu# ARG( +INF,+-(anything but INF and NaN) ) is +-0 ; 4324566Szliu# ARG( -INF,+-(anything but INF and NaN) ) is +-PI; 4424566Szliu# ARG( +INF,+-INF ) is +-PI/4 ; 4524566Szliu# ARG( -INF,+-INF ) is +-3PI/4; 4624566Szliu# ARG( (anything but,0,NaN, and INF),+-INF ) is +-PI/2; 4724566Szliu# 4824566Szliu# Accuracy: 4924566Szliu# atan2(y,x) returns the exact ARG(x+iy) nearly rounded. 5024566Szliu# 5124566Szliu .text 5224566Szliu .align 1 5324566Szliu .globl _atan2 5424566Szliu_atan2 : 5524566Szliu .word 0x0ff4 5624566Szliu movq 4(ap),r2 # r2 = y 5724566Szliu movq 12(ap),r4 # r4 = x 5824566Szliu bicw3 $0x7f,r2,r0 5924566Szliu bicw3 $0x7f,r4,r1 6024566Szliu cmpw r0,$0x8000 # y is the reserved operand 6124566Szliu jeql resop 6224566Szliu cmpw r1,$0x8000 # x is the reserved operand 6324566Szliu jeql resop 6424566Szliu subl2 $8,sp 6524566Szliu bicw3 $0x7fff,r2,-4(fp) # copy y sign bit to -4(fp) 6624566Szliu bicw3 $0x7fff,r4,-8(fp) # copy x sign bit to -8(fp) 6724566Szliu cmpd r4,$0x4080 # x = 1.0 ? 6824566Szliu bneq xnot1 6924566Szliu movq r2,r0 7024566Szliu bicw2 $0x8000,r0 # t = |y| 7124566Szliu movq r0,r2 # y = |y| 7224566Szliu brb begin 7324566Szliuxnot1: 7424566Szliu bicw3 $0x807f,r2,r11 # yexp 7524566Szliu jeql yeq0 # if y=0 goto yeq0 7624566Szliu bicw3 $0x807f,r4,r10 # xexp 7724566Szliu jeql pio2 # if x=0 goto pio2 7824566Szliu subw2 r10,r11 # k = yexp - xexp 7924566Szliu cmpw r11,$0x2000 # k >= 64 (exp) ? 8024566Szliu jgeq pio2 # atan2 = +-pi/2 8124566Szliu divd3 r4,r2,r0 # t = y/x never overflow 8224566Szliu bicw2 $0x8000,r0 # t > 0 8324566Szliu bicw2 $0xff80,r2 # clear the exponent of y 8424566Szliu bicw2 $0xff80,r4 # clear the exponent of x 8524566Szliu bisw2 $0x4080,r2 # normalize y to [1,2) 8624566Szliu bisw2 $0x4080,r4 # normalize x to [1,2) 8724566Szliu subw2 r11,r4 # scale x so that yexp-xexp=k 8824566Szliubegin: 8924566Szliu cmpw r0,$0x411c # t : 39/16 9024566Szliu jgeq L50 9124566Szliu addl3 $0x180,r0,r10 # 8*t 9224566Szliu cvtrfl r10,r10 # [8*t] rounded to int 9324566Szliu ashl $-1,r10,r10 # [8*t]/2 9424566Szliu casel r10,$0,$4 9524566SzliuL1: 9624566Szliu .word L20-L1 9724566Szliu .word L20-L1 9824566Szliu .word L30-L1 9924566Szliu .word L40-L1 10024566Szliu .word L40-L1 10124566SzliuL10: 10224566Szliu movq $0xb4d9940f985e407b,r6 # Hi=.98279372324732906796d0 10324566Szliu movq $0x21b1879a3bc2a2fc,r8 # Lo=-.17092002525602665777d-17 10424566Szliu subd3 r4,r2,r0 # y-x 10524566Szliu addw2 $0x80,r0 # 2(y-x) 10624566Szliu subd2 r4,r0 # 2(y-x)-x 10724566Szliu addw2 $0x80,r4 # 2x 10824566Szliu movq r2,r10 10924566Szliu addw2 $0x80,r10 # 2y 11024566Szliu addd2 r10,r2 # 3y 11124566Szliu addd2 r4,r2 # 3y+2x 11224566Szliu divd2 r2,r0 # (2y-3x)/(2x+3y) 11324566Szliu brw L60 11424566SzliuL20: 11524566Szliu cmpw r0,$0x3280 # t : 2**(-28) 11624566Szliu jlss L80 11724566Szliu clrq r6 # Hi=r6=0, Lo=r8=0 11824566Szliu clrq r8 11924566Szliu brw L60 12024566SzliuL30: 12124566Szliu movq $0xda7b2b0d63383fed,r6 # Hi=.46364760900080611433d0 12224566Szliu movq $0xf0ea17b2bf912295,r8 # Lo=.10147340032515978826d-17 12324566Szliu movq r2,r0 12424566Szliu addw2 $0x80,r0 # 2y 12524566Szliu subd2 r4,r0 # 2y-x 12624566Szliu addw2 $0x80,r4 # 2x 12724566Szliu addd2 r2,r4 # 2x+y 12824566Szliu divd2 r4,r0 # (2y-x)/(2x+y) 12924566Szliu brb L60 13024566SzliuL50: 13124566Szliu movq $0x68c2a2210fda40c9,r6 # Hi=1.5707963267948966135d1 13224566Szliu movq $0x06e0145c26332326,r8 # Lo=.22517417741562176079d-17 13324566Szliu cmpw r0,$0x5100 # y : 2**57 13424566Szliu bgeq L90 13524566Szliu divd3 r2,r4,r0 13624566Szliu bisw2 $0x8000,r0 # -x/y 13724566Szliu brb L60 13824566SzliuL40: 13924566Szliu movq $0x68c2a2210fda4049,r6 # Hi=.78539816339744830676d0 14024566Szliu movq $0x06e0145c263322a6,r8 # Lo=.11258708870781088040d-17 14124566Szliu subd3 r4,r2,r0 # y-x 14224566Szliu addd2 r4,r2 # y+x 14324566Szliu divd2 r2,r0 # (y-x)/(y+x) 14424566SzliuL60: 14524566Szliu movq r0,r10 14624566Szliu muld2 r0,r0 14724566Szliu polyd r0,$12,ptable 14824566Szliu muld2 r10,r0 14924566Szliu subd2 r0,r8 15024566Szliu addd3 r8,r10,r0 15124566Szliu addd2 r6,r0 15224566SzliuL80: 15324566Szliu movw -8(fp),r2 15424566Szliu bneq pim 15524566Szliu bisw2 -4(fp),r0 # return sign(y)*r0 15624566Szliu ret 15724566SzliuL90: # x >= 2**25 15824566Szliu movq r6,r0 15924566Szliu brb L80 16024566Szliupim: 16124566Szliu subd3 r0,$0x68c2a2210fda4149,r0 # pi-t 16224566Szliu bisw2 -4(fp),r0 16324566Szliu ret 16424566Szliuyeq0: 16524566Szliu movw -8(fp),r2 16624566Szliu beql zero # if sign(x)=1 return pi 16724566Szliu movq $0x68c2a2210fda4149,r0 # pi=3.1415926535897932270d1 16824566Szliu ret 16924566Szliuzero: 17024566Szliu clrq r0 # return 0 17124566Szliu ret 17224566Szliupio2: 17324566Szliu movq $0x68c2a2210fda40c9,r0 # pi/2=1.5707963267948966135d1 17424566Szliu bisw2 -4(fp),r0 # return sign(y)*pi/2 17524566Szliu ret 17624566Szliuresop: 17724566Szliu movq $0x8000,r0 # propagate the reserved operand 17824566Szliu ret 17924566Szliu .align 2 18024566Szliuptable: 18124566Szliu .quad 0xb50f5ce96e7abd60 18224566Szliu .quad 0x51e44a42c1073e02 18324566Szliu .quad 0x3487e3289643be35 18424566Szliu .quad 0xdb62066dffba3e54 18524566Szliu .quad 0xcf8e2d5199abbe70 18624566Szliu .quad 0x26f39cb884883e88 18724566Szliu .quad 0x135117d18998be9d 18824566Szliu .quad 0x602ce9742e883eba 18924566Szliu .quad 0xa35ad0be8e38bee3 19024566Szliu .quad 0xffac922249243f12 19124566Szliu .quad 0x7f14ccccccccbf4c 19224566Szliu .quad 0xaa8faaaaaaaa3faa 19324566Szliu .quad 0x0000000000000000 194