float-formats 0.1.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.
@@ -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
+