// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
 *
 * Floating-point emulation code
 *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
 */
/*
 * BEGIN_DESC
 *
 *  File:
 *	@(#)	pa/spmath/dfsqrt.c		$Revision: 1.1 $
 *
 *  Purpose:
 *	Double Floating-point Square Root
 *
 *  External Interfaces:
 *	dbl_fsqrt(srcptr,nullptr,dstptr,status)
 *
 *  Internal Interfaces:
 *
 *  Theory:
 *	<<please update with a overview of the operation of this file>>
 *
 * END_DESC
*/


#include "float.h"
#include "dbl_float.h"

/*
 *  Double Floating-point Square Root
 */

/*ARGSUSED*/
unsigned int
dbl_fsqrt(
	    dbl_floating_point *srcptr,
	    unsigned int *nullptr,
	    dbl_floating_point *dstptr,
	    unsigned int *status)
{
	register unsigned int srcp1, srcp2, resultp1, resultp2;
	register unsigned int newbitp1, newbitp2, sump1, sump2;
	register int src_exponent;
	register boolean guardbit = FALSE, even_exponent;

	Dbl_copyfromptr(srcptr,srcp1,srcp2);
        /*
         * check source operand for NaN or infinity
         */
        if ((src_exponent = Dbl_exponent(srcp1)) == DBL_INFINITY_EXPONENT) {
                /*
                 * is signaling NaN?
                 */
                if (Dbl_isone_signaling(srcp1)) {
                        /* trap if INVALIDTRAP enabled */
                        if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
                        /* make NaN quiet */
                        Set_invalidflag();
                        Dbl_set_quiet(srcp1);
                }
                /*
                 * Return quiet NaN or positive infinity.
		 *  Fall through to negative test if negative infinity.
                 */
		if (Dbl_iszero_sign(srcp1) || 
		    Dbl_isnotzero_mantissa(srcp1,srcp2)) {
                	Dbl_copytoptr(srcp1,srcp2,dstptr);
                	return(NOEXCEPTION);
		}
        }

        /*
         * check for zero source operand
         */
	if (Dbl_iszero_exponentmantissa(srcp1,srcp2)) {
		Dbl_copytoptr(srcp1,srcp2,dstptr);
		return(NOEXCEPTION);
	}

        /*
         * check for negative source operand 
         */
	if (Dbl_isone_sign(srcp1)) {
		/* trap if INVALIDTRAP enabled */
		if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
		/* make NaN quiet */
		Set_invalidflag();
		Dbl_makequietnan(srcp1,srcp2);
		Dbl_copytoptr(srcp1,srcp2,dstptr);
		return(NOEXCEPTION);
	}

	/*
	 * Generate result
	 */
	if (src_exponent > 0) {
		even_exponent = Dbl_hidden(srcp1);
		Dbl_clear_signexponent_set_hidden(srcp1);
	}
	else {
		/* normalize operand */
		Dbl_clear_signexponent(srcp1);
		src_exponent++;
		Dbl_normalize(srcp1,srcp2,src_exponent);
		even_exponent = src_exponent & 1;
	}
	if (even_exponent) {
		/* exponent is even */
		/* Add comment here.  Explain why odd exponent needs correction */
		Dbl_leftshiftby1(srcp1,srcp2);
	}
	/*
	 * Add comment here.  Explain following algorithm.
	 * 
	 * Trust me, it works.
	 *
	 */
	Dbl_setzero(resultp1,resultp2);
	Dbl_allp1(newbitp1) = 1 << (DBL_P - 32);
	Dbl_setzero_mantissap2(newbitp2);
	while (Dbl_isnotzero(newbitp1,newbitp2) && Dbl_isnotzero(srcp1,srcp2)) {
		Dbl_addition(resultp1,resultp2,newbitp1,newbitp2,sump1,sump2);
		if(Dbl_isnotgreaterthan(sump1,sump2,srcp1,srcp2)) {
			Dbl_leftshiftby1(newbitp1,newbitp2);
			/* update result */
			Dbl_addition(resultp1,resultp2,newbitp1,newbitp2,
			 resultp1,resultp2);  
			Dbl_subtract(srcp1,srcp2,sump1,sump2,srcp1,srcp2);
			Dbl_rightshiftby2(newbitp1,newbitp2);
		}
		else {
			Dbl_rightshiftby1(newbitp1,newbitp2);
		}
		Dbl_leftshiftby1(srcp1,srcp2);
	}
	/* correct exponent for pre-shift */
	if (even_exponent) {
		Dbl_rightshiftby1(resultp1,resultp2);
	}

	/* check for inexact */
	if (Dbl_isnotzero(srcp1,srcp2)) {
		if (!even_exponent && Dbl_islessthan(resultp1,resultp2,srcp1,srcp2)) {
			Dbl_increment(resultp1,resultp2);
		}
		guardbit = Dbl_lowmantissap2(resultp2);
		Dbl_rightshiftby1(resultp1,resultp2);

		/*  now round result  */
		switch (Rounding_mode()) {
		case ROUNDPLUS:
		     Dbl_increment(resultp1,resultp2);
		     break;
		case ROUNDNEAREST:
		     /* stickybit is always true, so guardbit 
		      * is enough to determine rounding */
		     if (guardbit) {
			    Dbl_increment(resultp1,resultp2);
		     }
		     break;
		}
		/* increment result exponent by 1 if mantissa overflowed */
		if (Dbl_isone_hiddenoverflow(resultp1)) src_exponent+=2;

		if (Is_inexacttrap_enabled()) {
			Dbl_set_exponent(resultp1,
			 ((src_exponent-DBL_BIAS)>>1)+DBL_BIAS);
			Dbl_copytoptr(resultp1,resultp2,dstptr);
			return(INEXACTEXCEPTION);
		}
		else Set_inexactflag();
	}
	else {
		Dbl_rightshiftby1(resultp1,resultp2);
	}
	Dbl_set_exponent(resultp1,((src_exponent-DBL_BIAS)>>1)+DBL_BIAS);
	Dbl_copytoptr(resultp1,resultp2,dstptr);
	return(NOEXCEPTION);
}
