-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfloattovax.go
151 lines (129 loc) · 4.3 KB
/
floattovax.go
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
143
144
145
146
147
148
149
150
151
package vaxdata
import (
"encoding/binary"
"errors"
"io"
"math"
)
// WriteFFloat takes a float32 and writes an F_Float to the io.Writer.
func WriteFFloat(w io.Writer, f float32) error {
v, err := VaxFFloatfromFloat32(f)
if err != nil {
return err
}
return binary.Write(w, binary.BigEndian, uint32(v))
}
// VaxFFloatfromFloat32 returns the VAX F_Float representation of a float32.
func VaxFFloatfromFloat32(f float32) (VaxFFloat, error) {
const (
MantissaMask uint32 = VaxFMantissaMask
MantissaSize uint32 = VaxFMantissaSize
HiddenBit uint32 = VaxFHiddenBit
ExponentAdjustment uint32 = (1 + VaxFExponentBias - IeeeSExponentBias)
)
var (
result uint32
err error
)
ieeepart1 := math.Float32bits(f)
if (ieeepart1 & ^SignBit) == 0 {
// Set IEEE +-zero [e=m=0] to VAX zero [s=e=m=0]
result = 0
} else if e := (ieeepart1 & IeeeSExponentMask); e == IeeeSExponentMask {
// VAX's have no equivalents for IEEE +-Infinity and +-NaN [e=all-1's]
err = errors.New("no VAX equivalent for IEEE +-Infinity and +-NaN")
// Fixup to VAX +-extrema [e=all-1's] with zero mantissa [m=0]
result = (ieeepart1 & SignBit) | VaxFExponentMask
} else {
e >>= MantissaSize // Obtain the biased IEEE exponent
m := (ieeepart1 & MantissaMask) // Obtain the IEEE mantissa
// Denormalized? [e=0, m<>0]
if e == 0 {
// Adjust representation from 2**(1-bias) to 2**(e-bias)
m <<= 1
for (m & HiddenBit) == 0 {
m <<= 1
e-- // Adjust exponent
}
// Adjust mantissa to hidden-bit form
m &= MantissaMask
}
if e += ExponentAdjustment; e <= 0 {
result = 0 // Silent underflow
} else if e > (2*VaxFExponentBias - 1) {
// Overflow; fixup to VAX +-extrema [e=m=all-1's]
err = errors.New("IEEE S_Float too large for VAX F_Float")
result = (ieeepart1 & SignBit) | ^SignBit
} else {
// VAX normalized form [e>0] (both mantissas are 23 bits)
result = (ieeepart1 & SignBit) | (e << MantissaSize) | m
}
}
return VaxFFloat(uint32FromVax(result)), err
}
// WriteGFloat takes a float64 and writes an G_Float to the io.Writer.
func WriteGFloat(w io.Writer, f float64) error {
v, err := VaxGFloatfromFloat64(f)
if err != nil {
return err
}
return binary.Write(w, binary.BigEndian, uint64(v))
}
// VaxGFloatfromFloat64 returns the VAX G_Float representation of a float64.
func VaxGFloatfromFloat64(f float64) (VaxGFloat, error) {
const (
MantissaMask uint32 = VaxGMantissaMask
MantissaSize uint32 = VaxGMantissaSize
HiddenBit uint32 = VaxGHiddenBit
ExponentAdjustment uint32 = (1 + VaxGExponentBias - IeeeTExponentBias)
)
var (
in uint64 = math.Float64bits(f)
vaxpart1 uint32
err error
)
ieeepart1 := uint32(in >> 32)
vaxpart2 := uint32(in & 0x0FFFFFFFF)
if ((ieeepart1 & ^SignBit) | vaxpart2) == 0 {
// Set IEEE +-zero [e=m=0] to VAX zero [s=e=m=0]
vaxpart1 = 0
// vaxpart2 is already zero
} else if e := (ieeepart1 & IeeeTExponentMask); e == IeeeTExponentMask {
// VAX's have no equivalents for IEEE +-Infinity and +-NaN [e=all-1's]
err = errors.New("no VAX equivalent for IEEE +-Infinity and +-NaN")
// Fixup to VAX +-extrema [e=all-1's] with zero mantissa [m=0]
vaxpart1 = (ieeepart1 & SignBit) | VaxGExponentMask
vaxpart2 = 0
} else {
e >>= MantissaSize // Obtain the biased IEEE exponent
m := ieeepart1 & MantissaMask // Obtain the IEEE mantissa
// Denormalized? [e=0, m<>0]
if e == 0 {
// Adjust representation from 2**(1-bias) to 2**(e-bias)
m = (m << 1) | (vaxpart2 >> 31)
vaxpart2 <<= 1
for (m & HiddenBit) == 0 {
m = (m << 1) | (vaxpart2 >> 31)
vaxpart2 <<= 1
e-- // Adjust exponent
}
// Adjust mantissa to hidden-bit form
m &= MantissaMask
}
if e += ExponentAdjustment; e <= 0 {
vaxpart1 = 0 // Silent underflow
vaxpart2 = 0
} else if e > (2*VaxGExponentBias - 1) {
err = errors.New("IEEE T_Float too large for VAX G_Float")
// Overflow; fixup to VAX +-extrema [e=m=all-1's]
vaxpart1 = (ieeepart1 & SignBit) | ^SignBit
vaxpart2 = 0xFFFFFFFF
} else {
// VAX normalized form [e>0] (both mantissas are 52 bits)
vaxpart1 = (ieeepart1 & SignBit) | (e << MantissaSize) | m
// vaxpart2 is already correct
}
}
result := (uint64(uint32FromVax(vaxpart2)) << 32) | uint64(uint32FromVax(vaxpart1))
return VaxGFloat(result), err
}