float-formats 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/History.txt +5 -0
- data/README.md +3 -3
- data/float-formats.gemspec +5 -2
- data/lib/float-formats/bytes.rb +7 -10
- data/lib/float-formats/classes.rb +144 -100
- data/lib/float-formats/formats.rb +256 -255
- data/lib/float-formats/native.rb +9 -54
- data/lib/float-formats/version.rb +1 -1
- data/test/test_bytes.rb +44 -38
- data/test/test_data.yaml +172 -172
- data/test/test_float_formats.rb +49 -47
- data/test/test_native-float.rb +1 -1
- metadata +22 -8
@@ -1,9 +1,6 @@
|
|
1
1
|
# Float-Formats
|
2
2
|
# Definition of common floating-point formats
|
3
3
|
|
4
|
-
require 'nio'
|
5
|
-
require 'nio/sugar'
|
6
|
-
|
7
4
|
require 'enumerator'
|
8
5
|
|
9
6
|
require 'float-formats/classes.rb'
|
@@ -22,36 +19,42 @@ module IEEE
|
|
22
19
|
def self.binary(name, parameters)
|
23
20
|
significand_bits = parameters[:significand]
|
24
21
|
exponent_bits = parameters[:exponent]
|
25
|
-
Flt.define(name,{
|
26
|
-
:
|
27
|
-
:
|
28
|
-
:
|
29
|
-
:
|
30
|
-
:
|
31
|
-
:
|
32
|
-
|
22
|
+
Flt.define(name, {
|
23
|
+
base: BinaryFormat,
|
24
|
+
fields: [:significand, significand_bits, :exponent, exponent_bits, :sign, 1],
|
25
|
+
bias: 2**(exponent_bits-1)-1, bias_mode: :scientific_significand,
|
26
|
+
hidden_bit: true,
|
27
|
+
endianness: :little_endian,
|
28
|
+
round: :half_even,
|
29
|
+
gradual_underflow: true,
|
30
|
+
infinity: true, nan: true
|
31
|
+
}.merge(parameters)
|
32
|
+
)
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
# Define an IEEE binary interchange format given its width in bits
|
36
36
|
def self.interchange_binary(name,width_in_bits, options={})
|
37
|
-
|
37
|
+
unless (width_in_bits%32)==0 && (width_in_bits/32)>=4
|
38
|
+
raise "Invalid IEEE binary interchange format definition: size (#{width_in_bits}) is not valid"
|
39
|
+
end
|
38
40
|
p = width_in_bits - (4*Math.log(width_in_bits)/Math.log(2)).round.to_i + 13
|
39
|
-
binary(name,{:
|
40
|
-
end
|
41
|
-
|
41
|
+
binary(name, { significand: p-1, exponent: width_in_bits-p }.merge(options))
|
42
|
+
end
|
43
|
+
|
42
44
|
# Define an IEEE decimal format by passing parameters in a hash;
|
43
45
|
# :significand and :exponent are used to defined the fields,
|
44
46
|
# optional parameters may follow.
|
45
47
|
def self.decimal(name,parameters)
|
46
48
|
significand_continuation_bits = parameters[:significand]
|
47
49
|
exponent_continuation_bits = parameters[:exponent]
|
48
|
-
Flt.define(name,{
|
49
|
-
:
|
50
|
-
:
|
51
|
-
:
|
52
|
-
:
|
53
|
-
|
54
|
-
:
|
50
|
+
Flt.define(name, {
|
51
|
+
base: DPDFormat,
|
52
|
+
fields: [:significand_continuation, significand_continuation_bits, :exponent_continuation, exponent_continuation_bits, :combination, 5, :sign, 1],
|
53
|
+
normalized: false,
|
54
|
+
endianness: :big_endian,
|
55
|
+
gradual_underflow: true,
|
56
|
+
infinity: true, nan: true,
|
57
|
+
round: :half_even
|
55
58
|
}.merge(parameters))
|
56
59
|
end
|
57
60
|
|
@@ -61,27 +64,26 @@ module IEEE
|
|
61
64
|
p = width_in_bits*9/32 - 2
|
62
65
|
t = (p-1)*10/3
|
63
66
|
w = width_in_bits - t - 6
|
64
|
-
decimal(name,{:
|
65
|
-
end
|
67
|
+
decimal(name,{ significand: t, exponent: w }.merge(options))
|
68
|
+
end
|
66
69
|
|
67
70
|
end
|
68
71
|
|
69
72
|
# IEEE 754 binary types, as stored in little endian architectures such as Intel, Alpha
|
70
73
|
|
71
|
-
IEEE.binary :IEEE_binary16, :
|
72
|
-
IEEE.binary :IEEE_binary32, :
|
73
|
-
IEEE.binary :IEEE_binary64, :
|
74
|
-
IEEE.binary :IEEE_binary80, :
|
75
|
-
IEEE.binary :IEEE_binary128, :
|
76
|
-
|
74
|
+
IEEE.binary :IEEE_binary16, significand: 10, exponent: 5
|
75
|
+
IEEE.binary :IEEE_binary32, significand: 23,exponent: 8
|
76
|
+
IEEE.binary :IEEE_binary64, significand: 52,exponent: 11
|
77
|
+
IEEE.binary :IEEE_binary80, significand: 64,exponent: 15, hidden_bit: false, min_encoded_exp: 1
|
78
|
+
IEEE.binary :IEEE_binary128, significand: 112,exponent: 15
|
77
79
|
|
78
80
|
# IEEE 754 in big endian order (SPARC, Motorola 68k, PowerPC)
|
79
81
|
|
80
|
-
IEEE.binary :IEEE_binary16_BE, :
|
81
|
-
IEEE.binary :IEEE_binary32_BE, :
|
82
|
-
IEEE.binary :IEEE_binary64_BE, :
|
83
|
-
IEEE.binary :IEEE_binary80_BE, :
|
84
|
-
IEEE.binary :IEEE_binary128_BE, :
|
82
|
+
IEEE.binary :IEEE_binary16_BE, significand: 10, exponent: 5, endianness: :big_endian
|
83
|
+
IEEE.binary :IEEE_binary32_BE, significand: 23,exponent: 8, endianness: :big_endian
|
84
|
+
IEEE.binary :IEEE_binary64_BE, significand: 52,exponent: 11, endianness: :big_endian
|
85
|
+
IEEE.binary :IEEE_binary80_BE, significand: 64,exponent: 15, endianness: :big_endian, hidden_bit: false, min_encoded_exp: 1
|
86
|
+
IEEE.binary :IEEE_binary128_BE, significand: 112,exponent: 15, endianness: :big_endian
|
85
87
|
|
86
88
|
|
87
89
|
# some IEEE745r interchange binary formats
|
@@ -89,9 +91,9 @@ IEEE.binary :IEEE_binary128_BE, :significand=>112,:exponent=>15, :endianness=>:b
|
|
89
91
|
IEEE.interchange_binary :IEEE_binary256, 256
|
90
92
|
IEEE.interchange_binary :IEEE_binary512, 512
|
91
93
|
IEEE.interchange_binary :IEEE_binary1024, 1024
|
92
|
-
IEEE.interchange_binary :IEEE_binary256_BE, 256, :
|
93
|
-
IEEE.interchange_binary :IEEE_binary512_BE, 512, :
|
94
|
-
IEEE.interchange_binary :IEEE_binary1024_BE, 1024, :
|
94
|
+
IEEE.interchange_binary :IEEE_binary256_BE, 256, endianness: :big_endian
|
95
|
+
IEEE.interchange_binary :IEEE_binary512_BE, 512, endianness: :big_endian
|
96
|
+
IEEE.interchange_binary :IEEE_binary1024_BE, 1024, endianness: :big_endian
|
95
97
|
|
96
98
|
|
97
99
|
# old names
|
@@ -112,16 +114,16 @@ IEEE_Q_BE = IEEE_binary128_BE
|
|
112
114
|
|
113
115
|
# Decimal IEEE 754r formats
|
114
116
|
|
115
|
-
IEEE.decimal :IEEE_decimal32, :
|
116
|
-
IEEE.decimal :IEEE_decimal64, :
|
117
|
-
IEEE.decimal :IEEE_decimal128, :
|
117
|
+
IEEE.decimal :IEEE_decimal32, significand: 20, exponent: 6
|
118
|
+
IEEE.decimal :IEEE_decimal64, significand: 50, exponent: 8
|
119
|
+
IEEE.decimal :IEEE_decimal128, significand: 110, exponent: 12
|
118
120
|
|
119
121
|
# some IEEE745r interchange binary formats
|
120
122
|
|
121
123
|
IEEE.interchange_decimal :IEEE_decimal96, 96
|
122
124
|
IEEE.interchange_decimal :IEEE_decimal192, 192
|
123
125
|
IEEE.interchange_decimal :IEEE_decimal256, 256
|
124
|
-
|
126
|
+
|
125
127
|
# old names
|
126
128
|
|
127
129
|
IEEE_DEC32 = IEEE_decimal32
|
@@ -131,194 +133,194 @@ IEEE_DEC128 = IEEE_decimal128
|
|
131
133
|
# Excess 128 used by Microsoft Basic in 8-bit micros, Spectrum, ...
|
132
134
|
|
133
135
|
Flt.define BinaryFormat, :XS128,
|
134
|
-
:
|
135
|
-
:
|
136
|
-
:
|
137
|
-
:
|
138
|
-
:
|
139
|
-
:
|
140
|
-
|
141
|
-
# HP-3000 excess 256 format, HP-Tandem...
|
142
|
-
|
136
|
+
fields:[:significand,31,:sign,1,:exponent,8],
|
137
|
+
bias: 128, bias_mode: :fractional_significand,
|
138
|
+
hidden_bit: true,
|
139
|
+
endianness: :big_endian, round: :half_up,
|
140
|
+
endianness: :big_endian,
|
141
|
+
gradual_underflow: false, infinity: false, nan: false
|
142
|
+
|
143
|
+
# HP-3000 excess 256 format, HP-Tandem...
|
144
|
+
|
143
145
|
Flt.define BinaryFormat, :XS256,
|
144
|
-
:
|
145
|
-
:
|
146
|
-
:
|
147
|
-
:
|
148
|
-
:
|
146
|
+
fields:[:significand,22,:exponent,9,:sign,1],
|
147
|
+
bias: 256, bias_mode: :scientific_significand,
|
148
|
+
hidden_bit: true, min_encoded_exp: 0,
|
149
|
+
endianness: :big_endian, round: :half_up,
|
150
|
+
gradual_underflow: false, infinity: false, nan: false
|
149
151
|
|
150
152
|
Flt.define :XS256_DOUBLE, BinaryFormat,
|
151
|
-
:
|
152
|
-
:
|
153
|
-
:
|
154
|
-
:
|
155
|
-
:
|
156
|
-
|
157
|
-
# Borland Pascal 48 bits "Real" Format
|
158
|
-
|
153
|
+
fields:[:significand,54,:exponent,9,:sign,1],
|
154
|
+
bias: 256, bias_mode: :scientific_significand,
|
155
|
+
hidden_bit: true, min_encoded_exp: 0,
|
156
|
+
endianness: :big_endian, round: :half_up,
|
157
|
+
gradual_underflow: false, infinity: false, nan: false
|
158
|
+
|
159
|
+
# Borland Pascal 48 bits "Real" Format
|
160
|
+
|
159
161
|
Flt.define :BORLAND48, BinaryFormat,
|
160
|
-
:
|
161
|
-
:
|
162
|
-
:
|
163
|
-
:
|
164
|
-
:
|
165
|
-
|
166
|
-
# Microsoft Binary Floating-point (Quickbasic)
|
167
|
-
|
162
|
+
fields:[:exponent,8,:significand,39,:sign,1],
|
163
|
+
bias: 128, bias_mode: :fractional_significand,
|
164
|
+
hidden_bit: true,
|
165
|
+
endianness: :little_endian,
|
166
|
+
gradual_underflow: false, infinity: false, nan: false
|
167
|
+
|
168
|
+
# Microsoft Binary Floating-point (Quickbasic)
|
169
|
+
|
168
170
|
Flt.define :MBF_SINGLE, BinaryFormat,
|
169
|
-
:
|
170
|
-
:
|
171
|
-
:
|
172
|
-
:
|
173
|
-
:
|
171
|
+
fields:[:significand,23,:sign,1,:exponent,8],
|
172
|
+
bias: 128, bias_mode: :fractional_significand,
|
173
|
+
hidden_bit: true,
|
174
|
+
endianness: :little_endian,
|
175
|
+
gradual_underflow: false, infinity: false, nan: false
|
174
176
|
|
175
177
|
Flt.define :MBF_DOUBLE, BinaryFormat,
|
176
|
-
:
|
177
|
-
:
|
178
|
-
:
|
179
|
-
:
|
180
|
-
:
|
181
|
-
|
178
|
+
fields:[:significand,55,:sign,1,:exponent,8],
|
179
|
+
bias: 128, bias_mode: :fractional_significand,
|
180
|
+
hidden_bit: true,
|
181
|
+
endianness: :little_endian,
|
182
|
+
gradual_underflow: false, infinity: false, nan: false
|
183
|
+
|
182
184
|
# DEC formats (VAX)
|
183
|
-
|
185
|
+
|
184
186
|
Flt.define :VAX_F, BinaryFormat,
|
185
|
-
:
|
186
|
-
:
|
187
|
-
:
|
188
|
-
:
|
189
|
-
:
|
190
|
-
|
187
|
+
fields:[:significand, 23, :exponent, 8, :sign, 1],
|
188
|
+
bias: 128, bias_mode: :fractional_significand,
|
189
|
+
hidden_bit: true,
|
190
|
+
endianness: :little_big_endian,
|
191
|
+
gradual_underflow: false, infinity: false, nan: false
|
192
|
+
|
191
193
|
Flt.define :VAX_D, BinaryFormat,
|
192
|
-
:
|
193
|
-
:
|
194
|
-
:
|
195
|
-
:
|
196
|
-
:
|
194
|
+
fields:[:significand, 55, :exponent, 8, :sign, 1],
|
195
|
+
bias: 128, bias_mode: :fractional_significand,
|
196
|
+
hidden_bit: true,
|
197
|
+
endianness: :little_big_endian,
|
198
|
+
gradual_underflow: false, infinity: false, nan: false
|
197
199
|
|
198
200
|
Flt.define :VAX_G, BinaryFormat,
|
199
|
-
:
|
200
|
-
:
|
201
|
-
:
|
202
|
-
:
|
203
|
-
:
|
201
|
+
fields:[:significand, 52, :exponent, 11, :sign, 1],
|
202
|
+
bias: 1024, bias_mode: :fractional_significand,
|
203
|
+
hidden_bit: true,
|
204
|
+
endianness: :little_big_endian,
|
205
|
+
gradual_underflow: false, infinity: false, nan: false
|
204
206
|
|
205
207
|
Flt.define :VAX_H, BinaryFormat,
|
206
|
-
:
|
207
|
-
:
|
208
|
-
:
|
209
|
-
:
|
210
|
-
:
|
208
|
+
fields:[:significand, 112, :exponent, 15, :sign, 1],
|
209
|
+
bias: 16384, bias_mode: :fractional_significand,
|
210
|
+
hidden_bit: true,
|
211
|
+
endianness: :little_big_endian,
|
212
|
+
gradual_underflow: false, infinity: false, nan: false
|
211
213
|
|
212
214
|
# DEC PDP 11 variants (minimum exponent used for normalized values other than zero)
|
213
215
|
|
214
216
|
Flt.define :PDP11_F, BinaryFormat,
|
215
|
-
:
|
216
|
-
:
|
217
|
-
:
|
218
|
-
:
|
219
|
-
:
|
217
|
+
fields:[:significand, 23, :exponent, 8, :sign, 1],
|
218
|
+
bias: 128, bias_mode: :fractional_significand,
|
219
|
+
hidden_bit: true, min_encoded_exp: 0,
|
220
|
+
endianness: :little_big_endian,
|
221
|
+
gradual_underflow: false, infinity: false, nan: false
|
220
222
|
|
221
223
|
Flt.define :PDP11_D, BinaryFormat,
|
222
|
-
:
|
223
|
-
:
|
224
|
-
:
|
225
|
-
:
|
226
|
-
:
|
224
|
+
fields:[:significand, 55, :exponent, 8, :sign, 1],
|
225
|
+
bias: 128, bias_mode: :fractional_significand,
|
226
|
+
hidden_bit: true, min_encoded_exp: 0,
|
227
|
+
endianness: :little_big_endian,
|
228
|
+
gradual_underflow: false, infinity: false, nan: false
|
227
229
|
|
228
230
|
|
229
231
|
# Format used in HP Saturn-based RPL calculators (HP48,HP49,HP50, also HP32s, HP42s --which use RPL internally)
|
230
232
|
# (these formats are not used in the HP-71B which is a Saturn, non-RPL machine)
|
231
|
-
|
233
|
+
|
232
234
|
Flt.define :SATURN, BCDFormat,
|
233
|
-
:
|
234
|
-
:
|
235
|
-
:
|
236
|
-
:
|
237
|
-
:
|
235
|
+
fields:[:prolog,5,:exponent,3,:significand,12,:sign,1],
|
236
|
+
fields_handler: lambda{|fields| fields[0]=2933},
|
237
|
+
exponent_mode: :radix_complement,
|
238
|
+
endianness: :little_endian, round: :half_even,
|
239
|
+
gradual_underflow: false, infinity: false, nan: false
|
238
240
|
|
239
241
|
Flt.define :SATURN_X, BCDFormat,
|
240
|
-
:
|
241
|
-
:
|
242
|
-
:
|
243
|
-
:
|
244
|
-
:
|
245
|
-
|
246
|
-
|
242
|
+
fields:[:prolog,5,:exponent,5,:significand,15,:sign,1],
|
243
|
+
fields_handler: lambda{|fields| fields[0]=2955},
|
244
|
+
exponent_mode: :radix_complement,
|
245
|
+
endianness: :little_endian, round: :half_even,
|
246
|
+
gradual_underflow: false, infinity: false, nan: false
|
247
|
+
|
248
|
+
|
247
249
|
RPL = SATURN
|
248
250
|
RPL_X = SATURN_X
|
249
|
-
|
251
|
+
|
250
252
|
# SATURN HP-71B (IEEE, NON-RPL) formats
|
251
253
|
|
252
254
|
# HP-71B REAL format (12-form) which is stored in a single register
|
253
255
|
Flt.define :HP71B, BCDFormat,
|
254
|
-
:
|
255
|
-
:
|
256
|
-
:
|
257
|
-
:
|
258
|
-
:
|
259
|
-
:
|
260
|
-
:
|
256
|
+
fields:[:exponent,3,:significand,12,:sign,1],
|
257
|
+
exponent_mode: :radix_complement,
|
258
|
+
endianness: :little_endian, round: :half_even,
|
259
|
+
gradual_underflow: true, infinity: true, nan: true,
|
260
|
+
denormal_encoded_exp: 501,
|
261
|
+
nan_encoded_exp:"F01", # signaling NaN is F02
|
262
|
+
infinite_encoded_exp:"F00"
|
261
263
|
|
262
264
|
# HP-71B internal 15-digit format (15-form), stored in a pair of registers
|
263
265
|
# we use here a little-endian order for the registers, otherwise the
|
264
266
|
# definition would be [:significand,15,:unused1,1,:exponent,5,:unused2,10,:sign,1]
|
265
267
|
Flt.define :HP71B_X, BCDFormat,
|
266
|
-
:
|
267
|
-
:
|
268
|
-
:
|
269
|
-
:
|
270
|
-
:
|
271
|
-
:
|
268
|
+
fields:[:exponent,5,:unused2,10,:sign,1, :significand,15,:unused1,1],
|
269
|
+
exponent_mode: :radix_complement,
|
270
|
+
endianness: :little_endian, round: :half_even,
|
271
|
+
gradual_underflow: false, infinity: true, nan: true,
|
272
|
+
nan_encoded_exp:"00F01",
|
273
|
+
infinite_encoded_exp:"00F00"
|
272
274
|
|
273
275
|
# Format used in classic HP calculators (HP-35, ... HP-15C)
|
274
276
|
# Endianness is indeterminate, since these machines have named registers that
|
275
277
|
# hold a floating-point value in a single 56-bit word.
|
276
278
|
# (But intra-word field/nibble addressing is little-endian)
|
277
279
|
Flt.define :HP_CLASSIC, BCDFormat,
|
278
|
-
:
|
279
|
-
:
|
280
|
-
|
281
|
-
:
|
282
|
-
:
|
280
|
+
fields:[:exponent,3,:significand,10,:sign,1],
|
281
|
+
exponent_mode: :radix_complement,
|
282
|
+
min_exp:-99, max_exp: 99, # the most significant nibble of exponent if for sign only
|
283
|
+
endianness: :big_endian, round: :half_up,
|
284
|
+
gradual_underflow: false, infinity: false, nan: false
|
285
|
+
|
283
286
|
|
284
|
-
|
285
287
|
# IBM Floating Point Architecture (IBM 360,370, DG Eclipse, ...)
|
286
|
-
|
287
|
-
# short
|
288
|
+
|
289
|
+
# short
|
288
290
|
Flt.define :IBM32, HexadecimalFormat,
|
289
|
-
:
|
290
|
-
:
|
291
|
-
:
|
292
|
-
|
291
|
+
fields:[:significand,24,:exponent,7,:sign,1],
|
292
|
+
bias: 64, bias_mode: :fractional_significand,
|
293
|
+
endianness: :big_endian
|
294
|
+
|
293
295
|
# long
|
294
296
|
Flt.define :IBM64, HexadecimalFormat,
|
295
|
-
:
|
296
|
-
:
|
297
|
-
:
|
298
|
-
|
299
|
-
# extended: two long values pasted together
|
297
|
+
fields:[:significand,56,:exponent,7,:sign,1],
|
298
|
+
bias: 64, bias_mode: :fractional_significand,
|
299
|
+
endianness: :big_endian
|
300
|
+
|
301
|
+
# extended: two long values pasted together
|
300
302
|
Flt.define :IBM128, HexadecimalFormat,
|
301
|
-
:
|
302
|
-
:
|
303
|
-
:
|
304
|
-
:
|
305
|
-
:
|
303
|
+
fields:[:significand,14*4,:lo_exponent,7,:lo_sign,1,:significand,14*4,:exponent,7,:sign,1],
|
304
|
+
fields_handler: lambda{|fields| fields[1]=(fields[4]>=14&&fields[4]<127) ? fields[4]-14 : fields[4];fields[2]=fields[5] },
|
305
|
+
bias: 64, bias_mode: :fractional_significand,
|
306
|
+
min_encoded_exp: 14, # to avoid out-of-range exponents in the lower half
|
307
|
+
endianness: :big_endian
|
306
308
|
|
307
309
|
# It think this has never been used:
|
308
310
|
Flt.define :IBMX, HexadecimalFormat,
|
309
|
-
:
|
310
|
-
:
|
311
|
-
:
|
312
|
-
:
|
313
|
-
|
311
|
+
fields:[:significand,14*4,:exponent,7,:unused_sign,1,:significand,14*4,:exponent,7,:sign,1],
|
312
|
+
fields_handler: lambda{|fields| fields[2]=0},
|
313
|
+
bias: 8192, bias_mode: :fractional_significand,
|
314
|
+
endianness: :big_endian
|
315
|
+
|
314
316
|
# Cray-1
|
315
317
|
Flt.define :CRAY, BinaryFormat,
|
316
|
-
:
|
317
|
-
:
|
318
|
-
:
|
319
|
-
:
|
320
|
-
:
|
321
|
-
:
|
318
|
+
fields:[:significand,48,:exponent,15,:sign,1],
|
319
|
+
bias: 16384, bias_mode: :fractional_significand,
|
320
|
+
hidden_bit: false,
|
321
|
+
min_encoded_exp: 8192, max_encoded_exp: 24575, zero_encoded_exp: 0,
|
322
|
+
endianness: :big_endian,
|
323
|
+
gradual_underflow: false, infinity: false, nan: false
|
322
324
|
|
323
325
|
# CDC 6600/7600
|
324
326
|
# Byte endianness is arbitrary, since these machines were word-addressable, in 60-bit words,
|
@@ -330,29 +332,29 @@ Flt.define :CRAY, BinaryFormat,
|
|
330
332
|
#
|
331
333
|
# The exponent needs special treatment, because instead of excess encoding, which is equivalent to two's complement followed
|
332
334
|
# by sign bit reversal, one's complement followed by sign bit reversal is used, which is equivalent
|
333
|
-
# to use a bias diminished by one for negative exponents. Note that the exponent encoded value that equals the bias is
|
335
|
+
# to use a bias diminished by one for negative exponents. Note that the exponent encoded value that equals the bias is
|
334
336
|
# not used (is used as a NaN indicator)
|
335
337
|
class CDCFormat < BinaryFormat # :nodoc:
|
336
338
|
def self.encode_exponent(e,mode)
|
337
339
|
ee = super
|
338
340
|
ee -= 1 if e<0
|
339
341
|
ee
|
340
|
-
end
|
342
|
+
end
|
341
343
|
def self.decode_exponent(ee,mode)
|
342
344
|
e = super
|
343
345
|
e += 1 if e<0
|
344
346
|
e
|
345
|
-
end
|
347
|
+
end
|
346
348
|
end
|
347
349
|
|
348
350
|
Flt.define :CDC_SINGLE, CDCFormat,
|
349
|
-
:
|
350
|
-
:
|
351
|
-
|
352
|
-
:
|
353
|
-
:
|
354
|
-
:
|
355
|
-
:
|
351
|
+
fields:[:significand,48, :exponent,11, :sign,1],
|
352
|
+
bias: 1024, bias_mode: :integral_significand,
|
353
|
+
min_exp:-1023,
|
354
|
+
neg_mode: :diminished_radix_complement,
|
355
|
+
hidden_bit: false,
|
356
|
+
endianess: :big_endian,
|
357
|
+
gradual_underflow: false, infinity: false, nan: false
|
356
358
|
|
357
359
|
# The CDC_DOUBLE can be splitted in two CDC_SINGLE values:
|
358
360
|
# get_bitfields(v,[CDC_SINGLE.total_bits]*2,CDC_DOUBLE.endianness).collect{|x| int_to_bytes(x,0,CDC_SINGLE.endianness)}
|
@@ -361,53 +363,53 @@ Flt.define :CDC_SINGLE, CDCFormat,
|
|
361
363
|
# the exponent would refer to the whole significand, but it must refer only to the most significant half.
|
362
364
|
# we substract the number of bits in the single to the bias and exponent because of this change,
|
363
365
|
# and add 48 to the min_exponent to avoid the exponent of the low order single to be out of range
|
364
|
-
# because the exponent of the low order single is adjusted to
|
366
|
+
# because the exponent of the low order single is adjusted to
|
365
367
|
# the position of its digits by substracting 48 from the high order exponent
|
366
368
|
# when its exponent would be out of range
|
367
|
-
# Note that when computing the low order exponent with the fields handler we must take into account the sign
|
369
|
+
# Note that when computing the low order exponent with the fields handler we must take into account the sign
|
368
370
|
# because for negative numbers all the fields are one-complemented.
|
369
371
|
Flt.define :CDC_DOUBLE, CDCFormat,
|
370
|
-
:
|
371
|
-
:
|
372
|
+
fields:[:significand,48,:lo_exponent,11,:lo_sign,1,:significand,48,:exponent,11,:sign,1],
|
373
|
+
fields_handler: lambda{|fields|
|
372
374
|
fields[1]=(fields[4]>0&&fields[4]<2047) ? fields[4]-((-1)**fields[5])*48 : fields[4]
|
373
375
|
fields[2]=fields[5]
|
374
376
|
},
|
375
|
-
:
|
376
|
-
:
|
377
|
-
:
|
378
|
-
:
|
379
|
-
:
|
380
|
-
:
|
377
|
+
bias: 1024-48, bias_mode: :fractional_significand,
|
378
|
+
min_encoded_exp: 48+1, # + 1 because the bias for negative is 1023
|
379
|
+
neg_mode: :diminished_radix_complement,
|
380
|
+
hidden_bit: false,
|
381
|
+
endianess: :big_endian,
|
382
|
+
gradual_underflow: false, infinity: false, nan: false
|
381
383
|
|
382
384
|
|
383
385
|
# Univac 1100
|
384
386
|
# Byte endianness is arbitrary, since these machines were word-addressable, in 36-bit words,
|
385
387
|
# but the two words used in double precision numbers are in big endian order
|
386
388
|
Flt.define :UNIVAC_SINGLE, BinaryFormat,
|
387
|
-
:
|
388
|
-
:
|
389
|
-
:
|
390
|
-
:
|
391
|
-
:
|
392
|
-
:
|
393
|
-
|
389
|
+
fields:[:significand,27, :exponent,8, :sign,1],
|
390
|
+
bias: 128, bias_mode: :fractional_significand,
|
391
|
+
neg_mode: :diminished_radix_complement,
|
392
|
+
hidden_bit: false,
|
393
|
+
endianess: :big_endian,
|
394
|
+
gradual_underflow: false, infinity: false, nan: false
|
395
|
+
|
394
396
|
Flt.define :UNIVAC_DOUBLE, BinaryFormat,
|
395
|
-
:
|
396
|
-
:
|
397
|
-
:
|
398
|
-
:
|
399
|
-
:
|
400
|
-
:
|
401
|
-
|
397
|
+
fields:[:significand,60, :exponent,11, :sign,1],
|
398
|
+
bias: 1024, bias_mode: :fractional_significand,
|
399
|
+
neg_mode: :diminished_radix_complement,
|
400
|
+
hidden_bit: false,
|
401
|
+
endianess: :big_endian,
|
402
|
+
gradual_underflow: false, infinity: false, nan: false
|
403
|
+
|
402
404
|
|
403
405
|
# :stopdoc: # the next definition is not handled correctly by RDoc
|
404
406
|
Flt.define(:APPLE_INSANE,BinaryFormat,
|
405
|
-
:
|
406
|
-
:
|
407
|
-
:
|
408
|
-
:
|
409
|
-
:
|
410
|
-
:
|
407
|
+
fields:[:significand,23,:sign,1,:exponent,8],
|
408
|
+
bias: 128, bias_mode: :scientific_significand,
|
409
|
+
hidden_bit: false, min_encoded_exp: 0,
|
410
|
+
neg_mode: :radix_complement_significand,
|
411
|
+
endianness: :big_endian,
|
412
|
+
gradual_underflow: true, infinity: false, nan: false) { |fp|
|
411
413
|
# This needs a peculiar treatment for the negative values, which not simply use two's complement
|
412
414
|
# but also avoid having the sign and msb of the significand equal.
|
413
415
|
# Note that here we have a separate sign bit, but it can also be considered as the msb of the significand
|
@@ -441,11 +443,11 @@ APPLE = APPLE_INSANE
|
|
441
443
|
|
442
444
|
# Wang 2200 Basic Decimal floating point
|
443
445
|
Flt.define(:WANG2200,BCDFormat,
|
444
|
-
:
|
445
|
-
:
|
446
|
-
:
|
447
|
-
|
448
|
-
:
|
446
|
+
fields:[:significand,13,:exponent,2,:signs,1],
|
447
|
+
endiannes: :big_endian,
|
448
|
+
bias_mode: :scientific_significand,
|
449
|
+
min_exp:-99, max_exp: 99,
|
450
|
+
zero_encoded_exp: 0, min_encoded_exp: 0
|
449
451
|
) { |wang2200|
|
450
452
|
|
451
453
|
# needs special handling because significand and exponent are both stored
|
@@ -463,7 +465,7 @@ Flt.define(:WANG2200,BCDFormat,
|
|
463
465
|
elsif @infinite_encoded_exp && e==@infinite_encoded_exp && m==0
|
464
466
|
# +-inifinity
|
465
467
|
e = :infinity
|
466
|
-
elsif @nan_encoded_exp && e==@nan_encoded_exp && m!=0
|
468
|
+
elsif @nan_encoded_exp && e==@nan_encoded_exp && m!=0
|
467
469
|
# NaN
|
468
470
|
e = :nan
|
469
471
|
else
|
@@ -474,13 +476,13 @@ Flt.define(:WANG2200,BCDFormat,
|
|
474
476
|
e -= (significand_digits-1)
|
475
477
|
end
|
476
478
|
s = sign_to_unit(s)
|
477
|
-
[s,m,e]
|
479
|
+
[s,m,e]
|
478
480
|
end
|
479
481
|
|
480
482
|
def wang2200.pack(s,m,e)
|
481
483
|
s = sign_from_unit(s)
|
482
484
|
msb = radix_power(@significand_digits-1)
|
483
|
-
es = 0
|
485
|
+
es = 0
|
484
486
|
if e==:zero
|
485
487
|
e = @zero_encoded_exp
|
486
488
|
m = 0
|
@@ -492,17 +494,17 @@ Flt.define(:WANG2200,BCDFormat,
|
|
492
494
|
s = minus_sign_value # ?
|
493
495
|
m = radix_power(@significand_digits-2) if m==0
|
494
496
|
elsif e==:denormal
|
495
|
-
e = @denormal_encoded_exp
|
497
|
+
e = @denormal_encoded_exp
|
496
498
|
else
|
497
499
|
# to do: try to adjust m to keep e in range if out of valid range
|
498
500
|
# to do: reduce m and adjust e if m too big
|
499
|
-
|
501
|
+
|
500
502
|
min_exp = radix_min_exp(:integral_significand)
|
501
503
|
if m>0
|
502
504
|
while m<msb && e>min_exp
|
503
505
|
e -= 1
|
504
506
|
m *= radix
|
505
|
-
end
|
507
|
+
end
|
506
508
|
end
|
507
509
|
if m<msb && @denormal_encoded_exp
|
508
510
|
e = @denormal_encoded_exp
|
@@ -517,15 +519,15 @@ Flt.define(:WANG2200,BCDFormat,
|
|
517
519
|
es = 0
|
518
520
|
end
|
519
521
|
end
|
520
|
-
end
|
522
|
+
end
|
521
523
|
ss = (s%2) + (es==0 ? 0 : 8)
|
522
524
|
# reverse exponent nibbles
|
523
525
|
e = ("%0#{exponent_digits}d"%e).reverse.to_i
|
524
|
-
pack_fields_hash :
|
526
|
+
pack_fields_hash signs: ss, significand: m, exponent: e
|
525
527
|
end
|
526
528
|
}
|
527
|
-
|
528
|
-
|
529
|
+
|
530
|
+
|
529
531
|
# C51 (C compiler for the Intel 8051) BCD Floating point formats
|
530
532
|
class C51BCDFormat < BCDFormat # :nodoc:
|
531
533
|
def self.exponent_radix
|
@@ -538,7 +540,7 @@ class C51BCDFormat < BCDFormat # :nodoc:
|
|
538
540
|
1
|
539
541
|
end
|
540
542
|
def self.unpack(v)
|
541
|
-
f =
|
543
|
+
f = unpack_fields_hash(v)
|
542
544
|
m = f[:significand]
|
543
545
|
e_s = f[:exponent_sign]
|
544
546
|
exp_bits = exponent_digits
|
@@ -550,7 +552,7 @@ class C51BCDFormat < BCDFormat # :nodoc:
|
|
550
552
|
elsif @infinite_encoded_exp && e==@infinite_encoded_exp && m==0
|
551
553
|
# +-inifinity
|
552
554
|
e = :infinity
|
553
|
-
elsif @nan_encoded_exp && e==@nan_encoded_exp && m!=0
|
555
|
+
elsif @nan_encoded_exp && e==@nan_encoded_exp && m!=0
|
554
556
|
# NaN
|
555
557
|
e = :nan
|
556
558
|
else
|
@@ -558,7 +560,7 @@ class C51BCDFormat < BCDFormat # :nodoc:
|
|
558
560
|
e = decode_exponent(e, :integral_significand)
|
559
561
|
end
|
560
562
|
s = sign_to_unit(s)
|
561
|
-
[s,m,e]
|
563
|
+
[s,m,e]
|
562
564
|
end
|
563
565
|
def self.bcd_field?(i)
|
564
566
|
@field_meaning[i]==:significand
|
@@ -567,7 +569,7 @@ class C51BCDFormat < BCDFormat # :nodoc:
|
|
567
569
|
def self.pack(s,m,e)
|
568
570
|
s = sign_from_unit(s)
|
569
571
|
msb = radix_power(@significand_digits-1)
|
570
|
-
es = 0
|
572
|
+
es = 0
|
571
573
|
if e==:zero
|
572
574
|
e = @zero_encoded_exp
|
573
575
|
m = 0
|
@@ -579,17 +581,17 @@ class C51BCDFormat < BCDFormat # :nodoc:
|
|
579
581
|
s = minus_sign_value # ?
|
580
582
|
m = radix_power(@significand_digits-2) if m==0
|
581
583
|
elsif e==:denormal
|
582
|
-
e = @denormal_encoded_exp
|
584
|
+
e = @denormal_encoded_exp
|
583
585
|
else
|
584
586
|
# to do: try to adjust m to keep e in range if out of valid range
|
585
587
|
# to do: reduce m and adjust e if m too big
|
586
|
-
|
588
|
+
|
587
589
|
min_exp = radix_min_exp(:integral_significand)
|
588
590
|
if m>0
|
589
591
|
while m<msb && e>min_exp
|
590
592
|
e -= 1
|
591
593
|
m *= radix
|
592
|
-
end
|
594
|
+
end
|
593
595
|
end
|
594
596
|
if m<msb && @denormal_encoded_exp
|
595
597
|
e = @denormal_encoded_exp
|
@@ -598,36 +600,35 @@ class C51BCDFormat < BCDFormat # :nodoc:
|
|
598
600
|
else
|
599
601
|
e = encode_exponent(e, :integral_significand)
|
600
602
|
end
|
601
|
-
end
|
603
|
+
end
|
602
604
|
exp_bits = exponent_digits
|
603
605
|
e_s = e + (s << exp_bits)
|
604
|
-
pack_fields_hash :
|
606
|
+
pack_fields_hash significand: m, exponent_sign: e_s
|
605
607
|
end
|
606
608
|
end
|
607
609
|
|
608
610
|
Flt.define :C51_BCD_FLOAT, C51BCDFormat,
|
609
|
-
:
|
610
|
-
:
|
611
|
-
:
|
612
|
-
:
|
611
|
+
fields:[:exponent_sign, 2, :significand,6],
|
612
|
+
endiannes: :big_endian,
|
613
|
+
bias: 64, bias_mode: :fractional_significand,
|
614
|
+
zero_encoded_exp: 0, min_encoded_exp: 0,max_encoded_exp: 127
|
613
615
|
|
614
616
|
Flt.define :C51_BCD_DOUBLE,C51BCDFormat,
|
615
|
-
:
|
616
|
-
:
|
617
|
-
:
|
618
|
-
:
|
617
|
+
fields:[:exponent_sign, 2, :significand,10],
|
618
|
+
endiannes: :big_endian,
|
619
|
+
bias: 64, bias_mode: :fractional_significand,
|
620
|
+
zero_encoded_exp: 0, min_encoded_exp: 0,max_encoded_exp: 127
|
619
621
|
|
620
622
|
Flt.define :C51_BCD_LONG_DOUBLE, C51BCDFormat,
|
621
|
-
:
|
622
|
-
:
|
623
|
-
:
|
624
|
-
:
|
623
|
+
fields:[:exponent_sign, 2, :significand,12],
|
624
|
+
endiannes: :big_endian,
|
625
|
+
bias: 64, bias_mode: :fractional_significand,
|
626
|
+
zero_encoded_exp: 0, min_encoded_exp: 0,max_encoded_exp: 127
|
625
627
|
|
626
628
|
|
627
629
|
# double-double format as used in the PowerPC
|
628
|
-
Flt.define :IEEE_DOUBLE_DOUBLE, DoubleFormat, :
|
630
|
+
Flt.define :IEEE_DOUBLE_DOUBLE, DoubleFormat, half: IEEE_binary64, extra_prec: true
|
629
631
|
|
630
|
-
|
631
632
|
|
632
|
-
end
|
633
633
|
|
634
|
+
end
|