1a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes/*- 2a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * ==================================================== 3a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 4a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * Copyright (c) 2009-2011, Bruce D. Evans, Steven G. Kargl, David Schultz. 5a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * 6a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * Developed at SunPro, a Sun Microsystems, Inc. business. 7a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * Permission to use, copy, modify, and distribute this 8a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * software is freely granted, provided that this notice 9a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * is preserved. 10a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * ==================================================== 11a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * 12a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * The argument reduction and testing for exceptional cases was 13a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * written by Steven G. Kargl with input from Bruce D. Evans 14a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * and David A. Schultz. 15a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes */ 16a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes 17a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#include <sys/cdefs.h> 18a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes__FBSDID("$FreeBSD$"); 19a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes 20a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#include <float.h> 21a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#ifdef __i386__ 22a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#include <ieeefp.h> 23a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#endif 24a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes 25a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#include "fpmath.h" 26a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#include "math.h" 27a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#include "math_private.h" 28a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes 29a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#define BIAS (LDBL_MAX_EXP - 1) 30a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes 31a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughesstatic const unsigned 32a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes B1 = 709958130; /* B1 = (127-127.0/3-0.03306235651)*2**23 */ 33a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes 34a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hugheslong double 35a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughescbrtl(long double x) 36a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes{ 37a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes union IEEEl2bits u, v; 38a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes long double r, s, t, w; 39a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes double dr, dt, dx; 40a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes float ft, fx; 41a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes uint32_t hx; 42a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes uint16_t expsign; 43a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes int k; 44a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes 45a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes u.e = x; 46a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes expsign = u.xbits.expsign; 47a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes k = expsign & 0x7fff; 48a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes 49a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes /* 50a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * If x = +-Inf, then cbrt(x) = +-Inf. 51a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * If x = NaN, then cbrt(x) = NaN. 52a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes */ 53a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes if (k == BIAS + LDBL_MAX_EXP) 54a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes return (x + x); 55a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes 56a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes ENTERI(); 57a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes if (k == 0) { 58a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes /* If x = +-0, then cbrt(x) = +-0. */ 59a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes if ((u.bits.manh | u.bits.manl) == 0) 60a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes RETURNI(x); 61a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes /* Adjust subnormal numbers. */ 62a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes u.e *= 0x1.0p514; 63a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes k = u.bits.exp; 64a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes k -= BIAS + 514; 65a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes } else 66a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes k -= BIAS; 67a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes u.xbits.expsign = BIAS; 68a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes v.e = 1; 69a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes 70a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes x = u.e; 71a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes switch (k % 3) { 72a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes case 1: 73a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes case -2: 74a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes x = 2*x; 75a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes k--; 76a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes break; 77a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes case 2: 78a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes case -1: 79a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes x = 4*x; 80a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes k -= 2; 81a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes break; 82a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes } 83a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes v.xbits.expsign = (expsign & 0x8000) | (BIAS + k / 3); 84a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes 85a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes /* 86a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * The following is the guts of s_cbrtf, with the handling of 87a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * special values removed and extra care for accuracy not taken, 88a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * but with most of the extra accuracy not discarded. 89a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes */ 90a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes 91a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes /* ~5-bit estimate: */ 92a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes fx = x; 93a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes GET_FLOAT_WORD(hx, fx); 94a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes SET_FLOAT_WORD(ft, ((hx & 0x7fffffff) / 3 + B1)); 95a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes 96a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes /* ~16-bit estimate: */ 97a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes dx = x; 98a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes dt = ft; 99a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes dr = dt * dt * dt; 100a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes dt = dt * (dx + dx + dr) / (dx + dr + dr); 101a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes 102a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes /* ~47-bit estimate: */ 103a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes dr = dt * dt * dt; 104a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes dt = dt * (dx + dx + dr) / (dx + dr + dr); 105a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes 106a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#if LDBL_MANT_DIG == 64 107a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes /* 108a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * dt is cbrtl(x) to ~47 bits (after x has been reduced to 1 <= x < 8). 109a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * Round it away from zero to 32 bits (32 so that t*t is exact, and 110a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * away from zero for technical reasons). 111a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes */ 112a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes volatile double vd2 = 0x1.0p32; 113a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes volatile double vd1 = 0x1.0p-31; 114a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes #define vd ((long double)vd2 + vd1) 115a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes 116a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes t = dt + vd - 0x1.0p32; 117a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#elif LDBL_MANT_DIG == 113 118a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes /* 119a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * Round dt away from zero to 47 bits. Since we don't trust the 47, 120a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * add 2 47-bit ulps instead of 1 to round up. Rounding is slow and 121a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * might be avoidable in this case, since on most machines dt will 122a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * have been evaluated in 53-bit precision and the technical reasons 123a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * for rounding up might not apply to either case in cbrtl() since 124a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * dt is much more accurate than needed. 125a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes */ 126a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes t = dt + 0x2.0p-46 + 0x1.0p60L - 0x1.0p60; 127a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#else 128a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#error "Unsupported long double format" 129a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#endif 130a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes 131a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes /* 132a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * Final step Newton iteration to 64 or 113 bits with 133a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes * error < 0.667 ulps 134a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes */ 135a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes s=t*t; /* t*t is exact */ 136a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes r=x/s; /* error <= 0.5 ulps; |r| < |t| */ 137a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes w=t+t; /* t+t is exact */ 138a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes r=(r-t)/(w+r); /* r-t is exact; w+r ~= 3*t */ 139a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes t=t+t*r; /* error <= 0.5 + 0.5/3 + epsilon */ 140a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes 141a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes t *= v.e; 142a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes RETURNI(t); 143a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes} 144