Skip to main content

c/
math_trig.rs

1// Translated from musl: sin, cos, tan, sinf, cosf, tanf,
2// __sin, __cos, __tan, __rem_pio2, __rem_pio2f, __rem_pio2_large,
3// __sindf, __cosdf, __tandf
4
5const INIT_JK: [i32; 4] = [3, 4, 4, 6];
6
7const IPIO2: [i32; 66] = [
8    0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62,
9    0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A,
10    0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129,
11    0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41,
12    0x3991D6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8,
13    0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF,
14    0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5,
15    0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08,
16    0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3,
17    0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880,
18    0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B,
19];
20
21const PIO2: [f64; 8] = [
22    asdouble(0x3FF921FB40000000),
23    asdouble(0x3E74442D00000000),
24    asdouble(0x3CF8469880000000),
25    asdouble(0x3B78CC5160000000),
26    asdouble(0x39F01B8380000000),
27    asdouble(0x387A252040000000),
28    asdouble(0x36E3822280000000),
29    asdouble(0x3569F31D00000000),
30];
31
32const S1PIO2: f64 = asdouble(0x3FF921FB54442D18);
33const S2PIO2: f64 = asdouble(0x400921FB54442D18);
34const S3PIO2: f64 = asdouble(0x4012D97C7F3321D2);
35const S4PIO2: f64 = asdouble(0x401921FB54442D18);
36
37#[allow(non_snake_case)]
38fn __rem_pio2_large(x: &[f64], y: &mut [f64], e0: i32, nx: i32, prec: i32) -> i32 {
39    let mut iq = [0i32; 20];
40    let mut f = [0.0f64; 30];
41    let mut fq = [0.0f64; 20];
42    let mut q = [0.0f64; 20];
43
44    let jk = INIT_JK[prec as usize];
45    let jp = jk;
46    let jx = nx - 1;
47    let mut jv = (e0 - 3) / 24;
48    if jv < 0 { jv = 0; }
49    let mut q0 = e0 - 24 * (jv + 1);
50
51    let mut j = jv - jx;
52    let m = jx + jk;
53    for ii in 0..=m {
54        f[ii as usize] = if j < 0 { 0.0 } else { IPIO2[j as usize] as f64 };
55        j += 1;
56    }
57
58    for ii in 0..=jk {
59        let mut fw = 0.0f64;
60        for jj in 0..=jx {
61            fw += x[jj as usize] * f[(jx + ii - jj) as usize];
62        }
63        q[ii as usize] = fw;
64    }
65
66    let mut jz = jk;
67    let mut need_recompute = true;
68    let mut n_val = 0i32;
69    let mut ih_val = 0i32;
70    let mut z = 0.0f64;
71
72    while need_recompute {
73        need_recompute = false;
74        // distill q[] into iq[]
75        z = q[jz as usize];
76        j = jz;
77        let mut ii = 0i32;
78        while j > 0 {
79            let fw = (z * p2d(-24)) as i32;
80            iq[ii as usize] = (z - fw as f64 * p2d(24)) as i32;
81            z = q[(j - 1) as usize] + fw as f64;
82            ii += 1;
83            j -= 1;
84        }
85
86        z = scalbn(z, q0);
87        z -= 8.0 * floor(z * 0.125);
88        n_val = z as i32;
89        z -= n_val as f64;
90        ih_val = 0;
91        if q0 > 0 {
92            let i_part = iq[(jz - 1) as usize] >> (24 - q0);
93            n_val += i_part;
94            iq[(jz - 1) as usize] -= i_part << (24 - q0);
95            ih_val = iq[(jz - 1) as usize] >> (23 - q0);
96        } else if q0 == 0 {
97            ih_val = iq[(jz - 1) as usize] >> 23;
98        } else if z >= 0.5 {
99            ih_val = 2;
100        }
101
102        if ih_val > 0 {
103            n_val += 1;
104            let mut carry = 0i32;
105            for idx in 0..(jz as usize) {
106                let jv = iq[idx];
107                if carry == 0 {
108                    if jv != 0 {
109                        carry = 1;
110                        iq[idx] = 0x1000000 - jv;
111                    }
112                } else {
113                    iq[idx] = 0xffffff - jv;
114                }
115            }
116            if q0 > 0 {
117                match q0 {
118                    1 => { iq[(jz - 1) as usize] &= 0x7fffff; }
119                    2 => { iq[(jz - 1) as usize] &= 0x3fffff; }
120                    _ => {}
121                }
122            }
123            if ih_val == 2 {
124                z = 1.0 - z;
125                if carry != 0 {
126                    z -= scalbn(1.0, q0);
127                }
128            }
129        }
130
131        // check recomputation
132        if z == 0.0 {
133            j = 0;
134            let mut idx = jz - 1;
135            while idx >= jk {
136                j |= iq[idx as usize];
137                idx -= 1;
138            }
139            if j == 0 {
140                let mut k = 1i32;
141                while iq[(jk - k) as usize] == 0 { k += 1; }
142                for idx2 in (jz + 1)..=(jz + k) {
143                    f[(jx + idx2) as usize] = IPIO2[(jv + idx2) as usize] as f64;
144                    let mut fw = 0.0f64;
145                    for jj in 0..=jx {
146                        fw += x[jj as usize] * f[(jx + idx2 - jj) as usize];
147                    }
148                    q[idx2 as usize] = fw;
149                }
150                jz += k;
151                need_recompute = true;
152            }
153        }
154    }
155
156    // chop off zero terms
157    if z == 0.0 {
158        jz -= 1;
159        q0 -= 24;
160        while iq[jz as usize] == 0 {
161            jz -= 1;
162            q0 -= 24;
163        }
164    } else {
165        z = scalbn(z, -q0);
166        if z >= p2d(24) {
167            let fw = (z * p2d(-24)) as i32;
168            iq[jz as usize] = (z - fw as f64 * p2d(24)) as i32;
169            jz += 1;
170            q0 += 24;
171            iq[jz as usize] = fw;
172        } else {
173            iq[jz as usize] = z as i32;
174        }
175    }
176
177    // convert integer chunks to float
178    let mut fw = scalbn(1.0, q0);
179    for idx in (0..=(jz as usize)).rev() {
180        q[idx] = fw * iq[idx] as f64;
181        fw *= p2d(-24);
182    }
183
184    // compute PIo2 * q
185    for idx in (0..=(jz as usize)).rev() {
186        fw = 0.0;
187        for k in 0..=(jp as usize) {
188            if k <= (jz as usize - idx) {
189                fw += PIO2[k] * q[idx + k];
190            }
191        }
192        fq[(jz as usize) - idx] = fw;
193    }
194
195    // compress fq[] into y[]
196    match prec {
197        0 => {
198            fw = 0.0;
199            for idx in (0..=(jz as usize)).rev() {
200                fw += fq[idx];
201            }
202            y[0] = if ih_val == 0 { fw } else { -fw };
203        }
204        1 | 2 => {
205            fw = 0.0;
206            for idx in (0..=(jz as usize)).rev() {
207                fw += fq[idx];
208            }
209            fw = fw; // double_t = f64 when FLT_EVAL_METHOD==0
210            y[0] = if ih_val == 0 { fw } else { -fw };
211            fw = fq[0] - fw;
212            for idx in 1..=(jz as usize) {
213                fw += fq[idx];
214            }
215            y[1] = if ih_val == 0 { fw } else { -fw };
216        }
217        _ => {
218            for idx in (1..=(jz as usize)).rev() {
219                let tmp = fq[idx - 1] + fq[idx];
220                fq[idx] += fq[idx - 1] - tmp;
221                fq[idx - 1] = tmp;
222            }
223            for idx in (2..=(jz as usize)).rev() {
224                let tmp = fq[idx - 1] + fq[idx];
225                fq[idx] += fq[idx - 1] - tmp;
226                fq[idx - 1] = tmp;
227            }
228            fw = 0.0;
229            for idx in (2..=(jz as usize)).rev() {
230                fw += fq[idx];
231            }
232            if ih_val == 0 {
233                y[0] = fq[0]; y[1] = fq[1]; y[2] = fw;
234            } else {
235                y[0] = -fq[0]; y[1] = -fq[1]; y[2] = -fw;
236            }
237        }
238    }
239    n_val & 7
240}
241
242const REM_PIO2_TOINT: f64 = asdouble(0x4338000000000000);
243const REM_PIO2_PIO4: f64 = asdouble(0x3FE921FB54442D18);
244const REM_PIO2_INVPIO2: f64 = asdouble(0x3FE45F306DC9C883);
245const REM_PIO2_PIO2_1: f64 = asdouble(0x3FF921FB54400000);
246const REM_PIO2_PIO2_1T: f64 = asdouble(0x3DD0B4611A626331);
247const REM_PIO2_PIO2_2: f64 = asdouble(0x3DD0B4611A600000);
248const REM_PIO2_PIO2_2T: f64 = asdouble(0x3BA3198A2E037073);
249const REM_PIO2_PIO2_3: f64 = asdouble(0x3BA3198A2E000000);
250const REM_PIO2_PIO2_3T: f64 = asdouble(0x397B839A252049C1);
251
252fn __rem_pio2(x: f64, y: &mut [f64; 2]) -> i32 {
253    let ix64 = asuint64(x);
254    let sign = (ix64 >> 63) as i32;
255    let ix = ((ix64 >> 32) & 0x7fffffff) as u32;
256
257    if ix <= 0x400f6a7a {
258        if (ix & 0xfffff) == 0x921fb {
259            // cancellation -- use medium case
260            return rem_pio2_medium(x, sign, ix, y);
261        }
262        if ix <= 0x4002d97c {
263            if sign == 0 {
264                let z = x - REM_PIO2_PIO2_1;
265                y[0] = z - REM_PIO2_PIO2_1T;
266                y[1] = (z - y[0]) - REM_PIO2_PIO2_1T;
267                return 1;
268            } else {
269                let z = x + REM_PIO2_PIO2_1;
270                y[0] = z + REM_PIO2_PIO2_1T;
271                y[1] = (z - y[0]) + REM_PIO2_PIO2_1T;
272                return -1;
273            }
274        } else {
275            if sign == 0 {
276                let z = x - 2.0 * REM_PIO2_PIO2_1;
277                y[0] = z - 2.0 * REM_PIO2_PIO2_1T;
278                y[1] = (z - y[0]) - 2.0 * REM_PIO2_PIO2_1T;
279                return 2;
280            } else {
281                let z = x + 2.0 * REM_PIO2_PIO2_1;
282                y[0] = z + 2.0 * REM_PIO2_PIO2_1T;
283                y[1] = (z - y[0]) + 2.0 * REM_PIO2_PIO2_1T;
284                return -2;
285            }
286        }
287    }
288    if ix <= 0x401c463b {
289        if ix <= 0x4015fdbc {
290            if ix == 0x4012d97c {
291                return rem_pio2_medium(x, sign, ix, y);
292            }
293            if sign == 0 {
294                let z = x - 3.0 * REM_PIO2_PIO2_1;
295                y[0] = z - 3.0 * REM_PIO2_PIO2_1T;
296                y[1] = (z - y[0]) - 3.0 * REM_PIO2_PIO2_1T;
297                return 3;
298            } else {
299                let z = x + 3.0 * REM_PIO2_PIO2_1;
300                y[0] = z + 3.0 * REM_PIO2_PIO2_1T;
301                y[1] = (z - y[0]) + 3.0 * REM_PIO2_PIO2_1T;
302                return -3;
303            }
304        } else {
305            if ix == 0x401921fb {
306                return rem_pio2_medium(x, sign, ix, y);
307            }
308            if sign == 0 {
309                let z = x - 4.0 * REM_PIO2_PIO2_1;
310                y[0] = z - 4.0 * REM_PIO2_PIO2_1T;
311                y[1] = (z - y[0]) - 4.0 * REM_PIO2_PIO2_1T;
312                return 4;
313            } else {
314                let z = x + 4.0 * REM_PIO2_PIO2_1;
315                y[0] = z + 4.0 * REM_PIO2_PIO2_1T;
316                y[1] = (z - y[0]) + 4.0 * REM_PIO2_PIO2_1T;
317                return -4;
318            }
319        }
320    }
321    if ix < 0x413921fb {
322        return rem_pio2_medium(x, sign, ix, y);
323    }
324    // all other (large) arguments
325    if ix >= 0x7ff00000 {
326        y[0] = x - x;
327        y[1] = y[0];
328        return 0;
329    }
330    // set z = scalbn(|x|,-ilogb(x)+23)
331    let mut ux = ix64;
332    ux &= (-1i64 as u64) >> 12;
333    ux |= ((0x3ff + 23) as u64) << 52;
334    let mut z = asdouble(ux);
335    let mut tx = [0.0f64; 3];
336    for i in 0..2 {
337        tx[i] = z as i32 as f64;
338        z = (z - tx[i]) * p2d(24);
339    }
340    tx[2] = z;
341    let mut i = 2i32;
342    while tx[i as usize] == 0.0 {
343        i -= 1;
344    }
345    let n = __rem_pio2_large(&tx, y, (ix >> 20) as i32 - (0x3ff + 23), i + 1, 1);
346    if sign != 0 {
347        y[0] = -y[0];
348        y[1] = -y[1];
349        return -(n as i32);
350    }
351    n as i32
352}
353
354fn rem_pio2_medium(x: f64, _sign: i32, ix: u32, y: &mut [f64; 2]) -> i32 {
355    let mut fn_val = x as f64 * REM_PIO2_INVPIO2 + REM_PIO2_TOINT - REM_PIO2_TOINT;
356    let mut n = fn_val as i32;
357    let mut r = x - fn_val * REM_PIO2_PIO2_1;
358    let mut w = fn_val * REM_PIO2_PIO2_1T;
359    if predict_false(r - w < -REM_PIO2_PIO4) {
360        n -= 1;
361        fn_val -= 1.0;
362        r = x - fn_val * REM_PIO2_PIO2_1;
363        w = fn_val * REM_PIO2_PIO2_1T;
364    } else if predict_false(r - w > REM_PIO2_PIO4) {
365        n += 1;
366        fn_val += 1.0;
367        r = x - fn_val * REM_PIO2_PIO2_1;
368        w = fn_val * REM_PIO2_PIO2_1T;
369    }
370    y[0] = r - w;
371    let ey = ((asuint64(y[0]) >> 52) & 0x7ff) as i32;
372    let ex = (ix >> 20) as i32;
373    if ex - ey > 16 {
374        let t = r;
375        w = fn_val * REM_PIO2_PIO2_2;
376        r = t - w;
377        w = fn_val * REM_PIO2_PIO2_2T - ((t - r) - w);
378        y[0] = r - w;
379        let ey = ((asuint64(y[0]) >> 52) & 0x7ff) as i32;
380        if ex - ey > 49 {
381            let t = r;
382            w = fn_val * REM_PIO2_PIO2_3;
383            r = t - w;
384            w = fn_val * REM_PIO2_PIO2_3T - ((t - r) - w);
385            y[0] = r - w;
386        }
387    }
388    y[1] = (r - y[0]) - w;
389    n
390}
391
392const REMPIO2F_TOINT: f64 = asdouble(0x4338000000000000);
393const REMPIO2F_PIO4: f64 = asdouble(0x3FE921FB60000000);
394const REMPIO2F_INVPIO2: f64 = asdouble(0x3FE45F306DC9C883);
395const REMPIO2F_PIO2_1: f64 = asdouble(0x3FF921FB50000000);
396const REMPIO2F_PIO2_1T: f64 = asdouble(0x3E5110B4611A6263);
397
398fn __rem_pio2f(x: f32, y: &mut f64) -> i32 {
399    let ix = asuint(x) & 0x7fffffff;
400    if ix < 0x4dc90fdb {
401        let mut fn_val = x as f64 * REMPIO2F_INVPIO2 + REMPIO2F_TOINT - REMPIO2F_TOINT;
402        let mut n = fn_val as i32;
403        *y = x as f64 - fn_val * REMPIO2F_PIO2_1 - fn_val * REMPIO2F_PIO2_1T;
404        if predict_false(*y < -REMPIO2F_PIO4) {
405            n -= 1;
406            fn_val -= 1.0;
407            *y = x as f64 - fn_val * REMPIO2F_PIO2_1 - fn_val * REMPIO2F_PIO2_1T;
408        } else if predict_false(*y > REMPIO2F_PIO4) {
409            n += 1;
410            fn_val += 1.0;
411            *y = x as f64 - fn_val * REMPIO2F_PIO2_1 - fn_val * REMPIO2F_PIO2_1T;
412        }
413        return n;
414    }
415    if ix >= 0x7f800000 {
416        *y = x as f64 - x as f64;
417        return 0;
418    }
419    let sign = (asuint(x) >> 31) as i32;
420    let e0 = ((ix >> 23) as i32) - (0x7f + 23);
421    let ux = ix - ((e0 as u32) << 23);
422    let tx = [asfloat(ux) as f64];
423    let mut ty = [0.0f64];
424    let n = __rem_pio2_large(&tx, &mut ty, e0, 1, 0);
425    if sign != 0 {
426        *y = -ty[0];
427        return -(n as i32);
428    }
429    *y = ty[0];
430    n as i32
431}
432
433// __sin kernel
434const SIN_S1: f64 = asdouble(0xBFC5555555555549);
435const SIN_S2: f64 = asdouble(0x3F8111111110F8A6);
436const SIN_S3: f64 = asdouble(0xBF2A01A019C161D5);
437const SIN_S4: f64 = asdouble(0x3EC71DE357B1FE7D);
438const SIN_S5: f64 = asdouble(0xBE5AE5E68A2B9CEB);
439const SIN_S6: f64 = asdouble(0x3DE5D93A5ACFD57C);
440
441fn __sin(x: f64, y: f64, iy: i32) -> f64 {
442    let z = x * x;
443    let w = z * z;
444    let r = SIN_S2 + z * (SIN_S3 + z * SIN_S4) + z * w * (SIN_S5 + z * SIN_S6);
445    let v = z * x;
446    if iy == 0 {
447        x + v * (SIN_S1 + z * r)
448    } else {
449        x - ((z * (0.5 * y - v * r) - y) - v * SIN_S1)
450    }
451}
452
453// __cos kernel
454const COS_C1: f64 = asdouble(0x3FA555555555554C);
455const COS_C2: f64 = asdouble(0xBF56C16C16C15177);
456const COS_C3: f64 = asdouble(0x3EFA01A019CB1590);
457const COS_C4: f64 = asdouble(0xBE927E4F809C52AD);
458const COS_C5: f64 = asdouble(0x3E21EE9EBDB4B1C4);
459const COS_C6: f64 = asdouble(0xBDA8FAE9BE8838D4);
460
461fn __cos(x: f64, y: f64) -> f64 {
462    let z = x * x;
463    let w = z * z;
464    let r = z * (COS_C1 + z * (COS_C2 + z * COS_C3)) + w * w * (COS_C4 + z * (COS_C5 + z * COS_C6));
465    let hz = 0.5 * z;
466    let w = 1.0 - hz;
467    w + (((1.0 - w) - hz) + (z * r - x * y))
468}
469
470// __tan kernel
471const TAN_T: [f64; 13] = [
472    asdouble(0x3FD5555555555563),
473    asdouble(0x3FC111111110FE7A),
474    asdouble(0x3FABA1BA1BB341FE),
475    asdouble(0x3F9664F48406D637),
476    asdouble(0x3F8226E3E96E8493),
477    asdouble(0x3F6D6D22C9560328),
478    asdouble(0x3F57DBC8FEE08315),
479    asdouble(0x3F4344D8F2F26501),
480    asdouble(0x3F3026F71A8D1068),
481    asdouble(0x3F147E88A03792A6),
482    asdouble(0x3F12B80F32F0A7E9),
483    asdouble(0xBEF375CBDB605373),
484    asdouble(0x3EFB2A7074BF7AD4),
485];
486const TAN_PIO4: f64 = asdouble(0x3FE921FB54442D18);
487const TAN_PIO4LO: f64 = asdouble(0x3C81A62633145C07);
488
489fn __tan(x: f64, y: f64, odd: i32) -> f64 {
490    let hx = (asuint64(x) >> 32) as u32;
491    let big = (hx & 0x7fffffff) >= 0x3FE59428;
492    let (x, y, sign) = if big {
493        let sign = hx >> 31;
494        let (nx, ny) = if sign != 0 { (-x, -y) } else { (x, y) };
495        ((TAN_PIO4 - nx) + (TAN_PIO4LO - ny), 0.0, sign)
496    } else {
497        (x, y, 0u32)
498    };
499    let z = x * x;
500    let w = z * z;
501    let r = TAN_T[1] + w * (TAN_T[3] + w * (TAN_T[5] + w * (TAN_T[7] + w * (TAN_T[9] + w * TAN_T[11]))));
502    let v = z * (TAN_T[2] + w * (TAN_T[4] + w * (TAN_T[6] + w * (TAN_T[8] + w * (TAN_T[10] + w * TAN_T[12])))));
503    let s = z * x;
504    let r = y + z * (s * (r + v) + y) + s * TAN_T[0];
505    let w = x + r;
506    if big {
507        let s_val = 1.0 - 2.0 * odd as f64;
508        let v = s_val - 2.0 * (x + (r - w * w / (w + s_val)));
509        return if sign != 0 { -v } else { v };
510    }
511    if odd == 0 {
512        return w;
513    }
514    // -1.0/(x+r) has up to 2ulp error, so compute it accurately
515    let w0 = {
516        let mut tmp = w;
517        unsafe { set_low_word(&mut tmp, 0); }
518        tmp
519    };
520    let v = r - (w0 - x);
521    let mut a0 = -1.0 / w;
522    let a = a0;
523    unsafe { set_low_word(&mut a0, 0); }
524    a0 + a * (1.0 + a0 * w0 + a0 * v)
525}
526
527// __sindf kernel
528const SINDF_S1: f64 = asdouble(0xBFC5555554CBAC77);
529const SINDF_S2: f64 = asdouble(0x3F811110896EFBB2);
530const SINDF_S3: f64 = asdouble(0xBF2A00F9E2CAE774);
531const SINDF_S4: f64 = asdouble(0x3EC6CD878C3B46A7);
532
533fn __sindf(x: f64) -> f32 {
534    let z = x * x;
535    let w = z * z;
536    let r = SINDF_S3 + z * SINDF_S4;
537    let s = z * x;
538    ((x + s * (SINDF_S1 + z * SINDF_S2)) + s * w * r) as f32
539}
540
541// __cosdf kernel
542const COSDF_C0: f64 = asdouble(0xBFDFFFFFFD0C5E81);
543const COSDF_C1: f64 = asdouble(0x3FA55553E1053A42);
544const COSDF_C2: f64 = asdouble(0xBF56C087E80F1E27);
545const COSDF_C3: f64 = asdouble(0x3EF99342E0EE5069);
546
547fn __cosdf(x: f64) -> f32 {
548    let z = x * x;
549    let w = z * z;
550    let r = COSDF_C2 + z * COSDF_C3;
551    ((1.0 + z * COSDF_C0) + w * COSDF_C1 + (w * z) * r) as f32
552}
553
554// __tandf kernel
555const TANDF_T: [f64; 6] = [
556    asdouble(0x3FD5554D3418C99F),
557    asdouble(0x3FC112FD38999F72),
558    asdouble(0x3FAB54C91D865AFE),
559    asdouble(0x3F991DF3908C33CE),
560    asdouble(0x3F685DADFCECF44E),
561    asdouble(0x3F8362B9BF971BCD),
562];
563
564fn __tandf(x: f64, odd: i32) -> f32 {
565    let z = x * x;
566    let r = TANDF_T[4] + z * TANDF_T[5];
567    let t = TANDF_T[2] + z * TANDF_T[3];
568    let w = z * z;
569    let s = z * x;
570    let u = TANDF_T[0] + z * TANDF_T[1];
571    let r = (x + s * u) + (s * w) * (t + w * r);
572    if odd != 0 { (-1.0 / r) as f32 } else { r as f32 }
573}
574
575// ============================================================
576// sin, cos, tan (double precision)
577// ============================================================
578
579#[no_mangle]
580pub extern "C" fn sin(x: f64) -> f64 {
581    let mut ix = (asuint64(x) >> 32) as u32;
582    ix &= 0x7fffffff;
583
584    if ix <= 0x3fe921fb {
585        if ix < 0x3e500000 {
586            force_eval(if ix < 0x00100000 { x / p2f(120) as f64 } else { x + p2f(120) as f64 });
587            return x;
588        }
589        return __sin(x, 0.0, 0);
590    }
591    if ix >= 0x7ff00000 {
592        return x - x;
593    }
594    let mut y = [0.0f64; 2];
595    let n = __rem_pio2(x, &mut y);
596    match n & 3 {
597        0 =>  __sin(y[0], y[1], 1),
598        1 =>  __cos(y[0], y[1]),
599        2 => -__sin(y[0], y[1], 1),
600        _ => -__cos(y[0], y[1]),
601    }
602}
603
604#[no_mangle]
605pub extern "C" fn cos(x: f64) -> f64 {
606    let mut ix = (asuint64(x) >> 32) as u32;
607    ix &= 0x7fffffff;
608
609    if ix <= 0x3fe921fb {
610        if ix < 0x3e46a09e {
611            force_eval(x + p2f(120) as f64);
612            return 1.0;
613        }
614        return __cos(x, 0.0);
615    }
616    if ix >= 0x7ff00000 {
617        return x - x;
618    }
619    let mut y = [0.0f64; 2];
620    let n = __rem_pio2(x, &mut y);
621    match n & 3 {
622        0 =>  __cos(y[0], y[1]),
623        1 => -__sin(y[0], y[1], 1),
624        2 => -__cos(y[0], y[1]),
625        _ =>  __sin(y[0], y[1], 1),
626    }
627}
628
629#[no_mangle]
630pub extern "C" fn tan(x: f64) -> f64 {
631    let mut ix = (asuint64(x) >> 32) as u32;
632    ix &= 0x7fffffff;
633
634    if ix <= 0x3fe921fb {
635        if ix < 0x3e400000 {
636            force_eval(if ix < 0x00100000 { x / p2f(120) as f64 } else { x + p2f(120) as f64 });
637            return x;
638        }
639        return __tan(x, 0.0, 0);
640    }
641    if ix >= 0x7ff00000 {
642        return x - x;
643    }
644    let mut y = [0.0f64; 2];
645    let n = __rem_pio2(x, &mut y);
646    __tan(y[0], y[1], n & 1)
647}
648
649// ============================================================
650// sinf, cosf, tanf (single precision)
651// ============================================================
652
653#[no_mangle]
654pub extern "C" fn sinf(x: f32) -> f32 {
655    let ix = asuint(x);
656    let sign = ix >> 31;
657    let ix = ix & 0x7fffffff;
658
659    if ix <= 0x3f490fda {
660        if ix < 0x39800000 {
661            force_eval(if ix < 0x00800000 { x / p2f(120) } else { x + p2f(120) });
662            return x;
663        }
664        return __sindf(x as f64);
665    }
666    if ix <= 0x407b53d1 {
667        if ix <= 0x4016cbe3 {
668            return if sign != 0 { -__cosdf(x as f64 + S1PIO2) } else { __cosdf(x as f64 - S1PIO2) };
669        }
670        return __sindf(if sign != 0 { -(x as f64 + S2PIO2) } else { -(x as f64 - S2PIO2) });
671    }
672    if ix <= 0x40e231d5 {
673        if ix <= 0x40afeddf {
674            return if sign != 0 { __cosdf(x as f64 + S3PIO2) } else { -__cosdf(x as f64 - S3PIO2) };
675        }
676        return __sindf(if sign != 0 { x as f64 + S4PIO2 } else { x as f64 - S4PIO2 });
677    }
678    if ix >= 0x7f800000 {
679        return x - x;
680    }
681    let mut y = 0.0f64;
682    let n = __rem_pio2f(x, &mut y);
683    match n & 3 {
684        0 =>  __sindf(y),
685        1 =>  __cosdf(y),
686        2 =>  __sindf(-y),
687        _ => -__cosdf(y),
688    }
689}
690
691#[no_mangle]
692pub extern "C" fn cosf(x: f32) -> f32 {
693    let ix = asuint(x);
694    let sign = ix >> 31;
695    let ix = ix & 0x7fffffff;
696
697    if ix <= 0x3f490fda {
698        if ix < 0x39800000 {
699            force_eval(x + p2f(120));
700            return 1.0f32;
701        }
702        return __cosdf(x as f64);
703    }
704    if ix <= 0x407b53d1 {
705        if ix > 0x4016cbe3 {
706            return -__cosdf(if sign != 0 { x as f64 + S2PIO2 } else { x as f64 - S2PIO2 });
707        } else {
708            return if sign != 0 { __sindf(x as f64 + S1PIO2) } else { __sindf(S1PIO2 - x as f64) };
709        }
710    }
711    if ix <= 0x40e231d5 {
712        if ix > 0x40afeddf {
713            return __cosdf(if sign != 0 { x as f64 + S4PIO2 } else { x as f64 - S4PIO2 });
714        } else {
715            return if sign != 0 { __sindf(-x as f64 - S3PIO2) } else { __sindf(x as f64 - S3PIO2) };
716        }
717    }
718    if ix >= 0x7f800000 {
719        return x - x;
720    }
721    let mut y = 0.0f64;
722    let n = __rem_pio2f(x, &mut y);
723    match n & 3 {
724        0 =>  __cosdf(y),
725        1 =>  __sindf(-y),
726        2 => -__cosdf(y),
727        _ =>  __sindf(y),
728    }
729}
730
731#[no_mangle]
732pub extern "C" fn tanf(x: f32) -> f32 {
733    let ix = asuint(x);
734    let sign = ix >> 31;
735    let ix = ix & 0x7fffffff;
736
737    if ix <= 0x3f490fda {
738        if ix < 0x39800000 {
739            force_eval(if ix < 0x00800000 { x / p2f(120) } else { x + p2f(120) });
740            return x;
741        }
742        return __tandf(x as f64, 0);
743    }
744    if ix <= 0x407b53d1 {
745        if ix <= 0x4016cbe3 {
746            return __tandf(if sign != 0 { x as f64 + S1PIO2 } else { x as f64 - S1PIO2 }, 1);
747        } else {
748            return __tandf(if sign != 0 { x as f64 + S2PIO2 } else { x as f64 - S2PIO2 }, 0);
749        }
750    }
751    if ix <= 0x40e231d5 {
752        if ix <= 0x40afeddf {
753            return __tandf(if sign != 0 { x as f64 + S3PIO2 } else { x as f64 - S3PIO2 }, 1);
754        } else {
755            return __tandf(if sign != 0 { x as f64 + S4PIO2 } else { x as f64 - S4PIO2 }, 0);
756        }
757    }
758    if ix >= 0x7f800000 {
759        return x - x;
760    }
761    let mut y = 0.0f64;
762    let n = __rem_pio2f(x, &mut y);
763    __tandf(y, n & 1)
764}