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