1 /*- 2 * Copyright (c) 2017,2023 Steven G. Kargl 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice unmodified, this list of conditions, and the following 10 * disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 29 /* 30 * See ../src/s_tanpi.c for implementation details. 31 */ 32 33 #include "namespace.h" 34 __weak_alias(tanpif, _tanpif) 35 #define INLINE_KERNEL_TANDF 36 37 #include "math.h" 38 #include "math_private.h" 39 #include "k_tandf.c" 40 41 static const float 42 pi_hi = 3.14160156e+00F, /* 0x40491000 */ 43 pi_lo = -8.90890988e-06F; /* 0xb715777a */ 44 45 static inline float 46 __kernel_tanpif(float x) 47 { 48 float t; 49 50 if (x < 0.25F) 51 t = __kernel_tandf(M_PI * x, 1); 52 else if (x > 0.25F) 53 t = -__kernel_tandf(M_PI * (0.5 - x), -1); 54 else 55 t = 1; 56 57 return (t); 58 } 59 60 static volatile const float vzero = 0; 61 62 float 63 tanpif(float x) 64 { 65 float ax, hi, lo, odd, t; 66 uint32_t hx, ix, jj0; 67 68 GET_FLOAT_WORD(hx, x); 69 ix = hx & 0x7fffffff; 70 SET_FLOAT_WORD(ax, ix); 71 72 if (ix < 0x3f800000) { /* |x| < 1 */ 73 if (ix < 0x3f000000) { /* |x| < 0.5 */ 74 if (ix < 0x38800000) { /* |x| < 0x1p-14 */ 75 if (ix == 0) 76 return (x); 77 SET_FLOAT_WORD(hi, hx & 0xffff0000); 78 hi *= 0x1p23F; 79 lo = x * 0x1p23F - hi; 80 t = (pi_lo + pi_hi) * lo + pi_lo * hi + 81 pi_hi * hi; 82 return (t * 0x1p-23F); 83 } 84 t = __kernel_tanpif(ax); 85 } else if (ix == 0x3f000000) 86 t = 1 / vzero; 87 else 88 t = - __kernel_tanpif(1 - ax); 89 return ((hx & 0x80000000) ? -t : t); 90 } 91 92 if (ix < 0x4b000000) { /* 1 <= |x| < 0x1p23 */ 93 FFLOORF(x, jj0, ix); /* Integer part of ax. */ 94 odd = (uint32_t)x & 1 ? -1 : 1; 95 ax -= x; 96 GET_FLOAT_WORD(ix, ax); 97 98 if (ix < 0x3f000000) /* |x| < 0.5 */ 99 t = ix == 0 ? copysignf(0, odd) : __kernel_tanpif(ax); 100 else if (ix == 0x3f000000) 101 t = odd / vzero; 102 else 103 t = - __kernel_tanpif(1 - ax); 104 return ((hx & 0x80000000) ? -t : t); 105 } 106 107 /* x = +-inf or nan. */ 108 if (ix >= 0x7f800000) 109 return (vzero / vzero); 110 111 /* 112 * For 0x1p23 <= |x| < 0x1p24 need to determine if x is an even 113 * or odd integer to set t = +0 or -0. 114 * For |x| >= 0x1p24, it is always an even integer, so t = 0. 115 */ 116 t = ix >= 0x4b800000 ? 0 : (copysignf(0, (ix & 1) ? -1 : 1)); 117 return ((hx & 0x80000000) ? -t : t); 118 } 119