amath  1.8.5
Simple command line calculator
sqrt.c
Go to the documentation of this file.
1 /*-
2  * Copyright (c) 2014-2018 Carsten Sonne Larsen <cs@innolan.net>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  * Project homepage:
26  * https://amath.innolan.net
27  *
28  * The original source code can be obtained from:
29  * http://www.netlib.org/fdlibm/e_sqrt.c
30  *
31  * =================================================================
32  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
33  *
34  * Developed at SunSoft, a Sun Microsystems, Inc. business.
35  * Permission to use, copy, modify, and distribute this
36  * software is freely granted, provided that this notice
37  * is preserved.
38  * =================================================================
39  */
40 
41 /**
42  * @file sqrt.c
43  * @brief Square root function
44  */
45 
46 #include "prim.h"
47 
48 static const double
49  one = 1.0,
50  tiny = 1.0e-300;
51 
52 /**
53  * @brief Square root function
54  * @return Correctly rounded sqrt
55  * @details
56  * <pre>
57  * Method:
58  * Bit by bit method using integer arithmetic. (Slow, but portable)
59  * 1. Normalization
60  * Scale x to y in [1,4) with even powers of 2:
61  * find an integer k such that 1 <= (y=x*2^(2k)) < 4, then
62  * sqrt(x) = 2^k * sqrt(y)
63  * 2. Bit by bit computation
64  * Let q = sqrt(y) truncated to i bit after binary point (q = 1),
65  * i 0
66  * i+1 2
67  * s = 2*q , and y = 2 * ( y - q ). (1)
68  * i i i i
69  *
70  * To compute q from q , one checks whether
71  * i+1 i
72  *
73  * -(i+1) 2
74  * (q + 2 ) <= y. (2)
75  * i
76  * -(i+1)
77  * If (2) is false, then q = q ; otherwise q = q + 2 .
78  * i+1 i i+1 i
79  *
80  * With some algebric manipulation, it is not difficult to see
81  * that (2) is equivalent to
82  * -(i+1)
83  * s + 2 <= y (3)
84  * i i
85  *
86  * The advantage of (3) is that s and y can be computed by
87  * i i
88  * the following recurrence formula:
89  * if (3) is false
90  *
91  * s = s , y = y ; (4)
92  * i+1 i i+1 i
93  *
94  * otherwise,
95  * -i -(i+1)
96  * s = s + 2 , y = y - s - 2 (5)
97  * i+1 i i+1 i i
98  *
99  * One may easily use induction to prove (4) and (5).
100  * Note. Since the left hand side of (3) contain only i+2 bits,
101  * it does not necessary to do a full (53-bit) comparison
102  * in (3).
103  * 3. Final rounding
104  * After generating the 53 bits result, we compute one more bit.
105  * Together with the remainder, we can decide whether the
106  * result is exact, bigger than 1/2ulp, or less than 1/2ulp
107  * (it will never equal to 1/2ulp).
108  * The rounding mode can be detected by checking whether
109  * huge + tiny is equal to huge, and whether huge - tiny is
110  * equal to huge for some floating point number "huge" and "tiny".
111  *
112  * Special cases:
113  * sqrt(+-0) = +-0 ... exact
114  * sqrt(inf) = inf
115  * sqrt(-ve) = NaN ... with invalid signal
116  * sqrt(NaN) = NaN ... with invalid signal for signaling NaN
117  * </pre>
118  */
119 double sqrt(double x)
120 {
121  double z;
122  int32_t sign = (int32_t)0x80000000;
123  uint32_t r, t1, s1, ix1, q1;
124  int32_t ix0, s0, q, m, t, i;
125 
126  EXTRACT_WORDS(ix0, ix1, x);
127 
128  // take care of Inf and NaN
129  if ((ix0 & 0x7FF00000) == 0x7FF00000)
130  {
131  // sqrt(NaN)=NaN
132  // sqrt(+inf)=+inf
133  // sqrt(-inf)=sNaN
134  return x * x + x;
135  }
136 
137  // take care of zero
138  if (ix0 <= 0)
139  {
140  if (((ix0 & (~sign)) | ix1) == 0)
141  {
142  // sqrt(+-0) = +-0
143  return x;
144  }
145  else if (ix0 < 0)
146  {
147  //sqrt(-ve) = NaN
148  return NAN;
149  }
150  }
151 
152  // normalize x
153  m = (ix0 >> 20);
154  if (m == 0)
155  {
156  // subnormal x
157  while (ix0 == 0)
158  {
159  m -= 21;
160  ix0 |= (ix1 >> 11);
161  ix1 <<= 21;
162  }
163 
164  for (i = 0; (ix0 & 0x00100000) == 0; i++)
165  {
166  ix0 <<= 1;
167  }
168 
169  m -= i - 1;
170  ix0 |= (ix1 >> (32 - i));
171  ix1 <<= i;
172  }
173 
174  m -= 1023; // unbias exponent
175  ix0 = (ix0 & 0x000FFFFF) | 0x00100000;
176  if (m & 1)
177  {
178  // odd m, double x to make it even
179  ix0 += ix0 + ((ix1 & sign) >> 31);
180  ix1 += ix1;
181  }
182 
183  // m = [m/2]
184  m >>= 1;
185 
186  // generate sqrt(x) bit by bit
187  ix0 += ix0 + ((ix1 & sign) >> 31);
188  ix1 += ix1;
189  q = q1 = s0 = s1 = 0; // [q,q1] = sqrt(x)
190  r = 0x00200000; // r = moving bit from right to left
191 
192  while (r != 0)
193  {
194  t = s0 + r;
195  if (t <= ix0)
196  {
197  s0 = t + r;
198  ix0 -= t;
199  q += r;
200  }
201  ix0 += ix0 + ((ix1 & sign) >> 31);
202  ix1 += ix1;
203  r >>= 1;
204  }
205 
206  r = sign;
207  while (r != 0)
208  {
209  t1 = s1 + r;
210  t = s0;
211  if ((t < ix0) || ((t == ix0) && (t1 <= ix1)))
212  {
213  s1 = t1 + r;
214  if (((t1 & sign) == (uint32_t)sign) && (s1 & sign) == 0)
215  {
216  s0 += 1;
217  }
218  ix0 -= t;
219  if (ix1 < t1)
220  {
221  ix0 -= 1;
222  }
223  ix1 -= t1;
224  q1 += r;
225  }
226 
227  ix0 += ix0 + ((ix1 & sign) >> 31);
228  ix1 += ix1;
229  r >>= 1;
230  }
231 
232  // use floating add to find out rounding direction
233  if ((ix0 | ix1) != 0)
234  {
235  // trigger inexact flag
236  z = one - tiny;
237  if (z >= one)
238  {
239  z = one + tiny;
240  if (q1 == (uint32_t)0xFFFFFFFF)
241  {
242  q1 = 0;
243  q += 1;
244  }
245  else if (z > one)
246  {
247  if (q1 == (uint32_t)0xFFFFFFFE)
248  {
249  q += 1;
250  }
251  q1 += 2;
252  }
253  else
254  {
255  q1 += (q1 & 1);
256  }
257  }
258  }
259 
260  ix0 = (q >> 1) + 0x3FE00000;
261  ix1 = q1 >> 1;
262  if ((q & 1) == 1)
263  {
264  ix1 |= sign;
265  }
266 
267  ix0 += (m << 20);
268  INSERT_WORDS(z, ix0, ix1);
269 
270  return z;
271 }
double sqrt(double x)
Square root function.
Definition: sqrt.c:119
#define INSERT_WORDS(d, ix0, ix1)
Set a double from two 32 bit ints.
Definition: prim.h:187
static const double tiny
Definition: sqrt.c:50
#define EXTRACT_WORDS(ix0, ix1, d)
Get two 32 bit ints from a double.
Definition: prim.h:156
static const double one
Definition: sqrt.c:49
#define NAN
Definition: mathr.h:53