ReactOS 0.4.17-dev-1321-g5c122a9
sqrt.c File Reference
#include <stdint.h>
#include <math.h>
#include "libm.h"
#include "sqrt_data.h"
Include dependency graph for sqrt.c:

Go to the source code of this file.

Macros

#define FENV_SUPPORT   1
 

Functions

static uint32_t mul32 (uint32_t a, uint32_t b)
 
static uint64_t mul64 (uint64_t a, uint64_t b)
 
double sqrt (double x)
 

Macro Definition Documentation

◆ FENV_SUPPORT

#define FENV_SUPPORT   1

Definition at line 20 of file sqrt.c.

Function Documentation

◆ mul32()

static uint32_t mul32 ( uint32_t  a,
uint32_t  b 
)
inlinestatic

Definition at line 23 of file sqrt.c.

24{
25 return (uint64_t)a*b >> 32;
26}
UINT64 uint64_t
Definition: types.h:77
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204

Referenced by sqrt().

◆ mul64()

static uint64_t mul64 ( uint64_t  a,
uint64_t  b 
)
inlinestatic

Definition at line 29 of file sqrt.c.

30{
31 uint64_t ahi = a>>32;
32 uint64_t alo = a&0xffffffff;
33 uint64_t bhi = b>>32;
34 uint64_t blo = b&0xffffffff;
35 return ahi*bhi + (ahi*blo >> 32) + (alo*bhi >> 32);
36}

Referenced by sqrt().

◆ sqrt()

double sqrt ( double  x)

Definition at line 38 of file sqrt.c.

