using System.IO; using System; namespace Com.Xagasoft.Gats { public class GatsFloat : GatsObject { private static readonly double Log256 = Math.Log( 256.0 ); public double Value { get; set; } public GatsFloat() { Value = 0.0; } public GatsFloat( double val ) { Value = val; } public override string ToString() { return Value.ToString(); } public override void Read( Stream s, char type ) { if( type == 'F' ) { int subType = s.ReadByte(); if( subType == -1 ) throw new GatsException( GatsException.Type.PrematureEnd ); switch( (char)subType ) { case 'N': Value = -Double.NaN; break; case 'n': Value = Double.NaN; break; case 'I': Value = Double.NegativeInfinity; break; case 'i': Value = Double.PositiveInfinity; break; case 'Z': Value = -0.0; break; case 'z': Value = 0.0; break; } } else if( type == 'f' ) { int len = (int)GatsInteger.ReadPackedInt( s ); bool neg = false; if( len < 0 ) { neg = true; len = -len; } int[] buf = new int[len]; for( int j = 0; j < len; j++ ) { buf[j] = s.ReadByte(); } Value = 0.0; for( int j = len-1; j > 0; j-- ) { Value = (Value+(double)buf[j]) * (1.0/256.0); } Value += buf[0]; long scale = GatsInteger.ReadPackedInt( s ); Value *= Math.Pow( 256.0, scale ); if( neg ) Value = -Value; } } public override void Write( Stream s ) { if( Value == 0.0 ) { s.WriteByte( (int)'F' ); s.WriteByte( (int)'z' ); } else if( Double.IsInfinity( Value ) ) { s.WriteByte( (int)'F' ); if( Double.IsNegativeInfinity( Value ) ) s.WriteByte( (int)'I' ); else s.WriteByte( (int)'i' ); } else if( Double.IsNaN( Value ) ) { s.WriteByte( (int)'F' ); s.WriteByte( (int)'n' ); } else { s.WriteByte( (int)'f' ); double d = Value; bool neg = false; if( d < 0.0 ) { neg = true; d = -d; } MemoryStream ms = new MemoryStream(); long scale = (long)(Math.Log( d ) / Log256); if( scale < 0 ) scale--; d /= Math.Pow( 256.0, scale ); ms.WriteByte( (byte)d ); d -= (int)d; for( int j = 0; j < 150 && d != 0.0; j++ ) { d = d*256.0; ms.WriteByte( (byte)d ); d -= (int)d; } byte[] msbuf = ms.ToArray(); if( neg ) GatsInteger.WritePackedInt( s, -msbuf.Length ); else GatsInteger.WritePackedInt( s, msbuf.Length ); s.Write( msbuf, 0, msbuf.Length ); GatsInteger.WritePackedInt( s, scale ); } } } }