aboutsummaryrefslogtreecommitdiff
path: root/cs-dotnet/src/gatsfloat.cs
blob: 7161975309d97a30290b67722dd6a70daff01509 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
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 );
            }
        }
    }
}