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