/* origin: FreeBSD /usr/src/lib/msun/src/s_cbrtl.c */1/*-2* ====================================================3* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.4* Copyright (c) 2009-2011, Bruce D. Evans, Steven G. Kargl, David Schultz.5*6* Developed at SunPro, a Sun Microsystems, Inc. business.7* Permission to use, copy, modify, and distribute this8* software is freely granted, provided that this notice9* is preserved.10* ====================================================11*12* The argument reduction and testing for exceptional cases was13* written by Steven G. Kargl with input from Bruce D. Evans14* and David A. Schultz.15*/1617#include "libm.h"1819#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 102420long double cbrtl(long double x)21{22return cbrt(x);23}24#elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 1638425static const unsigned B1 = 709958130; /* B1 = (127-127.0/3-0.03306235651)*2**23 */2627long double cbrtl(long double x)28{29union ldshape u = {x}, v;30union {float f; uint32_t i;} uft;31long double r, s, t, w;32double_t dr, dt, dx;33float_t ft;34int e = u.i.se & 0x7fff;35int sign = u.i.se & 0x8000;3637/*38* If x = +-Inf, then cbrt(x) = +-Inf.39* If x = NaN, then cbrt(x) = NaN.40*/41if (e == 0x7fff)42return x + x;43if (e == 0) {44/* Adjust subnormal numbers. */45u.f *= 0x1p120;46e = u.i.se & 0x7fff;47/* If x = +-0, then cbrt(x) = +-0. */48if (e == 0)49return x;50e -= 120;51}52e -= 0x3fff;53u.i.se = 0x3fff;54x = u.f;55switch (e % 3) {56case 1:57case -2:58x *= 2;59e--;60break;61case 2:62case -1:63x *= 4;64e -= 2;65break;66}67v.f = 1.0;68v.i.se = sign | (0x3fff + e/3);6970/*71* The following is the guts of s_cbrtf, with the handling of72* special values removed and extra care for accuracy not taken,73* but with most of the extra accuracy not discarded.74*/7576/* ~5-bit estimate: */77uft.f = x;78uft.i = (uft.i & 0x7fffffff)/3 + B1;79ft = uft.f;8081/* ~16-bit estimate: */82dx = x;83dt = ft;84dr = dt * dt * dt;85dt = dt * (dx + dx + dr) / (dx + dr + dr);8687/* ~47-bit estimate: */88dr = dt * dt * dt;89dt = dt * (dx + dx + dr) / (dx + dr + dr);9091#if LDBL_MANT_DIG == 6492/*93* dt is cbrtl(x) to ~47 bits (after x has been reduced to 1 <= x < 8).94* Round it away from zero to 32 bits (32 so that t*t is exact, and95* away from zero for technical reasons).96*/97t = dt + (0x1.0p32L + 0x1.0p-31L) - 0x1.0p32;98#elif LDBL_MANT_DIG == 11399/*100* Round dt away from zero to 47 bits. Since we don't trust the 47,101* add 2 47-bit ulps instead of 1 to round up. Rounding is slow and102* might be avoidable in this case, since on most machines dt will103* have been evaluated in 53-bit precision and the technical reasons104* for rounding up might not apply to either case in cbrtl() since105* dt is much more accurate than needed.106*/107t = dt + 0x2.0p-46 + 0x1.0p60L - 0x1.0p60;108#endif109110/*111* Final step Newton iteration to 64 or 113 bits with112* error < 0.667 ulps113*/114s = t*t; /* t*t is exact */115r = x/s; /* error <= 0.5 ulps; |r| < |t| */116w = t+t; /* t+t is exact */117r = (r-t)/(w+r); /* r-t is exact; w+r ~= 3*t */118t = t+t*r; /* error <= 0.5 + 0.5/3 + epsilon */119120t *= v.f;121return t;122}123#endif124125126