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::align() { // NaN? if(NaN) { fraction=0; exponent=0; sign=false; return; } // do sign if(fraction<0) { sign=!sign; 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); mp_integer exponent_offset=0; if(fraction<f_power) // too small? { mp_integer tmp_fraction=fraction; while(tmp_fraction<f_power) { tmp_fraction*=2; --exponent_offset; } } else if(fraction>=f_power_next) // too big? { mp_integer tmp_fraction=fraction; while(tmp_fraction>=f_power_next) { tmp_fraction/=2; ++exponent_offset; } } mp_integer biased_exponent=exponent+exponent_offset+spec.bias(); // exponent too large (infinity)? if(biased_exponent>=spec.max_exponent()) infinity=true; 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; }