rework langinfo code for ABI compat and for use by time code
[musl] / src / math / sincosl.c
1 #define _GNU_SOURCE
2 #include "libm.h"
3
4 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
5 void sincosl(long double x, long double *sin, long double *cos)
6 {
7         sincos(x, (double *)sin, (double *)cos);
8 }
9 #elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384
10 void sincosl(long double x, long double *sin, long double *cos)
11 {
12         union IEEEl2bits u;
13         unsigned n;
14         long double y[2], s, c;
15
16         u.e = x;
17         u.bits.sign = 0;
18
19         /* x = nan or inf */
20         if (u.bits.exp == 0x7fff) {
21                 *sin = *cos = x - x;
22                 return;
23         }
24
25         /* |x| < (double)pi/4 */
26         if (u.e < M_PI_4) {
27                 /* |x| < 0x1p-64 */
28                 if (u.bits.exp < 0x3fff - 64) {
29                         /* raise underflow if subnormal */
30                         if (u.bits.exp == 0) FORCE_EVAL(x*0x1p-120f);
31                         *sin = x;
32                         /* raise inexact if x!=0 */
33                         *cos = 1.0 + x;
34                         return;
35                 }
36                 *sin = __sinl(x, 0, 0);
37                 *cos = __cosl(x, 0);
38                 return;
39         }
40
41         n = __rem_pio2l(x, y);
42         s = __sinl(y[0], y[1], 1);
43         c = __cosl(y[0], y[1]);
44         switch (n & 3) {
45         case 0:
46                 *sin = s;
47                 *cos = c;
48                 break;
49         case 1:
50                 *sin = c;
51                 *cos = -s;
52                 break;
53         case 2:
54                 *sin = -s;
55                 *cos = -c;
56                 break;
57         case 3:
58         default:
59                 *sin = -c;
60                 *cos = s;
61                 break;
62         }
63 }
64 #endif