1 // SPDX-License-Identifier: GPL-2.0
2 /*---------------------------------------------------------------------------+
5 | Compute the arctan of a FPU_REG, using a polynomial approximation. |
7 | Copyright (C) 1992,1993,1994,1997 |
8 | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
9 | E-mail billm@suburbia.net |
12 +---------------------------------------------------------------------------*/
14 #include "exception.h"
15 #include "reg_constant.h"
17 #include "fpu_system.h"
19 #include "control_w.h"
22 #define HIPOWERon 6 /* odd poly, negative terms */
23 static const unsigned long long oddnegterms
[HIPOWERon
] = {
24 0x0000000000000000LL
, /* Dummy (not for - 1.0) */
32 #define HIPOWERop 6 /* odd poly, positive terms */
33 static const unsigned long long oddplterms
[HIPOWERop
] = {
34 /* 0xaaaaaaaaaaaaaaabLL, transferred to fixedpterm[] */
43 static const unsigned long long denomterm
= 0xebd9b842c5c53a0eLL
;
45 static const Xsig fixedpterm
= MK_XSIG(0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa);
47 static const Xsig pi_signif
= MK_XSIG(0xc90fdaa2, 0x2168c234, 0xc4c6628b);
49 /*--- poly_atan() -----------------------------------------------------------+
51 +---------------------------------------------------------------------------*/
52 void poly_atan(FPU_REG
*st0_ptr
, u_char st0_tag
,
53 FPU_REG
*st1_ptr
, u_char st1_tag
)
55 u_char transformed
, inverted
, sign1
, sign2
;
58 Xsig accumulator
, Numer
, Denom
, accumulatore
, argSignif
, argSq
, argSqSq
;
61 sign1
= getsign(st0_ptr
);
62 sign2
= getsign(st1_ptr
);
63 if (st0_tag
== TAG_Valid
) {
64 exponent
= exponent(st0_ptr
);
66 /* This gives non-compatible stack contents... */
67 FPU_to_exp16(st0_ptr
, st0_ptr
);
68 exponent
= exponent16(st0_ptr
);
70 if (st1_tag
== TAG_Valid
) {
71 exponent
-= exponent(st1_ptr
);
73 /* This gives non-compatible stack contents... */
74 FPU_to_exp16(st1_ptr
, st1_ptr
);
75 exponent
-= exponent16(st1_ptr
);
78 if ((exponent
< 0) || ((exponent
== 0) &&
79 ((st0_ptr
->sigh
< st1_ptr
->sigh
) ||
80 ((st0_ptr
->sigh
== st1_ptr
->sigh
) &&
81 (st0_ptr
->sigl
< st1_ptr
->sigl
))))) {
83 Numer
.lsw
= Denom
.lsw
= 0;
84 XSIG_LL(Numer
) = significand(st0_ptr
);
85 XSIG_LL(Denom
) = significand(st1_ptr
);
89 Numer
.lsw
= Denom
.lsw
= 0;
90 XSIG_LL(Numer
) = significand(st1_ptr
);
91 XSIG_LL(Denom
) = significand(st0_ptr
);
93 div_Xsig(&Numer
, &Denom
, &argSignif
);
94 exponent
+= norm_Xsig(&argSignif
);
97 || ((exponent
== -2) && (argSignif
.msw
> 0xd413ccd0))) {
98 /* The argument is greater than sqrt(2)-1 (=0.414213562...) */
99 /* Convert the argument by an identity for atan */
104 if (!((exponent
== 0) &&
105 (argSignif
.lsw
== 0) && (argSignif
.midw
== 0) &&
106 (argSignif
.msw
== 0x80000000))) {
107 EXCEPTION(EX_INTERNAL
| 0x104); /* There must be a logic error */
110 #endif /* PARANOID */
111 argSignif
.msw
= 0; /* Make the transformed arg -> 0.0 */
113 Numer
.lsw
= Denom
.lsw
= argSignif
.lsw
;
114 XSIG_LL(Numer
) = XSIG_LL(Denom
) = XSIG_LL(argSignif
);
117 shr_Xsig(&Numer
, -1 - exponent
);
120 shr_Xsig(&Denom
, -exponent
);
121 Denom
.msw
|= 0x80000000;
123 div_Xsig(&Numer
, &Denom
, &argSignif
);
125 exponent
= -1 + norm_Xsig(&argSignif
);
131 argSq
.lsw
= argSignif
.lsw
;
132 argSq
.midw
= argSignif
.midw
;
133 argSq
.msw
= argSignif
.msw
;
134 mul_Xsig_Xsig(&argSq
, &argSq
);
136 argSqSq
.lsw
= argSq
.lsw
;
137 argSqSq
.midw
= argSq
.midw
;
138 argSqSq
.msw
= argSq
.msw
;
139 mul_Xsig_Xsig(&argSqSq
, &argSqSq
);
141 accumulatore
.lsw
= argSq
.lsw
;
142 XSIG_LL(accumulatore
) = XSIG_LL(argSq
);
144 shr_Xsig(&argSq
, 2 * (-1 - exponent
- 1));
145 shr_Xsig(&argSqSq
, 4 * (-1 - exponent
- 1));
147 /* Now have argSq etc with binary point at the left
150 /* Do the basic fixed point polynomial evaluation */
151 accumulator
.msw
= accumulator
.midw
= accumulator
.lsw
= 0;
152 polynomial_Xsig(&accumulator
, &XSIG_LL(argSqSq
),
153 oddplterms
, HIPOWERop
- 1);
154 mul64_Xsig(&accumulator
, &XSIG_LL(argSq
));
155 negate_Xsig(&accumulator
);
156 polynomial_Xsig(&accumulator
, &XSIG_LL(argSqSq
), oddnegterms
,
158 negate_Xsig(&accumulator
);
159 add_two_Xsig(&accumulator
, &fixedpterm
, &dummy_exp
);
161 mul64_Xsig(&accumulatore
, &denomterm
);
162 shr_Xsig(&accumulatore
, 1 + 2 * (-1 - exponent
));
163 accumulatore
.msw
|= 0x80000000;
165 div_Xsig(&accumulator
, &accumulatore
, &accumulator
);
167 mul_Xsig_Xsig(&accumulator
, &argSignif
);
168 mul_Xsig_Xsig(&accumulator
, &argSq
);
170 shr_Xsig(&accumulator
, 3);
171 negate_Xsig(&accumulator
);
172 add_Xsig_Xsig(&accumulator
, &argSignif
);
175 /* compute pi/4 - accumulator */
176 shr_Xsig(&accumulator
, -1 - exponent
);
177 negate_Xsig(&accumulator
);
178 add_Xsig_Xsig(&accumulator
, &pi_signif
);
183 /* compute pi/2 - accumulator */
184 shr_Xsig(&accumulator
, -exponent
);
185 negate_Xsig(&accumulator
);
186 add_Xsig_Xsig(&accumulator
, &pi_signif
);
191 /* compute pi - accumulator */
192 shr_Xsig(&accumulator
, 1 - exponent
);
193 negate_Xsig(&accumulator
);
194 add_Xsig_Xsig(&accumulator
, &pi_signif
);
198 exponent
+= round_Xsig(&accumulator
);
200 significand(st1_ptr
) = XSIG_LL(accumulator
);
201 setexponent16(st1_ptr
, exponent
);
203 tag
= FPU_round(st1_ptr
, 1, 0, FULL_PRECISION
, sign2
);
206 set_precision_flag_up(); /* We do not really know if up or down,
207 use this as the default. */