#include "gats/float.h" #include "gats/integer.h" #include #include #include using namespace Bu; Gats::Float::Float() : fVal( 0.0 ) { } Gats::Float::Float( double f ) : fVal( f ) { } Gats::Float::~Float() { } Gats::Object *Gats::Float::clone() const { return new Gats::Float( fVal ); } void Gats::Float::write( Bu::Stream &rOut ) const { if( fVal == 0.0 ) { if( signbit( fVal ) ) rOut.write("FZ", 2 ); else rOut.write("Fz", 2 ); } else if( !isfinite( fVal ) ) { if( isnan( fVal ) ) { if( signbit( fVal ) ) rOut.write("FN", 2 ); else rOut.write("Fn", 2 ); } else { if( signbit( fVal ) ) rOut.write("FI", 2 ); else rOut.write("Fi", 2 ); } } else { rOut.write("f", 1 ); double d = fVal; bool bNeg = false; int64_t iScale=0; if( signbit( d ) ) { bNeg = true; d = -d; } iScale = log( d ) / 0x1.62e42fefa39efp+2; // log( 256.0 ) if( iScale < 0 ) iScale--; d /= pow( 256.0, iScale ); Bu::String s; s += (uint8_t)(d); d -= (int)d; for( int j = 0; j < 150 && d; j++ ) { d = d*256.0; s += (uint8_t)d; d -= (int)d; } Gats::Integer::writePackedInt( rOut, bNeg?-s.getSize():s.getSize() ); rOut.write( s.getStr(), s.getSize() ); Gats::Integer::writePackedInt( rOut, iScale ); } } void Gats::Float::read( Bu::Stream &rIn, char cType ) { if( cType == 'F' ) { char buf; rIn.read( &buf, 1 ); switch( buf ) { case 'N': fVal = -NAN; break; case 'n': fVal = NAN; break; case 'I': fVal = -INFINITY; break; case 'i': fVal = INFINITY; break; case 'Z': fVal = -0.0; break; case 'z': fVal = 0.0; break; } } else if( cType == 'f' ) { int64_t iStr; Gats::Integer::readPackedInt( rIn, iStr ); bool bNeg = false; if( iStr < 0 ) { bNeg = true; iStr = -iStr; } Bu::String s( iStr ); rIn.read( s.getStr(), iStr ); fVal = 0.0; for( int j = iStr-1; j > 0; j-- ) { fVal = (fVal+(uint8_t)s[j])*0x1p-8; } fVal += (uint8_t)s[0]; int64_t iScale; Gats::Integer::readPackedInt( rIn, iScale ); fVal *= pow( 256.0, iScale ); if( bNeg ) fVal = -fVal; } } Bu::Formatter &operator<<( Bu::Formatter &f, const Gats::Float &flt ) { return f << "(float) " << flt.getValue(); }