exp2l: Work around a NetBSD 10.0/i386 bug.
[gnulib.git] / lib / cosl.c
blobaf561ac1ff2abb6641d456a4dee090c21eb31e48
1 /* cos (cosine) function with 'long double' argument.
3 Copyright (C) 2003-2024 Free Software Foundation, Inc.
5 This file is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as
7 published by the Free Software Foundation, either version 3 of the
8 License, or (at your option) any later version.
10 This file is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>. */
18 /* s_cosl.c -- long double version of s_sin.c.
19 * Conversion to long double by Jakub Jelinek, jj@ultra.linux.cz.
23 * ====================================================
24 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
26 * Developed at SunPro, a Sun Microsystems, Inc. business.
27 * Permission to use, copy, modify, and distribute this
28 * software is freely granted, provided that this notice
29 * is preserved.
30 * ====================================================
33 #include <config.h>
35 /* Specification. */
36 #include <math.h>
38 #if HAVE_SAME_LONG_DOUBLE_AS_DOUBLE
40 long double
41 cosl (long double x)
43 return cos (x);
46 #else
48 /* Code based on glibc/sysdeps/ieee754/ldbl-128/s_cosl.c. */
50 /* cosl(x)
51 * Return cosine function of x.
53 * kernel function:
54 * __kernel_sinl ... sine function on [-pi/4,pi/4]
55 * __kernel_cosl ... cosine function on [-pi/4,pi/4]
56 * __ieee754_rem_pio2l ... argument reduction routine
58 * Method.
59 * Let S,C and T denote the sin, cos and tan respectively on
60 * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
61 * in [-pi/4 , +pi/4], and let n = k mod 4.
62 * We have
64 * n sin(x) cos(x) tan(x)
65 * ----------------------------------------------------------
66 * 0 S C T
67 * 1 C -S -1/T
68 * 2 -S -C T
69 * 3 -C S -1/T
70 * ----------------------------------------------------------
72 * Special cases:
73 * Let trig be any of sin, cos, or tan.
74 * trig(+-INF) is NaN, with signals;
75 * trig(NaN) is that NaN;
77 * Accuracy:
78 * TRIG(x) returns trig(x) nearly rounded
81 # include "trigl.h"
83 long double
84 cosl (long double x)
86 long double y[2],z=0.0L;
87 int n;
89 /* cosl(NaN) is NaN */
90 if (isnanl (x))
91 return x;
93 /* |x| ~< pi/4 */
94 if (x >= -0.7853981633974483096156608458198757210492
95 && x <= 0.7853981633974483096156608458198757210492)
96 return kernel_cosl(x, z);
98 /* cosl(Inf) is NaN, cosl(0) is 1 */
99 else if (x + x == x && x != 0.0)
100 return x - x; /* NaN */
102 /* argument reduction needed */
103 else
105 n = ieee754_rem_pio2l (x, y);
106 switch (n & 3)
108 case 0:
109 return kernel_cosl (y[0], y[1]);
110 case 1:
111 return -kernel_sinl (y[0], y[1], 1);
112 case 2:
113 return -kernel_cosl (y[0], y[1]);
114 default:
115 return kernel_sinl (y[0], y[1], 1);
120 #endif
122 #if 0
124 main (void)
126 printf ("%.16Lg\n", cosl (0.7853981633974483096156608458198757210492));
127 printf ("%.16Lg\n", cosl (0.7853981633974483096156608458198757210492 *29));
128 printf ("%.16Lg\n", cosl (0.7853981633974483096156608458198757210492 *2));
129 printf ("%.16Lg\n", cosl (0.7853981633974483096156608458198757210492 *30));
130 printf ("%.16Lg\n", cosl (0.7853981633974483096156608458198757210492 *4));
131 printf ("%.16Lg\n", cosl (0.7853981633974483096156608458198757210492 *32));
132 printf ("%.16Lg\n", cosl (0.7853981633974483096156608458198757210492 *2/3));
133 printf ("%.16Lg\n", cosl (0.7853981633974483096156608458198757210492 *4/3));
135 #endif