/// Sets *this to the next representable number closer to plus infinity (greater /// = true) or minus infinity (greater = false). void ieee_floatt::next_representable(bool greater) { if(is_NaN()) return; bool old_sign=get_sign(); if(is_zero()) { unpack(1); set_sign(!greater); return; } if(is_infinity()) { if(get_sign()==greater) { make_fltmax(); set_sign(old_sign); } return; } bool dir; if(greater) dir=!get_sign(); else dir=get_sign(); set_sign(false); mp_integer old=pack(); if(dir) ++old; else --old; unpack(old); // sign change impossible (zero case caught earler) set_sign(old_sign); }
void ieee_floatt::align() { // NaN? if(NaN_flag) { fraction=0; exponent=0; sign_flag=false; return; } // do sign if(fraction<0) { sign_flag=!sign_flag; fraction=-fraction; } // zero? if(fraction==0) { exponent=0; return; } // 'usual case' mp_integer f_power=power(2, spec.f); mp_integer f_power_next=power(2, spec.f+1); std::size_t lowPower2=fraction.floorPow2(); mp_integer exponent_offset=0; if(lowPower2<spec.f) // too small { exponent_offset-=(spec.f-lowPower2); assert(fraction*power(2, (spec.f-lowPower2))>=f_power); assert(fraction*power(2, (spec.f-lowPower2))<f_power_next); } else if(lowPower2>spec.f) // too large { exponent_offset+=(lowPower2-spec.f); assert(fraction/power(2, (lowPower2-spec.f))>=f_power); assert(fraction/power(2, (lowPower2-spec.f))<f_power_next); } mp_integer biased_exponent=exponent+exponent_offset+spec.bias(); // exponent too large (infinity)? if(biased_exponent>=spec.max_exponent()) { // we need to consider the rounding mode here switch(rounding_mode) { case UNKNOWN: case NONDETERMINISTIC: case ROUND_TO_EVEN: infinity_flag=true; break; case ROUND_TO_MINUS_INF: // the result of the rounding is never larger than the argument if(sign_flag) infinity_flag=true; else make_fltmax(); break; case ROUND_TO_PLUS_INF: // the result of the rounding is never smaller than the argument if(sign_flag) { make_fltmax(); sign_flag=true; // restore sign } else infinity_flag=true; break; case ROUND_TO_ZERO: if(sign_flag) { make_fltmax(); sign_flag=true; // restore sign } else make_fltmax(); // positive break; } return; // done } else if(biased_exponent<=0) // exponent too small? { // produce a denormal (or zero) mp_integer new_exponent=mp_integer(1)-spec.bias(); exponent_offset=new_exponent-exponent; } exponent+=exponent_offset; if(exponent_offset>0) { divide_and_round(fraction, power(2, exponent_offset)); // rounding might make the fraction too big! if(fraction==f_power_next) { fraction=f_power; ++exponent; } } else if(exponent_offset<0) fraction*=power(2, -exponent_offset); if(fraction==0) exponent=0; }
void ieee_floatt::next_representable(bool greater) { if(is_NaN()) return; bool old_sign = get_sign(); if(is_zero()) { unpack(1); set_sign(!greater); return; } if(is_infinity()) { if(get_sign() == greater) { make_fltmax(); set_sign(old_sign); } return; } bool dir; if(greater) { if(get_sign()) dir = false; else dir = true; } else { if(get_sign()) dir = true; else dir = false; } set_sign(false); mp_integer old = pack(); if(dir) ++old; else --old; unpack(old); //sign change impossible (zero case caught earler) set_sign(old_sign); //mp_integer new_exp = exponent; //mp_integer new_frac = fraction + dir; //std::cout << exponent << ":" << fraction << std::endl; //std::cout << new_exp << ":" << new_frac << std::endl; //if(get_sign()) // new_frac.negate(); //new_exp -= spec.f; //build(new_frac, new_exp); }