|
Packit Service |
82fcde |
/*
|
|
Packit Service |
82fcde |
* IBM Accurate Mathematical Library
|
|
Packit Service |
82fcde |
* written by International Business Machines Corp.
|
|
Packit Service |
82fcde |
* Copyright (C) 2001-2018 Free Software Foundation, Inc.
|
|
Packit Service |
82fcde |
*
|
|
Packit Service |
82fcde |
* This program is free software; you can redistribute it and/or modify
|
|
Packit Service |
82fcde |
* it under the terms of the GNU Lesser General Public License as published by
|
|
Packit Service |
82fcde |
* the Free Software Foundation; either version 2.1 of the License, or
|
|
Packit Service |
82fcde |
* (at your option) any later version.
|
|
Packit Service |
82fcde |
*
|
|
Packit Service |
82fcde |
* This program is distributed in the hope that it will be useful,
|
|
Packit Service |
82fcde |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
82fcde |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
82fcde |
* GNU Lesser General Public License for more details.
|
|
Packit Service |
82fcde |
*
|
|
Packit Service |
82fcde |
* You should have received a copy of the GNU Lesser General Public License
|
|
Packit Service |
82fcde |
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
Packit Service |
82fcde |
*/
|
|
Packit Service |
82fcde |
/*********************************************************************/
|
|
Packit Service |
82fcde |
/* MODULE_NAME: uroot.c */
|
|
Packit Service |
82fcde |
/* */
|
|
Packit Service |
82fcde |
/* FUNCTION: usqrt */
|
|
Packit Service |
82fcde |
/* */
|
|
Packit Service |
82fcde |
/* FILES NEEDED: dla.h endian.h mydefs.h */
|
|
Packit Service |
82fcde |
/* uroot.tbl */
|
|
Packit Service |
82fcde |
/* */
|
|
Packit Service |
82fcde |
/* An ultimate sqrt routine. Given an IEEE double machine number x */
|
|
Packit Service |
82fcde |
/* it computes the correctly rounded (to nearest) value of square */
|
|
Packit Service |
82fcde |
/* root of x. */
|
|
Packit Service |
82fcde |
/* Assumption: Machine arithmetic operations are performed in */
|
|
Packit Service |
82fcde |
/* round to nearest mode of IEEE 754 standard. */
|
|
Packit Service |
82fcde |
/* */
|
|
Packit Service |
82fcde |
/*********************************************************************/
|
|
Packit Service |
82fcde |
|
|
Packit Service |
82fcde |
#include "endian.h"
|
|
Packit Service |
82fcde |
#include "mydefs.h"
|
|
Packit Service |
82fcde |
#include <dla.h>
|
|
Packit Service |
82fcde |
#include "MathLib.h"
|
|
Packit Service |
82fcde |
#include "root.tbl"
|
|
Packit Service |
82fcde |
#include <math-barriers.h>
|
|
Packit Service |
82fcde |
#include <math_private.h>
|
|
Packit Service |
82fcde |
|
|
Packit Service |
82fcde |
/*********************************************************************/
|
|
Packit Service |
82fcde |
/* An ultimate sqrt routine. Given an IEEE double machine number x */
|
|
Packit Service |
82fcde |
/* it computes the correctly rounded (to nearest) value of square */
|
|
Packit Service |
82fcde |
/* root of x. */
|
|
Packit Service |
82fcde |
/*********************************************************************/
|
|
Packit Service |
82fcde |
double
|
|
Packit Service |
82fcde |
__ieee754_sqrt (double x)
|
|
Packit Service |
82fcde |
{
|
|
Packit Service |
82fcde |
static const double
|
|
Packit Service |
82fcde |
rt0 = 9.99999999859990725855365213134618E-01,
|
|
Packit Service |
82fcde |
rt1 = 4.99999999495955425917856814202739E-01,
|
|
Packit Service |
82fcde |
rt2 = 3.75017500867345182581453026130850E-01,
|
|
Packit Service |
82fcde |
rt3 = 3.12523626554518656309172508769531E-01;
|
|
Packit Service |
82fcde |
static const double big = 134217728.0;
|
|
Packit Service |
82fcde |
double y, t, del, res, res1, hy, z, zz, p, hx, tx, ty, s;
|
|
Packit Service |
82fcde |
mynumber a, c = { { 0, 0 } };
|
|
Packit Service |
82fcde |
int4 k;
|
|
Packit Service |
82fcde |
|
|
Packit Service |
82fcde |
a.x = x;
|
|
Packit Service |
82fcde |
k = a.i[HIGH_HALF];
|
|
Packit Service |
82fcde |
a.i[HIGH_HALF] = (k & 0x001fffff) | 0x3fe00000;
|
|
Packit Service |
82fcde |
t = inroot[(k & 0x001fffff) >> 14];
|
|
Packit Service |
82fcde |
s = a.x;
|
|
Packit Service |
82fcde |
/*----------------- 2^-1022 <= | x |< 2^1024 -----------------*/
|
|
Packit Service |
82fcde |
if (k > 0x000fffff && k < 0x7ff00000)
|
|
Packit Service |
82fcde |
{
|
|
Packit Service |
82fcde |
int rm = __fegetround ();
|
|
Packit Service |
82fcde |
fenv_t env;
|
|
Packit Service |
82fcde |
libc_feholdexcept_setround (&env, FE_TONEAREST);
|
|
Packit Service |
82fcde |
double ret;
|
|
Packit Service |
82fcde |
y = 1.0 - t * (t * s);
|
|
Packit Service |
82fcde |
t = t * (rt0 + y * (rt1 + y * (rt2 + y * rt3)));
|
|
Packit Service |
82fcde |
c.i[HIGH_HALF] = 0x20000000 + ((k & 0x7fe00000) >> 1);
|
|
Packit Service |
82fcde |
y = t * s;
|
|
Packit Service |
82fcde |
hy = (y + big) - big;
|
|
Packit Service |
82fcde |
del = 0.5 * t * ((s - hy * hy) - (y - hy) * (y + hy));
|
|
Packit Service |
82fcde |
res = y + del;
|
|
Packit Service |
82fcde |
if (res == (res + 1.002 * ((y - res) + del)))
|
|
Packit Service |
82fcde |
ret = res * c.x;
|
|
Packit Service |
82fcde |
else
|
|
Packit Service |
82fcde |
{
|
|
Packit Service |
82fcde |
res1 = res + 1.5 * ((y - res) + del);
|
|
Packit Service |
82fcde |
EMULV (res, res1, z, zz, p, hx, tx, hy, ty); /* (z+zz)=res*res1 */
|
|
Packit Service |
82fcde |
res = ((((z - s) + zz) < 0) ? max (res, res1) :
|
|
Packit Service |
82fcde |
min (res, res1));
|
|
Packit Service |
82fcde |
ret = res * c.x;
|
|
Packit Service |
82fcde |
}
|
|
Packit Service |
82fcde |
math_force_eval (ret);
|
|
Packit Service |
82fcde |
libc_fesetenv (&env;;
|
|
Packit Service |
82fcde |
double dret = x / ret;
|
|
Packit Service |
82fcde |
if (dret != ret)
|
|
Packit Service |
82fcde |
{
|
|
Packit Service |
82fcde |
double force_inexact = 1.0 / 3.0;
|
|
Packit Service |
82fcde |
math_force_eval (force_inexact);
|
|
Packit Service |
82fcde |
/* The square root is inexact, ret is the round-to-nearest
|
|
Packit Service |
82fcde |
value which may need adjusting for other rounding
|
|
Packit Service |
82fcde |
modes. */
|
|
Packit Service |
82fcde |
switch (rm)
|
|
Packit Service |
82fcde |
{
|
|
Packit Service |
82fcde |
#ifdef FE_UPWARD
|
|
Packit Service |
82fcde |
case FE_UPWARD:
|
|
Packit Service |
82fcde |
if (dret > ret)
|
|
Packit Service |
82fcde |
ret = (res + 0x1p-1022) * c.x;
|
|
Packit Service |
82fcde |
break;
|
|
Packit Service |
82fcde |
#endif
|
|
Packit Service |
82fcde |
|
|
Packit Service |
82fcde |
#ifdef FE_DOWNWARD
|
|
Packit Service |
82fcde |
case FE_DOWNWARD:
|
|
Packit Service |
82fcde |
#endif
|
|
Packit Service |
82fcde |
#ifdef FE_TOWARDZERO
|
|
Packit Service |
82fcde |
case FE_TOWARDZERO:
|
|
Packit Service |
82fcde |
#endif
|
|
Packit Service |
82fcde |
#if defined FE_DOWNWARD || defined FE_TOWARDZERO
|
|
Packit Service |
82fcde |
if (dret < ret)
|
|
Packit Service |
82fcde |
ret = (res - 0x1p-1022) * c.x;
|
|
Packit Service |
82fcde |
break;
|
|
Packit Service |
82fcde |
#endif
|
|
Packit Service |
82fcde |
|
|
Packit Service |
82fcde |
default:
|
|
Packit Service |
82fcde |
break;
|
|
Packit Service |
82fcde |
}
|
|
Packit Service |
82fcde |
}
|
|
Packit Service |
82fcde |
/* Otherwise (x / ret == ret), either the square root was exact or
|
|
Packit Service |
82fcde |
the division was inexact. */
|
|
Packit Service |
82fcde |
return ret;
|
|
Packit Service |
82fcde |
}
|
|
Packit Service |
82fcde |
else
|
|
Packit Service |
82fcde |
{
|
|
Packit Service |
82fcde |
if ((k & 0x7ff00000) == 0x7ff00000)
|
|
Packit Service |
82fcde |
return x * x + x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf, sqrt(-inf)=sNaN */
|
|
Packit Service |
82fcde |
if (x == 0)
|
|
Packit Service |
82fcde |
return x; /* sqrt(+0)=+0, sqrt(-0)=-0 */
|
|
Packit Service |
82fcde |
if (k < 0)
|
|
Packit Service |
82fcde |
return (x - x) / (x - x); /* sqrt(-ve)=sNaN */
|
|
Packit Service |
82fcde |
return 0x1p-256 * __ieee754_sqrt (x * 0x1p512);
|
|
Packit Service |
82fcde |
}
|
|
Packit Service |
82fcde |
}
|
|
Packit Service |
82fcde |
strong_alias (__ieee754_sqrt, __sqrt_finite)
|