Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/waterbox/libc/functions/math/cbrtl.c
2 views
1
/* origin: FreeBSD /usr/src/lib/msun/src/s_cbrtl.c */
2
/*-
3
* ====================================================
4
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
5
* Copyright (c) 2009-2011, Bruce D. Evans, Steven G. Kargl, David Schultz.
6
*
7
* Developed at SunPro, a Sun Microsystems, Inc. business.
8
* Permission to use, copy, modify, and distribute this
9
* software is freely granted, provided that this notice
10
* is preserved.
11
* ====================================================
12
*
13
* The argument reduction and testing for exceptional cases was
14
* written by Steven G. Kargl with input from Bruce D. Evans
15
* and David A. Schultz.
16
*/
17
18
#include "libm.h"
19
20
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
21
long double cbrtl(long double x)
22
{
23
return cbrt(x);
24
}
25
#elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384
26
static const unsigned B1 = 709958130; /* B1 = (127-127.0/3-0.03306235651)*2**23 */
27
28
long double cbrtl(long double x)
29
{
30
union ldshape u = {x}, v;
31
union {float f; uint32_t i;} uft;
32
long double r, s, t, w;
33
double_t dr, dt, dx;
34
float_t ft;
35
int e = u.i.se & 0x7fff;
36
int sign = u.i.se & 0x8000;
37
38
/*
39
* If x = +-Inf, then cbrt(x) = +-Inf.
40
* If x = NaN, then cbrt(x) = NaN.
41
*/
42
if (e == 0x7fff)
43
return x + x;
44
if (e == 0) {
45
/* Adjust subnormal numbers. */
46
u.f *= 0x1p120;
47
e = u.i.se & 0x7fff;
48
/* If x = +-0, then cbrt(x) = +-0. */
49
if (e == 0)
50
return x;
51
e -= 120;
52
}
53
e -= 0x3fff;
54
u.i.se = 0x3fff;
55
x = u.f;
56
switch (e % 3) {
57
case 1:
58
case -2:
59
x *= 2;
60
e--;
61
break;
62
case 2:
63
case -1:
64
x *= 4;
65
e -= 2;
66
break;
67
}
68
v.f = 1.0;
69
v.i.se = sign | (0x3fff + e/3);
70
71
/*
72
* The following is the guts of s_cbrtf, with the handling of
73
* special values removed and extra care for accuracy not taken,
74
* but with most of the extra accuracy not discarded.
75
*/
76
77
/* ~5-bit estimate: */
78
uft.f = x;
79
uft.i = (uft.i & 0x7fffffff)/3 + B1;
80
ft = uft.f;
81
82
/* ~16-bit estimate: */
83
dx = x;
84
dt = ft;
85
dr = dt * dt * dt;
86
dt = dt * (dx + dx + dr) / (dx + dr + dr);
87
88
/* ~47-bit estimate: */
89
dr = dt * dt * dt;
90
dt = dt * (dx + dx + dr) / (dx + dr + dr);
91
92
#if LDBL_MANT_DIG == 64
93
/*
94
* dt is cbrtl(x) to ~47 bits (after x has been reduced to 1 <= x < 8).
95
* Round it away from zero to 32 bits (32 so that t*t is exact, and
96
* away from zero for technical reasons).
97
*/
98
t = dt + (0x1.0p32L + 0x1.0p-31L) - 0x1.0p32;
99
#elif LDBL_MANT_DIG == 113
100
/*
101
* Round dt away from zero to 47 bits. Since we don't trust the 47,
102
* add 2 47-bit ulps instead of 1 to round up. Rounding is slow and
103
* might be avoidable in this case, since on most machines dt will
104
* have been evaluated in 53-bit precision and the technical reasons
105
* for rounding up might not apply to either case in cbrtl() since
106
* dt is much more accurate than needed.
107
*/
108
t = dt + 0x2.0p-46 + 0x1.0p60L - 0x1.0p60;
109
#endif
110
111
/*
112
* Final step Newton iteration to 64 or 113 bits with
113
* error < 0.667 ulps
114
*/
115
s = t*t; /* t*t is exact */
116
r = x/s; /* error <= 0.5 ulps; |r| < |t| */
117
w = t+t; /* t+t is exact */
118
r = (r-t)/(w+r); /* r-t is exact; w+r ~= 3*t */
119
t = t+t*r; /* error <= 0.5 + 0.5/3 + epsilon */
120
121
t *= v.f;
122
return t;
123
}
124
#endif
125
126