float-formats 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,580 @@
1
+ # Float-Formats
2
+ # Definition of common floating-point formats
3
+
4
+ require 'nio'
5
+ require 'nio/sugar'
6
+
7
+ require 'enumerator'
8
+
9
+ require 'float-formats/classes.rb'
10
+
11
+
12
+ module FltPnt
13
+
14
+
15
+ # Floating Point Format Definitions ==========================================
16
+
17
+ # IEEE 754 binary types, as stored in little endian architectures such as Intel, Alpha
18
+
19
+ IEEE_SINGLE = BinaryFormat.new(
20
+ :fields=>[:significand,23,:exponent,8,:sign,1],
21
+ :bias=>127, :bias_mode=>:normalized_significand,
22
+ :hidden_bit=>true,
23
+ :endianness=>:little_endian, :round=>:even,
24
+ :gradual_underflow=>true, :infinity=>true, :nan=>true
25
+ )
26
+ IEEE_DOUBLE = BinaryFormat.new(
27
+ :fields=>[:significand,52,:exponent,11,:sign,1],
28
+ :bias=>1023, :bias_mode=>:normalized_significand,
29
+ :hidden_bit=>true,
30
+ :endianness=>:little_endian, :round=>:even,
31
+ :gradual_underflow=>true, :infinity=>true, :nan=>true
32
+ )
33
+ IEEE_EXTENDED = BinaryFormat.new(
34
+ :fields=>[:significand,64,:exponent,15,:sign,1],
35
+ :bias=>16383, :bias_mode=>:normalized_significand,
36
+ :hidden_bit=>false, :min_encoded_exp=>1, :round=>:even,
37
+ :endianness=>:little_endian,
38
+ :gradual_underflow=>true, :infinity=>true, :nan=>true
39
+ )
40
+ IEEE_128 = BinaryFormat.new(
41
+ :fields=>[:significand,112,:exponent,15,:sign,1],
42
+ :bias=>16383, :bias_mode=>:normalized_significand,
43
+ :hidden_bit=>false, :min_encoded_exp=>1, :round=>:even,
44
+ :endianness=>:little_endian,
45
+ :gradual_underflow=>true, :infinity=>true, :nan=>true
46
+ )
47
+
48
+ # IEEE 754 in big endian order (SPARC, Motorola 68k, PowerPC)
49
+
50
+ IEEE_S_BE = BinaryFormat.new(
51
+ :fields=>[:significand,23,:exponent,8,:sign,1],
52
+ :bias=>127, :bias_mode=>:normalized_significand,
53
+ :hidden_bit=>true,
54
+ :endianness=>:big_endian,
55
+ :gradual_underflow=>true, :infinity=>true, :nan=>true)
56
+ IEEE_D_BE = BinaryFormat.new(
57
+ :fields=>[:significand,52,:exponent,11,:sign,1],
58
+ :bias=>1023, :bias_mode=>:normalized_significand,
59
+ :hidden_bit=>true, :round=>:even,
60
+ :endianness=>:big_endian,
61
+ :gradual_underflow=>true, :infinity=>true, :nan=>true
62
+ )
63
+ IEEE_X_BE = BinaryFormat.new(
64
+ :fields=>[:significand,64,:exponent,15,:sign,1],
65
+ :bias=>16383, :bias_mode=>:normalized_significand,
66
+ :hidden_bit=>false, :round=>:even,
67
+ :endianness=>:big_endian,
68
+ :gradual_underflow=>true, :infinity=>true, :nan=>true
69
+ )
70
+ IEEE_128_BE = BinaryFormat.new(
71
+ :fields=>[:significand,112,:exponent,15,:sign,1],
72
+ :bias=>16383, :bias_mode=>:normalized_significand,
73
+ :hidden_bit=>false, :min_encoded_exp=>1, :round=>:even,
74
+ :endianness=>:big_endian,
75
+ :gradual_underflow=>true, :infinity=>true, :nan=>true
76
+ )
77
+ # Decimal IEEE 754r formats
78
+
79
+ IEEE_DEC32 = DPDFormat.new(
80
+ :fields=>[:significand_continuation,20,:exponent_continuation,6,:combination,5,:sign,1],
81
+ :endianness=>:big_endian,
82
+ :gradual_underflow=>true, :infinity=>true, :nan=>true
83
+ )
84
+ IEEE_DEC64 = DPDFormat.new(
85
+ :fields=>[:significand_continuation,50,:exponent_continuation,8,:combination,5,:sign,1],
86
+ :endianness=>:big_endian,
87
+ :gradual_underflow=>true, :infinity=>true, :nan=>true
88
+ )
89
+ IEEE_DEC128 = DPDFormat.new(
90
+ :fields=>[:significand_continuation,110,:exponent_continuation,12,:combination,5,:sign,1],
91
+ :endianness=>:big_endian,
92
+ :gradual_underflow=>true, :infinity=>true, :nan=>true
93
+ )
94
+
95
+
96
+ # Excess 128 used by Microsoft Basic in 8-bit micros, Spectrum, ...
97
+
98
+ XS128 = BinaryFormat.new(
99
+ :fields=>[:significand,31,:sign,1,:exponent,8],
100
+ :bias=>128, :bias_mode=>:fractional_significand,
101
+ :hidden_bit=>true,
102
+ :endianness=>:big_endian, :round=>:inf,
103
+ :endianness=>:big_endian,
104
+ :gradual_underflow=>false, :infinity=>false, :nan=>false
105
+ )
106
+
107
+ # HP-3000 excess 256 format, HP-Tandem...
108
+
109
+ XS256 = BinaryFormat.new(
110
+ :fields=>[:significand,22,:exponent,9,:sign,1],
111
+ :bias=>256, :bias_mode=>:normalized_significand,
112
+ :hidden_bit=>true, :min_encoded_exp=>0,
113
+ :endianness=>:big_endian, :round=>:inf,
114
+ :gradual_underflow=>false, :infinity=>false, :nan=>false
115
+ )
116
+ XS256_DOUBLE = BinaryFormat.new(
117
+ :fields=>[:significand,54,:exponent,9,:sign,1],
118
+ :bias=>256, :bias_mode=>:normalized_significand,
119
+ :hidden_bit=>true, :min_encoded_exp=>0,
120
+ :endianness=>:big_endian, :round=>:inf,
121
+ :gradual_underflow=>false, :infinity=>false, :nan=>false
122
+ )
123
+
124
+ # Borland Pascal 48 bits "Real" Format
125
+
126
+ BORLAND48 = BinaryFormat.new(
127
+ :fields=>[:exponent,8,:significand,39,:sign,1],
128
+ :bias=>128, :bias_mode=>:fractional_significand,
129
+ :hidden_bit=>true,
130
+ :endianness=>:little_endian,
131
+ :gradual_underflow=>false, :infinity=>false, :nan=>false
132
+ )
133
+
134
+ # Microsoft Binary Floating-point (Quickbasic)
135
+
136
+ MBF_SINGLE = BinaryFormat.new(
137
+ :fields=>[:significand,23,:sign,1,:exponent,8],
138
+ :bias=>128, :bias_mode=>:fractional_significand,
139
+ :hidden_bit=>true,
140
+ :endianness=>:little_endian,
141
+ :gradual_underflow=>false, :infinity=>false, :nan=>false
142
+ )
143
+ MBF_DOUBLE = BinaryFormat.new(
144
+ :fields=>[:significand,55,:sign,1,:exponent,8],
145
+ :bias=>128, :bias_mode=>:fractional_significand,
146
+ :hidden_bit=>true,
147
+ :endianness=>:little_endian,
148
+ :gradual_underflow=>false, :infinity=>false, :nan=>false
149
+ )
150
+
151
+ # DEC formats (VAX)
152
+
153
+ VAX_F = BinaryFormat.new(
154
+ :fields=>[:significand, 23, :exponent, 8, :sign, 1],
155
+ :bias=>128, :bias_mode=>:fractional_significand,
156
+ :hidden_bit=>true,
157
+ :endianness=>:little_big_endian,
158
+ :gradual_underflow=>false, :infinity=>false, :nan=>false
159
+ )
160
+
161
+ VAX_D = BinaryFormat.new(
162
+ :fields=>[:significand, 55, :exponent, 8, :sign, 1],
163
+ :bias=>128, :bias_mode=>:fractional_significand,
164
+ :hidden_bit=>true,
165
+ :endianness=>:little_big_endian,
166
+ :gradual_underflow=>false, :infinity=>false, :nan=>false
167
+ )
168
+
169
+ VAX_G = BinaryFormat.new(
170
+ :fields=>[:significand, 52, :exponent, 11, :sign, 1],
171
+ :bias=>1024, :bias_mode=>:fractional_significand,
172
+ :hidden_bit=>true,
173
+ :endianness=>:little_big_endian,
174
+ :gradual_underflow=>false, :infinity=>false, :nan=>false
175
+ )
176
+
177
+ VAX_H = BinaryFormat.new(
178
+ :fields=>[:significand, 112, :exponent, 15, :sign, 1],
179
+ :bias=>16384, :bias_mode=>:fractional_significand,
180
+ :hidden_bit=>true,
181
+ :endianness=>:little_big_endian,
182
+ :gradual_underflow=>false, :infinity=>false, :nan=>false
183
+ )
184
+
185
+ # DEC PDP 11 variants (minimum exponent used for normalized values other than zero)
186
+
187
+ PDP11_F = BinaryFormat.new(
188
+ :fields=>[:significand, 23, :exponent, 8, :sign, 1],
189
+ :bias=>128, :bias_mode=>:fractional_significand,
190
+ :hidden_bit=>true, :min_encoded_exp=>0,
191
+ :endianness=>:little_big_endian,
192
+ :gradual_underflow=>false, :infinity=>false, :nan=>false
193
+ )
194
+
195
+ PDP11_D = BinaryFormat.new(
196
+ :fields=>[:significand, 55, :exponent, 8, :sign, 1],
197
+ :bias=>128, :bias_mode=>:fractional_significand,
198
+ :hidden_bit=>true, :min_encoded_exp=>0,
199
+ :endianness=>:little_big_endian,
200
+ :gradual_underflow=>false, :infinity=>false, :nan=>false
201
+ )
202
+
203
+
204
+ # Format used in HP Saturn-based RPL calculators (HP48,HP49,HP50, also HP32s, HP42s --which use RPL internally)
205
+
206
+ SATURN = BCDFormat.new(
207
+ :fields=>[:prolog,5,:exponent,3,:significand,12,:sign,1],
208
+ :fields_handler=>lambda{|fields| fields[0]=2933},
209
+ :exponent_mode=>:radix_complement,
210
+ :endianness=>:little_endian, :round=>:even,
211
+ :gradual_underflow=>false, :infinity=>false, :nan=>false
212
+ )
213
+ SATURN_X = BCDFormat.new(
214
+ :fields=>[:prolog,5,:exponent,5,:significand,15,:sign,1],
215
+ :fields_handler=>lambda{|fields| fields[0]=2955},
216
+ :exponent_mode=>:radix_complement,
217
+ :endianness=>:little_endian, :round=>:even,
218
+ :gradual_underflow=>false, :infinity=>false, :nan=>false
219
+ )
220
+
221
+ # Format used in classic HP calculators (HP-35, ... HP-15C) (endianess is unknown)
222
+
223
+ HP_CLASSIC = BCDFormat.new(
224
+ :fields=>[:exponent,3,:significand,10,:sign,1],
225
+ :exponent_mode=>:radix_complement,
226
+ :min_exp=>-99, :max_exp=>99, # the most significant nibble of exponent if for sign only
227
+ :endianness=>:big_endian, :round=>:inf,
228
+ :gradual_underflow=>false, :infinity=>false, :nan=>false
229
+ )
230
+
231
+
232
+ # IBM Floating Point Architecture (IBM 360,370, DG Eclipse, ...)
233
+
234
+ # short
235
+ IBM32 = HexadecimalFormat.new(
236
+ :fields=>[:significand,24,:exponent,7,:sign,1],
237
+ :bias=>64, :bias_mode=>:fractional_significand,
238
+ :endianness=>:big_endian
239
+ )
240
+ # long
241
+ IBM64 = HexadecimalFormat.new(
242
+ :fields=>[:significand,56,:exponent,7,:sign,1],
243
+ :bias=>64, :bias_mode=>:fractional_significand,
244
+ :endianness=>:big_endian
245
+ )
246
+
247
+ # extended: two long values pasted together
248
+ IBM128 = HexadecimalFormat.new(
249
+ :fields=>[:significand,14*4,:lo_exponent,7,:lo_sign,1,:significand,14*4,:exponent,7,:sign,1],
250
+ :fields_handler=>lambda{|fields| fields[1]=(fields[4]>=14&&fields[4]<127) ? fields[4]-14 : fields[4];fields[2]=fields[5] },
251
+ :bias=>64, :bias_mode=>:fractional_significand,
252
+ :min_encoded_exp=>14, # to avoid out-of-range exponents in the lower half
253
+ :endianness=>:big_endian
254
+ )
255
+
256
+ # It think this has never been used:
257
+ IBMX = HexadecimalFormat.new(
258
+ :fields=>[:significand,14*4,:exponent,7,:unused_sign,1,:significand,14*4,:exponent,7,:sign,1],
259
+ :fields_handler=>lambda{|fields| fields[2]=0},
260
+ :bias=>8192, :bias_mode=>:fractional_significand,
261
+ :endianness=>:big_endian
262
+ )
263
+
264
+ # Cray-1
265
+ CRAY = BinaryFormat.new(
266
+ :fields=>[:significand,48,:exponent,15,:sign,1],
267
+ :bias=>16384, :bias_mode=>:fractional_significand,
268
+ :hidden_bit=>false,
269
+ :min_encoded_exp=>8192, :max_encoded_exp=>24575, :zero_encoded_exp=>0,
270
+ :endianness=>:big_endian,
271
+ :gradual_underflow=>false, :infinity=>false, :nan=>false
272
+ )
273
+
274
+ # CDC 6600/7600
275
+ # Byte endianness is arbitrary, since these machines were word-addressable, in 60-bit words,
276
+ # but the two words used in double precision numbers are in big endian order
277
+ # TO DO: apply this:
278
+ # The exponent encoded value 1023 is used for NaN
279
+ # The exponent encoded value 0 is used for underflow
280
+ # The exponent encoded value 2047 is used for overflow
281
+ #
282
+ # The exponent needs special treatment, because instead of excess encoding, which is equivalent to two's complement followed
283
+ # by sign bit reversal, one's complement followed by sign bit reversal is used, which is equivalent
284
+ # to use a bias diminished by one for negative exponents. Note that the exponent encoded value that equals the bias is
285
+ # not used (is used as a NaN indicator)
286
+ class CDCFLoatingPoint < BinaryFormat # :nodoc:
287
+ def encode_exponent(e,mode)
288
+ ee = super
289
+ ee -= 1 if e<0
290
+ ee
291
+ end
292
+ def decode_exponent(ee,mode)
293
+ e = super
294
+ e += 1 if e<0
295
+ e
296
+ end
297
+ end
298
+
299
+ CDC_SINGLE = CDCFLoatingPoint.new(
300
+ :fields=>[:significand,48, :exponent,11, :sign,1],
301
+ :bias=>1024, :bias_mode=>:integral_significand,
302
+ :min_exp=>-1023,
303
+ :neg_mode=>:diminished_radix_complement,
304
+ :hidden_bit=>false,
305
+ :endianess=>:big_endian,
306
+ :gradual_underflow=>false, :infinity=>false, :nan=>false
307
+ )
308
+
309
+ # the CDC_DOUBLE can be splitted in two CDC_SINGLE values:
310
+ # get_bitfields(v,[CDC_SINGLE.total_bits]*2,CDC_DOUBLE.endianness).collect{|x| int_to_bytes(x,0,CDC_SINGLE.endianness)}
311
+ # and the value of the double is the sum of the values of the singles.
312
+ # unlike the single, we must use :fractional_significand mode because with :integral_significand
313
+ # the exponent would refer to the whole significand, but it must refer only to the most significant half.
314
+ # we substract the number of bits in the single to the bias and exponent because of this change,
315
+ # and add 48 to the min_exponent to avoid the exponent of the low order single to be out of range
316
+ # because the exponent of the low order single is adjusted to
317
+ # the position of its digits by substracting 48 from the high order exponent
318
+ # Note that when computing the low order exponent with the fields handler we must take into account the sign
319
+ # because for negative numbers all the fields are one-complemented.
320
+ CDC_DOUBLE= CDCFLoatingPoint.new(
321
+ :fields=>[:significand,48,:lo_exponent,11,:lo_sign,1,:significand,48,:exponent,11,:sign,1],
322
+ :fields_handler=>lambda{|fields|
323
+ fields[1]=(fields[4]>0&&fields[4]<2047) ? fields[4]-((-1)**fields[5])*48 : fields[4]
324
+ fields[2]=fields[5]
325
+ },
326
+ :bias=>1024-48, :bias_mode=>:fractional_significand,
327
+ :min_encoded_exp=>48+1, # + 1 because the bias for negative is 1023
328
+ :neg_mode=>:diminished_radix_complement,
329
+ :hidden_bit=>false,
330
+ :endianess=>:big_endian,
331
+ :gradual_underflow=>false, :infinity=>false, :nan=>false
332
+ )
333
+
334
+
335
+ # Univac 1100
336
+ # Byte endianness is arbitrary, since these machines were word-addressable, in 36-bit words,
337
+ # but the two words used in double precision numbers are in big endian order
338
+ UNIVAC_SINGLE = BinaryFormat.new(
339
+ :fields=>[:significand,27, :exponent,8, :sign,1],
340
+ :bias=>128, :bias_mode=>:fractional_significand,
341
+ :neg_mode=>:diminished_radix_complement,
342
+ :hidden_bit=>false,
343
+ :endianess=>:big_endian,
344
+ :gradual_underflow=>false, :infinity=>false, :nan=>false
345
+ )
346
+
347
+ UNIVAC_DOUBLE = BinaryFormat.new(
348
+ :fields=>[:significand,60, :exponent,11, :sign,1],
349
+ :bias=>1024, :bias_mode=>:fractional_significand,
350
+ :neg_mode=>:diminished_radix_complement,
351
+ :hidden_bit=>false,
352
+ :endianess=>:big_endian,
353
+ :gradual_underflow=>false, :infinity=>false, :nan=>false
354
+ )
355
+
356
+ # Sofware floating point implementatin for the Apple II (6502)
357
+ # the significand & sign are a single field in two's commplement
358
+
359
+ APPLE = BinaryFormat.new(
360
+ :fields=>[:significand,23,:sign,1,:exponent,8],
361
+ :bias=>128, :bias_mode=>:normalized_significand,
362
+ :hidden_bit=>false, :min_encoded_exp=>0,
363
+ :neg_mode=>:radix_complement_significand,
364
+ :endianness=>:big_endian,
365
+ :gradual_underflow=>true, :infinity=>false, :nan=>false) { |fp|
366
+
367
+ # This needs a peculiar treatment for the negative values, which not simply use two's complement
368
+ # but also avoid having the sign and msb of the significand equal.
369
+ # Note that here we have a separate sign bit, but it can also be considered as the msb of the significand
370
+ # in two's complement, in which case the radix point is after the two msbs, which are the ones that
371
+ # should not be equal. (except for zero and other values using the minimum exponent).
372
+ def fp.neg_significand_exponent(s,f,e)
373
+ #puts "before: #{s} #{f.to_s(16)}"
374
+ f,e = super
375
+ s = (s+1)%2
376
+ #print "neg #{f.to_s(16)}"
377
+ if e>@zero_encoded_exp && f==0
378
+ f = 1<<(significand_digits-1)
379
+ e += 1
380
+ else
381
+ while (e>@zero_encoded_exp) && (f>>(significand_digits-1))&1 == s
382
+ e -= 1
383
+ f = (f << 1) & (radix_power(significand_digits)-1)
384
+ #print " << "
385
+ end
386
+ end
387
+ #puts ""
388
+ [f,e]
389
+ end
390
+
391
+ }
392
+
393
+
394
+ # Wang 2200 Basic Decimal floating point
395
+ WANG2200 = BCDFormat.new(
396
+ :fields=>[:significand,13,:exponent,2,:signs,1],
397
+ :endiannes=>:big_endian,
398
+ :bias_mode=>:normalized_significand,
399
+ :min_exp=>-99, :max_exp=>99,
400
+ :zero_encoded_exp=>0, :min_encoded_exp=>0
401
+ ) { |wang2200|
402
+
403
+ # needs special handling because significand and exponent are both stored
404
+ # as sign-magnitude, with both signs combined in a single nibble (decimal digit)
405
+ def wang2200.to_integral_sign_significand_exponent(v)
406
+ f = to_fields_hash(v)
407
+ m = f[:significand]
408
+ e = f[:exponent]
409
+ ss = f[:signs]
410
+ s = (ss==9 || ss==1) ? 9 : 0
411
+ es = (ss==8 || ss==1) ? 9 : 0
412
+ if m==0
413
+ # +-zero
414
+ e = :zero
415
+ elsif @infinite_encoded_exp && e==@infinite_encoded_exp && m==0
416
+ # +-inifinity
417
+ e = :infinity
418
+ elsif @nan_encoded_exp && e==@nan_encoded_exp && m!=0
419
+ # NaN
420
+ e = :nan
421
+ else
422
+ # normalized number
423
+ # reverse exponent nibbles
424
+ e = ("%0#{exponent_digits}d"%e).reverse.to_i
425
+ e = -e if es%2!=0
426
+ e -= (significand_digits-1)
427
+ end
428
+ [s,m,e]
429
+ end
430
+
431
+ def wang2200.from_integral_sign_significand_exponent(s,m,e)
432
+ msb = radix_power(@significand_digits-1)
433
+ es = 0
434
+ if e==:zero
435
+ e = @zero_encoded_exp
436
+ m = 0
437
+ elsif e==:infinity
438
+ e = @infinite_encoded_exp || radix_power(@fields[:exponent])-1
439
+ m = 0
440
+ elsif e==:nan
441
+ e = @infinite_encoded_exp || radix_power(@fields[:exponent])-1
442
+ s = minus_sign_value # ?
443
+ m = radix_power(@significand_digits-2) if m==0
444
+ elsif e==:denormal
445
+ e = @denormal_encoded_exp
446
+ else
447
+ # to do: try to adjust m to keep e in range if out of valid range
448
+ # to do: reduce m and adjust e if m too big
449
+
450
+ min_exp = radix_min_exp(:integral_significand)
451
+ if m>0
452
+ while m<msb && e>min_exp
453
+ e -= 1
454
+ m *= radix
455
+ end
456
+ end
457
+ if m<msb && @denormal_encoded_exp
458
+ e = @denormal_encoded_exp
459
+ elsif m==0 # => && @denormal_encoded_exp.nil?
460
+ e = 0
461
+ else
462
+ e += (significand_digits-1)
463
+ if e<0
464
+ e = -e
465
+ es = 9
466
+ else
467
+ es = 0
468
+ end
469
+ end
470
+ end
471
+ ss = (s%2) + (es==0 ? 0 : 8)
472
+ # reverse exponent nibbles
473
+ e = ("%0#{exponent_digits}d"%e).reverse.to_i
474
+ from_fields_hash :signs=>ss, :significand=>m, :exponent=>e
475
+ end
476
+ }
477
+
478
+
479
+ # C51 (C compiler for the Intel 8051) BCD Floating point formats
480
+ class C51BCDFloatingPoint < BCDFormat # :nodoc:
481
+ def exponent_radix
482
+ 2
483
+ end
484
+ def exponent_digits
485
+ @fields[:exponent_sign]*4-1
486
+ end
487
+ def minus_sign_value
488
+ 1
489
+ end
490
+ def to_integral_sign_significand_exponent(v)
491
+ f = to_fields_hash(v)
492
+ m = f[:significand]
493
+ e_s = f[:exponent_sign]
494
+ exp_bits = exponent_digits
495
+ e = e_s & (2**exp_bits-1)
496
+ s = e_s >> exp_bits
497
+ if m==0
498
+ # +-zero
499
+ e = :zero
500
+ elsif @infinite_encoded_exp && e==@infinite_encoded_exp && m==0
501
+ # +-inifinity
502
+ e = :infinity
503
+ elsif @nan_encoded_exp && e==@nan_encoded_exp && m!=0
504
+ # NaN
505
+ e = :nan
506
+ else
507
+ # normalized number
508
+ e = decode_exponent(e, :integral_significand)
509
+ end
510
+ [s,m,e]
511
+ end
512
+ def bcd_field?(i)
513
+ @field_meaning[i]==:significand
514
+ end
515
+
516
+ def from_integral_sign_significand_exponent(s,m,e)
517
+ msb = radix_power(@significand_digits-1)
518
+ es = 0
519
+ if e==:zero
520
+ e = @zero_encoded_exp
521
+ m = 0
522
+ elsif e==:infinity
523
+ e = @infinite_encoded_exp || radix_power(@fields[:exponent])-1
524
+ m = 0
525
+ elsif e==:nan
526
+ e = @infinite_encoded_exp || radix_power(@fields[:exponent])-1
527
+ s = minus_sign_value # ?
528
+ m = radix_power(@significand_digits-2) if m==0
529
+ elsif e==:denormal
530
+ e = @denormal_encoded_exp
531
+ else
532
+ # to do: try to adjust m to keep e in range if out of valid range
533
+ # to do: reduce m and adjust e if m too big
534
+
535
+ min_exp = radix_min_exp(:integral_significand)
536
+ if m>0
537
+ while m<msb && e>min_exp
538
+ e -= 1
539
+ m *= radix
540
+ end
541
+ end
542
+ if m<msb && @denormal_encoded_exp
543
+ e = @denormal_encoded_exp
544
+ elsif m==0 # => && @denormal_encoded_exp.nil?
545
+ e = 0
546
+ else
547
+ e = encode_exponent(e, :integral_significand)
548
+ end
549
+ end
550
+ exp_bits = exponent_digits
551
+ e_s = e + (s << exp_bits)
552
+ from_fields_hash :significand=>m, :exponent_sign=>e_s
553
+ end
554
+ end
555
+
556
+ C51_BCD_FLOAT = C51BCDFloatingPoint.new(
557
+ :fields=>[:exponent_sign, 2, :significand,6],
558
+ :endiannes=>:big_endian,
559
+ :bias=>64, :bias_mode=>:fractional_significand,
560
+ :zero_encoded_exp=>0, :min_encoded_exp=>0,:max_encoded_exp=>127
561
+ )
562
+ C51_BCD_DOUBLE = C51BCDFloatingPoint.new(
563
+ :fields=>[:exponent_sign, 2, :significand,10],
564
+ :endiannes=>:big_endian,
565
+ :bias=>64, :bias_mode=>:fractional_significand,
566
+ :zero_encoded_exp=>0, :min_encoded_exp=>0,:max_encoded_exp=>127
567
+ )
568
+ C51_BCD_LONG_DOUBLE = C51BCDFloatingPoint.new(
569
+ :fields=>[:exponent_sign, 2, :significand,12],
570
+ :endiannes=>:big_endian,
571
+ :bias=>64, :bias_mode=>:fractional_significand,
572
+ :zero_encoded_exp=>0, :min_encoded_exp=>0,:max_encoded_exp=>127
573
+ )
574
+
575
+
576
+
577
+
578
+
579
+ end
580
+