1 #include <gnumeric-config.h>
5 /* ------------------------------------------------------------------------- */
8 gnm_cot_helper (volatile gnm_float
*x
)
10 gnm_float s
= gnm_sin (*x
);
11 gnm_float c
= gnm_cos (*x
);
21 * @x: an angle in radians
23 * Returns: The co-tangent of the given angle.
28 /* See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59089 */
29 return gnm_cot_helper (&x
);
36 * Returns: The inverse co-tangent of the given number.
39 gnm_acot (gnm_float x
)
44 return gnm_atan (1 / x
);
57 * Returns: The hyperbolic co-tangent of the given number.
60 gnm_coth (gnm_float x
)
62 return 1 / gnm_tanh (x
);
69 * Returns: The inverse hyperbolic co-tangent of the given number.
72 gnm_acoth (gnm_float x
)
74 return (gnm_abs (x
) > 2)
75 ? gnm_log1p (2 / (x
- 1)) / 2
76 : gnm_log ((x
- 1) / (x
+ 1)) / -2;
79 /* ------------------------------------------------------------------------- */
83 reduce_pi_simple (gnm_float x
, int *pk
, int kbits
)
85 static const gnm_float two_over_pi
= GNM_const(0.63661977236758134307553505349);
86 static const gnm_float pi_over_two
[] = {
94 gnm_float k
= gnm_floor (x
* gnm_ldexp (two_over_pi
, kbits
- 2) + 0.5);
97 g_assert (k
< (1 << 26));
103 x
-= k
* gnm_ldexp (pi_over_two
[0], 2 - kbits
);
104 for (i
= 1; i
< 5; i
++) {
105 gnm_float dx
= k
* gnm_ldexp (pi_over_two
[i
], 2 - kbits
);
106 gnm_float s
= x
- dx
;
115 * Add the 64-bit number p at *dst and backwards. This would be very
116 * simple and fast in assembler. In C it's a bit of a mess.
119 add_at (guint32
*dst
, guint64 p
)
121 unsigned h
= p
>> 63;
124 *dst
-- = p
& 0xffffffffu
;
128 *dst
-- = p
& 0xffffffffu
;
133 /* p overflowed, pass carry on. */
141 reduce_pi_full (gnm_float x
, int *pk
, int kbits
)
143 /* FIXME? This table isn't big enough for long double's range */
144 static const guint32 one_over_two_pi
[] = {
182 static const guint32 pi_over_four
[] = {
190 guint32 w2
, w1
, w0
, wm1
, wm2
;
194 gnm_float rh
, rl
, l48
, h48
;
196 m
= gnm_frexp (x
, &e
);
197 if (e
>= GNM_MANT_DIG
) {
198 di
= ((unsigned)e
- GNM_MANT_DIG
) / 32u;
202 m
= gnm_ldexp (m
, e
- 64);
203 w2
= (guint32
)gnm_floor (m
); m
= gnm_ldexp (m
- w2
, 32);
204 w1
= (guint32
)gnm_floor (m
); m
= gnm_ldexp (m
- w1
, 32);
205 w0
= (guint32
)gnm_floor (m
); m
= gnm_ldexp (m
- w0
, 32);
206 wm1
= (guint32
)gnm_floor (m
); m
= gnm_ldexp (m
- wm1
, 32);
207 wm2
= (guint32
)gnm_floor (m
);
210 * r[0] is an integer overflow area to be ignored. We will not create
211 * any carry into r[-1] because 5/(2pi) < 1.
215 for (i
= 0; i
< 5; i
++) {
216 g_assert (i
+ 2 + di
< G_N_ELEMENTS (one_over_two_pi
));
219 add_at (&r
[i
+ 1], (guint64
)wm2
* one_over_two_pi
[i
- 2]);
221 add_at (&r
[i
+ 1], (guint64
)wm1
* one_over_two_pi
[i
- 1]);
223 add_at (&r
[i
+ 1], (guint64
)w0
* one_over_two_pi
[i
+ di
]);
225 add_at (&r
[i
+ 1], (guint64
)w1
* one_over_two_pi
[i
+ 1 + di
]);
227 add_at (&r
[i
+ 1], (guint64
)w2
* one_over_two_pi
[i
+ 2 + di
]);
230 * We're done at i==3 unless the first 31-kbits bits, not counting
231 * those ending up in sign and *pk, are all zeros or ones.
233 if (i
== 3 && ((r
[1] + 1u) & (0x7fffffffu
>> kbits
)) > 1)
237 *pk
= kbits
? (r
[1] >> (32 - kbits
)) : 0;
238 if ((neg
= ((r
[1] >> (31 - kbits
)) & 1))) {
240 /* Two-complement negation */
241 for (j
= 1; j
<= i
; j
++) r
[j
] ^= 0xffffffffu
;
244 r
[1] &= (0xffffffffu
>> kbits
);
248 r4
[0] = r4
[1] = r4
[2] = r4
[3] = 0;
249 add_at (&r4
[1], (guint64
)r
[j
] * pi_over_four
[0]);
250 add_at (&r4
[2], (guint64
)r
[j
] * pi_over_four
[1]);
251 add_at (&r4
[2], (guint64
)r
[j
+ 1] * pi_over_four
[0]);
252 add_at (&r4
[3], (guint64
)r
[j
] * pi_over_four
[2]);
253 add_at (&r4
[3], (guint64
)r
[j
+ 1] * pi_over_four
[1]);
254 add_at (&r4
[3], (guint64
)r
[j
+ 2] * pi_over_four
[0]);
256 h48
= gnm_ldexp (((guint64
)r4
[0] << 16) | (r4
[1] >> 16),
257 -32 * j
+ (kbits
+ 1) - 16);
258 l48
= gnm_ldexp (((guint64
)(r4
[1] & 0xffff) << 32) | r4
[2],
259 -32 * j
+ (kbits
+ 1) - 64);
269 return gnm_ldexp (rh
+ rl
, 2 - kbits
);
274 * @x: number of reduce
275 * @e: scale between -1 and 8, inclusive.
276 * @k: (out): location to return lower @e+1 bits of reduction count
278 * This function performs range reduction for trigonometric functions.
280 * Returns: a value, xr, such that x = xr + j * Pi/2^@e for some integer
281 * number j and |xr| <= Pi/2^(@e+1). The lower @e+1 bits of j will be
285 gnm_reduce_pi (gnm_float x
, int e
, int *k
)
290 g_return_val_if_fail (e
>= -1 && e
<= 8, x
);
291 g_return_val_if_fail (k
!= NULL
, x
);
293 if (!gnm_finite (x
)) {
299 * We aren't actually using quads, but we rely somewhat on
300 * proper ieee double semantics.
302 state
= gnm_quad_start ();
304 if (gnm_abs (x
) < (1u << (27 - e
)))
305 xr
= reduce_pi_simple (gnm_abs (x
), k
, e
+ 1);
307 xr
= reduce_pi_full (gnm_abs (x
), k
, e
+ 1);
313 *k
&= ((1 << (e
+ 1)) - 1);
315 gnm_quad_end (state
);
323 #ifdef GNM_REDUCES_TRIG_RANGE
326 gnm_sin (gnm_float x
)
329 gnm_float xr
= gnm_reduce_pi (x
, 1, &km4
);
333 case 0: return +sin (xr
);
334 case 1: return +cos (xr
);
335 case 2: return -sin (xr
);
336 case 3: return -cos (xr
);
341 gnm_cos (gnm_float x
)
344 gnm_float xr
= gnm_reduce_pi (x
, 1, &km4
);
348 case 0: return +cos (xr
);
349 case 1: return -sin (xr
);
350 case 2: return -cos (xr
);
351 case 3: return +sin (xr
);
356 gnm_tan (gnm_float x
)
359 gnm_float xr
= gnm_reduce_pi (x
, 1, &km4
);
363 case 0: case 2: return +tan (xr
);
364 case 1: case 3: return -cos (xr
) / sin (xr
);
370 /* ------------------------------------------------------------------------- */