aboutsummaryrefslogtreecommitdiff
path: root/java/com/xagasoft/gats/GatsFloat.java
blob: 3d7583eb24a8cc6e83bba40d0ee8be4f1b655f8f (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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package com.xagasoft.gats;

import java.io.InputStream;
import java.io.DataInputStream;
import java.io.OutputStream;
import java.io.ByteArrayOutputStream;

import java.lang.Math;

/**
 * Represents a simple java double value.  This does not represent an arbitrary
 * precision floating point number, a class to handle that is forthcoming.
 */
public class GatsFloat extends GatsObject
{
	double dValue = 0.0;

	public GatsFloat()
	{
	}

	public GatsFloat( double dValue )
	{
		this.dValue = dValue;
	}

	public double getValue()
	{
		return dValue;
	}

	public void setValue( double dValue )
	{
		this.dValue = dValue;
	}

	public String toString()
	{
		return "" + dValue;
	}

	public int getType()
	{
		return GatsObject.FLOAT;
	}

	void read( InputStream is, char cType ) throws java.io.IOException
	{
		if( cType == 'F' )
		{
			char cSubType = (char)is.read();
			switch( cSubType )
			{
				case 'N': dValue = -Double.NaN;					break;
				case 'n': dValue = Double.NaN;					break;
				case 'I': dValue = Double.NEGATIVE_INFINITY;	break;
				case 'i': dValue = Double.POSITIVE_INFINITY;	break;
				case 'Z': dValue = -0.0;						break;
				case 'z': dValue = 0.0;							break;
			}
		}
		else if( cType == 'f' )
		{
			int iStr = (int)GatsInteger.readPackedInt( is );
			boolean bNeg = false;
			if( iStr < 0 )
			{
				bNeg = true;
				iStr = -iStr;
			}
			int aBuf[] = new int[iStr];
			DataInputStream dis = new DataInputStream( is );
			for( int j = 0; j < iStr; j++ )
			{
				aBuf[j] = dis.readUnsignedByte();
			}
			dValue = 0.0;
			for( int j = iStr-1; j > 0; j-- )
			{
				dValue = (dValue+(double)aBuf[j])*0x1p-8;
			}
			dValue += aBuf[0];
			long iScale = GatsInteger.readPackedInt( is );
			dValue *= Math.pow( 256.0, iScale );
			if( bNeg )
				dValue = -dValue;
		}
	}

	void write( OutputStream os ) throws java.io.IOException
	{
		if( dValue == 0.0 )
		{
			os.write( (int)'F' );
			os.write( (int)'z' );
		}
		else if( Double.isInfinite( dValue ) )
		{
			os.write( (int)'F' );
			if( dValue < 0 )
				os.write( (int)'I' );
			else
				os.write( (int)'i' );
		}
		else if( Double.isNaN( dValue ) )
		{
			os.write( (int)'F' );
			os.write( (int)'n' );
		}
		else
		{
			os.write( (int)'f' );
			double d = dValue;
			boolean bNeg = false;
			if( d < 0.0 )
			{
				bNeg = true;
				d = -d;
			}
			
			ByteArrayOutputStream oTmp = new ByteArrayOutputStream();
			long iScale = (long)(Math.log( d ) / 0x1.62e42fefa39efp+2);
			if( iScale < 0 ) iScale--;
			d /= Math.pow( 256.0, iScale );
			oTmp.write( (int)d );
			d -= (int)d;
			for( int j = 0; j < 150 && d != 0.0; j++ )
			{
				d = d*256.0;
				oTmp.write( (int)d );
				d -= (int)d;
			}
			if( bNeg )
				GatsInteger.writePackedInt( os, -oTmp.size() );
			else
				GatsInteger.writePackedInt( os, oTmp.size() );
			os.write( oTmp.toByteArray() );
			GatsInteger.writePackedInt( os, iScale );
		}
	}
};