xref: /titanic_41/usr/src/lib/libm/common/Q/sqrtl.c (revision a9d3dcd5820128b4f34bf38f447e47aa95c004e8)
15b2ba9d3SPiotr Jasiukajtis /*
25b2ba9d3SPiotr Jasiukajtis  * CDDL HEADER START
35b2ba9d3SPiotr Jasiukajtis  *
45b2ba9d3SPiotr Jasiukajtis  * The contents of this file are subject to the terms of the
55b2ba9d3SPiotr Jasiukajtis  * Common Development and Distribution License (the "License").
65b2ba9d3SPiotr Jasiukajtis  * You may not use this file except in compliance with the License.
75b2ba9d3SPiotr Jasiukajtis  *
85b2ba9d3SPiotr Jasiukajtis  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95b2ba9d3SPiotr Jasiukajtis  * or http://www.opensolaris.org/os/licensing.
105b2ba9d3SPiotr Jasiukajtis  * See the License for the specific language governing permissions
115b2ba9d3SPiotr Jasiukajtis  * and limitations under the License.
125b2ba9d3SPiotr Jasiukajtis  *
135b2ba9d3SPiotr Jasiukajtis  * When distributing Covered Code, include this CDDL HEADER in each
145b2ba9d3SPiotr Jasiukajtis  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155b2ba9d3SPiotr Jasiukajtis  * If applicable, add the following below this CDDL HEADER, with the
165b2ba9d3SPiotr Jasiukajtis  * fields enclosed by brackets "[]" replaced with your own identifying
175b2ba9d3SPiotr Jasiukajtis  * information: Portions Copyright [yyyy] [name of copyright owner]
185b2ba9d3SPiotr Jasiukajtis  *
195b2ba9d3SPiotr Jasiukajtis  * CDDL HEADER END
205b2ba9d3SPiotr Jasiukajtis  */
215b2ba9d3SPiotr Jasiukajtis 
225b2ba9d3SPiotr Jasiukajtis /*
235b2ba9d3SPiotr Jasiukajtis  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
245b2ba9d3SPiotr Jasiukajtis  */
255b2ba9d3SPiotr Jasiukajtis /*
265b2ba9d3SPiotr Jasiukajtis  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
275b2ba9d3SPiotr Jasiukajtis  * Use is subject to license terms.
285b2ba9d3SPiotr Jasiukajtis  */
295b2ba9d3SPiotr Jasiukajtis 
30*a9d3dcd5SRichard Lowe #pragma weak __sqrtl = sqrtl
315b2ba9d3SPiotr Jasiukajtis 
325b2ba9d3SPiotr Jasiukajtis #include "libm.h"
335b2ba9d3SPiotr Jasiukajtis #include "longdouble.h"
345b2ba9d3SPiotr Jasiukajtis 
355b2ba9d3SPiotr Jasiukajtis extern int __swapTE(int);
365b2ba9d3SPiotr Jasiukajtis extern int __swapEX(int);
375b2ba9d3SPiotr Jasiukajtis extern enum fp_direction_type __swapRD(enum fp_direction_type);
385b2ba9d3SPiotr Jasiukajtis 
395b2ba9d3SPiotr Jasiukajtis /*
405b2ba9d3SPiotr Jasiukajtis  * in struct longdouble, msw consists of
415b2ba9d3SPiotr Jasiukajtis  *	unsigned short	sgn:1;
425b2ba9d3SPiotr Jasiukajtis  *	unsigned short	exp:15;
435b2ba9d3SPiotr Jasiukajtis  *	unsigned short	frac1:16;
445b2ba9d3SPiotr Jasiukajtis  */
455b2ba9d3SPiotr Jasiukajtis 
465b2ba9d3SPiotr Jasiukajtis #ifdef __LITTLE_ENDIAN
475b2ba9d3SPiotr Jasiukajtis 
485b2ba9d3SPiotr Jasiukajtis /* array indices used to access words within a double */
495b2ba9d3SPiotr Jasiukajtis #define	HIWORD	1
505b2ba9d3SPiotr Jasiukajtis #define	LOWORD	0
515b2ba9d3SPiotr Jasiukajtis 
525b2ba9d3SPiotr Jasiukajtis /* structure used to access words within a quad */
535b2ba9d3SPiotr Jasiukajtis union longdouble {
545b2ba9d3SPiotr Jasiukajtis 	struct {
555b2ba9d3SPiotr Jasiukajtis 		unsigned int	frac4;
565b2ba9d3SPiotr Jasiukajtis 		unsigned int	frac3;
575b2ba9d3SPiotr Jasiukajtis 		unsigned int	frac2;
585b2ba9d3SPiotr Jasiukajtis 		unsigned int	msw;
595b2ba9d3SPiotr Jasiukajtis 	} l;
605b2ba9d3SPiotr Jasiukajtis 	long double	d;
615b2ba9d3SPiotr Jasiukajtis };
625b2ba9d3SPiotr Jasiukajtis 
635b2ba9d3SPiotr Jasiukajtis /* default NaN returned for sqrt(neg) */
645b2ba9d3SPiotr Jasiukajtis static const union longdouble
655b2ba9d3SPiotr Jasiukajtis 	qnan = { 0xffffffff, 0xffffffff, 0xffffffff, 0x7fffffff };
665b2ba9d3SPiotr Jasiukajtis 
675b2ba9d3SPiotr Jasiukajtis /* signalling NaN used to raise invalid */
685b2ba9d3SPiotr Jasiukajtis static const union {
695b2ba9d3SPiotr Jasiukajtis 	unsigned u[2];
705b2ba9d3SPiotr Jasiukajtis 	double d;
715b2ba9d3SPiotr Jasiukajtis } snan = { 0, 0x7ff00001 };
725b2ba9d3SPiotr Jasiukajtis 
735b2ba9d3SPiotr Jasiukajtis #else
745b2ba9d3SPiotr Jasiukajtis 
755b2ba9d3SPiotr Jasiukajtis /* array indices used to access words within a double */
765b2ba9d3SPiotr Jasiukajtis #define	HIWORD	0
775b2ba9d3SPiotr Jasiukajtis #define	LOWORD	1
785b2ba9d3SPiotr Jasiukajtis 
795b2ba9d3SPiotr Jasiukajtis /* structure used to access words within a quad */
805b2ba9d3SPiotr Jasiukajtis union longdouble {
815b2ba9d3SPiotr Jasiukajtis 	struct {
825b2ba9d3SPiotr Jasiukajtis 		unsigned int	msw;
835b2ba9d3SPiotr Jasiukajtis 		unsigned int	frac2;
845b2ba9d3SPiotr Jasiukajtis 		unsigned int	frac3;
855b2ba9d3SPiotr Jasiukajtis 		unsigned int	frac4;
865b2ba9d3SPiotr Jasiukajtis 	} l;
875b2ba9d3SPiotr Jasiukajtis 	long double	d;
885b2ba9d3SPiotr Jasiukajtis };
895b2ba9d3SPiotr Jasiukajtis 
905b2ba9d3SPiotr Jasiukajtis /* default NaN returned for sqrt(neg) */
915b2ba9d3SPiotr Jasiukajtis static const union longdouble
925b2ba9d3SPiotr Jasiukajtis 	qnan = { 0x7fffffff, 0xffffffff, 0xffffffff, 0xffffffff };
935b2ba9d3SPiotr Jasiukajtis 
945b2ba9d3SPiotr Jasiukajtis /* signalling NaN used to raise invalid */
955b2ba9d3SPiotr Jasiukajtis static const union {
965b2ba9d3SPiotr Jasiukajtis 	unsigned u[2];
975b2ba9d3SPiotr Jasiukajtis 	double d;
985b2ba9d3SPiotr Jasiukajtis } snan = { 0x7ff00001, 0 };
995b2ba9d3SPiotr Jasiukajtis 
1005b2ba9d3SPiotr Jasiukajtis #endif /* __LITTLE_ENDIAN */
1015b2ba9d3SPiotr Jasiukajtis 
1025b2ba9d3SPiotr Jasiukajtis 
1035b2ba9d3SPiotr Jasiukajtis static const double
1045b2ba9d3SPiotr Jasiukajtis 	zero = 0.0,
1055b2ba9d3SPiotr Jasiukajtis 	half = 0.5,
1065b2ba9d3SPiotr Jasiukajtis 	one = 1.0,
1075b2ba9d3SPiotr Jasiukajtis 	huge = 1.0e300,
1085b2ba9d3SPiotr Jasiukajtis 	tiny = 1.0e-300,
1095b2ba9d3SPiotr Jasiukajtis 	two36 = 6.87194767360000000000e+10,
1105b2ba9d3SPiotr Jasiukajtis 	two30 = 1.07374182400000000000e+09,
1115b2ba9d3SPiotr Jasiukajtis 	two6 = 6.40000000000000000000e+01,
1125b2ba9d3SPiotr Jasiukajtis 	two4 = 1.60000000000000000000e+01,
1135b2ba9d3SPiotr Jasiukajtis 	twom18 = 3.81469726562500000000e-06,
1145b2ba9d3SPiotr Jasiukajtis 	twom28 = 3.72529029846191406250e-09,
1155b2ba9d3SPiotr Jasiukajtis 	twom42 = 2.27373675443232059479e-13,
1165b2ba9d3SPiotr Jasiukajtis 	twom60 = 8.67361737988403547206e-19,
1175b2ba9d3SPiotr Jasiukajtis 	twom62 = 2.16840434497100886801e-19,
1185b2ba9d3SPiotr Jasiukajtis 	twom66 = 1.35525271560688054251e-20,
1195b2ba9d3SPiotr Jasiukajtis 	twom90 = 8.07793566946316088742e-28,
1205b2ba9d3SPiotr Jasiukajtis 	twom113 = 9.62964972193617926528e-35,
1215b2ba9d3SPiotr Jasiukajtis 	twom124 = 4.70197740328915003187e-38;
1225b2ba9d3SPiotr Jasiukajtis 
1235b2ba9d3SPiotr Jasiukajtis 
1245b2ba9d3SPiotr Jasiukajtis /*
1255b2ba9d3SPiotr Jasiukajtis *	Extract the exponent and normalized significand (represented as
1265b2ba9d3SPiotr Jasiukajtis *	an array of five doubles) from a finite, nonzero quad.
1275b2ba9d3SPiotr Jasiukajtis */
1285b2ba9d3SPiotr Jasiukajtis static int
__q_unpack(const union longdouble * x,double * s)1295b2ba9d3SPiotr Jasiukajtis __q_unpack(const union longdouble *x, double *s)
1305b2ba9d3SPiotr Jasiukajtis {
1315b2ba9d3SPiotr Jasiukajtis 	union {
1325b2ba9d3SPiotr Jasiukajtis 		double			d;
1335b2ba9d3SPiotr Jasiukajtis 		unsigned int	l[2];
1345b2ba9d3SPiotr Jasiukajtis 	} u;
1355b2ba9d3SPiotr Jasiukajtis 	double			b;
1365b2ba9d3SPiotr Jasiukajtis 	unsigned int	lx, w[3];
1375b2ba9d3SPiotr Jasiukajtis 	int				ex;
1385b2ba9d3SPiotr Jasiukajtis 
1395b2ba9d3SPiotr Jasiukajtis 	/* get the normalized significand and exponent */
1405b2ba9d3SPiotr Jasiukajtis 	ex = (int) ((x->l.msw & 0x7fffffff) >> 16);
1415b2ba9d3SPiotr Jasiukajtis 	lx = x->l.msw & 0xffff;
1425b2ba9d3SPiotr Jasiukajtis 	if (ex)
1435b2ba9d3SPiotr Jasiukajtis 	{
1445b2ba9d3SPiotr Jasiukajtis 		lx |= 0x10000;
1455b2ba9d3SPiotr Jasiukajtis 		w[0] = x->l.frac2;
1465b2ba9d3SPiotr Jasiukajtis 		w[1] = x->l.frac3;
1475b2ba9d3SPiotr Jasiukajtis 		w[2] = x->l.frac4;
1485b2ba9d3SPiotr Jasiukajtis 	}
1495b2ba9d3SPiotr Jasiukajtis 	else
1505b2ba9d3SPiotr Jasiukajtis 	{
1515b2ba9d3SPiotr Jasiukajtis 		if (lx | (x->l.frac2 & 0xfffe0000))
1525b2ba9d3SPiotr Jasiukajtis 		{
1535b2ba9d3SPiotr Jasiukajtis 			w[0] = x->l.frac2;
1545b2ba9d3SPiotr Jasiukajtis 			w[1] = x->l.frac3;
1555b2ba9d3SPiotr Jasiukajtis 			w[2] = x->l.frac4;
1565b2ba9d3SPiotr Jasiukajtis 			ex = 1;
1575b2ba9d3SPiotr Jasiukajtis 		}
1585b2ba9d3SPiotr Jasiukajtis 		else if (x->l.frac2 | (x->l.frac3 & 0xfffe0000))
1595b2ba9d3SPiotr Jasiukajtis 		{
1605b2ba9d3SPiotr Jasiukajtis 			lx = x->l.frac2;
1615b2ba9d3SPiotr Jasiukajtis 			w[0] = x->l.frac3;
1625b2ba9d3SPiotr Jasiukajtis 			w[1] = x->l.frac4;
1635b2ba9d3SPiotr Jasiukajtis 			w[2] = 0;
1645b2ba9d3SPiotr Jasiukajtis 			ex = -31;
1655b2ba9d3SPiotr Jasiukajtis 		}
1665b2ba9d3SPiotr Jasiukajtis 		else if (x->l.frac3 | (x->l.frac4 & 0xfffe0000))
1675b2ba9d3SPiotr Jasiukajtis 		{
1685b2ba9d3SPiotr Jasiukajtis 			lx = x->l.frac3;
1695b2ba9d3SPiotr Jasiukajtis 			w[0] = x->l.frac4;
1705b2ba9d3SPiotr Jasiukajtis 			w[1] = w[2] = 0;
1715b2ba9d3SPiotr Jasiukajtis 			ex = -63;
1725b2ba9d3SPiotr Jasiukajtis 		}
1735b2ba9d3SPiotr Jasiukajtis 		else
1745b2ba9d3SPiotr Jasiukajtis 		{
1755b2ba9d3SPiotr Jasiukajtis 			lx = x->l.frac4;
1765b2ba9d3SPiotr Jasiukajtis 			w[0] = w[1] = w[2] = 0;
1775b2ba9d3SPiotr Jasiukajtis 			ex = -95;
1785b2ba9d3SPiotr Jasiukajtis 		}
1795b2ba9d3SPiotr Jasiukajtis 		while ((lx & 0x10000) == 0)
1805b2ba9d3SPiotr Jasiukajtis 		{
1815b2ba9d3SPiotr Jasiukajtis 			lx = (lx << 1) | (w[0] >> 31);
1825b2ba9d3SPiotr Jasiukajtis 			w[0] = (w[0] << 1) | (w[1] >> 31);
1835b2ba9d3SPiotr Jasiukajtis 			w[1] = (w[1] << 1) | (w[2] >> 31);
1845b2ba9d3SPiotr Jasiukajtis 			w[2] <<= 1;
1855b2ba9d3SPiotr Jasiukajtis 			ex--;
1865b2ba9d3SPiotr Jasiukajtis 		}
1875b2ba9d3SPiotr Jasiukajtis 	}
1885b2ba9d3SPiotr Jasiukajtis 
1895b2ba9d3SPiotr Jasiukajtis 	/* extract the significand into five doubles */
1905b2ba9d3SPiotr Jasiukajtis 	u.l[HIWORD] = 0x42300000;
1915b2ba9d3SPiotr Jasiukajtis 	u.l[LOWORD] = 0;
1925b2ba9d3SPiotr Jasiukajtis 	b = u.d;
1935b2ba9d3SPiotr Jasiukajtis 	u.l[LOWORD] = lx;
1945b2ba9d3SPiotr Jasiukajtis 	s[0] = u.d - b;
1955b2ba9d3SPiotr Jasiukajtis 
1965b2ba9d3SPiotr Jasiukajtis 	u.l[HIWORD] = 0x40300000;
1975b2ba9d3SPiotr Jasiukajtis 	u.l[LOWORD] = 0;
1985b2ba9d3SPiotr Jasiukajtis 	b = u.d;
1995b2ba9d3SPiotr Jasiukajtis 	u.l[LOWORD] = w[0] & 0xffffff00;
2005b2ba9d3SPiotr Jasiukajtis 	s[1] = u.d - b;
2015b2ba9d3SPiotr Jasiukajtis 
2025b2ba9d3SPiotr Jasiukajtis 	u.l[HIWORD] = 0x3e300000;
2035b2ba9d3SPiotr Jasiukajtis 	u.l[LOWORD] = 0;
2045b2ba9d3SPiotr Jasiukajtis 	b = u.d;
2055b2ba9d3SPiotr Jasiukajtis 	u.l[HIWORD] |= w[0] & 0xff;
2065b2ba9d3SPiotr Jasiukajtis 	u.l[LOWORD] = w[1] & 0xffff0000;
2075b2ba9d3SPiotr Jasiukajtis 	s[2] = u.d - b;
2085b2ba9d3SPiotr Jasiukajtis 
2095b2ba9d3SPiotr Jasiukajtis 	u.l[HIWORD] = 0x3c300000;
2105b2ba9d3SPiotr Jasiukajtis 	u.l[LOWORD] = 0;
2115b2ba9d3SPiotr Jasiukajtis 	b = u.d;
2125b2ba9d3SPiotr Jasiukajtis 	u.l[HIWORD] |= w[1] & 0xffff;
2135b2ba9d3SPiotr Jasiukajtis 	u.l[LOWORD] = w[2] & 0xff000000;
2145b2ba9d3SPiotr Jasiukajtis 	s[3] = u.d - b;
2155b2ba9d3SPiotr Jasiukajtis 
2165b2ba9d3SPiotr Jasiukajtis 	u.l[HIWORD] = 0x3c300000;
2175b2ba9d3SPiotr Jasiukajtis 	u.l[LOWORD] = 0;
2185b2ba9d3SPiotr Jasiukajtis 	b = u.d;
2195b2ba9d3SPiotr Jasiukajtis 	u.l[LOWORD] = w[2] & 0xffffff;
2205b2ba9d3SPiotr Jasiukajtis 	s[4] = u.d - b;
2215b2ba9d3SPiotr Jasiukajtis 
2225b2ba9d3SPiotr Jasiukajtis 	return ex - 0x3fff;
2235b2ba9d3SPiotr Jasiukajtis }
2245b2ba9d3SPiotr Jasiukajtis 
2255b2ba9d3SPiotr Jasiukajtis 
2265b2ba9d3SPiotr Jasiukajtis /*
2275b2ba9d3SPiotr Jasiukajtis *	Pack an exponent and array of three doubles representing a finite,
2285b2ba9d3SPiotr Jasiukajtis *	nonzero number into a quad.  Assume the sign is already there and
2295b2ba9d3SPiotr Jasiukajtis *	the rounding mode has been fudged accordingly.
2305b2ba9d3SPiotr Jasiukajtis */
2315b2ba9d3SPiotr Jasiukajtis static void
__q_pack(const double * z,int exp,enum fp_direction_type rm,union longdouble * x,int * inexact)2325b2ba9d3SPiotr Jasiukajtis __q_pack(const double *z, int exp, enum fp_direction_type rm,
2335b2ba9d3SPiotr Jasiukajtis 	union longdouble *x, int *inexact)
2345b2ba9d3SPiotr Jasiukajtis {
2355b2ba9d3SPiotr Jasiukajtis 	union {
2365b2ba9d3SPiotr Jasiukajtis 		double			d;
2375b2ba9d3SPiotr Jasiukajtis 		unsigned int	l[2];
2385b2ba9d3SPiotr Jasiukajtis 	} u;
2395b2ba9d3SPiotr Jasiukajtis 	double			s[3], t, t2;
2405b2ba9d3SPiotr Jasiukajtis 	unsigned int	msw, frac2, frac3, frac4;
2415b2ba9d3SPiotr Jasiukajtis 
2425b2ba9d3SPiotr Jasiukajtis 	/* bias exponent and strip off integer bit */
2435b2ba9d3SPiotr Jasiukajtis 	exp += 0x3fff;
2445b2ba9d3SPiotr Jasiukajtis 	s[0] = z[0] - one;
2455b2ba9d3SPiotr Jasiukajtis 	s[1] = z[1];
2465b2ba9d3SPiotr Jasiukajtis 	s[2] = z[2];
2475b2ba9d3SPiotr Jasiukajtis 
2485b2ba9d3SPiotr Jasiukajtis 	/*
2495b2ba9d3SPiotr Jasiukajtis 	 * chop the significand to obtain the fraction;
2505b2ba9d3SPiotr Jasiukajtis 	 * use round-to-minus-infinity to ensure chopping
2515b2ba9d3SPiotr Jasiukajtis 	 */
2525b2ba9d3SPiotr Jasiukajtis 	(void) __swapRD(fp_negative);
2535b2ba9d3SPiotr Jasiukajtis 
2545b2ba9d3SPiotr Jasiukajtis 	/* extract the first eighty bits of fraction */
2555b2ba9d3SPiotr Jasiukajtis 	t = s[1] + s[2];
2565b2ba9d3SPiotr Jasiukajtis 	u.d = two36 + (s[0] + t);
2575b2ba9d3SPiotr Jasiukajtis 	msw = u.l[LOWORD];
2585b2ba9d3SPiotr Jasiukajtis 	s[0] -= (u.d - two36);
2595b2ba9d3SPiotr Jasiukajtis 
2605b2ba9d3SPiotr Jasiukajtis 	u.d = two4 + (s[0] + t);
2615b2ba9d3SPiotr Jasiukajtis 	frac2 = u.l[LOWORD];
2625b2ba9d3SPiotr Jasiukajtis 	s[0] -= (u.d - two4);
2635b2ba9d3SPiotr Jasiukajtis 
2645b2ba9d3SPiotr Jasiukajtis 	u.d = twom28 + (s[0] + t);
2655b2ba9d3SPiotr Jasiukajtis 	frac3 = u.l[LOWORD];
2665b2ba9d3SPiotr Jasiukajtis 	s[0] -= (u.d - twom28);
2675b2ba9d3SPiotr Jasiukajtis 
2685b2ba9d3SPiotr Jasiukajtis 	/* condense the remaining fraction; errors here won't matter */
2695b2ba9d3SPiotr Jasiukajtis 	t = s[0] + s[1];
2705b2ba9d3SPiotr Jasiukajtis 	s[1] = ((s[0] - t) + s[1]) + s[2];
2715b2ba9d3SPiotr Jasiukajtis 	s[0] = t;
2725b2ba9d3SPiotr Jasiukajtis 
2735b2ba9d3SPiotr Jasiukajtis 	/* get the last word of fraction */
2745b2ba9d3SPiotr Jasiukajtis 	u.d = twom60 + (s[0] + s[1]);
2755b2ba9d3SPiotr Jasiukajtis 	frac4 = u.l[LOWORD];
2765b2ba9d3SPiotr Jasiukajtis 	s[0] -= (u.d - twom60);
2775b2ba9d3SPiotr Jasiukajtis 
2785b2ba9d3SPiotr Jasiukajtis 	/*
2795b2ba9d3SPiotr Jasiukajtis 	 * keep track of what's left for rounding; note that
2805b2ba9d3SPiotr Jasiukajtis 	 * t2 will be non-negative due to rounding mode
2815b2ba9d3SPiotr Jasiukajtis 	 */
2825b2ba9d3SPiotr Jasiukajtis 	t = s[0] + s[1];
2835b2ba9d3SPiotr Jasiukajtis 	t2 = (s[0] - t) + s[1];
2845b2ba9d3SPiotr Jasiukajtis 
2855b2ba9d3SPiotr Jasiukajtis 	if (t != zero)
2865b2ba9d3SPiotr Jasiukajtis 	{
2875b2ba9d3SPiotr Jasiukajtis 		*inexact = 1;
2885b2ba9d3SPiotr Jasiukajtis 
2895b2ba9d3SPiotr Jasiukajtis 		/* decide whether to round the fraction up */
2905b2ba9d3SPiotr Jasiukajtis 		if (rm == fp_positive || (rm == fp_nearest && (t > twom113 ||
2915b2ba9d3SPiotr Jasiukajtis 			(t == twom113 && (t2 != zero || frac4 & 1)))))
2925b2ba9d3SPiotr Jasiukajtis 		{
2935b2ba9d3SPiotr Jasiukajtis 			/* round up and renormalize if necessary */
2945b2ba9d3SPiotr Jasiukajtis 			if (++frac4 == 0)
2955b2ba9d3SPiotr Jasiukajtis 				if (++frac3 == 0)
2965b2ba9d3SPiotr Jasiukajtis 					if (++frac2 == 0)
2975b2ba9d3SPiotr Jasiukajtis 						if (++msw == 0x10000)
2985b2ba9d3SPiotr Jasiukajtis 						{
2995b2ba9d3SPiotr Jasiukajtis 							msw = 0;
3005b2ba9d3SPiotr Jasiukajtis 							exp++;
3015b2ba9d3SPiotr Jasiukajtis 						}
3025b2ba9d3SPiotr Jasiukajtis 		}
3035b2ba9d3SPiotr Jasiukajtis 	}
3045b2ba9d3SPiotr Jasiukajtis 
3055b2ba9d3SPiotr Jasiukajtis 	/* assemble the result */
3065b2ba9d3SPiotr Jasiukajtis 	x->l.msw |= msw | (exp << 16);
3075b2ba9d3SPiotr Jasiukajtis 	x->l.frac2 = frac2;
3085b2ba9d3SPiotr Jasiukajtis 	x->l.frac3 = frac3;
3095b2ba9d3SPiotr Jasiukajtis 	x->l.frac4 = frac4;
3105b2ba9d3SPiotr Jasiukajtis }
3115b2ba9d3SPiotr Jasiukajtis 
3125b2ba9d3SPiotr Jasiukajtis 
3135b2ba9d3SPiotr Jasiukajtis /*
3145b2ba9d3SPiotr Jasiukajtis *	Compute the square root of x and place the TP result in s.
3155b2ba9d3SPiotr Jasiukajtis */
3165b2ba9d3SPiotr Jasiukajtis static void
__q_tp_sqrt(const double * x,double * s)3175b2ba9d3SPiotr Jasiukajtis __q_tp_sqrt(const double *x, double *s)
3185b2ba9d3SPiotr Jasiukajtis {
3195b2ba9d3SPiotr Jasiukajtis 	double	c, rr, r[3], tt[3], t[5];
3205b2ba9d3SPiotr Jasiukajtis 
3215b2ba9d3SPiotr Jasiukajtis 	/* approximate the divisor for the Newton iteration */
3225b2ba9d3SPiotr Jasiukajtis 	c = sqrt((x[0] + x[1]) + x[2]);
3235b2ba9d3SPiotr Jasiukajtis 	rr = half / c;
3245b2ba9d3SPiotr Jasiukajtis 
3255b2ba9d3SPiotr Jasiukajtis 	/* compute the first five "digits" of the square root */
3265b2ba9d3SPiotr Jasiukajtis 	t[0] = (c + two30) - two30;
3275b2ba9d3SPiotr Jasiukajtis 	tt[0] = t[0] + t[0];
3285b2ba9d3SPiotr Jasiukajtis 	r[0] = ((x[0] - t[0] * t[0]) + x[1]) + x[2];
3295b2ba9d3SPiotr Jasiukajtis 
3305b2ba9d3SPiotr Jasiukajtis 	t[1] = (rr * (r[0] + x[3]) + two6) - two6;
3315b2ba9d3SPiotr Jasiukajtis 	tt[1] = t[1] + t[1];
3325b2ba9d3SPiotr Jasiukajtis 	r[0] -= tt[0] * t[1];
3335b2ba9d3SPiotr Jasiukajtis 	r[1] = x[3] - t[1] * t[1];
3345b2ba9d3SPiotr Jasiukajtis 	c = (r[1] + twom18) - twom18;
3355b2ba9d3SPiotr Jasiukajtis 	r[0] += c;
3365b2ba9d3SPiotr Jasiukajtis 	r[1] = (r[1] - c) + x[4];
3375b2ba9d3SPiotr Jasiukajtis 
3385b2ba9d3SPiotr Jasiukajtis 	t[2] = (rr * (r[0] + r[1]) + twom18) - twom18;
3395b2ba9d3SPiotr Jasiukajtis 	tt[2] = t[2] + t[2];
3405b2ba9d3SPiotr Jasiukajtis 	r[0] -= tt[0] * t[2];
3415b2ba9d3SPiotr Jasiukajtis 	r[1] -= tt[1] * t[2];
3425b2ba9d3SPiotr Jasiukajtis 	c = (r[1] + twom42) - twom42;
3435b2ba9d3SPiotr Jasiukajtis 	r[0] += c;
3445b2ba9d3SPiotr Jasiukajtis 	r[1] = (r[1] - c) - t[2] * t[2];
3455b2ba9d3SPiotr Jasiukajtis 
3465b2ba9d3SPiotr Jasiukajtis 	t[3] = (rr * (r[0] + r[1]) + twom42) - twom42;
3475b2ba9d3SPiotr Jasiukajtis 	r[0] = ((r[0] - tt[0] * t[3]) + r[1]) - tt[1] * t[3];
3485b2ba9d3SPiotr Jasiukajtis 	r[1] = -tt[2] * t[3];
3495b2ba9d3SPiotr Jasiukajtis 	c = (r[1] + twom90) - twom90;
3505b2ba9d3SPiotr Jasiukajtis 	r[0] += c;
3515b2ba9d3SPiotr Jasiukajtis 	r[1] = (r[1] - c) - t[3] * t[3];
3525b2ba9d3SPiotr Jasiukajtis 
3535b2ba9d3SPiotr Jasiukajtis 	t[4] = (rr * (r[0] + r[1]) + twom66) - twom66;
3545b2ba9d3SPiotr Jasiukajtis 
3555b2ba9d3SPiotr Jasiukajtis 	/* here we just need to get the sign of the remainder */
3565b2ba9d3SPiotr Jasiukajtis 	c = (((((r[0] - tt[0] * t[4]) - tt[1] * t[4]) + r[1])
3575b2ba9d3SPiotr Jasiukajtis 		- tt[2] * t[4]) - (t[3] + t[3]) * t[4]) - t[4] * t[4];
3585b2ba9d3SPiotr Jasiukajtis 
3595b2ba9d3SPiotr Jasiukajtis 	/* reduce to three doubles */
3605b2ba9d3SPiotr Jasiukajtis 	t[0] += t[1];
3615b2ba9d3SPiotr Jasiukajtis 	t[1] = t[2] + t[3];
3625b2ba9d3SPiotr Jasiukajtis 	t[2] = t[4];
3635b2ba9d3SPiotr Jasiukajtis 
3645b2ba9d3SPiotr Jasiukajtis 	/* if the third term might lie on a rounding boundary, perturb it */
3655b2ba9d3SPiotr Jasiukajtis 	if (c != zero && t[2] == (twom62 + t[2]) - twom62)
3665b2ba9d3SPiotr Jasiukajtis 	{
3675b2ba9d3SPiotr Jasiukajtis 		if (c < zero)
3685b2ba9d3SPiotr Jasiukajtis 			t[2] -= twom124;
3695b2ba9d3SPiotr Jasiukajtis 		else
3705b2ba9d3SPiotr Jasiukajtis 			t[2] += twom124;
3715b2ba9d3SPiotr Jasiukajtis 	}
3725b2ba9d3SPiotr Jasiukajtis 
3735b2ba9d3SPiotr Jasiukajtis 	/* condense the square root */
3745b2ba9d3SPiotr Jasiukajtis 	c = t[1] + t[2];
3755b2ba9d3SPiotr Jasiukajtis 	t[2] += (t[1] - c);
3765b2ba9d3SPiotr Jasiukajtis 	t[1] = c;
3775b2ba9d3SPiotr Jasiukajtis 	c = t[0] + t[1];
3785b2ba9d3SPiotr Jasiukajtis 	s[1] = t[1] + (t[0] - c);
3795b2ba9d3SPiotr Jasiukajtis 	s[0] = c;
3805b2ba9d3SPiotr Jasiukajtis 	if (s[1] == zero)
3815b2ba9d3SPiotr Jasiukajtis 	{
3825b2ba9d3SPiotr Jasiukajtis 		c = s[0] + t[2];
3835b2ba9d3SPiotr Jasiukajtis 		s[1] = t[2] + (s[0] - c);
3845b2ba9d3SPiotr Jasiukajtis 		s[0] = c;
3855b2ba9d3SPiotr Jasiukajtis 		s[2] = zero;
3865b2ba9d3SPiotr Jasiukajtis 	}
3875b2ba9d3SPiotr Jasiukajtis 	else
3885b2ba9d3SPiotr Jasiukajtis 	{
3895b2ba9d3SPiotr Jasiukajtis 		c = s[1] + t[2];
3905b2ba9d3SPiotr Jasiukajtis 		s[2] = t[2] + (s[1] - c);
3915b2ba9d3SPiotr Jasiukajtis 		s[1] = c;
3925b2ba9d3SPiotr Jasiukajtis 	}
3935b2ba9d3SPiotr Jasiukajtis }
3945b2ba9d3SPiotr Jasiukajtis 
3955b2ba9d3SPiotr Jasiukajtis 
3965b2ba9d3SPiotr Jasiukajtis long double
sqrtl(long double ldx)3975b2ba9d3SPiotr Jasiukajtis sqrtl(long double ldx)
3985b2ba9d3SPiotr Jasiukajtis {
3995b2ba9d3SPiotr Jasiukajtis 	union	longdouble		x;
4005b2ba9d3SPiotr Jasiukajtis 	volatile double			t;
4015b2ba9d3SPiotr Jasiukajtis 	double					xx[5], zz[3];
4025b2ba9d3SPiotr Jasiukajtis 	enum fp_direction_type	rm;
4035b2ba9d3SPiotr Jasiukajtis 	int				ex, inexact, exc, traps;
4045b2ba9d3SPiotr Jasiukajtis 
4055b2ba9d3SPiotr Jasiukajtis 	/* clear cexc */
4065b2ba9d3SPiotr Jasiukajtis 	t = zero;
4075b2ba9d3SPiotr Jasiukajtis 	t -= zero;
4085b2ba9d3SPiotr Jasiukajtis 
4095b2ba9d3SPiotr Jasiukajtis 	/* check for zero operand */
4105b2ba9d3SPiotr Jasiukajtis 	x.d = ldx;
4115b2ba9d3SPiotr Jasiukajtis 	if (!((x.l.msw & 0x7fffffff) | x.l.frac2 | x.l.frac3 | x.l.frac4))
4125b2ba9d3SPiotr Jasiukajtis 		return ldx;
4135b2ba9d3SPiotr Jasiukajtis 
4145b2ba9d3SPiotr Jasiukajtis 	/* handle nan and inf cases */
4155b2ba9d3SPiotr Jasiukajtis 	if ((x.l.msw & 0x7fffffff) >= 0x7fff0000)
4165b2ba9d3SPiotr Jasiukajtis 	{
4175b2ba9d3SPiotr Jasiukajtis 		if ((x.l.msw & 0xffff) | x.l.frac2 | x.l.frac3 | x.l.frac4)
4185b2ba9d3SPiotr Jasiukajtis 		{
4195b2ba9d3SPiotr Jasiukajtis 			if (!(x.l.msw & 0x8000))
4205b2ba9d3SPiotr Jasiukajtis 			{
4215b2ba9d3SPiotr Jasiukajtis 				/* snan, signal invalid */
4225b2ba9d3SPiotr Jasiukajtis 				t += snan.d;
4235b2ba9d3SPiotr Jasiukajtis 			}
4245b2ba9d3SPiotr Jasiukajtis 			x.l.msw |= 0x8000;
4255b2ba9d3SPiotr Jasiukajtis 			return x.d;
4265b2ba9d3SPiotr Jasiukajtis 		}
4275b2ba9d3SPiotr Jasiukajtis 		if (x.l.msw & 0x80000000)
4285b2ba9d3SPiotr Jasiukajtis 		{
4295b2ba9d3SPiotr Jasiukajtis 			/* sqrt(-inf), signal invalid */
4305b2ba9d3SPiotr Jasiukajtis 			t = -one;
4315b2ba9d3SPiotr Jasiukajtis 			t = sqrt(t);
4325b2ba9d3SPiotr Jasiukajtis 			return qnan.d;
4335b2ba9d3SPiotr Jasiukajtis 		}
4345b2ba9d3SPiotr Jasiukajtis 		/* sqrt(inf), return inf */
4355b2ba9d3SPiotr Jasiukajtis 		return x.d;
4365b2ba9d3SPiotr Jasiukajtis 	}
4375b2ba9d3SPiotr Jasiukajtis 
4385b2ba9d3SPiotr Jasiukajtis 	/* handle negative numbers */
4395b2ba9d3SPiotr Jasiukajtis 	if (x.l.msw & 0x80000000)
4405b2ba9d3SPiotr Jasiukajtis 	{
4415b2ba9d3SPiotr Jasiukajtis 		t = -one;
4425b2ba9d3SPiotr Jasiukajtis 		t = sqrt(t);
4435b2ba9d3SPiotr Jasiukajtis 		return qnan.d;
4445b2ba9d3SPiotr Jasiukajtis 	}
4455b2ba9d3SPiotr Jasiukajtis 
4465b2ba9d3SPiotr Jasiukajtis 	/* now x is finite, positive */
4475b2ba9d3SPiotr Jasiukajtis 
4485b2ba9d3SPiotr Jasiukajtis 	traps = __swapTE(0);
4495b2ba9d3SPiotr Jasiukajtis 	exc = __swapEX(0);
4505b2ba9d3SPiotr Jasiukajtis 	rm = __swapRD(fp_nearest);
4515b2ba9d3SPiotr Jasiukajtis 
4525b2ba9d3SPiotr Jasiukajtis 	ex = __q_unpack(&x, xx);
4535b2ba9d3SPiotr Jasiukajtis 	if (ex & 1)
4545b2ba9d3SPiotr Jasiukajtis 	{
4555b2ba9d3SPiotr Jasiukajtis 		/* make exponent even */
4565b2ba9d3SPiotr Jasiukajtis 		xx[0] += xx[0];
4575b2ba9d3SPiotr Jasiukajtis 		xx[1] += xx[1];
4585b2ba9d3SPiotr Jasiukajtis 		xx[2] += xx[2];
4595b2ba9d3SPiotr Jasiukajtis 		xx[3] += xx[3];
4605b2ba9d3SPiotr Jasiukajtis 		xx[4] += xx[4];
4615b2ba9d3SPiotr Jasiukajtis 		ex--;
4625b2ba9d3SPiotr Jasiukajtis 	}
4635b2ba9d3SPiotr Jasiukajtis 	__q_tp_sqrt(xx, zz);
4645b2ba9d3SPiotr Jasiukajtis 
4655b2ba9d3SPiotr Jasiukajtis 	/* put everything together */
4665b2ba9d3SPiotr Jasiukajtis 	x.l.msw = 0;
4675b2ba9d3SPiotr Jasiukajtis 	inexact = 0;
4685b2ba9d3SPiotr Jasiukajtis 	__q_pack(zz, ex >> 1, rm, &x, &inexact);
4695b2ba9d3SPiotr Jasiukajtis 
4705b2ba9d3SPiotr Jasiukajtis 	(void) __swapRD(rm);
4715b2ba9d3SPiotr Jasiukajtis 	(void) __swapEX(exc);
4725b2ba9d3SPiotr Jasiukajtis 	(void) __swapTE(traps);
4735b2ba9d3SPiotr Jasiukajtis 	if (inexact)
4745b2ba9d3SPiotr Jasiukajtis 	{
4755b2ba9d3SPiotr Jasiukajtis 		t = huge;
4765b2ba9d3SPiotr Jasiukajtis 		t += tiny;
4775b2ba9d3SPiotr Jasiukajtis 	}
4785b2ba9d3SPiotr Jasiukajtis 	return x.d;
4795b2ba9d3SPiotr Jasiukajtis }
480