void bn_cx_sqrt(bn_complex_t *op, const bn_complex_t *ip) { const fastf_t re = ip->re; const fastf_t im = ip->im; /* special cases are not necessary; they are here for speed */ if (ZERO(re)) { if (ZERO(im)) { op->re = op->im = 0.0; } else if (im > 0.0) { op->re = op->im = sqrt(im * 0.5); } else { /* ip->im < 0.0 */ op->re = -(op->im = sqrt(im * -0.5)); } } else if (ZERO(im)) { if (re > 0.0) { op->re = sqrt(re); op->im = 0.0; } else { /* ip->re < 0.0 */ op->im = sqrt(-re); op->re = 0.0; } } else { fastf_t ampl, temp; /* no shortcuts */ ampl = bn_cx_ampl(ip); if ((temp = (ampl - re) * 0.5) < 0.0) { /* This case happens rather often, when the hypot() in * bn_cx_ampl() returns an ampl ever so slightly smaller * than ip->re. This can easily happen when ip->re ~= * 10**20. Just ignore the imaginary part. */ op->im = 0.0; } else { op->im = sqrt(temp); } if ((temp = (ampl + re) * 0.5) < 0.0) { op->re = 0.0; } else { if (im > 0.0) { op->re = sqrt(temp); } else { /* ip->im < 0.0 */ op->re = -sqrt(temp); } } } }
/** * B N _ C X _ S Q R T *@brief * Compute square root of complex number * * bn_cx_sqrt( &out, &c ) replaces out by sqrt(c) * * Note: This is a double-valued function; the result of * bn_cx_sqrt() always has nonnegative imaginary part. */ void bn_cx_sqrt(bn_complex_t *op, register const bn_complex_t *ip) { register fastf_t ampl, temp; /* record signs of original real & imaginary parts */ register int re_sign; register int im_sign; /* special cases are not necessary; they are here for speed */ im_sign = SIGN( ip->im ); if ( (re_sign = SIGN(ip->re)) == 0 ) { if ( im_sign == 0 ) op->re = op->im = 0; else if ( im_sign > 0 ) op->re = op->im = sqrt( ip->im * 0.5 ); else /* im_sign < 0 */ op->re = -(op->im = sqrt( ip->im * -0.5 )); } else if ( im_sign == 0 ) { if ( re_sign > 0 ) { op->re = sqrt( ip->re ); op->im = 0.0; } else { /* re_sign < 0 */ op->im = sqrt( -ip->re ); op->re = 0.0; } } else { /* no shortcuts */ ampl = bn_cx_ampl( ip ); if ( (temp = (ampl - ip->re) * 0.5) < 0.0 ) { /* This case happens rather often, when the * hypot() in bn_cx_ampl() returns an ampl ever so * slightly smaller than ip->re. This can easily * happen when ip->re ~= 10**20. * Just ignore the imaginary part. */ op->im = 0; } else op->im = sqrt( temp ); if ( (temp = (ampl + ip->re) * 0.5) < 0.0 ) { op->re = 0.0; } else { if ( im_sign > 0 ) op->re = sqrt(temp); else /* im_sign < 0 */ op->re = -sqrt(temp); } } }