/* * sgl_cmp: compare two values */ int sgl_fcmp (sgl_floating_point * leftptr, sgl_floating_point * rightptr, unsigned int cond, unsigned int *status) /* The predicate to be tested */ { register unsigned int left, right; register int xorresult; /* Create local copies of the numbers */ left = *leftptr; right = *rightptr; /* * Test for NaN */ if( (Sgl_exponent(left) == SGL_INFINITY_EXPONENT) || (Sgl_exponent(right) == SGL_INFINITY_EXPONENT) ) { /* Check if a NaN is involved. Signal an invalid exception when * comparing a signaling NaN or when comparing quiet NaNs and the * low bit of the condition is set */ if( ( (Sgl_exponent(left) == SGL_INFINITY_EXPONENT) && Sgl_isnotzero_mantissa(left) && (Exception(cond) || Sgl_isone_signaling(left))) || ( (Sgl_exponent(right) == SGL_INFINITY_EXPONENT) && Sgl_isnotzero_mantissa(right) && (Exception(cond) || Sgl_isone_signaling(right)) ) ) { if( Is_invalidtrap_enabled() ) { Set_status_cbit(Unordered(cond)); return(INVALIDEXCEPTION); } else Set_invalidflag(); Set_status_cbit(Unordered(cond)); return(NOEXCEPTION); } /* All the exceptional conditions are handled, now special case NaN compares */ else if( ((Sgl_exponent(left) == SGL_INFINITY_EXPONENT) && Sgl_isnotzero_mantissa(left)) || ((Sgl_exponent(right) == SGL_INFINITY_EXPONENT) && Sgl_isnotzero_mantissa(right)) ) { /* NaNs always compare unordered. */ Set_status_cbit(Unordered(cond)); return(NOEXCEPTION); } /* infinities will drop down to the normal compare mechanisms */ } /* First compare for unequal signs => less or greater or * special equal case */ Sgl_xortointp1(left,right,xorresult); if( xorresult < 0 ) { /* left negative => less, left positive => greater. * equal is possible if both operands are zeros. */ if( Sgl_iszero_exponentmantissa(left) && Sgl_iszero_exponentmantissa(right) ) { Set_status_cbit(Equal(cond)); } else if( Sgl_isone_sign(left) ) { Set_status_cbit(Lessthan(cond)); } else { Set_status_cbit(Greaterthan(cond)); } } /* Signs are the same. Treat negative numbers separately * from the positives because of the reversed sense. */ else if( Sgl_all(left) == Sgl_all(right) ) { Set_status_cbit(Equal(cond)); } else if( Sgl_iszero_sign(left) ) { /* Positive compare */ if( Sgl_all(left) < Sgl_all(right) ) { Set_status_cbit(Lessthan(cond)); } else { Set_status_cbit(Greaterthan(cond)); } } else { /* Negative compare. Signed or unsigned compares * both work the same. That distinction is only * important when the sign bits differ. */ if( Sgl_all(left) > Sgl_all(right) ) { Set_status_cbit(Lessthan(cond)); } else { Set_status_cbit(Greaterthan(cond)); } } return(NOEXCEPTION); }
/*ARGSUSED*/ int sgl_fsqrt(sgl_floating_point *srcptr, sgl_floating_point *dstptr, unsigned int *status) { register unsigned int src, result; register int src_exponent, newbit, sum; register int guardbit = false, even_exponent; src = *srcptr; /* * check source operand for NaN or infinity */ if ((src_exponent = Sgl_exponent(src)) == SGL_INFINITY_EXPONENT) { /* * is signaling NaN? */ if (Sgl_isone_signaling(src)) { /* trap if INVALIDTRAP enabled */ if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); /* make NaN quiet */ Set_invalidflag(); Sgl_set_quiet(src); } /* * Return quiet NaN or positive infinity. * Fall thru to negative test if negative infinity. */ if (Sgl_iszero_sign(src) || Sgl_isnotzero_mantissa(src)) { *dstptr = src; return(NOEXCEPTION); } } /* * check for zero source operand */ if (Sgl_iszero_exponentmantissa(src)) { *dstptr = src; return(NOEXCEPTION); } /* * check for negative source operand */ if (Sgl_isone_sign(src)) { /* trap if INVALIDTRAP enabled */ if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); /* make NaN quiet */ Set_invalidflag(); Sgl_makequietnan(src); *dstptr = src; return(NOEXCEPTION); } /* * Generate result */ if (src_exponent > 0) { even_exponent = Sgl_hidden(src); Sgl_clear_signexponent_set_hidden(src); } else { /* normalize operand */ Sgl_clear_signexponent(src); src_exponent++; Sgl_normalize(src,src_exponent); even_exponent = src_exponent & 1; } if (even_exponent) { /* exponent is even */ /* Add comment here. Explain why odd exponent needs correction */ Sgl_leftshiftby1(src); } /* * Add comment here. Explain following algorithm. * * Trust me, it works. * */ Sgl_setzero(result); newbit = 1 << SGL_P; while (newbit && Sgl_isnotzero(src)) { Sgl_addition(result,newbit,sum); if(sum <= Sgl_all(src)) { /* update result */ Sgl_addition(result,(newbit<<1),result); Sgl_subtract(src,sum,src); } Sgl_rightshiftby1(newbit); Sgl_leftshiftby1(src); } /* correct exponent for pre-shift */ if (even_exponent) { Sgl_rightshiftby1(result); } /* check for inexact */ if (Sgl_isnotzero(src)) { if (!even_exponent & Sgl_islessthan(result,src)) Sgl_increment(result); guardbit = Sgl_lowmantissa(result); Sgl_rightshiftby1(result); /* now round result */ switch (Rounding_mode()) { case ROUNDPLUS: Sgl_increment(result); break; case ROUNDNEAREST: /* stickybit is always true, so guardbit * is enough to determine rounding */ if (guardbit) { Sgl_increment(result); } break; } /* increment result exponent by 1 if mantissa overflowed */ if (Sgl_isone_hiddenoverflow(result)) src_exponent+=2; if (Is_inexacttrap_enabled()) { Sgl_set_exponent(result, ((src_exponent-SGL_BIAS)>>1)+SGL_BIAS); *dstptr = result; return(INEXACTEXCEPTION); } else Set_inexactflag(); }