/* * IBM Accurate Mathematical Library * written by International Business Machines Corp. * Copyright (C) 2001-2024 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, see . */ /*********************************************************************/ /* MODULE_NAME: utan.c */ /* */ /* FUNCTIONS: utan */ /* */ /* FILES NEEDED:dla.h endian.h mydefs.h utan.h */ /* branred.c */ /* utan.tbl */ /* */ /*********************************************************************/ #include #include #include "endian.h" #include #include "mydefs.h" #include #include #include #include #include #include #ifndef SECTION # define SECTION #endif /* tan with max ULP of ~0.619 based on random sampling. */ double SECTION __tan (double x) { #include "utan.h" #include "utan.tbl" int ux, i, n; double a, da, a2, b, db, c, dc, fi, gi, pz, s, sy, t, t1, t2, t3, t4, w, x2, xn, y, ya, yya, z0, z, z2; mynumber num, v; double retval; int __branred (double, double *, double *); SET_RESTORE_ROUND_53BIT (FE_TONEAREST); /* x=+-INF, x=NaN */ num.d = x; ux = num.i[HIGH_HALF]; if ((ux & 0x7ff00000) == 0x7ff00000) { if ((ux & 0x7fffffff) == 0x7ff00000) __set_errno (EDOM); retval = x - x; goto ret; } w = (x < 0.0) ? -x : x; /* (I) The case abs(x) <= 1.259e-8 */ if (w <= g1.d) { math_check_force_underflow_nonneg (w); retval = x; goto ret; } /* (II) The case 1.259e-8 < abs(x) <= 0.0608 */ if (w <= g2.d) { x2 = x * x; t2 = d9.d + x2 * d11.d; t2 = d7.d + x2 * t2; t2 = d5.d + x2 * t2; t2 = d3.d + x2 * t2; t2 *= x * x2; y = x + t2; retval = y; /* Max ULP is 0.504. */ goto ret; } /* (III) The case 0.0608 < abs(x) <= 0.787 */ if (w <= g3.d) { i = ((int) (mfftnhf.d + 256 * w)); z = w - xfg[i][0].d; z2 = z * z; s = (x < 0.0) ? -1 : 1; pz = z + z * z2 * (e0.d + z2 * e1.d); fi = xfg[i][1].d; gi = xfg[i][2].d; t2 = pz * (gi + fi) / (gi - pz); y = fi + t2; retval = (s * y); /* Max ULP is 0.60. */ goto ret; } /* (---) The case 0.787 < abs(x) <= 25 */ if (w <= g4.d) { /* Range reduction by algorithm i */ t = (x * hpinv.d + toint.d); xn = t - toint.d; v.d = t; t1 = (x - xn * mp1.d) - xn * mp2.d; n = v.i[LOW_HALF] & 0x00000001; da = xn * mp3.d; a = t1 - da; da = (t1 - a) - da; if (a < 0.0) { ya = -a; yya = -da; sy = -1; } else { ya = a; yya = da; sy = 1; } /* (VI) The case 0.787 < abs(x) <= 25, 0 < abs(y) <= 0.0608 */ if (ya <= gy2.d) { a2 = a * a; t2 = d9.d + a2 * d11.d; t2 = d7.d + a2 * t2; t2 = d5.d + a2 * t2; t2 = d3.d + a2 * t2; t2 = da + a * a2 * t2; if (n) { /* -cot */ EADD (a, t2, b, db); DIV2 (1.0, 0.0, b, db, c, dc, t1, t2, t3, t4); y = c + dc; retval = (-y); /* Max ULP is 0.506. */ goto ret; } else { /* tan */ y = a + t2; retval = y; /* Max ULP is 0.506. */ goto ret; } } /* (VII) The case 0.787 < abs(x) <= 25, 0.0608 < abs(y) <= 0.787 */ i = ((int) (mfftnhf.d + 256 * ya)); z = (z0 = (ya - xfg[i][0].d)) + yya; z2 = z * z; pz = z + z * z2 * (e0.d + z2 * e1.d); fi = xfg[i][1].d; gi = xfg[i][2].d; if (n) { /* -cot */ t2 = pz * (fi + gi) / (fi + pz); y = gi - t2; retval = (-sy * y); /* Max ULP is 0.62. */ goto ret; } else { /* tan */ t2 = pz * (gi + fi) / (gi - pz); y = fi + t2; retval = (sy * y); /* Max ULP is 0.62. */ goto ret; } } /* (---) The case 25 < abs(x) <= 1e8 */ if (w <= g5.d) { /* Range reduction by algorithm ii */ t = (x * hpinv.d + toint.d); xn = t - toint.d; v.d = t; t1 = (x - xn * mp1.d) - xn * mp2.d; n = v.i[LOW_HALF] & 0x00000001; da = xn * pp3.d; t = t1 - da; da = (t1 - t) - da; t1 = xn * pp4.d; a = t - t1; da = ((t - a) - t1) + da; EADD (a, da, t1, t2); a = t1; da = t2; if (a < 0.0) { ya = -a; yya = -da; sy = -1; } else { ya = a; yya = da; sy = 1; } /* (VIII) The case 25 < abs(x) <= 1e8, 0 < abs(y) <= 0.0608 */ if (ya <= gy2.d) { a2 = a * a; t2 = d9.d + a2 * d11.d; t2 = d7.d + a2 * t2; t2 = d5.d + a2 * t2; t2 = d3.d + a2 * t2; t2 = da + a * a2 * t2; if (n) { /* -cot */ EADD (a, t2, b, db); DIV2 (1.0, 0.0, b, db, c, dc, t1, t2, t3, t4); y = c + dc; retval = (-y); /* Max ULP is 0.506. */ goto ret; } else { /* tan */ y = a + t2; retval = y; /* Max ULP is 0.506. */ goto ret; } } /* (IX) The case 25 < abs(x) <= 1e8, 0.0608 < abs(y) <= 0.787 */ i = ((int) (mfftnhf.d + 256 * ya)); z = (z0 = (ya - xfg[i][0].d)) + yya; z2 = z * z; pz = z + z * z2 * (e0.d + z2 * e1.d); fi = xfg[i][1].d; gi = xfg[i][2].d; if (n) { /* -cot */ t2 = pz * (fi + gi) / (fi + pz); y = gi - t2; retval = (-sy * y); /* Max ULP is 0.62. */ goto ret; } else { /* tan */ t2 = pz * (gi + fi) / (gi - pz); y = fi + t2; retval = (sy * y); /* Max ULP is 0.62. */ goto ret; } } /* (---) The case 1e8 < abs(x) < 2**1024 */ /* Range reduction by algorithm iii */ n = (__branred (x, &a, &da)) & 0x00000001; EADD (a, da, t1, t2); a = t1; da = t2; if (a < 0.0) { ya = -a; yya = -da; sy = -1; } else { ya = a; yya = da; sy = 1; } /* (X) The case 1e8 < abs(x) < 2**1024, 0 < abs(y) <= 0.0608 */ if (ya <= gy2.d) { a2 = a * a; t2 = d9.d + a2 * d11.d; t2 = d7.d + a2 * t2; t2 = d5.d + a2 * t2; t2 = d3.d + a2 * t2; t2 = da + a * a2 * t2; if (n) { /* -cot */ EADD (a, t2, b, db); DIV2 (1.0, 0.0, b, db, c, dc, t1, t2, t3, t4); y = c + dc; retval = (-y); /* Max ULP is 0.506. */ goto ret; } else { /* tan */ y = a + t2; retval = y; /* Max ULP is 0.507. */ goto ret; } } /* (XI) The case 1e8 < abs(x) < 2**1024, 0.0608 < abs(y) <= 0.787 */ i = ((int) (mfftnhf.d + 256 * ya)); z = (z0 = (ya - xfg[i][0].d)) + yya; z2 = z * z; pz = z + z * z2 * (e0.d + z2 * e1.d); fi = xfg[i][1].d; gi = xfg[i][2].d; if (n) { /* -cot */ t2 = pz * (fi + gi) / (fi + pz); y = gi - t2; retval = (-sy * y); /* Max ULP is 0.62. */ goto ret; } else { /* tan */ t2 = pz * (gi + fi) / (gi - pz); y = fi + t2; retval = (sy * y); /* Max ULP is 0.62. */ goto ret; } ret: return retval; } #ifndef __tan libm_alias_double (__tan, tan) #endif