| #include "quadmath-imp.h" | |
| #include <math.h> | |
| #include <float.h> | |
| __float128 | |
| sqrtq (const __float128 x) | |
| { | |
| __float128 y; | |
| int exp; | |
| if (isnanq (x) || (isinfq (x) && x > 0)) | |
| return x; | |
| if (x == 0) | |
| return x; | |
| if (x < 0) | |
| { | |
| /* Return NaN with invalid signal. */ | |
| return (x - x) / (x - x); | |
| } | |
| if (x <= DBL_MAX && x >= DBL_MIN) | |
| { | |
| /* Use double result as starting point. */ | |
| y = sqrt ((double) x); | |
| /* Two Newton iterations. */ | |
| y -= 0.5q * (y - x / y); | |
| y -= 0.5q * (y - x / y); | |
| return y; | |
| } | |
| #ifdef HAVE_SQRTL | |
| { | |
| long double xl = (long double) x; | |
| if (xl <= LDBL_MAX && xl >= LDBL_MIN) | |
| { | |
| /* Use long double result as starting point. */ | |
| y = (__float128) sqrtl (xl); | |
| /* One Newton iteration. */ | |
| y -= 0.5q * (y - x / y); | |
| return y; | |
| } | |
| } | |
| #endif | |
| /* If we're outside of the range of C types, we have to compute | |
| the initial guess the hard way. */ | |
| y = frexpq (x, &exp); | |
| if (exp % 2) | |
| y *= 2, exp--; | |
| y = sqrt (y); | |
| y = scalbnq (y, exp / 2); | |
| /* Two Newton iterations. */ | |
| y -= 0.5q * (y - x / y); | |
| y -= 0.5q * (y - x / y); | |
| return y; | |
| } | |