#include "quadmath-imp.h"
#include <math.h>
#include <float.h>
#if __has_include("../../libgcc/soft-fp/soft-fp.h") \
   && __has_include("../../libgcc/soft-fp/quad.h") \
   && defined(FE_TONEAREST) \
   && defined(FE_UPWARD) \
   && defined(FE_DOWNWARD) \
   && defined(FE_TOWARDZERO) \
   && defined(FE_INEXACT)
#define USE_SOFT_FP 1
#if defined(_ARCH_PPC) && !defined(__LONG_DOUBLE_IEEE128__)
#define TFtype __float128
#endif
#include "../../libgcc/soft-fp/soft-fp.h"
#include "../../libgcc/soft-fp/quad.h"
#endif

__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 USE_SOFT_FP
 FP_DECL_EX;
 FP_DECL_Q (X);
 FP_DECL_Q (Y);

 FP_INIT_ROUNDMODE;
 FP_UNPACK_Q (X, x);
 FP_SQRT_Q (Y, X);
 FP_PACK_Q (y, Y);
 FP_HANDLE_EXCEPTIONS;
 return y;
#else
 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;
#endif
}