示例#1
0
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;
}
示例#2
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;
}