float-formats 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|