39{
40 uint64_t ix, top, m;
41
42 /* special case handling. */
43 ix = asuint64(x);
44 top = ix >> 52;
45 if (predict_false(top - 0x001 >= 0x7ff - 0x001)) {
46 /* x < 0x1p-1022 or inf or nan. */
47 if (ix * 2 == 0)
48 return x;
49 if (ix == 0x7ff0000000000000)
50 return x;
51 if (ix > 0x7ff0000000000000)
52 return __math_invalid(x);
53 /* x is subnormal, normalize it. */
54 ix = asuint64(x * 0x1p52);
55 top = ix >> 52;
56 top -= 52;
57 }
58
59 /* argument reduction:
60 x = 4^e m; with integer e, and m in [1, 4)
61 m: fixed point representation [2.62]
62 2^e is the exponent part of the result. */
63 int even = top & 1;
64 m = (ix << 11) | 0x8000000000000000;
65 if (even) m >>= 1;
66 top = (top + 0x3ff) >> 1;
67
68 /* approximate r ~ 1/sqrt(m) and s ~ sqrt(m) when m in [1,4)
69
70 initial estimate:
71 7bit table lookup (1bit exponent and 6bit significand).
72
73 iterative approximation:
74 using 2 goldschmidt iterations with 32bit int arithmetics
75 and a final iteration with 64bit int arithmetics.
76
77 details:
78
79 the relative error (e = r0 sqrt(m)-1) of a linear estimate
80 (r0 = a m + b) is |e| < 0.085955 ~ 0x1.6p-4 at best,
81 a table lookup is faster and needs one less iteration
82 6 bit lookup table (128b) gives |e| < 0x1.f9p-8
83 7 bit lookup table (256b) gives |e| < 0x1.fdp-9
84 for single and double prec 6bit is enough but for quad
85 prec 7bit is needed (or modified iterations). to avoid
86 one more iteration >=13bit table would be needed (16k).
87
88 a newton-raphson iteration for r is
89 w = r*r
90 u = 3 - m*w
91 r = r*u/2
92 can use a goldschmidt iteration for s at the end or
93 s = m*r
94
95 first goldschmidt iteration is
96 s = m*r
97 u = 3 - s*r
98 r = r*u/2
99 s = s*u/2
100 next goldschmidt iteration is
101 u = 3 - s*r
102 r = r*u/2
103 s = s*u/2
104 and at the end r is not computed only s.
105
106 they use the same amount of operations and converge at the
107 same quadratic rate, i.e. if
108 r1 sqrt(m) - 1 = e, then
109 r2 sqrt(m) - 1 = -3/2 e^2 - 1/2 e^3
110 the advantage of goldschmidt is that the mul for s and r
111 are independent (computed in parallel), however it is not
112 "self synchronizing": it only uses the input m in the
113 first iteration so rounding errors accumulate. at the end
114 or when switching to larger precision arithmetics rounding
115 errors dominate so the first iteration should be used.
116
117 the fixed point representations are
118 m: 2.30 r: 0.32, s: 2.30, d: 2.30, u: 2.30, three: 2.30
119 and after switching to 64 bit
120 m: 2.62 r: 0.64, s: 2.62, d: 2.62, u: 2.62, three: 2.62 */
121
122 static const uint64_t three = 0xc0000000;
123 uint64_t r, s, d, u, i;
124
125 i = (ix >> 46) % 128;
126 r = (uint32_t)__rsqrt_tab[i] << 16;
127 /* |r sqrt(m) - 1| < 0x1.fdp-9 */
128 s = mul32(m>>32, r);
129 /* |s/sqrt(m) - 1| < 0x1.fdp-9 */
130 d = mul32(s, r);
131 u = three - d;
132 r = mul32(r, u) << 1;
133 /* |r sqrt(m) - 1| < 0x1.7bp-16 */
134 s = mul32(s, u) << 1;
135 /* |s/sqrt(m) - 1| < 0x1.7bp-16 */
136 d = mul32(s, r);
137 u = three - d;
138 r = mul32(r, u) << 1;
139 /* |r sqrt(m) - 1| < 0x1.3704p-29 (measured worst-case) */
140 r = r << 32;
141 s = mul64(m, r);
142 d = mul64(s, r);
143 u = (three<<32) - d;
144 s = mul64(s, u); /* repr: 3.61 */
145 /* -0x1p-57 < s - sqrt(m) < 0x1.8001p-61 */
146 s = (s - 2) >> 9; /* repr: 12.52 */
147 /* -0x1.09p-52 < s - sqrt(m) < -0x1.fffcp-63 */
148
149 /* s < sqrt(m) < s + 0x1.09p-52,
150 compute nearest rounded result:
151 the nearest result to 52 bits is either s or s+0x1p-52,
152 we can decide by comparing (2^52 s + 0.5)^2 to 2^104 m. */
153 uint64_t d0, d1, d2;
154 double y, t;
155 d0 = (m << 42) - s*s;
156 d1 = s - d0;
157 d2 = d1 + s + 1;
158 s += d1 >> 63;
159 s &= 0x000fffffffffffff;
160 s |= top << 52;
161 y = asdouble(s);
162 if (FENV_SUPPORT) {
163 /* handle rounding modes and inexact exception:
164 only (s+1)^2 == 2^42 m case is exact otherwise
165 add a tiny value to cause the fenv effects. */
166 uint64_t tiny = predict_false(d2==0) ? 0 : 0x0010000000000000;
167 tiny |= (d1^d2) & 0x8000000000000000;
168 t = asdouble(tiny);
169 y = eval_as_double(y + t);
170 }
171 return y;
172}
double __math_invalid(double x)
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLdouble s
Definition: gl.h:2039
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLdouble GLdouble t
Definition: gl.h:2047
GLdouble GLdouble GLdouble GLdouble top
Definition: glext.h:10859
const GLfloat * m
Definition: glext.h:10848
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
#define d
Definition: ke_i.h:81
static double asdouble(uint64_t i)
Definition: libm.h:142
static uint64_t asuint64(double f)
Definition: libm.h:135
static double eval_as_double(double x)
Definition: libm.h:102
#define predict_false(x)
Definition: libm.h:93
#define uint32_t
Definition: nsiface.idl:61
#define even(p)
Definition: raisecond.c:50
static uint32_t mul32(uint32_t a, uint32_t b)
Definition: sqrt.c:23
static uint64_t mul64(uint64_t a, uint64_t b)
Definition: sqrt.c:29
#define FENV_SUPPORT
Definition: sqrt.c:20
const uint16_t __rsqrt_tab[128]
Definition: sqrt_data.c:12

Referenced by __ieee754_sqrt(), _cabs(), _CIsqrt(), _hypot(), _libm_sse2_sqrt_precise(), _y0(), _y1(), _yn(), acos(), acosh(), asin(), asinh(), atanh(), bezier_deviation_squared(), D3DRMVectorModulus(), D3DXBoundProbeTest(), D3DXMatrixTest(), D3DXPlaneTest(), draw_cap(), NS1::f(), fold_sqrt(), anonymous_namespace{resolve_name.cpp}::g(), GdipSetLineSigmaBlend(), GdipSetPathGradientSigmaBlend(), gear(), CAppScrnshotPreview::GetFrameDotShift(), gl_sqrt(), Global_Sqr(), h(), OpenGLSurfaceEvaluator::inComputeNormal2(), init_hatch_palette(), init_layer3(), init_sqrt(), IntGdiWidenPath(), Math_sqrt(), normalize(), prepare_dc(), pres_rsq(), rpn_s_ex(), rpn_sqrt(), SOFTWARE_GdipDrawPath(), sq::sqroot(), sqrtf(), sqrtl(), test_printf_fp(), test_sprintf(), Test_sqrt_approx(), Test_sqrt_exact(), test_timer(), ValarrayTest::transcendentals(), VectorMagnitude(), and CardRegion::ZoomCard().