[gnu.g++.lib.bug] Floating point execption in libg++/tests/tFix

pa1412@sdcc13.ucsd.edu (pa1412) (10/27/89)

Library Source: labrea.stanford.edu:gnu/libg++.xtar.Z (2-Oct-89)

I noted that some one else has seen a similar problem on a machine I
can't remember. (One of these days I'll learn how to use 'rn'
comands).

My machine: MASSCOMP 5600, RTU 4.0A, (unix Sys V.2 with BSD'isms)
Processor: 68020, 68881 FPU.

When running the tFix program in libg++/tests, I got a floating
point execption. On further investigation I found that the Fix.cc
code in libg++/src/Fix.cc had an error. The routine

new_Fix( uint16 len, double d)

was converting negative floating point value erroneously. The
corresponding conversion from Fixed to double expected the Fixed
number to lie in the ranged of 0.0 to 2.0. As a final act the Fixed
to double routine would subtract 2.0 from a value which was in the
range of 1.0-2.0. The doube to Fixed routine did not do the
cooresponding translation of floating point values in the range of
-1.0-0.0 to the range of 1.0-2.0.

If the above doesn't make sense then the code is given below.


-------------------------- Cut Here ---------------------------------

// Source for the errant subroutine.

_Fix new_Fix(uint16 len, _Fix x)
{
  _Fix z = _new_Fix(len);
  return copy(x,z);
}

_Fix new_Fix(uint16 len, double d)
{
  _Fix z = _new_Fix(len);

  if ( d == _Fix_max_value )
  {
    z->s[0] = 0x7fff;
    for ( int i=1; i < z->siz; i++ )
      z->s[i] = 0xffff;
  }
  else if ( d < _Fix_min_value || d > _Fix_max_value )
    (*Fix_range_error_handler)("declaration");
  else
  {
    d = ( d < 0.0 ) ? (d + 2.0) : d; // Fix for floating point execptions.
				// the value( Fix& x ) function expects a
				// values between 0.0 and 2.0 with values
				// 0.0-1.0 mapping to positive reals,
				// and values 1.0-2.0 mapping negative
				// reals from -1.0-0.0.
				// The old code did not map negative reals
				// to positive reals in the range of 1.0-2.0
				// and would overflow a long int value on
				// a 680x0(4 bytes) eventually.

    d *= 32768;
    for ( int i=0; i < z->siz; i++ )
    {
      z->s[i] = (uint16 )d;
      d -= z->s[i];
      d *= 65536;
    }

    if ( d >= 32768 )
      z->s[z->siz-1]++;
  }
  mask(z);
  return z;
}

// convert to a double 

double value(Fix& x)
{ 
  double d = 0.0;
  for ( int i=x.rep->siz-1; i >= 0; i-- )
  {
    d += x.rep->s[i];
    d *= 1./65536.;
  }
  d *= 2.;
  return d < 1. ? d : d - 2.;
}

************************* Diff of Fix.cc and fixed Fix.cc **************
102a103,104
>     d = ( d < 0.0 ) ? (d + 2.0) : d;
> 
109a112
> 
--
John Clark
jclark@ucsd.edu
pa1412@iugrad2.ucsd.edu
ucsd!scubed!irt!clark