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