float-formats 0.1.1 → 0.2.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.
- data/History.txt +27 -32
- data/Manifest.txt +10 -18
- data/README.txt +330 -327
- data/Rakefile +38 -4
- data/lib/float-formats.rb +9 -9
- data/lib/float-formats/bytes.rb +463 -303
- data/lib/float-formats/classes.rb +1950 -1605
- data/lib/float-formats/formats.rb +633 -669
- data/lib/float-formats/native.rb +144 -272
- data/lib/float-formats/version.rb +4 -4
- data/tasks/ann.rake +80 -0
- data/tasks/bones.rake +20 -0
- data/tasks/gem.rake +192 -0
- data/tasks/git.rake +40 -0
- data/tasks/manifest.rake +48 -0
- data/tasks/notes.rake +27 -0
- data/tasks/post_load.rake +39 -0
- data/tasks/rdoc.rake +50 -0
- data/tasks/rubyforge.rake +55 -0
- data/tasks/setup.rb +279 -0
- data/tasks/spec.rake +54 -0
- data/tasks/svn.rake +47 -0
- data/tasks/test.rake +40 -0
- data/test/gen_test_data.rb +119 -119
- data/test/test_arithmetic.rb +36 -0
- data/test/test_bytes.rb +43 -0
- data/test/test_data.yaml +1667 -1667
- data/test/test_float_formats.rb +208 -0
- data/test/test_helper.rb +2 -1
- data/test/test_native-float.rb +84 -77
- metadata +123 -60
- data/config/hoe.rb +0 -73
- data/config/requirements.rb +0 -17
- data/script/destroy +0 -14
- data/script/destroy.cmd +0 -1
- data/script/generate +0 -14
- data/script/generate.cmd +0 -1
- data/script/txt2html +0 -74
- data/script/txt2html.cmd +0 -1
- data/tasks/deployment.rake +0 -34
- data/tasks/environment.rake +0 -7
- data/tasks/website.rake +0 -17
- data/test/test_float-formats.rb +0 -169
@@ -1,1605 +1,1950 @@
|
|
1
|
-
# Float-Formats
|
2
|
-
# Floating-point classes -- tools to handle floating point formats
|
3
|
-
|
4
|
-
# Nomenclature:
|
5
|
-
# * radix: the numerical base of the floating point notation
|
6
|
-
# * significand: the digits part of the number; also called coefficient or, arguably, mantissa.
|
7
|
-
# * exponent: the radix exponent, also called characteristic;
|
8
|
-
# * encoded exponent: the value stored in the f.p. format to denote the exponent
|
9
|
-
#
|
10
|
-
# Significand modes determine the interpretation of the significand value and also
|
11
|
-
# of the exponent values. For excess-notation encoded exponents this means that
|
12
|
-
# the value of the bias depends upon the interpretation of the significand.
|
13
|
-
# * integral significand: the significand is interpreted as an integer, i.e. the radix
|
14
|
-
# point is at the right (after the last digit);
|
15
|
-
# Some examples of this pont of view:
|
16
|
-
# - HP-50G LONGFLOAT library
|
17
|
-
# - HP-16C Floating Point-Integer conversion
|
18
|
-
# * fractional significand: the radix point is at the left, before the first significand digit
|
19
|
-
# (before the hidden bit if there is one); the value v of a normalized significand is 1/r<=v<1
|
20
|
-
# Examples:
|
21
|
-
# - The C standard library frexp/ldexp uses this interpretation, and the <float.h> constants.
|
22
|
-
# (and so this is also used by Ruby's Math.frexp and the constants defined in Float)
|
23
|
-
# - Don Knuth's The Art of Computer Programming, Vol.2
|
24
|
-
# - BigDecimal#split
|
25
|
-
# *
|
26
|
-
# the value v of a normalized significand is 1<=v<r
|
27
|
-
# Examples:
|
28
|
-
# - IEEE 754 definitions
|
29
|
-
# - RPL's MANT/XPON
|
30
|
-
# - HP calculators SCI mode
|
31
|
-
#
|
32
|
-
# zero representation in hidden bit formats:
|
33
|
-
# * with gradual underflow: the minimium encoded exponent (0) is used for zero and denormal numbers;
|
34
|
-
# i.e. the minimum encoded exponent implies the hidden bit is 0
|
35
|
-
# * minimum encoded exponent reserved for zero (nonzero significands are not used with it)
|
36
|
-
# * special all zeros representation: minimun encoded exponent is a regular exponent except for 0
|
37
|
-
|
38
|
-
require 'nio'
|
39
|
-
require 'nio/sugar'
|
40
|
-
require '
|
41
|
-
require '
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
class
|
47
|
-
|
48
|
-
|
49
|
-
#
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
@
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
when
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
@
|
149
|
-
|
150
|
-
|
151
|
-
if
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
#
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
(
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
#
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
#
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
#
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
@
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
#
|
541
|
-
#
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
def
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
m
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
#
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
#
|
773
|
-
def
|
774
|
-
|
775
|
-
end
|
776
|
-
|
777
|
-
def
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
826
|
-
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
#
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
end
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
|
927
|
-
|
928
|
-
|
929
|
-
|
930
|
-
|
931
|
-
|
932
|
-
|
933
|
-
|
934
|
-
|
935
|
-
|
936
|
-
|
937
|
-
#
|
938
|
-
|
939
|
-
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
@
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
|
960
|
-
|
961
|
-
|
962
|
-
|
963
|
-
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
968
|
-
|
969
|
-
|
970
|
-
|
971
|
-
|
972
|
-
|
973
|
-
|
974
|
-
|
975
|
-
|
976
|
-
|
977
|
-
|
978
|
-
|
979
|
-
|
980
|
-
|
981
|
-
|
982
|
-
|
983
|
-
|
984
|
-
|
985
|
-
|
986
|
-
|
987
|
-
|
988
|
-
|
989
|
-
|
990
|
-
|
991
|
-
|
992
|
-
|
993
|
-
|
994
|
-
|
995
|
-
|
996
|
-
|
997
|
-
|
998
|
-
|
999
|
-
|
1000
|
-
|
1001
|
-
|
1002
|
-
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1011
|
-
|
1012
|
-
|
1013
|
-
|
1014
|
-
|
1015
|
-
|
1016
|
-
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1027
|
-
|
1028
|
-
|
1029
|
-
|
1030
|
-
|
1031
|
-
|
1032
|
-
|
1033
|
-
|
1034
|
-
|
1035
|
-
|
1036
|
-
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
1045
|
-
|
1046
|
-
|
1047
|
-
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
1055
|
-
|
1056
|
-
|
1057
|
-
e
|
1058
|
-
|
1059
|
-
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
1063
|
-
end
|
1064
|
-
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1068
|
-
|
1069
|
-
|
1070
|
-
#
|
1071
|
-
|
1072
|
-
|
1073
|
-
|
1074
|
-
|
1075
|
-
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1082
|
-
|
1083
|
-
|
1084
|
-
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1089
|
-
|
1090
|
-
|
1091
|
-
|
1092
|
-
|
1093
|
-
|
1094
|
-
|
1095
|
-
|
1096
|
-
|
1097
|
-
|
1098
|
-
|
1099
|
-
|
1100
|
-
|
1101
|
-
|
1102
|
-
|
1103
|
-
|
1104
|
-
|
1105
|
-
|
1106
|
-
|
1107
|
-
|
1108
|
-
|
1109
|
-
|
1110
|
-
|
1111
|
-
|
1112
|
-
|
1113
|
-
|
1114
|
-
|
1115
|
-
end
|
1116
|
-
|
1117
|
-
|
1118
|
-
|
1119
|
-
|
1120
|
-
|
1121
|
-
|
1122
|
-
|
1123
|
-
|
1124
|
-
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1128
|
-
|
1129
|
-
|
1130
|
-
|
1131
|
-
|
1132
|
-
|
1133
|
-
|
1134
|
-
|
1135
|
-
|
1136
|
-
|
1137
|
-
|
1138
|
-
|
1139
|
-
|
1140
|
-
|
1141
|
-
|
1142
|
-
|
1143
|
-
|
1144
|
-
|
1145
|
-
|
1146
|
-
|
1147
|
-
|
1148
|
-
|
1149
|
-
|
1150
|
-
|
1151
|
-
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1156
|
-
|
1157
|
-
|
1158
|
-
|
1159
|
-
|
1160
|
-
|
1161
|
-
|
1162
|
-
|
1163
|
-
|
1164
|
-
|
1165
|
-
|
1166
|
-
|
1167
|
-
|
1168
|
-
|
1169
|
-
|
1170
|
-
|
1171
|
-
|
1172
|
-
|
1173
|
-
|
1174
|
-
|
1175
|
-
|
1176
|
-
|
1177
|
-
|
1178
|
-
|
1179
|
-
|
1180
|
-
|
1181
|
-
|
1182
|
-
|
1183
|
-
|
1184
|
-
|
1185
|
-
|
1186
|
-
|
1187
|
-
|
1188
|
-
|
1189
|
-
|
1190
|
-
|
1191
|
-
|
1192
|
-
|
1193
|
-
|
1194
|
-
|
1195
|
-
|
1196
|
-
|
1197
|
-
|
1198
|
-
|
1199
|
-
def
|
1200
|
-
|
1201
|
-
|
1202
|
-
|
1203
|
-
|
1204
|
-
|
1205
|
-
|
1206
|
-
|
1207
|
-
|
1208
|
-
e = :
|
1209
|
-
|
1210
|
-
#
|
1211
|
-
|
1212
|
-
|
1213
|
-
|
1214
|
-
e
|
1215
|
-
|
1216
|
-
|
1217
|
-
|
1218
|
-
|
1219
|
-
|
1220
|
-
|
1221
|
-
|
1222
|
-
|
1223
|
-
|
1224
|
-
|
1225
|
-
|
1226
|
-
|
1227
|
-
|
1228
|
-
|
1229
|
-
|
1230
|
-
|
1231
|
-
|
1232
|
-
|
1233
|
-
|
1234
|
-
|
1235
|
-
|
1236
|
-
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1240
|
-
|
1241
|
-
|
1242
|
-
|
1243
|
-
|
1244
|
-
|
1245
|
-
|
1246
|
-
|
1247
|
-
|
1248
|
-
|
1249
|
-
|
1250
|
-
|
1251
|
-
|
1252
|
-
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
1257
|
-
|
1258
|
-
|
1259
|
-
|
1260
|
-
|
1261
|
-
|
1262
|
-
|
1263
|
-
|
1264
|
-
|
1265
|
-
|
1266
|
-
|
1267
|
-
|
1268
|
-
|
1269
|
-
|
1270
|
-
|
1271
|
-
|
1272
|
-
|
1273
|
-
|
1274
|
-
|
1275
|
-
|
1276
|
-
|
1277
|
-
|
1278
|
-
|
1279
|
-
|
1280
|
-
|
1281
|
-
# :
|
1282
|
-
|
1283
|
-
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1287
|
-
|
1288
|
-
|
1289
|
-
|
1290
|
-
|
1291
|
-
|
1292
|
-
|
1293
|
-
|
1294
|
-
|
1295
|
-
|
1296
|
-
|
1297
|
-
|
1298
|
-
|
1299
|
-
|
1300
|
-
|
1301
|
-
|
1302
|
-
|
1303
|
-
|
1304
|
-
|
1305
|
-
|
1306
|
-
|
1307
|
-
|
1308
|
-
|
1309
|
-
|
1310
|
-
|
1311
|
-
|
1312
|
-
|
1313
|
-
|
1314
|
-
|
1315
|
-
|
1316
|
-
|
1317
|
-
|
1318
|
-
|
1319
|
-
|
1320
|
-
|
1321
|
-
|
1322
|
-
|
1323
|
-
|
1324
|
-
|
1325
|
-
|
1326
|
-
|
1327
|
-
|
1328
|
-
|
1329
|
-
|
1330
|
-
|
1331
|
-
|
1332
|
-
|
1333
|
-
|
1334
|
-
|
1335
|
-
|
1336
|
-
|
1337
|
-
|
1338
|
-
|
1339
|
-
|
1340
|
-
|
1341
|
-
|
1342
|
-
|
1343
|
-
|
1344
|
-
|
1345
|
-
|
1346
|
-
|
1347
|
-
|
1348
|
-
|
1349
|
-
|
1350
|
-
|
1351
|
-
|
1352
|
-
|
1353
|
-
|
1354
|
-
|
1355
|
-
|
1356
|
-
|
1357
|
-
|
1358
|
-
|
1359
|
-
|
1360
|
-
|
1361
|
-
|
1362
|
-
|
1363
|
-
|
1364
|
-
|
1365
|
-
|
1366
|
-
|
1367
|
-
|
1368
|
-
|
1369
|
-
|
1370
|
-
|
1371
|
-
|
1372
|
-
|
1373
|
-
|
1374
|
-
|
1375
|
-
|
1376
|
-
|
1377
|
-
|
1378
|
-
|
1379
|
-
|
1380
|
-
|
1381
|
-
|
1382
|
-
|
1383
|
-
|
1384
|
-
|
1385
|
-
|
1386
|
-
|
1387
|
-
end
|
1388
|
-
|
1389
|
-
|
1390
|
-
|
1391
|
-
|
1392
|
-
|
1393
|
-
|
1394
|
-
|
1395
|
-
|
1396
|
-
|
1397
|
-
|
1398
|
-
|
1399
|
-
|
1400
|
-
|
1401
|
-
|
1402
|
-
|
1403
|
-
|
1404
|
-
|
1405
|
-
|
1406
|
-
|
1407
|
-
|
1408
|
-
|
1409
|
-
|
1410
|
-
|
1411
|
-
|
1412
|
-
|
1413
|
-
|
1414
|
-
|
1415
|
-
|
1416
|
-
|
1417
|
-
|
1418
|
-
|
1419
|
-
|
1420
|
-
|
1421
|
-
|
1422
|
-
|
1423
|
-
|
1424
|
-
|
1425
|
-
|
1426
|
-
|
1427
|
-
|
1428
|
-
|
1429
|
-
|
1430
|
-
|
1431
|
-
|
1432
|
-
|
1433
|
-
|
1434
|
-
|
1435
|
-
|
1436
|
-
|
1437
|
-
|
1438
|
-
|
1439
|
-
|
1440
|
-
|
1441
|
-
|
1442
|
-
|
1443
|
-
|
1444
|
-
|
1445
|
-
|
1446
|
-
|
1447
|
-
|
1448
|
-
|
1449
|
-
|
1450
|
-
|
1451
|
-
|
1452
|
-
|
1453
|
-
|
1454
|
-
|
1455
|
-
|
1456
|
-
|
1457
|
-
|
1458
|
-
|
1459
|
-
|
1460
|
-
|
1461
|
-
|
1462
|
-
|
1463
|
-
|
1464
|
-
|
1465
|
-
|
1466
|
-
|
1467
|
-
|
1468
|
-
|
1469
|
-
|
1470
|
-
|
1471
|
-
|
1472
|
-
|
1473
|
-
|
1474
|
-
|
1475
|
-
|
1476
|
-
|
1477
|
-
|
1478
|
-
|
1479
|
-
|
1480
|
-
|
1481
|
-
|
1482
|
-
|
1483
|
-
|
1484
|
-
|
1485
|
-
|
1486
|
-
|
1487
|
-
|
1488
|
-
end
|
1489
|
-
|
1490
|
-
|
1491
|
-
|
1492
|
-
|
1493
|
-
|
1494
|
-
|
1495
|
-
|
1496
|
-
|
1497
|
-
|
1498
|
-
|
1499
|
-
#
|
1500
|
-
|
1501
|
-
|
1502
|
-
|
1503
|
-
|
1504
|
-
@
|
1505
|
-
|
1506
|
-
|
1507
|
-
|
1508
|
-
|
1509
|
-
|
1510
|
-
|
1511
|
-
|
1512
|
-
|
1513
|
-
|
1514
|
-
|
1515
|
-
|
1516
|
-
|
1517
|
-
|
1518
|
-
|
1519
|
-
def self.
|
1520
|
-
|
1521
|
-
|
1522
|
-
|
1523
|
-
|
1524
|
-
|
1525
|
-
|
1526
|
-
|
1527
|
-
|
1528
|
-
|
1529
|
-
|
1530
|
-
|
1531
|
-
|
1532
|
-
|
1533
|
-
|
1534
|
-
|
1535
|
-
|
1536
|
-
|
1537
|
-
|
1538
|
-
|
1539
|
-
|
1540
|
-
|
1541
|
-
|
1542
|
-
|
1543
|
-
|
1544
|
-
|
1545
|
-
|
1546
|
-
|
1547
|
-
|
1548
|
-
|
1549
|
-
|
1550
|
-
|
1551
|
-
|
1552
|
-
|
1553
|
-
|
1554
|
-
|
1555
|
-
|
1556
|
-
|
1557
|
-
|
1558
|
-
|
1559
|
-
|
1560
|
-
|
1561
|
-
|
1562
|
-
|
1563
|
-
|
1564
|
-
|
1565
|
-
|
1566
|
-
|
1567
|
-
|
1568
|
-
|
1569
|
-
|
1570
|
-
|
1571
|
-
|
1572
|
-
|
1573
|
-
|
1574
|
-
|
1575
|
-
|
1576
|
-
|
1577
|
-
|
1578
|
-
def
|
1579
|
-
|
1580
|
-
end
|
1581
|
-
|
1582
|
-
def
|
1583
|
-
@
|
1584
|
-
end
|
1585
|
-
def
|
1586
|
-
|
1587
|
-
end
|
1588
|
-
|
1589
|
-
|
1590
|
-
def
|
1591
|
-
|
1592
|
-
|
1593
|
-
|
1594
|
-
|
1595
|
-
|
1596
|
-
|
1597
|
-
|
1598
|
-
|
1599
|
-
|
1600
|
-
|
1601
|
-
|
1602
|
-
|
1603
|
-
|
1604
|
-
|
1605
|
-
|
1
|
+
# Float-Formats
|
2
|
+
# Floating-point classes -- tools to handle floating point formats
|
3
|
+
|
4
|
+
# Nomenclature:
|
5
|
+
# * radix: the numerical base of the floating point notation
|
6
|
+
# * significand: the digits part of the number; also called coefficient or, arguably, mantissa.
|
7
|
+
# * exponent: the radix exponent, also called characteristic;
|
8
|
+
# * encoded exponent: the value stored in the f.p. format to denote the exponent
|
9
|
+
#
|
10
|
+
# Significand modes determine the interpretation of the significand value and also
|
11
|
+
# of the exponent values. For excess-notation encoded exponents this means that
|
12
|
+
# the value of the bias depends upon the interpretation of the significand.
|
13
|
+
# * integral significand: the significand is interpreted as an integer, i.e. the radix
|
14
|
+
# point is at the right (after the last digit);
|
15
|
+
# Some examples of this pont of view:
|
16
|
+
# - HP-50G LONGFLOAT library
|
17
|
+
# - HP-16C Floating Point-Integer conversion
|
18
|
+
# * fractional significand: the radix point is at the left, before the first significand digit
|
19
|
+
# (before the hidden bit if there is one); the value v of a normalized significand is 1/r<=v<1
|
20
|
+
# Examples:
|
21
|
+
# - The C standard library frexp/ldexp uses this interpretation, and the <float.h> constants.
|
22
|
+
# (and so this is also used by Ruby's Math.frexp and the constants defined in Float)
|
23
|
+
# - Don Knuth's The Art of Computer Programming, Vol.2
|
24
|
+
# - BigDecimal#split
|
25
|
+
# * scientific significand: the radix point is after the first digit (after the hidden bit if present)
|
26
|
+
# the value v of a normalized significand is 1<=v<r
|
27
|
+
# Examples:
|
28
|
+
# - IEEE 754 definitions
|
29
|
+
# - RPL's MANT/XPON
|
30
|
+
# - HP calculators SCI mode
|
31
|
+
#
|
32
|
+
# zero representation in hidden bit formats:
|
33
|
+
# * with gradual underflow: the minimium encoded exponent (0) is used for zero and denormal numbers;
|
34
|
+
# i.e. the minimum encoded exponent implies the hidden bit is 0
|
35
|
+
# * minimum encoded exponent reserved for zero (nonzero significands are not used with it)
|
36
|
+
# * special all zeros representation: minimun encoded exponent is a regular exponent except for 0
|
37
|
+
|
38
|
+
require 'nio'
|
39
|
+
require 'nio/sugar'
|
40
|
+
require 'flt'
|
41
|
+
require 'enumerator'
|
42
|
+
require 'float-formats/bytes.rb'
|
43
|
+
|
44
|
+
module Flt
|
45
|
+
|
46
|
+
# General Floating Point Format Base class
|
47
|
+
class FormatBase
|
48
|
+
include Flt # make Flt module functions available to instance methods
|
49
|
+
extend Flt # make Flt module functions available to class methods
|
50
|
+
|
51
|
+
def initialize(*args)
|
52
|
+
if (args.size == 3 || args.size==4 || args.size==2) &&
|
53
|
+
(args.first.kind_of?(Integer) && args[1].kind_of?(Integer))
|
54
|
+
sign,significand,exponent,normalize = args
|
55
|
+
if normalize.nil?
|
56
|
+
if [nil,true,false].include?(exponent)
|
57
|
+
normalize = exponent
|
58
|
+
exponent = significand
|
59
|
+
significand = sign.abs
|
60
|
+
sign = sign<0 ? -1 : +1
|
61
|
+
end
|
62
|
+
end
|
63
|
+
@sign,@significand,@exponent = self.class.canonicalized(sign,significand,exponent,normalize)
|
64
|
+
else
|
65
|
+
v = form_class.nan
|
66
|
+
case args.first
|
67
|
+
when form_class
|
68
|
+
v = args.first
|
69
|
+
raise "Too many arguments for FormatBase constructor" if args.size>1
|
70
|
+
when Array
|
71
|
+
v = args.first
|
72
|
+
raise "Too many arguments for FormatBase constructor" if args.size>1
|
73
|
+
when FormatBase
|
74
|
+
v = args.first.convert_to(form_class)
|
75
|
+
raise "Too many arguments for FormatBase constructor" if args.size>1
|
76
|
+
when String
|
77
|
+
v = form_class.from_text(*args)
|
78
|
+
when Bytes
|
79
|
+
v = form_class.from_bytes(*args)
|
80
|
+
when Bits
|
81
|
+
v = form_class.from_bits(*args)
|
82
|
+
when Numeric
|
83
|
+
v = form_class.from_number(args.first)
|
84
|
+
raise "Too many arguments for FormatBase constructor" if args.size>1
|
85
|
+
when Symbol
|
86
|
+
if args.first.to_s[0..3]!='from'
|
87
|
+
args = ["from_#{args.first}".to_sym] + args[1..-1]
|
88
|
+
end
|
89
|
+
v = form_class.send(*args)
|
90
|
+
end
|
91
|
+
@sign,@significand,@exponent = v.to_a
|
92
|
+
end
|
93
|
+
end
|
94
|
+
attr_reader :sign, :significand, :exponent
|
95
|
+
def to_a
|
96
|
+
split
|
97
|
+
end
|
98
|
+
def split
|
99
|
+
return [@sign,@significand,@exponent]
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
def nan?
|
104
|
+
@exponent == :nan
|
105
|
+
end
|
106
|
+
def zero?
|
107
|
+
return @exponent==:zero || @significand==0
|
108
|
+
end
|
109
|
+
def infinite?
|
110
|
+
return @exponent==:infinity
|
111
|
+
end
|
112
|
+
def subnormal?
|
113
|
+
return @exponent==:denormal || (@significand.kind_of?(Integer) && @significand<self.class.minimum_normalized_integral_significand)
|
114
|
+
end
|
115
|
+
def normal?
|
116
|
+
@exponend.kind_of?(Integer) && @significand>=self.class.minimum_normalized_integral_significand
|
117
|
+
end
|
118
|
+
|
119
|
+
include Nio::Formattable
|
120
|
+
|
121
|
+
# from/to integral_sign_significand_exponent
|
122
|
+
|
123
|
+
def nio_write_neutral(fmt)
|
124
|
+
# this always treats the floating-point values as exact quantities
|
125
|
+
case @exponent
|
126
|
+
when :zero
|
127
|
+
v = 0.0/@sign
|
128
|
+
when :infinity
|
129
|
+
v = @sign/0.0
|
130
|
+
when :nan
|
131
|
+
v = 0.0/0.0
|
132
|
+
else
|
133
|
+
case form_class.radix
|
134
|
+
when 10
|
135
|
+
v = Flt.DecNum(@sign, @significand, @exponent)
|
136
|
+
when 2
|
137
|
+
v = Flt.BinNum(@sign, @significand, @exponent)
|
138
|
+
else
|
139
|
+
v = @significand*form_class.radix_power(@exponent)*@sign
|
140
|
+
end
|
141
|
+
end
|
142
|
+
v.nio_write_neutral(fmt)
|
143
|
+
end
|
144
|
+
def to_text(fmt=Nio::Fmt.default)
|
145
|
+
nio_write(fmt)
|
146
|
+
end
|
147
|
+
def to_bytes
|
148
|
+
form_class.pack(@sign,@significand,@exponent)
|
149
|
+
end
|
150
|
+
def to_hex(sep_bytes=false)
|
151
|
+
if (form_class.total_bits % 8)==0
|
152
|
+
to_bytes.to_hex(sep_bytes)
|
153
|
+
else
|
154
|
+
to_bits.to_hex
|
155
|
+
end
|
156
|
+
end
|
157
|
+
def to(number_class, mode=:approx)
|
158
|
+
if number_class==Bytes
|
159
|
+
to_bytes
|
160
|
+
elsif number_class==String
|
161
|
+
mode = Nio::Fmt.default if mode==:approx
|
162
|
+
to_text(mode)
|
163
|
+
elsif Nio::Fmt===number_class
|
164
|
+
to_text(number_class)
|
165
|
+
elsif number_class==Array
|
166
|
+
split
|
167
|
+
elsif Symbol===number_class
|
168
|
+
send "to_#{number_class}"
|
169
|
+
elsif number_class.is_a?(Flt::Num) && number_class.radix == form_class.radix
|
170
|
+
self.to_num
|
171
|
+
else # assume number_class.ancestors.include?(Numeric) (number_class < Numeric)
|
172
|
+
fmt = mode==:approx ? Nio::Fmt::CONV_FMT : Nio::Fmt::CONV_FMT_STRICT
|
173
|
+
v = nio_write(fmt)
|
174
|
+
number_class.nio_read(v,fmt)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
def to_bits
|
178
|
+
to_bytes.to_bits(form_class.endianness,false,form_class.total_bits)
|
179
|
+
end
|
180
|
+
# Returns the encoded integral value of a floating point number
|
181
|
+
# as a text representation in a given base.
|
182
|
+
# Accepts either a Value or a byte String.
|
183
|
+
def to_bits_text(base)
|
184
|
+
to_bits.to_s(base)
|
185
|
+
#i = to_bits
|
186
|
+
#fmt = Nio::Fmt.default.base(base,true).mode(:fix,:exact)
|
187
|
+
#if [2,4,8,16].include?(base)
|
188
|
+
# n = (Math.log(base)/Math.log(2)).round.to_i
|
189
|
+
# digits = (form_class.total_bits+n-1)/n
|
190
|
+
# fmt.pad0s!(digits)
|
191
|
+
#end
|
192
|
+
#i.to_i.nio_write(fmt)
|
193
|
+
end
|
194
|
+
|
195
|
+
# Computes the negation of a floating point value (unary minus)
|
196
|
+
def minus
|
197
|
+
form_class.new(-@sign,@significand,@exponent)
|
198
|
+
end
|
199
|
+
|
200
|
+
# Converts a floating point value to another format
|
201
|
+
def convert_to(fpclass)
|
202
|
+
fpclass.nio_read(nio_write)
|
203
|
+
end
|
204
|
+
|
205
|
+
|
206
|
+
# Computes the next adjacent floating point value.
|
207
|
+
# Accepts either a Value or a byte String.
|
208
|
+
# Returns a Value.
|
209
|
+
# TODO: use Flt
|
210
|
+
def next_plus
|
211
|
+
s,f,e = self.class.canonicalized(@sign,@significand,@exponent,true)
|
212
|
+
return minus.next_minus.minus if s<0 && e!=:zero
|
213
|
+
s = -s if e==:zero && s<0
|
214
|
+
|
215
|
+
if e!=:nan && e!=:infinity
|
216
|
+
if f==0
|
217
|
+
if form_class.gradual_underflow?
|
218
|
+
e = form_class.radix_min_exp(:integral_significand)
|
219
|
+
f = 1
|
220
|
+
else
|
221
|
+
e = form_class.radix_min_exp(:integral_significand)
|
222
|
+
f = form_class.minimum_normalized_integral_significand
|
223
|
+
end
|
224
|
+
else
|
225
|
+
f += 1
|
226
|
+
end
|
227
|
+
if f>=form_class.radix_power(form_class.significand_digits)
|
228
|
+
f /= form_class.radix
|
229
|
+
if e==:denormal
|
230
|
+
e = form_class.radix_min_exp(:integral_significand)
|
231
|
+
else
|
232
|
+
e += 1
|
233
|
+
end
|
234
|
+
if e>form_class.radix_max_exp(:integral_significand)
|
235
|
+
e = :infinity
|
236
|
+
f = 0
|
237
|
+
end
|
238
|
+
end
|
239
|
+
form_class.new s, f, e
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
# Computes the previous adjacent floating point value.
|
244
|
+
# Accepts either a Value or a byte String.
|
245
|
+
# Returns a Value.
|
246
|
+
def next_minus
|
247
|
+
s,f,e = self.class.canonicalized(@sign,@significand,@exponent,true)
|
248
|
+
return minus.next_plus.minus if s<0
|
249
|
+
return self.next_plus.minus if e==:zero
|
250
|
+
if e!=:nan
|
251
|
+
if e == :infinity
|
252
|
+
f = form_class.maximum_integral_significand
|
253
|
+
e = form_class.radix_max_exp(:integral_significand)
|
254
|
+
else
|
255
|
+
f -= 1
|
256
|
+
if f<form_class.minimum_normalized_integral_significand
|
257
|
+
if e!=:denormal && e>form_class.radix_min_exp(:integral_significand)
|
258
|
+
e -= 1
|
259
|
+
f *= form_class.radix
|
260
|
+
else
|
261
|
+
if form_class.gradual_underflow?
|
262
|
+
e = :denormal
|
263
|
+
else
|
264
|
+
e = :zero
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
form_class.new s, f, e
|
271
|
+
end
|
272
|
+
|
273
|
+
# ulp (unit in the last place) according to the definition proposed by J.M. Muller in
|
274
|
+
# "On the definition of ulp(x)" INRIA No. 5504
|
275
|
+
def ulp
|
276
|
+
sign,sig,exp = @sign,@significand,@exponent
|
277
|
+
|
278
|
+
mnexp = form_class.radix_min_exp(:integral_significand)
|
279
|
+
mxexp = form_class.radix_max_exp(:integral_significand)
|
280
|
+
prec = form_class.significand_digits
|
281
|
+
|
282
|
+
if exp==:nan
|
283
|
+
elsif exp==:infinity
|
284
|
+
sign,sig,exp = 1,1,mxexp
|
285
|
+
elsif exp==:zero || exp <= mnexp
|
286
|
+
return form_class.min_value
|
287
|
+
else
|
288
|
+
exp -= 1 if sig==form_class.minimum_normalized_integral_significand
|
289
|
+
sign,sig,exp = 1,1,exp
|
290
|
+
end
|
291
|
+
form_class.new sign, sig, exp
|
292
|
+
end
|
293
|
+
|
294
|
+
def <=>(other)
|
295
|
+
return 1 if nan? || other.nan?
|
296
|
+
return 0 if zero? && other.zero?
|
297
|
+
this_sign,this_significand,this_exponent = split
|
298
|
+
other_sign, other_significand, other_exponent = other.split
|
299
|
+
return -1 if other_sign < this_sign
|
300
|
+
return 1 if other_sign > this_sign
|
301
|
+
return 0 if infinite? && other.infinite?
|
302
|
+
|
303
|
+
if this_sign<0
|
304
|
+
this_significand,other_significand = other_significand,this_significand
|
305
|
+
this_exponent,other_exponent = other_exponent,this_exponent
|
306
|
+
end
|
307
|
+
|
308
|
+
if this_exponent==other_exponent
|
309
|
+
return this_significand <=> other_significand
|
310
|
+
else
|
311
|
+
mns = form_class.minimum_normalized_integral_significand
|
312
|
+
this_normal = this_significand >= mns
|
313
|
+
other_normal = other_significand >= mns
|
314
|
+
if this_normal && other_normal
|
315
|
+
return this_exponent <=> other_exponent
|
316
|
+
else
|
317
|
+
min_exp = form_class.radix_min_exp(:integral_significand)
|
318
|
+
max_exp = form_class.radix_max_exp(:integral_significand)
|
319
|
+
|
320
|
+
while this_significand<mns && this_exponent>min_exp
|
321
|
+
this_exponent -= 1
|
322
|
+
this_significand *= form_class.radix
|
323
|
+
end
|
324
|
+
|
325
|
+
while other_significand<mns && other_exponent>min_exp
|
326
|
+
other_exponent -= 1
|
327
|
+
other_significand *= form_class.radix
|
328
|
+
end
|
329
|
+
|
330
|
+
if this_exponent==other_exponent
|
331
|
+
return this_significand <=> other_significand
|
332
|
+
else
|
333
|
+
return this_exponent <=> other_exponent
|
334
|
+
end
|
335
|
+
end
|
336
|
+
end
|
337
|
+
end
|
338
|
+
include Comparable
|
339
|
+
|
340
|
+
#todo hash cononicalizing first
|
341
|
+
|
342
|
+
|
343
|
+
def fp_format
|
344
|
+
form_class
|
345
|
+
end
|
346
|
+
def form_class
|
347
|
+
self.class
|
348
|
+
end
|
349
|
+
|
350
|
+
|
351
|
+
# Common parameters for all floating-point formats:
|
352
|
+
# [<tt>:bias_mode</tt>] This defines how the significand is interpreted:
|
353
|
+
# * <tt>:fractional_significand</tt> The radix point is before the most significant
|
354
|
+
# digit of the significand (including a hidden bit if there's one).
|
355
|
+
# * <tt>:scientific_significand</tt> The radix point is after the most significant
|
356
|
+
# digit of the significand (including a hidden bit if there's one).
|
357
|
+
# * <tt>:integral_significand</tt> The significand is assumed to be an integer, i.e.
|
358
|
+
# the radix point is after the least significant digit.
|
359
|
+
# [<tt>:bias</tt>] Defines the exponent encoding method to be excess notation
|
360
|
+
# and defines the bias.
|
361
|
+
# [<tt>:endianness</tt>] Defines the byte endianness. One of:
|
362
|
+
# * <tt>:little_endian</tt> Least significant bytes come first. (Intel etc.)
|
363
|
+
# * <tt>:big_endian</tt> (Network order): most significant bytes come first. (Motorola, SPARC,...)
|
364
|
+
# * <tt>:little_big_endian</tt> (Middle endian) Each pair of bytes (16-bit word) has the bytes in
|
365
|
+
# little endian order, but the words are stored in big endian order
|
366
|
+
# (we assume the number of bytes is even). (PDP-11).
|
367
|
+
def self.define(params={})
|
368
|
+
@parameters = params
|
369
|
+
|
370
|
+
@normalized = params[:normalized]
|
371
|
+
@normalized = true if @normalized.nil?
|
372
|
+
@fields_handler = params[:fields_handler]
|
373
|
+
|
374
|
+
@exponent_radix = params[:exponent_radix] || radix
|
375
|
+
|
376
|
+
@zero_encoded_exp = params[:zero_encoded_exp] || 0
|
377
|
+
@min_encoded_exp = params[:min_encoded_exp] || 0
|
378
|
+
@denormal_encoded_exp = params[:denormal_encoded_exp]
|
379
|
+
@gradual_underflow = params[:gradual_underflow] || (@denormal_encoded_exp ? true : false)
|
380
|
+
if @gradual_underflow
|
381
|
+
@denormal_encoded_exp = 0 if !@denormal_encoded_exp
|
382
|
+
if @denormal_encoded_exp>=@min_encoded_exp
|
383
|
+
@min_encoded_exp = @denormal_encoded_exp
|
384
|
+
# originally, we incremented min_encoded_exp here unconditionally, but
|
385
|
+
# now we don't if there's no hidden bit
|
386
|
+
# (we assume the minimum exponent can be used for normalized and denormalized numbers)
|
387
|
+
# because of this, IEEE_EXTENDED & 128 formats now specify :min_encoded_exp=>1 in it's definitions
|
388
|
+
@min_encoded_exp += 1 if @hidden_bit
|
389
|
+
end
|
390
|
+
end
|
391
|
+
# Note that if there's a hidden bit and no gradual underflow, the minimum encoded exponent will only
|
392
|
+
# be used for zero unless a parameter :min_encoded_exp (=0) is passed. In this case all numbers with
|
393
|
+
# minimun exponent and nonzero encoded significand will have a 1-valued hidden bit. Otherwise
|
394
|
+
# the only valid encoded significand with minimun encoded exponent is 0.
|
395
|
+
# In case of gradual underflow, the minimum exponent implies a hidden bit value of 0
|
396
|
+
@min_encoded_exp += 1 if @min_encoded_exp==@zero_encoded_exp && (@hidden_bit && params[:min_encoded_exp].nil?)
|
397
|
+
|
398
|
+
@infinite_encoded_exp = params[:infinite_encoded_exp]
|
399
|
+
@nan_encoded_exp = params[:nan_encoded_exp]
|
400
|
+
|
401
|
+
@infinity = params[:infinity] || (@infinite_encoded_exp ? true : false)
|
402
|
+
@max_encoded_exp = params[:max_encoded_exp] || @exponent_radix**@fields[:exponent]-1 # maximum regular exponent, encoded
|
403
|
+
if @infinity
|
404
|
+
@infinite_encoded_exp = @nan_encoded_exp || @max_encoded_exp if !@infinite_encoded_exp
|
405
|
+
@max_encoded_exp = @infinite_encoded_exp - 1 if @infinite_encoded_exp.kind_of?(Integer) && @infinite_encoded_exp<=@max_encoded_exp
|
406
|
+
end
|
407
|
+
@nan = params[:nan] || (@nan_encoded_exp ? true : false)
|
408
|
+
if @nan
|
409
|
+
@nan_encoded_exp = @infinite_encoded_exp || @max_encoded_exp if !@nan_encoded_exp
|
410
|
+
@max_encoded_exp = @nan_encoded_exp - 1 if @nan_encoded_exp.kind_of?(Integer) && @nan_encoded_exp<=@max_encoded_exp
|
411
|
+
end
|
412
|
+
|
413
|
+
@exponent_mode = params[:exponent_mode]
|
414
|
+
if @exponent_mode.nil?
|
415
|
+
if params[:bias]
|
416
|
+
@exponent_mode = :excess
|
417
|
+
else
|
418
|
+
@exponent_mode = :radix_complement
|
419
|
+
end
|
420
|
+
end
|
421
|
+
@exponent_digits = @fields[:exponent]
|
422
|
+
|
423
|
+
if @exponent_mode==:excess
|
424
|
+
@bias = params[:bias] || (@exponent_radix**(@fields[:exponent]-1)-1)
|
425
|
+
@bias_mode = params[:bias_mode] || :scientific_significand
|
426
|
+
@min_exp = params[:min_exp]
|
427
|
+
@max_exp = params[:max_exp]
|
428
|
+
case @bias_mode
|
429
|
+
when :integral_significand
|
430
|
+
@integral_bias = @bias
|
431
|
+
@fractional_bias = @integral_bias-@significand_digits
|
432
|
+
@scientific_bias = @fractional_bias+1
|
433
|
+
when :fractional_significand
|
434
|
+
@fractional_bias = @bias
|
435
|
+
@integral_bias = @fractional_bias+@significand_digits
|
436
|
+
@scientific_bias = @fractional_bias+1
|
437
|
+
@min_exp -= @significand_digits if @min_exp
|
438
|
+
@max_exp -= @significand_digits if @max_exp
|
439
|
+
when :scientific_significand
|
440
|
+
@scientific_bias = @bias
|
441
|
+
@fractional_bias = @scientific_bias-1
|
442
|
+
@integral_bias = @fractional_bias+@significand_digits
|
443
|
+
@min_exp -= @significand_digits-1 if @min_exp
|
444
|
+
@max_exp -= @significand_digits-1 if @max_exp
|
445
|
+
end
|
446
|
+
else
|
447
|
+
#@bias_mode = :scientific_significand
|
448
|
+
@min_exp = params[:min_exp] || (-(@exponent_radix**@exponent_digits)/2 + 1)
|
449
|
+
@max_exp = params[:max_exp] || ((@exponent_radix**@exponent_digits)/2 - 1)
|
450
|
+
end
|
451
|
+
@endianness = params[:endianness] || :little_endian
|
452
|
+
|
453
|
+
@min_exp = @min_encoded_exp - @integral_bias if @min_exp.nil?
|
454
|
+
@max_exp = @max_encoded_exp - @integral_bias if @max_exp.nil?
|
455
|
+
|
456
|
+
if @exponent_mode==:excess
|
457
|
+
@integral_max_exp = @max_exp
|
458
|
+
@integral_min_exp = @min_exp
|
459
|
+
@fractional_max_exp = @max_exp+@significand_digits
|
460
|
+
@fractional_min_exp = @min_exp+@significand_digits
|
461
|
+
@scientific_max_exp = @max_exp+@significand_digits-1
|
462
|
+
@scientific_min_exp = @min_exp+@significand_digits-1
|
463
|
+
else
|
464
|
+
@integral_max_exp = @max_exp - (@significand_digits-1)
|
465
|
+
@integral_min_exp = @min_exp - (@significand_digits-1)
|
466
|
+
@fractional_max_exp = @max_exp+1
|
467
|
+
@fractional_min_exp = @min_exp+1
|
468
|
+
@scientific_max_exp = @max_exp
|
469
|
+
@scientific_min_exp = @min_exp
|
470
|
+
end
|
471
|
+
|
472
|
+
@round = params[:round] # || :half_even
|
473
|
+
|
474
|
+
@neg_mode = params[:neg_mode] || :sign_magnitude
|
475
|
+
|
476
|
+
yield self if block_given?
|
477
|
+
|
478
|
+
end
|
479
|
+
|
480
|
+
class <<self
|
481
|
+
# define format properties:
|
482
|
+
# [+radix+] Numeric base
|
483
|
+
# [+significand_digits+] Number of digits in the significand (precision)
|
484
|
+
# [+hidden_bit+] Has the format a hidden bit?
|
485
|
+
# [+parameters+] Parameters used to define the class
|
486
|
+
attr_reader :radix, :significand_digits, :parameters, :hidden_bit
|
487
|
+
# attr_accessor
|
488
|
+
end
|
489
|
+
|
490
|
+
# compute a power of the radix (base)
|
491
|
+
def self.radix_power(n)
|
492
|
+
radix**n
|
493
|
+
end
|
494
|
+
|
495
|
+
# base-10 logarithm of the radix
|
496
|
+
def self.radix_log10
|
497
|
+
Math.log(radix)/Math.log(10)
|
498
|
+
end
|
499
|
+
# radix-base logarithm
|
500
|
+
def self.radix_log(x)
|
501
|
+
Math.log(x)/Math.log(radix)
|
502
|
+
end
|
503
|
+
# number of decimal digits that can be stored in a floating point value and restored unaltered
|
504
|
+
def self.decimal_digits_stored
|
505
|
+
((significand_digits-1)*radix_log10).floor
|
506
|
+
end
|
507
|
+
# number of decimal digits necessary to unambiguosly define any floating point value
|
508
|
+
def self.decimal_digits_necessary
|
509
|
+
(significand_digits*radix_log10).ceil+1
|
510
|
+
end
|
511
|
+
|
512
|
+
# Maximum integer such that 10 raised to that power
|
513
|
+
# is in the range of the normalised floating point numbers
|
514
|
+
def self.decimal_max_exp
|
515
|
+
(radix_max_exp(:fractional_significand)*radix_log10+(1-radix_power(-significand_digits))*radix_log10).floor
|
516
|
+
#(Math.log((1-radix**(significand_digits))*radix**radix_max_exp(:fractional_significand))/Math.log(10)).floor
|
517
|
+
end
|
518
|
+
# Minimum negative integer such that 10 raised to that power
|
519
|
+
# is in the range of the normalised floating point numbers
|
520
|
+
def self.decimal_min_exp
|
521
|
+
(radix_min_exp(:fractional_significand)*radix_log10).ceil
|
522
|
+
end
|
523
|
+
# Stored (integral) value for the minus sign
|
524
|
+
def self.minus_sign_value
|
525
|
+
(-1) % radix
|
526
|
+
end
|
527
|
+
# switch between the encodings of minus and plus
|
528
|
+
def self.switch_sign_value(v)
|
529
|
+
(v==0) ? minus_sign_value : 0
|
530
|
+
end
|
531
|
+
|
532
|
+
def self.sign_to_unit(s)
|
533
|
+
s==0 ? +1 : -1 # ((-1)**s)
|
534
|
+
end
|
535
|
+
|
536
|
+
def self.sign_from_unit(u)
|
537
|
+
u<0 ? minus_sign_value : 0
|
538
|
+
end
|
539
|
+
|
540
|
+
# Rounding mode use for this floating-point format; can be one of:
|
541
|
+
# [<tt>:half_even</tt>] round to nearest with ties toward an even digits
|
542
|
+
# [<tt>:half_up</tt>] round to nearest with ties toward infinity (away from zero)
|
543
|
+
# [<tt>:half_down</tt>] round to nearest with ties toward zero
|
544
|
+
# [<tt>nil</tt>] rounding mode not specified
|
545
|
+
def self.rounding_mode
|
546
|
+
@round
|
547
|
+
end
|
548
|
+
|
549
|
+
def self.minimum_normalized_integral_significand
|
550
|
+
radix_power(significand_digits-1)
|
551
|
+
end
|
552
|
+
def self.maximum_integral_significand
|
553
|
+
radix_power(significand_digits)-1
|
554
|
+
end
|
555
|
+
|
556
|
+
# Maximum exponent
|
557
|
+
def self.radix_max_exp(significand_mode = :scientific_significand)
|
558
|
+
case significand_mode
|
559
|
+
when :integral_significand
|
560
|
+
@integral_max_exp
|
561
|
+
when :fractional_significand
|
562
|
+
@fractional_max_exp
|
563
|
+
when :scientific_significand
|
564
|
+
@scientific_max_exp
|
565
|
+
end
|
566
|
+
end
|
567
|
+
# Mminimum exponent
|
568
|
+
def self.radix_min_exp(significand_mode = :scientific_significand)
|
569
|
+
case significand_mode
|
570
|
+
when :integral_significand
|
571
|
+
@integral_min_exp
|
572
|
+
when :fractional_significand
|
573
|
+
@fractional_min_exp
|
574
|
+
when :scientific_significand
|
575
|
+
@scientific_min_exp
|
576
|
+
end
|
577
|
+
end
|
578
|
+
|
579
|
+
def self.num_class
|
580
|
+
Num[self.radix]
|
581
|
+
end
|
582
|
+
|
583
|
+
def self.context
|
584
|
+
num_class::Context.new(
|
585
|
+
:precision=>significand_digits,
|
586
|
+
:emin=>radix_min_exp(:scientific_significand),
|
587
|
+
:emax=>radix_max_exp(:scientific_significand),
|
588
|
+
:rounding=>@round || :half_even
|
589
|
+
)
|
590
|
+
end
|
591
|
+
|
592
|
+
def to_num
|
593
|
+
s,c,e = split
|
594
|
+
e = 0 if e == :zero
|
595
|
+
form_class.num_class.Num(s,c,e)
|
596
|
+
end
|
597
|
+
|
598
|
+
def self.num(x)
|
599
|
+
new(*x.split)
|
600
|
+
end
|
601
|
+
|
602
|
+
# Endianness of the format (:little_endian, :big_endian or :little_big_endian)
|
603
|
+
def self.endianness
|
604
|
+
@endianness
|
605
|
+
end
|
606
|
+
|
607
|
+
# Does the format support gradual underflow? (denormalized numbers)
|
608
|
+
def self.gradual_underflow?
|
609
|
+
@gradual_underflow
|
610
|
+
end
|
611
|
+
|
612
|
+
# Exponent bias for excess notation exponent encoding
|
613
|
+
# The argument defines the interpretation of the significand and so
|
614
|
+
# determines the actual bias value.
|
615
|
+
def self.bias(significand_mode = :scientific_significand)
|
616
|
+
case significand_mode
|
617
|
+
when :integral_significand
|
618
|
+
@integral_bias
|
619
|
+
when :fractional_significand
|
620
|
+
@fractional_bias
|
621
|
+
when :scientific_significand
|
622
|
+
@scientific_bias
|
623
|
+
end
|
624
|
+
end
|
625
|
+
|
626
|
+
def self.canonicalized(s,m,e,normalize=nil)
|
627
|
+
#puts "s=#{s} m=#{m} e=#{e}"
|
628
|
+
#return [s,m,e]
|
629
|
+
normalize = @normalized if normalize.nil?
|
630
|
+
min_exp = radix_min_exp(:integral_significand)
|
631
|
+
e = min_exp if e==:denormal
|
632
|
+
if m.kind_of?(Integer) && m>0 && e.kind_of?(Integer)
|
633
|
+
while e<min_exp
|
634
|
+
e += 1
|
635
|
+
m /= radix # TODO: round
|
636
|
+
end
|
637
|
+
end
|
638
|
+
s,m,e = normalized(s,m,e) if normalize
|
639
|
+
|
640
|
+
if m==0 && e.kind_of?(Integer)
|
641
|
+
e=:zero
|
642
|
+
end
|
643
|
+
#puts " -> s=#{s} m=#{m} e=#{e}"
|
644
|
+
[s,m,e]
|
645
|
+
end
|
646
|
+
|
647
|
+
|
648
|
+
protected
|
649
|
+
|
650
|
+
|
651
|
+
def self.normalized(s,m,e)
|
652
|
+
if m.kind_of?(Integer) && e.kind_of?(Integer)
|
653
|
+
min_exp = radix_min_exp(:integral_significand)
|
654
|
+
if m>0
|
655
|
+
while m<minimum_normalized_integral_significand && e>min_exp
|
656
|
+
e -= 1
|
657
|
+
m *= radix
|
658
|
+
end
|
659
|
+
if @normalized && !@gradual_underflow
|
660
|
+
if e<=min_exp && m<minimum_normalized_integral_significand
|
661
|
+
m = 0
|
662
|
+
e = :zero
|
663
|
+
end
|
664
|
+
end
|
665
|
+
end
|
666
|
+
end
|
667
|
+
[s,m,e]
|
668
|
+
end
|
669
|
+
|
670
|
+
def self.return_value(s,m,e,normalize=nil)
|
671
|
+
self.new s,m,e,normalize
|
672
|
+
end
|
673
|
+
def self.input_bytes(v)
|
674
|
+
if v.kind_of?(FormatBase)
|
675
|
+
raise "Invalid f.p. format" if v.fp_format!=self
|
676
|
+
v = v.to_bytes
|
677
|
+
elsif !v.kind_of?(Bytes)
|
678
|
+
v = Bytes.new(v)
|
679
|
+
end
|
680
|
+
v
|
681
|
+
end
|
682
|
+
|
683
|
+
public
|
684
|
+
|
685
|
+
|
686
|
+
# Greatest finite normalized floating point number in the representation.
|
687
|
+
# It can be made negative by passing the sign (a so this would be the smallest
|
688
|
+
# finite number).
|
689
|
+
def self.max_value(sign=+1)
|
690
|
+
s = sign
|
691
|
+
m = maximum_integral_significand
|
692
|
+
e = radix_max_exp(:integral_significand)
|
693
|
+
return_value s,m,e, false
|
694
|
+
end
|
695
|
+
# Smallest normalized floating point number greater than zero in the representation.
|
696
|
+
# It can be made negative by passing the sign.
|
697
|
+
def self.min_normalized_value(sign=+1)
|
698
|
+
s = sign
|
699
|
+
m = minimum_normalized_integral_significand
|
700
|
+
e = radix_min_exp(:integral_significand)
|
701
|
+
m += 1 if @hidden_bit && (@min_encoded_exp==@zero_encoded_exp)
|
702
|
+
return_value s,m,e, true
|
703
|
+
end
|
704
|
+
# Smallest floating point number greater than zero in the representation, including
|
705
|
+
# denormalized values if the representation supports it.
|
706
|
+
# It can be made negative by passing the sign.
|
707
|
+
def self.min_value(sign=+1)
|
708
|
+
if @denormal_encoded_exp
|
709
|
+
s = sign
|
710
|
+
m = 1
|
711
|
+
e = :denormal
|
712
|
+
return_value s,m,e, false
|
713
|
+
else
|
714
|
+
min_normalized_value(sign)
|
715
|
+
end
|
716
|
+
end
|
717
|
+
# This is the difference between 1.0 and the smallest floating-point
|
718
|
+
# value greater than 1.0, radix_power(1-significand_precision)
|
719
|
+
def self.epsilon(sign=+1)
|
720
|
+
s = sign
|
721
|
+
#m = 1
|
722
|
+
#e = 1-significand_digits
|
723
|
+
m = minimum_normalized_integral_significand
|
724
|
+
e = 2*(1-significand_digits)
|
725
|
+
return_value s,m,e, false
|
726
|
+
end
|
727
|
+
# The strict epsilon is the smallest value that produces something different from 1.0
|
728
|
+
# wehen added to 1.0. It may be smaller than the general epsilon, because
|
729
|
+
# of the particular rounding rules used with the floating point format.
|
730
|
+
# This is only meaningful when well-defined rules are used for rounding the result
|
731
|
+
# of floating-point addition.
|
732
|
+
# Note that (in pseudo-code):
|
733
|
+
# ((1.0+strict_epsilon)-1.0)==epsilon
|
734
|
+
# TODO: use Flt::Num
|
735
|
+
def self.strict_epsilon(sign=+1, round=nil)
|
736
|
+
round ||= @round
|
737
|
+
s = sign
|
738
|
+
m = minimum_normalized_integral_significand
|
739
|
+
e = 2*(1-significand_digits)
|
740
|
+
# assume radix is even
|
741
|
+
case @round
|
742
|
+
when :down, :floor, :any_rounding, nil
|
743
|
+
e = 2*(1-significand_digits)
|
744
|
+
m = minimum_normalized_integral_significand
|
745
|
+
when :half_even, :half_down
|
746
|
+
e = 1-2*significand_digits
|
747
|
+
m = 1 + radix_power(significand_digits)/2
|
748
|
+
when :half_up
|
749
|
+
e = 1-2*significand_digits
|
750
|
+
m = radix_power(significand_digits)/2
|
751
|
+
when :ceiling, :up, :up05
|
752
|
+
return min_value
|
753
|
+
end
|
754
|
+
return_value sign,m,e
|
755
|
+
|
756
|
+
end
|
757
|
+
|
758
|
+
# This is the maximum relative error corresponding to 1/2 ulp:
|
759
|
+
# (radix/2)*radix_power(-significand_precision) == epsilon/2
|
760
|
+
# This is called "machine epsilon" in [Goldberg]
|
761
|
+
# TODO: use Flt::Num
|
762
|
+
def self.half_epsilon(sign=+1)
|
763
|
+
s = sign
|
764
|
+
m = radix/2
|
765
|
+
e = -significand_digits
|
766
|
+
# normalize:
|
767
|
+
m *= minimum_normalized_integral_significand
|
768
|
+
e -= significand_digits-1
|
769
|
+
return_value s,m,e, false
|
770
|
+
end
|
771
|
+
|
772
|
+
# Floating point representation of zero.
|
773
|
+
def self.zero(sign=+1)
|
774
|
+
return_value sign, 0, :zero
|
775
|
+
end
|
776
|
+
# Floating point representation of infinity.
|
777
|
+
def self.infinity(sign=+1)
|
778
|
+
if @infinite_encoded_exp
|
779
|
+
return_value sign, 0, :infinity
|
780
|
+
else
|
781
|
+
nil
|
782
|
+
end
|
783
|
+
end
|
784
|
+
# Floating point representation of Not-a-Number.
|
785
|
+
def self.nan
|
786
|
+
if @nan_encoded_exp
|
787
|
+
return_value(+1, 0, :nan)
|
788
|
+
else
|
789
|
+
nil
|
790
|
+
end
|
791
|
+
end
|
792
|
+
|
793
|
+
# from methods
|
794
|
+
|
795
|
+
|
796
|
+
def self.nio_read_neutral(neutral)
|
797
|
+
if neutral.special?
|
798
|
+
case neutral.special
|
799
|
+
when :nan
|
800
|
+
return nan
|
801
|
+
when :inf
|
802
|
+
return infinity(neutral.sign=='-' ? -1 : +1)
|
803
|
+
end
|
804
|
+
end
|
805
|
+
if neutral.rep_pos<neutral.digits.length
|
806
|
+
nd = neutral.base==10 ? decimal_digits_necessary : (significand_digits*Math.log(radix)/Math.log(fmt.get_base)).ceil+1
|
807
|
+
neutral = neutral.round(nd,:sig)
|
808
|
+
end
|
809
|
+
f = neutral.digits.to_i(neutral.base)
|
810
|
+
e = neutral.dec_pos-neutral.digits.length
|
811
|
+
case neutral.rounding
|
812
|
+
when :even
|
813
|
+
rounding = :half_even
|
814
|
+
when :inf
|
815
|
+
rounding = :half_up
|
816
|
+
when :zero
|
817
|
+
rounding = :half_down
|
818
|
+
when :truncate
|
819
|
+
rounding = :down
|
820
|
+
end
|
821
|
+
s = (neutral.sign=='-') ? -1 : +1
|
822
|
+
if neutral.base!=radix
|
823
|
+
reader = Flt::Support::Reader.new(:mode=>:fixed)
|
824
|
+
s,f,e = reader.read(context, rounding, s, f, e, neutral.base).split
|
825
|
+
end
|
826
|
+
return_value s,f,e
|
827
|
+
|
828
|
+
end
|
829
|
+
|
830
|
+
def self.from(*args)
|
831
|
+
new(*args)
|
832
|
+
end
|
833
|
+
|
834
|
+
def self.from_bytes(b)
|
835
|
+
return_value(*unpack(b))
|
836
|
+
end
|
837
|
+
|
838
|
+
def self.from_hex(hex)
|
839
|
+
from_bytes Bytes.from_hex(hex)
|
840
|
+
end
|
841
|
+
|
842
|
+
def self.from_number(v, mode=:approx)
|
843
|
+
if v.is_a?(Flt::Num) && v.num_class.radix==self.radix
|
844
|
+
self.num(v)
|
845
|
+
else
|
846
|
+
fmt = mode==:approx ? Nio::Fmt::CONV_FMT : Nio::Fmt::CONV_FMT_STRICT
|
847
|
+
nio_read(v.nio_write(fmt),fmt)
|
848
|
+
end
|
849
|
+
end
|
850
|
+
|
851
|
+
def self.from_text(txt, fmt=Nio::Fmt.default) # ?
|
852
|
+
nio_read(txt,fmt)
|
853
|
+
end
|
854
|
+
|
855
|
+
def self.join(sign,significand,exponent)
|
856
|
+
self.new sign,significand,exponent
|
857
|
+
end
|
858
|
+
|
859
|
+
# Defines a floating-point number from the encoded integral value.
|
860
|
+
def self.from_bits(i)
|
861
|
+
v = Bytes.from_i(i)
|
862
|
+
if v.size<total_bytes
|
863
|
+
fill = (0.chr*(total_bytes-v.size))
|
864
|
+
if @endianness==:little_endian
|
865
|
+
v << fill
|
866
|
+
else
|
867
|
+
v = Bytes.new(fill) + bytes
|
868
|
+
end
|
869
|
+
elsif v.size>total_bytes
|
870
|
+
raise "Invalid floating point value"
|
871
|
+
end
|
872
|
+
from_bytes v
|
873
|
+
end
|
874
|
+
|
875
|
+
# Defines a floating-point number from a text representation of the
|
876
|
+
# encoded integral value in a given base.
|
877
|
+
# Returns a Value.
|
878
|
+
def self.from_bits_text(txt,base)
|
879
|
+
i = Integer.nio_read(txt,Nio::Fmt.base(base))
|
880
|
+
from_bits i
|
881
|
+
end
|
882
|
+
|
883
|
+
# Converts en ancoded floating point number to hash containing
|
884
|
+
# the internal fields that define the number.
|
885
|
+
# Accepts either a Value or a byte String.
|
886
|
+
def self.unpack_fields_hash(v)
|
887
|
+
a = unpack_fields(v)
|
888
|
+
h = {}
|
889
|
+
if @splitted_fields.nil?
|
890
|
+
(0...a.size).each do |i|
|
891
|
+
h[@field_meaning[i]] = a[i]
|
892
|
+
end
|
893
|
+
else
|
894
|
+
|
895
|
+
@fields.each_key do |f|
|
896
|
+
splits = @splitted_fields[f]
|
897
|
+
if splits
|
898
|
+
v = 0
|
899
|
+
k = 1
|
900
|
+
splits.each do |i|
|
901
|
+
v += k*a[i]
|
902
|
+
k *= fields_radix**(@field_lengths[i])
|
903
|
+
end
|
904
|
+
h[f] = v
|
905
|
+
else
|
906
|
+
h[f] = a[@field_meaning.index(f)]
|
907
|
+
end
|
908
|
+
end
|
909
|
+
end
|
910
|
+
h
|
911
|
+
end
|
912
|
+
|
913
|
+
# Produce an encoded floating point value using hash of the internal field values.
|
914
|
+
# Returns a Value.
|
915
|
+
def self.pack_fields_hash(h)
|
916
|
+
if @splitted_fields.nil?
|
917
|
+
pack_fields @field_meaning.collect{|f| h[f]}
|
918
|
+
else
|
919
|
+
flds = [nil]*@field_meaning.size
|
920
|
+
@fields.each_key do |f|
|
921
|
+
splits = @splitted_fields[f]
|
922
|
+
if splits
|
923
|
+
v = h[f]
|
924
|
+
splits.each do |i|
|
925
|
+
k = fields_radix**(@field_lengths[i])
|
926
|
+
flds[i] = v % k
|
927
|
+
v /= k
|
928
|
+
end
|
929
|
+
else
|
930
|
+
flds[@field_meaning.index(f)] = h[f]
|
931
|
+
end
|
932
|
+
end
|
933
|
+
pack_fields flds
|
934
|
+
end
|
935
|
+
end
|
936
|
+
|
937
|
+
# :stopdoc:
|
938
|
+
protected
|
939
|
+
def self.define_fields(field_definitions)
|
940
|
+
|
941
|
+
@field_lengths = []
|
942
|
+
@field_meaning = []
|
943
|
+
@fields = {}
|
944
|
+
@splitted_fields = nil
|
945
|
+
field_definitions.each_slice(2) do |m,l|
|
946
|
+
@field_lengths << l
|
947
|
+
@field_meaning << m
|
948
|
+
if @fields[m].nil?
|
949
|
+
@fields[m] = l
|
950
|
+
else
|
951
|
+
@splitted_fields ||= {}
|
952
|
+
@splitted_fields[m] = [@field_meaning.index(m)]
|
953
|
+
@fields[m] += l
|
954
|
+
@splitted_fields[m] <<= @field_meaning.size-1
|
955
|
+
end
|
956
|
+
end
|
957
|
+
raise "Invalid format" if @splitted_fields && !@splitted_fields_supported
|
958
|
+
end
|
959
|
+
def self.handle_fields(fields)
|
960
|
+
if @fields_handler
|
961
|
+
@fields_handler.call(fields)
|
962
|
+
end
|
963
|
+
end
|
964
|
+
|
965
|
+
# s is the sign of f,e
|
966
|
+
def self.neg_significand_exponent(s,f,e)
|
967
|
+
case @neg_mode
|
968
|
+
when :diminished_radix_complement
|
969
|
+
if exponent_radix==radix
|
970
|
+
f = (radix_power(significand_digits)-1) - f
|
971
|
+
e = (radix_power(exponent_digits)-1) - e
|
972
|
+
else
|
973
|
+
# unsupported case; we could use the exponent radix for
|
974
|
+
# the complement (so for hexadecimal significand/binary exponent we would use binary which is OK)
|
975
|
+
raise "Unsupported format"
|
976
|
+
end
|
977
|
+
when :radix_complement_significand
|
978
|
+
f = ((radix_power(significand_digits)-1) - f + 1) % radix_power(significand_digits)
|
979
|
+
when :radix_complement
|
980
|
+
if exponent_radix==radix
|
981
|
+
if @field_meaning.index(:exponent) < @field_meaning.index(:significand)
|
982
|
+
ls,ms = e,f
|
983
|
+
ls_digits = exponent_digits
|
984
|
+
else
|
985
|
+
ls,ms = f,e
|
986
|
+
ls_digits = significand_digits
|
987
|
+
end
|
988
|
+
comb = ls + ms*radix_power(ls_digits)
|
989
|
+
comb = ((radix_power(significand_digits)-1) - comb + 1) % radix_power(significand_digits)
|
990
|
+
ls = comb % radix_power(ls_digits)
|
991
|
+
ms = comb / radix_power(ls_digits)
|
992
|
+
if @field_meaning.index(:exponent) < @field_meaning.index(:significand)
|
993
|
+
e,f = ls,ms
|
994
|
+
else
|
995
|
+
e,f = ms,ls
|
996
|
+
end
|
997
|
+
else
|
998
|
+
# unsupported case; we could use the exponent radix for
|
999
|
+
# the complement (so for hexadecimal significand/binary exponent we would use binary which is OK)
|
1000
|
+
raise "Unsupported format"
|
1001
|
+
end
|
1002
|
+
end
|
1003
|
+
[f,e]
|
1004
|
+
end
|
1005
|
+
def self.exponent_digits
|
1006
|
+
@fields[:exponent]
|
1007
|
+
end
|
1008
|
+
def self.exponent_radix
|
1009
|
+
@exponent_radix
|
1010
|
+
end
|
1011
|
+
# radix of the field sizes, used for splitted fields
|
1012
|
+
def self.fields_radix
|
1013
|
+
radix
|
1014
|
+
end
|
1015
|
+
|
1016
|
+
def self.decode_exponent(e,mode)
|
1017
|
+
case @exponent_mode
|
1018
|
+
when :excess
|
1019
|
+
case mode
|
1020
|
+
when :integral_significand
|
1021
|
+
e -= @integral_bias
|
1022
|
+
when :fractional_significand
|
1023
|
+
e -= @fractional_bias
|
1024
|
+
when :scientific_significand
|
1025
|
+
e -= @scientific_bias
|
1026
|
+
end
|
1027
|
+
when :radix_complement
|
1028
|
+
n = @fields[:exponent]
|
1029
|
+
v = radix_power(n)
|
1030
|
+
e = e-v if e >= v/2
|
1031
|
+
case mode
|
1032
|
+
when :integral_significand
|
1033
|
+
e -= (significand_digits-1)
|
1034
|
+
when :fractional_significand
|
1035
|
+
e += 1
|
1036
|
+
when :scientific_significand
|
1037
|
+
end
|
1038
|
+
end
|
1039
|
+
e
|
1040
|
+
end
|
1041
|
+
def self.encode_exponent(e,mode)
|
1042
|
+
case @exponent_mode
|
1043
|
+
when :excess
|
1044
|
+
case mode
|
1045
|
+
when :integral_significand
|
1046
|
+
e += @integral_bias
|
1047
|
+
when :fractional_significand
|
1048
|
+
e += @fractional_bias
|
1049
|
+
when :scientific_significand
|
1050
|
+
e += @scientific_bias
|
1051
|
+
end
|
1052
|
+
when :radix_complement
|
1053
|
+
case mode
|
1054
|
+
when :integral_significand
|
1055
|
+
e += (significand_digits-1)
|
1056
|
+
when :fractional_significand
|
1057
|
+
e -= 1
|
1058
|
+
when :scientific_significand
|
1059
|
+
end
|
1060
|
+
n = @fields[:exponent]
|
1061
|
+
v = radix_power(n)
|
1062
|
+
e = e+v if e < 0
|
1063
|
+
end
|
1064
|
+
e
|
1065
|
+
end
|
1066
|
+
end
|
1067
|
+
|
1068
|
+
# Base class for decimal floating point formats
|
1069
|
+
class DecimalFormatBase < FormatBase
|
1070
|
+
# :stopdoc:
|
1071
|
+
def self.define(params)
|
1072
|
+
@hidden_bit = false
|
1073
|
+
super params
|
1074
|
+
end
|
1075
|
+
def self.radix
|
1076
|
+
10
|
1077
|
+
end
|
1078
|
+
def self.radix_power(n)
|
1079
|
+
10**n
|
1080
|
+
end
|
1081
|
+
|
1082
|
+
def self.radix_log10
|
1083
|
+
1
|
1084
|
+
end
|
1085
|
+
def self.radix_log(x)
|
1086
|
+
Math.log(x)/Math.log(10)
|
1087
|
+
end
|
1088
|
+
|
1089
|
+
def self.decimal_digits_stored
|
1090
|
+
significand_digits
|
1091
|
+
end
|
1092
|
+
def self.decimal_digits_necessary
|
1093
|
+
significand_digits
|
1094
|
+
end
|
1095
|
+
def self.decimal_max_exp
|
1096
|
+
radix_max_exp(:scientific_significand)
|
1097
|
+
end
|
1098
|
+
def self.decimal_min_exp
|
1099
|
+
radix_min_exp(:scientific_significand)
|
1100
|
+
end
|
1101
|
+
# :startdoc:
|
1102
|
+
end
|
1103
|
+
|
1104
|
+
# BCD (Binary-Coded-Decimal) floating point formats
|
1105
|
+
class BCDFormat < DecimalFormatBase
|
1106
|
+
# The fields lengths are defined in decimal digits
|
1107
|
+
def self.define(params)
|
1108
|
+
|
1109
|
+
@splitted_fields_supported = false
|
1110
|
+
define_fields params[:fields]
|
1111
|
+
|
1112
|
+
@significand_digits = @fields[:significand]
|
1113
|
+
super params
|
1114
|
+
|
1115
|
+
end
|
1116
|
+
# :stopdoc:
|
1117
|
+
def self.total_nibbles
|
1118
|
+
@field_lengths.inject{|x,y| x+y}
|
1119
|
+
end
|
1120
|
+
def self.total_bytes
|
1121
|
+
(total_nibbles+1)/2
|
1122
|
+
end
|
1123
|
+
def self.total_bits
|
1124
|
+
4*total_nibbles
|
1125
|
+
end
|
1126
|
+
|
1127
|
+
def self.unpack_fields(v)
|
1128
|
+
# bytes have always nibbles in big-endian order
|
1129
|
+
v = input_bytes(v).convert_endianness(@endianness,:little_endian).reverse_byte_nibbles
|
1130
|
+
nibbles = v.to_hex
|
1131
|
+
# now we have a little endian nibble string
|
1132
|
+
nibble_fields = []
|
1133
|
+
i = 0
|
1134
|
+
for l in @field_lengths
|
1135
|
+
nibble_fields << nibbles[i,l]
|
1136
|
+
i += l
|
1137
|
+
end
|
1138
|
+
# now we conver the nibble strings to numbers
|
1139
|
+
i = -1
|
1140
|
+
nibble_fields.collect do |ns|
|
1141
|
+
i+=1
|
1142
|
+
if bcd_field?(i)
|
1143
|
+
if /\A\d+\Z/.match(ns)
|
1144
|
+
ns.reverse.to_i
|
1145
|
+
else
|
1146
|
+
ns.reverse
|
1147
|
+
end
|
1148
|
+
else
|
1149
|
+
ns.reverse.to_i(16)
|
1150
|
+
end
|
1151
|
+
end
|
1152
|
+
end
|
1153
|
+
def self.pack_fields(*fields)
|
1154
|
+
fields = fields[0] if fields.size==1 and fields[0].kind_of?(Array)
|
1155
|
+
handle_fields fields
|
1156
|
+
i = 0
|
1157
|
+
nibbles = ""
|
1158
|
+
for l in @field_lengths
|
1159
|
+
f = fields[i]
|
1160
|
+
unless f.kind_of?(String)
|
1161
|
+
fmt = bcd_field?(i) ? 'd' : 'X'
|
1162
|
+
f = "%0#{l}#{fmt}" % fields[i]
|
1163
|
+
end
|
1164
|
+
nibbles << f.reverse
|
1165
|
+
i += 1
|
1166
|
+
end
|
1167
|
+
Bytes.from_hex(nibbles).reverse_byte_nibbles.convert_endianness(:little_endian,@endianness)
|
1168
|
+
end
|
1169
|
+
# this has beed added to allow some fields to contain binary integers rather than bcd
|
1170
|
+
def self.bcd_field?(i)
|
1171
|
+
true
|
1172
|
+
end
|
1173
|
+
|
1174
|
+
# assume @exponent_mode==:radix_complement
|
1175
|
+
|
1176
|
+
def self.unpack(v)
|
1177
|
+
f = unpack_fields_hash(v)
|
1178
|
+
m = f[:significand]
|
1179
|
+
e = f[:exponent]
|
1180
|
+
s = f[:sign]
|
1181
|
+
m,e = neg_significand_exponent(s,m,e) if s%2==1
|
1182
|
+
s = sign_to_unit(s)
|
1183
|
+
if @infinite_encoded_exp && e==@infinite_encoded_exp
|
1184
|
+
# +-infinity
|
1185
|
+
e = :infinity
|
1186
|
+
elsif @nan_encoded_exp && e==@nan_encoded_exp
|
1187
|
+
# NaN
|
1188
|
+
e = :nan
|
1189
|
+
elsif m==0
|
1190
|
+
# +-zero
|
1191
|
+
e = :zero
|
1192
|
+
else
|
1193
|
+
# normalized number
|
1194
|
+
e = decode_exponent(e, :integral_significand)
|
1195
|
+
end
|
1196
|
+
[s,m,e]
|
1197
|
+
end
|
1198
|
+
|
1199
|
+
def self.pack(s,m,e)
|
1200
|
+
msb = radix_power(@significand_digits-1)
|
1201
|
+
if e==:zero
|
1202
|
+
e = @zero_encoded_exp
|
1203
|
+
m = 0
|
1204
|
+
elsif e==:infinity
|
1205
|
+
e = @infinite_encoded_exp || radix_power(@fields[:exponent])-1
|
1206
|
+
m = 0
|
1207
|
+
elsif e==:nan
|
1208
|
+
e = @nan_encoded_exp || radix_power(@fields[:exponent])-1
|
1209
|
+
#s = -1 # ?
|
1210
|
+
#m = radix_power(@significand_digits-2) if m==0
|
1211
|
+
elsif e==:denormal
|
1212
|
+
e = @denormal_encoded_exp
|
1213
|
+
else
|
1214
|
+
# TODO: try to adjust m to keep e in range if out of valid range
|
1215
|
+
# TODO: reduce m and adjust e if m too big
|
1216
|
+
|
1217
|
+
min_exp = radix_min_exp(:integral_significand)
|
1218
|
+
if m>0
|
1219
|
+
while m<msb && e>min_exp
|
1220
|
+
e -= 1
|
1221
|
+
m *= radix
|
1222
|
+
end
|
1223
|
+
end
|
1224
|
+
if m<msb && @denormal_encoded_exp
|
1225
|
+
e = @denormal_encoded_exp
|
1226
|
+
elsif m==0 # => && @denormal_encoded_exp.nil?
|
1227
|
+
e = 0
|
1228
|
+
else
|
1229
|
+
e = encode_exponent(e, :integral_significand)
|
1230
|
+
end
|
1231
|
+
end
|
1232
|
+
s = sign_from_unit(s)
|
1233
|
+
m,e = neg_significand_exponent(0,m,e) if s%2==1
|
1234
|
+
pack_fields_hash :sign=>s, :significand=>m, :exponent=>e
|
1235
|
+
end
|
1236
|
+
# :startdoc:
|
1237
|
+
end
|
1238
|
+
|
1239
|
+
# DPD (Densely-Packed-Decimal) formats
|
1240
|
+
class DPDFormat < DecimalFormatBase
|
1241
|
+
# The field that need to be defined (with lenghts given in decimal digits) are
|
1242
|
+
# * :sign
|
1243
|
+
# * :combination
|
1244
|
+
# * :exponent_continuation
|
1245
|
+
# * :significand_continuation
|
1246
|
+
def self.define(params)
|
1247
|
+
|
1248
|
+
@splitted_fields_supported = false
|
1249
|
+
define_fields params[:fields]
|
1250
|
+
@internal_field_lengths = @field_lengths
|
1251
|
+
@internal_field_meaning = @field_meaning
|
1252
|
+
@internal_fields = @fields
|
1253
|
+
raise "Unsupported DPD format" unless @internal_fields[:combination]==5 && @internal_fields[:sign]==1 && [0,4,7].include?(@internal_fields[:significand_continuation]%10)
|
1254
|
+
|
1255
|
+
|
1256
|
+
@exponent_bits = 2 + @internal_fields[:exponent_continuation]
|
1257
|
+
|
1258
|
+
extra_bits = (@internal_fields[:significand_continuation] % 10)
|
1259
|
+
extra_digits = (extra_bits==0) ? 0 : ((extra_bits==4) ? 1 : 2)
|
1260
|
+
@significand_digits = 1 + 3*(@internal_fields[:significand_continuation]/10) + extra_digits
|
1261
|
+
|
1262
|
+
define_fields [:type,1,:sign,1,:exponent,@exponent_bits,:significand,@significand_digits]
|
1263
|
+
|
1264
|
+
if params[:bias].nil?
|
1265
|
+
|
1266
|
+
params[:bias_mode] = :scientific_significand
|
1267
|
+
|
1268
|
+
@exp_limit = 3*(2**@internal_fields[:exponent_continuation])-1
|
1269
|
+
|
1270
|
+
params[:max_exp] = @exp_limit/2
|
1271
|
+
params[:min_exp] = -params[:max_exp]
|
1272
|
+
params[:max_exp] += 1 if (@exp_limit%2)==1
|
1273
|
+
params[:bias]= -params[:min_exp]
|
1274
|
+
|
1275
|
+
end
|
1276
|
+
|
1277
|
+
super params
|
1278
|
+
|
1279
|
+
end
|
1280
|
+
|
1281
|
+
# :stopdoc:
|
1282
|
+
def self.total_bits
|
1283
|
+
@internal_field_lengths.inject{|x,y| x+y}
|
1284
|
+
end
|
1285
|
+
def self.total_bytes
|
1286
|
+
(total_bits+7)/8
|
1287
|
+
end
|
1288
|
+
|
1289
|
+
|
1290
|
+
def self.unpack_fields(v)
|
1291
|
+
# convert internal binary fields to bcd decoded fields
|
1292
|
+
a = input_bytes(v).to_bitfields(@internal_field_lengths,@endianness)
|
1293
|
+
h = {}
|
1294
|
+
(0...a.size).each do |i|
|
1295
|
+
h[@internal_field_meaning[i]] = a[i]
|
1296
|
+
end
|
1297
|
+
|
1298
|
+
i_sign = h[:sign]
|
1299
|
+
i_combination = h[:combination]
|
1300
|
+
i_exponent_continuation = h[:exponent_continuation]
|
1301
|
+
i_significand_continuation = h[:significand_continuation]
|
1302
|
+
|
1303
|
+
|
1304
|
+
type = nil
|
1305
|
+
sign = i_sign==0 ? 0 : 9
|
1306
|
+
|
1307
|
+
a,b,c,d,e = ("%05B"%i_combination).split('').collect{|bit| bit.to_i}
|
1308
|
+
|
1309
|
+
exp_msb = 0
|
1310
|
+
sig_msd = 0
|
1311
|
+
|
1312
|
+
if a==0 || b==0
|
1313
|
+
exp_msb = (a<<1)|b
|
1314
|
+
sig_msd = (c<<2)|(d<<1)|e
|
1315
|
+
elsif c==0 || d==0
|
1316
|
+
exp_msb = (c<<1)|d
|
1317
|
+
sig_msd = (1<<3)|e
|
1318
|
+
elsif e==0
|
1319
|
+
type = :infinity
|
1320
|
+
else
|
1321
|
+
type = :nan
|
1322
|
+
end
|
1323
|
+
|
1324
|
+
|
1325
|
+
hex_sig = sig_msd.to_s
|
1326
|
+
hex_sig << dpd_to_hexbcd(i_significand_continuation,@internal_fields[:significand_continuation])
|
1327
|
+
significand = hex_sig.to_i
|
1328
|
+
|
1329
|
+
exponent = i_exponent_continuation | (exp_msb << (@exponent_bits-2))
|
1330
|
+
[type,sign,exponent,significand]
|
1331
|
+
end
|
1332
|
+
def self.pack_fields(*fields)
|
1333
|
+
fields = fields[0] if fields.size==1 and fields[0].kind_of?(Array)
|
1334
|
+
handle_fields fields
|
1335
|
+
type,sign,exponent,significand = fields
|
1336
|
+
|
1337
|
+
sig_hex = "%0#{@significand_digits-1}d"%significand
|
1338
|
+
sig_cont_bits = 4*(@significand_digits-1)
|
1339
|
+
sig_msd = sig_hex[0,1].to_i
|
1340
|
+
i_significand_continuation,bits = hexbcd_to_dpd(sig_hex[1..-1])
|
1341
|
+
|
1342
|
+
|
1343
|
+
|
1344
|
+
exp_msb = exponent>>(@exponent_bits-2)
|
1345
|
+
i_exponent_continuation = exponent&((1<<(@exponent_bits-2))-1)
|
1346
|
+
|
1347
|
+
i_sign = ((sign==0) ? 0 : 1)
|
1348
|
+
|
1349
|
+
|
1350
|
+
case type
|
1351
|
+
when :infinity
|
1352
|
+
i_combination = 0x1E
|
1353
|
+
when :nan
|
1354
|
+
i_combination = 0x1F
|
1355
|
+
else
|
1356
|
+
if sig_msd&0x8==0
|
1357
|
+
i_combination = sig_msd|(exp_msb<<3)
|
1358
|
+
else
|
1359
|
+
i_combination = sig_msd|(1<<4)|(exp_msb<<1)
|
1360
|
+
end
|
1361
|
+
end
|
1362
|
+
h = {:sign=>i_sign, :combination=>i_combination, :exponent_continuation=>i_exponent_continuation, :significand_continuation=>i_significand_continuation}
|
1363
|
+
fields = @internal_field_meaning.collect{|f| h[f]}
|
1364
|
+
Bytes.from_bitfields(@internal_field_lengths,fields,@endianness)
|
1365
|
+
end
|
1366
|
+
|
1367
|
+
|
1368
|
+
def self.unpack(v)
|
1369
|
+
f = unpack_fields_hash(v)
|
1370
|
+
m = f[:significand]
|
1371
|
+
e = f[:exponent]
|
1372
|
+
s = f[:sign]
|
1373
|
+
t = f[:type]
|
1374
|
+
m,e = neg_significand_exponent(s,m,e) if s%2==1
|
1375
|
+
if m==0
|
1376
|
+
# +-zero
|
1377
|
+
e = :zero
|
1378
|
+
elsif t==:infinity
|
1379
|
+
# +-inifinity
|
1380
|
+
e = :infinity
|
1381
|
+
elsif t==:nan
|
1382
|
+
# NaN
|
1383
|
+
e = :nan
|
1384
|
+
else
|
1385
|
+
# normalized number
|
1386
|
+
e = decode_exponent(e, :integral_significand)
|
1387
|
+
end
|
1388
|
+
s = sign_to_unit(s)
|
1389
|
+
[s,m,e]
|
1390
|
+
end
|
1391
|
+
|
1392
|
+
def self.pack(s,m,e)
|
1393
|
+
msb = radix_power(@significand_digits-1)
|
1394
|
+
t = nil
|
1395
|
+
if e==:zero
|
1396
|
+
e = @zero_encoded_exp
|
1397
|
+
m = 0
|
1398
|
+
elsif e==:infinity
|
1399
|
+
e = @infinite_encoded_exp || radix_power(@fields[:exponent])-1
|
1400
|
+
m = 0
|
1401
|
+
t = :infinity
|
1402
|
+
elsif e==:nan
|
1403
|
+
t = :nan
|
1404
|
+
e = 0
|
1405
|
+
s = 0
|
1406
|
+
m = 0
|
1407
|
+
elsif e==:denormal
|
1408
|
+
e = @denormal_encoded_exp || @zero_encoded_exp
|
1409
|
+
else
|
1410
|
+
# TODO: try to adjust m to keep e in range if out of valid range
|
1411
|
+
# TODO: reduce m and adjust e if m too big
|
1412
|
+
|
1413
|
+
min_exp = radix_min_exp(:integral_significand)
|
1414
|
+
if m>0 && false
|
1415
|
+
while m<msb && e>min_exp
|
1416
|
+
e -= 1
|
1417
|
+
m *= radix
|
1418
|
+
end
|
1419
|
+
end
|
1420
|
+
if m<msb && @denormal_encoded_exp && false
|
1421
|
+
e = @denormal_encoded_exp
|
1422
|
+
elsif m==0 # => && @denormal_encoded_exp.nil?
|
1423
|
+
e = 0
|
1424
|
+
else
|
1425
|
+
e = encode_exponent(e, :integral_significand)
|
1426
|
+
end
|
1427
|
+
end
|
1428
|
+
s = sign_from_unit(s)
|
1429
|
+
m,e = neg_significand_exponent(0,m,e) if s%2==1
|
1430
|
+
pack_fields_hash :sign=>s, :significand=>m, :exponent=>e, :type=>t
|
1431
|
+
end
|
1432
|
+
|
1433
|
+
# :startdoc:
|
1434
|
+
|
1435
|
+
|
1436
|
+
end
|
1437
|
+
|
1438
|
+
# This is a base class for formats that specify the field lengths in bits
|
1439
|
+
class FieldsInBitsFormatBase < FormatBase
|
1440
|
+
# :stopdoc:
|
1441
|
+
def self.fields_radix
|
1442
|
+
2
|
1443
|
+
end
|
1444
|
+
def self.unpack_fields(v)
|
1445
|
+
input_bytes(v).to_bitfields(@field_lengths,@endianness)
|
1446
|
+
end
|
1447
|
+
def self.pack_fields(*fields)
|
1448
|
+
fields = fields[0] if fields.size==1 and fields[0].kind_of?(Array)
|
1449
|
+
handle_fields fields
|
1450
|
+
Bytes.from_bitfields(@field_lengths,fields,@endianness)
|
1451
|
+
end
|
1452
|
+
# :startdoc:
|
1453
|
+
end
|
1454
|
+
|
1455
|
+
# Binary floating point formats
|
1456
|
+
class BinaryFormat < FieldsInBitsFormatBase
|
1457
|
+
# a hidden bit can be define with :hidden_bit
|
1458
|
+
def self.define(params)
|
1459
|
+
@hidden_bit = params[:hidden_bit]
|
1460
|
+
@hidden_bit = true if @hidden_bit.nil?
|
1461
|
+
|
1462
|
+
@splitted_fields_supported = true
|
1463
|
+
define_fields params[:fields]
|
1464
|
+
|
1465
|
+
@significand_digits = @fields[:significand] + (@hidden_bit ? 1 : 0)
|
1466
|
+
super params
|
1467
|
+
|
1468
|
+
end
|
1469
|
+
|
1470
|
+
# :stopdoc:
|
1471
|
+
|
1472
|
+
def self.radix
|
1473
|
+
2
|
1474
|
+
end
|
1475
|
+
def self.radix_power(n)
|
1476
|
+
if n>=0
|
1477
|
+
1 << n
|
1478
|
+
else
|
1479
|
+
2**n
|
1480
|
+
end
|
1481
|
+
end
|
1482
|
+
|
1483
|
+
def self.total_bits
|
1484
|
+
@field_lengths.inject{|x,y| x+y}
|
1485
|
+
end
|
1486
|
+
def self.total_bytes
|
1487
|
+
(total_bits+7)/8
|
1488
|
+
end
|
1489
|
+
|
1490
|
+
def self.unpack(v)
|
1491
|
+
f = unpack_fields_hash(v)
|
1492
|
+
m = f[:significand]
|
1493
|
+
e = f[:exponent]
|
1494
|
+
s = f[:sign]
|
1495
|
+
m,e = neg_significand_exponent(s,m,e) if s%2==1
|
1496
|
+
if (m==0 && !@hidden_bit) ||
|
1497
|
+
(m==0 && (e==@zero_encoded_exp || e==@denormal_encoded_exp)) ||
|
1498
|
+
(e==@zero_encoded_exp && @min_encoded_exp>@zero_encoded_exp && !@denormal_encoded_exp)
|
1499
|
+
# +-zero
|
1500
|
+
e = :zero
|
1501
|
+
elsif (e==@denormal_encoded_exp)
|
1502
|
+
e = decode_exponent(e, :integral_significand)
|
1503
|
+
e += 1 if @denormal_encoded_exp==@zero_encoded_exp
|
1504
|
+
elsif @infinite_encoded_exp && e==@infinite_encoded_exp && m==0
|
1505
|
+
# +-inifinity
|
1506
|
+
e = :infinity
|
1507
|
+
elsif @nan_encoded_exp && e==@nan_encoded_exp && m!=0
|
1508
|
+
# NaN
|
1509
|
+
e = :nan
|
1510
|
+
else
|
1511
|
+
# normalized number
|
1512
|
+
e = decode_exponent(e, :integral_significand)
|
1513
|
+
m |= radix_power(@significand_digits-1) if @hidden_bit
|
1514
|
+
end
|
1515
|
+
s = sign_to_unit(s)
|
1516
|
+
[s,m,e]
|
1517
|
+
end
|
1518
|
+
|
1519
|
+
def self.pack(s,m,e)
|
1520
|
+
msb = radix_power(@significand_digits-1)
|
1521
|
+
|
1522
|
+
if e==:zero
|
1523
|
+
e = @zero_encoded_exp || @denormal_encoded_exp
|
1524
|
+
m = 0
|
1525
|
+
elsif e==:infinity
|
1526
|
+
e = @infinite_encoded_exp || radix_power(@fields[:exponent])-1
|
1527
|
+
m = 0
|
1528
|
+
elsif e==:nan
|
1529
|
+
e = @nan_encoded_exp || radix_power(@fields[:exponent])-1
|
1530
|
+
s = minus_sign_value # ?
|
1531
|
+
m = radix_power(@significand_digits-2) if m==0
|
1532
|
+
elsif e==:denormal
|
1533
|
+
e = @denormal_encoded_exp
|
1534
|
+
else
|
1535
|
+
# TODO: try to adjust m to keep e in range if out of valid range
|
1536
|
+
# TODO: reduce m and adjust e if m too big
|
1537
|
+
|
1538
|
+
min_exp = radix_min_exp(:integral_significand)
|
1539
|
+
if m>0
|
1540
|
+
while m<msb && e>min_exp
|
1541
|
+
e -= 1
|
1542
|
+
m <<= 1 # m *= radix
|
1543
|
+
end
|
1544
|
+
end
|
1545
|
+
if m<msb && @denormal_encoded_exp
|
1546
|
+
e = @denormal_encoded_exp
|
1547
|
+
elsif m==0 # => && @denormal_encoded_exp.nil?
|
1548
|
+
e = 0
|
1549
|
+
else
|
1550
|
+
m &= (radix_power(@significand_digits-1)-1) if @hidden_bit
|
1551
|
+
e = encode_exponent(e, :integral_significand)
|
1552
|
+
end
|
1553
|
+
end
|
1554
|
+
s = sign_from_unit(s)
|
1555
|
+
m,e = neg_significand_exponent(0,m,e) if s%2==1
|
1556
|
+
pack_fields_hash :sign=>s, :significand=>m, :exponent=>e
|
1557
|
+
end
|
1558
|
+
# :startdoc:
|
1559
|
+
|
1560
|
+
end
|
1561
|
+
|
1562
|
+
# Hexadecimal floating point format
|
1563
|
+
class HexadecimalFormat < FieldsInBitsFormatBase
|
1564
|
+
def self.define(params)
|
1565
|
+
@hidden_bit = false
|
1566
|
+
@splitted_fields_supported = true
|
1567
|
+
define_fields params[:fields]
|
1568
|
+
@significand_digits = @fields[:significand]/4
|
1569
|
+
params[:exponent_radix] = 2
|
1570
|
+
super params
|
1571
|
+
end
|
1572
|
+
|
1573
|
+
# :stopdoc:
|
1574
|
+
|
1575
|
+
def self.radix
|
1576
|
+
16
|
1577
|
+
end
|
1578
|
+
def self.fields_radix
|
1579
|
+
exponent_radix
|
1580
|
+
end
|
1581
|
+
|
1582
|
+
def self.total_bits
|
1583
|
+
@field_lengths.inject{|x,y| x+y}
|
1584
|
+
end
|
1585
|
+
def self.total_bytes
|
1586
|
+
(total_bits+7)/8
|
1587
|
+
end
|
1588
|
+
|
1589
|
+
|
1590
|
+
def self.unpack(v)
|
1591
|
+
f = unpack_fields_hash(v)
|
1592
|
+
m = f[:significand]
|
1593
|
+
e = f[:exponent]
|
1594
|
+
s = f[:sign]
|
1595
|
+
m,e = neg_significand_exponent(s,m,e) if s%2==1
|
1596
|
+
if m==0
|
1597
|
+
# +-zero
|
1598
|
+
e = :zero
|
1599
|
+
elsif @infinite_encoded_exp && e==@infinite_encoded_exp && m==0
|
1600
|
+
# +-inifinity
|
1601
|
+
e = :infinity
|
1602
|
+
elsif @nan_encoded_exp && e==@nan_encoded_exp && m!=0
|
1603
|
+
# NaN
|
1604
|
+
e = :nan
|
1605
|
+
else
|
1606
|
+
# normalized number
|
1607
|
+
e = decode_exponent(e, :integral_significand)
|
1608
|
+
end
|
1609
|
+
s = sign_to_unit(s)
|
1610
|
+
[s,m,e]
|
1611
|
+
end
|
1612
|
+
|
1613
|
+
def self.pack(s,m,e)
|
1614
|
+
msb = radix_power(@significand_digits-1)
|
1615
|
+
|
1616
|
+
if e==:zero
|
1617
|
+
e = @zero_encoded_exp
|
1618
|
+
m = 0
|
1619
|
+
elsif e==:infinity
|
1620
|
+
e = @infinite_encoded_exp || radix_power(@fields[:exponent])-1
|
1621
|
+
m = 0
|
1622
|
+
elsif e==:nan
|
1623
|
+
e = @nan_encoded_exp || radix_power(@fields[:exponent])-1
|
1624
|
+
s = minus_sign_value # ?
|
1625
|
+
m = radix_power(@significand_digits-2) if m==0
|
1626
|
+
elsif e==:denormal
|
1627
|
+
e = @denormal_encoded_exp || @zero_encoded_exp
|
1628
|
+
else
|
1629
|
+
# TODO: try to adjust m to keep e in range if out of valid range
|
1630
|
+
# TODO: reduce m and adjust e if m too big
|
1631
|
+
|
1632
|
+
min_exp = radix_min_exp(:integral_significand)
|
1633
|
+
if m>0
|
1634
|
+
while m<msb && e>min_exp
|
1635
|
+
e -= 1
|
1636
|
+
m <<= 4 # m *= radix
|
1637
|
+
end
|
1638
|
+
end
|
1639
|
+
if m<msb && @denormal_encoded_exp
|
1640
|
+
e = @denormal_encoded_exp
|
1641
|
+
elsif m==0 # => && @denormal_encoded_exp.nil?
|
1642
|
+
e = 0
|
1643
|
+
else
|
1644
|
+
e = encode_exponent(e, :integral_significand)
|
1645
|
+
end
|
1646
|
+
end
|
1647
|
+
s = sign_from_unit(s)
|
1648
|
+
m,e = neg_significand_exponent(0,m,e) if s%2==1
|
1649
|
+
pack_fields_hash :sign=>s, :significand=>m, :exponent=>e
|
1650
|
+
end
|
1651
|
+
|
1652
|
+
|
1653
|
+
def self.minus_sign_value
|
1654
|
+
(-1) % 2
|
1655
|
+
end
|
1656
|
+
|
1657
|
+
def self.exponent_digits
|
1658
|
+
@fields[exponent]/4
|
1659
|
+
end
|
1660
|
+
|
1661
|
+
# :startdoc:
|
1662
|
+
|
1663
|
+
end
|
1664
|
+
|
1665
|
+
|
1666
|
+
def -@
|
1667
|
+
minus
|
1668
|
+
end
|
1669
|
+
def +(v)
|
1670
|
+
# TODO: coercion
|
1671
|
+
if v.form_class==form_class
|
1672
|
+
form_class.arithmetic do |t|
|
1673
|
+
x = to(t,:exact) + v.to(t,:exact)
|
1674
|
+
form_class.from_number(x,:exact)
|
1675
|
+
end
|
1676
|
+
else
|
1677
|
+
# TODO
|
1678
|
+
end
|
1679
|
+
end
|
1680
|
+
def /(v)
|
1681
|
+
# TODO: coercion
|
1682
|
+
if v.form_class==form_class
|
1683
|
+
form_class.arithmetic do |t|
|
1684
|
+
x = to(t,:exact) / v.to(t,:exact)
|
1685
|
+
form_class.from_number(x,:exact)
|
1686
|
+
end
|
1687
|
+
else
|
1688
|
+
# TODO
|
1689
|
+
end
|
1690
|
+
end
|
1691
|
+
def -(v)
|
1692
|
+
# TODO: coercion
|
1693
|
+
if v.form_class==form_class
|
1694
|
+
form_class.arithmetic do |t|
|
1695
|
+
x = to(t,:exact) - v.to(t,:exact)
|
1696
|
+
form_class.from_number(x,:exact)
|
1697
|
+
end
|
1698
|
+
else
|
1699
|
+
# TODO
|
1700
|
+
end
|
1701
|
+
end
|
1702
|
+
def *(v)
|
1703
|
+
# TODO: coercion
|
1704
|
+
if v.form_class==form_class
|
1705
|
+
form_class.arithmetic do |t|
|
1706
|
+
x = to(t,:exact) * v.to(t,:exact)
|
1707
|
+
form_class.from_number(x,:exact)
|
1708
|
+
end
|
1709
|
+
else
|
1710
|
+
# TODO
|
1711
|
+
end
|
1712
|
+
end
|
1713
|
+
|
1714
|
+
class FormatBase
|
1715
|
+
# Type used internally for arithmetic operations.
|
1716
|
+
def self.arithmetic_type
|
1717
|
+
num_class
|
1718
|
+
# Rational
|
1719
|
+
end
|
1720
|
+
# Set up the arithmetic environment; the arithmetic type is passed to the block.
|
1721
|
+
def self.arithmetic
|
1722
|
+
at = arithmetic_type
|
1723
|
+
if at.ancestors.include?(Flt::Num)
|
1724
|
+
at.context(self.context) do
|
1725
|
+
yield at
|
1726
|
+
end
|
1727
|
+
else
|
1728
|
+
# Could also use Flt::Decimal with decimal_digits_necessary, decimal_max_exp(:integral_significand), ...
|
1729
|
+
yield at
|
1730
|
+
end
|
1731
|
+
end
|
1732
|
+
end
|
1733
|
+
|
1734
|
+
# Class to define formats such as "double double" by pairing two floating-point
|
1735
|
+
# values which define a higher precision value by its sum.
|
1736
|
+
# The :half parameter is a format class that defines the type of each part
|
1737
|
+
# of the numbers.
|
1738
|
+
# The formats defined here have a fixed precision, although these formats
|
1739
|
+
# can actually have a variable precision.
|
1740
|
+
# For binary formats there's an option to gain one bit of precision
|
1741
|
+
# by adjusting the sign of the second number. This is enabled by the
|
1742
|
+
# :extra_prec option.
|
1743
|
+
# For example, the "double double" format used in PowerPC is this
|
1744
|
+
# Flt.define :DoubleDouble, DoubleFormat, :half=>IEEE_binary64, :extra_prec=>true
|
1745
|
+
# Although this has a fixed 107 bits precision, the format as used in
|
1746
|
+
# the PowerPC can have greater precision for specific values (by having
|
1747
|
+
# greater separation between the exponents of both halves)
|
1748
|
+
class DoubleFormat < FormatBase
|
1749
|
+
|
1750
|
+
def self.define(params)
|
1751
|
+
@half = params[:half]
|
1752
|
+
params = @half.parameters.merge(params)
|
1753
|
+
if @half.radix==2
|
1754
|
+
@extra_prec = params[:extra_prec]
|
1755
|
+
else
|
1756
|
+
@extra_prec = false
|
1757
|
+
end
|
1758
|
+
params[:significand_digits] = 2*@half.significand_digits
|
1759
|
+
params[:significand_digits] += 1 if @extra_prec
|
1760
|
+
@significand_digits = params[:significand_digits]
|
1761
|
+
|
1762
|
+
@hidden_bit = params[:hidden_bit] = @half.hidden_bit
|
1763
|
+
|
1764
|
+
fields1 = []
|
1765
|
+
fields2 = []
|
1766
|
+
params[:fields].each_slice(2) do |s,v|
|
1767
|
+
fields1 << s # (s.to_s+"_1").to_sym
|
1768
|
+
fields1 << v
|
1769
|
+
fields2 << (s.to_s+"_2").to_sym
|
1770
|
+
fields2 << v
|
1771
|
+
end
|
1772
|
+
params[:fields] = fields1 + fields2
|
1773
|
+
|
1774
|
+
define_fields params[:fields]
|
1775
|
+
|
1776
|
+
super params
|
1777
|
+
end
|
1778
|
+
|
1779
|
+
def self.radix
|
1780
|
+
@half.radix
|
1781
|
+
end
|
1782
|
+
|
1783
|
+
def self.half
|
1784
|
+
@half
|
1785
|
+
end
|
1786
|
+
|
1787
|
+
def self.unpack(v)
|
1788
|
+
sz = @half.total_bytes
|
1789
|
+
v1 = @half.unpack(v[0...sz])
|
1790
|
+
v2 = @half.unpack(v[sz..-1])
|
1791
|
+
if v1.last == :nan
|
1792
|
+
nan
|
1793
|
+
elsif v1.last == :infinity
|
1794
|
+
infinity(v1.sign)
|
1795
|
+
else
|
1796
|
+
v2 = @half.zero.split if @half.new(*v1).subnormal?
|
1797
|
+
params = v1 + v2
|
1798
|
+
join_fp(*params)
|
1799
|
+
end
|
1800
|
+
end
|
1801
|
+
|
1802
|
+
def self.pack(s,m,e)
|
1803
|
+
if e.kind_of?(Symbol)
|
1804
|
+
f1 = @half.pack(s,m,e)
|
1805
|
+
f2 = @half.pack(+1,0,:zero)
|
1806
|
+
else
|
1807
|
+
s1,m1,e1,s2,m2,e2 = split_fp(s,m,e)
|
1808
|
+
f1 = @half.pack(s1,m1,e1)
|
1809
|
+
f2 = @half.pack(s2,m2,e2)
|
1810
|
+
end
|
1811
|
+
f1+f2
|
1812
|
+
end
|
1813
|
+
|
1814
|
+
def split_halfs
|
1815
|
+
b = to_bytes
|
1816
|
+
sz = form_class.half.total_bytes
|
1817
|
+
b1 = b[0...sz]
|
1818
|
+
b2 = b[sz..-1]
|
1819
|
+
[form_class.half.from_bytes(b1), form_class.half.from_bytes(b2)]
|
1820
|
+
end
|
1821
|
+
|
1822
|
+
def self.join_halfs(h1,h2)
|
1823
|
+
self.from_bytes(h1.to_bytes+h2.to_bytes)
|
1824
|
+
end
|
1825
|
+
|
1826
|
+
def self.total_nibbles
|
1827
|
+
2*total_bytes
|
1828
|
+
end
|
1829
|
+
def self.total_bytes
|
1830
|
+
2*@half.total_bytes
|
1831
|
+
end
|
1832
|
+
def self.total_bits
|
1833
|
+
8*total_bytes
|
1834
|
+
end
|
1835
|
+
|
1836
|
+
private
|
1837
|
+
def self.split_fp(s,m,e)
|
1838
|
+
n = @half.significand_digits
|
1839
|
+
if @half.radix==2
|
1840
|
+
if @extra_prec
|
1841
|
+
if (m & (1<<n))==0 # m.to_bits[n] == 0
|
1842
|
+
m1 = m >> (n+1) # m/2**(n+1)
|
1843
|
+
e1 = e + n + 1
|
1844
|
+
s1 = s
|
1845
|
+
m2 = m & ((1<<n) - 1) # m%2**n
|
1846
|
+
e2 = e
|
1847
|
+
s2 = s
|
1848
|
+
else
|
1849
|
+
m1 = (m >> (n+1)) + 1 # m/2**(n+1) + 1
|
1850
|
+
e1 = e + n + 1
|
1851
|
+
s1 = s
|
1852
|
+
if m1>=(1<<n) # 2**n
|
1853
|
+
m1 >>= 1
|
1854
|
+
e1 += 1
|
1855
|
+
end
|
1856
|
+
if m2==0
|
1857
|
+
m2 = (1<<(n-1)) # 2**(n-1)
|
1858
|
+
e2 = e+1
|
1859
|
+
s2 = -s
|
1860
|
+
else
|
1861
|
+
m2 = -((m & ((1<<n) - 1)) - (1<<n)) # m%2**n - 2**n
|
1862
|
+
e2 = e
|
1863
|
+
s2 = -s
|
1864
|
+
end
|
1865
|
+
end
|
1866
|
+
else # m has 2*n bits
|
1867
|
+
m1 = m >> n
|
1868
|
+
e1 = e + n
|
1869
|
+
s1 = s
|
1870
|
+
m2 = m & ((1<<n) - 1) # m%2**n
|
1871
|
+
e2 = e
|
1872
|
+
s2 = s
|
1873
|
+
end
|
1874
|
+
else
|
1875
|
+
m1 = m / @half.radix_power(n)
|
1876
|
+
e1 = e + n
|
1877
|
+
s1 = s
|
1878
|
+
m2 = m % @half.radix_power(n)
|
1879
|
+
e2 = e
|
1880
|
+
s2 = s
|
1881
|
+
end
|
1882
|
+
[s1,m1,e1,s2,m2,e2]
|
1883
|
+
end
|
1884
|
+
|
1885
|
+
def FormatBase.join_fp(s1,m1,e1,s2,m2,e2)
|
1886
|
+
if m2==0 || e2==:zero
|
1887
|
+
s = s1
|
1888
|
+
m = m1
|
1889
|
+
e = e1
|
1890
|
+
else
|
1891
|
+
m = s1*(m1<<(e1-e2)) + s2*m2
|
1892
|
+
e = e2
|
1893
|
+
end
|
1894
|
+
if m<0
|
1895
|
+
s = -1
|
1896
|
+
m = -m
|
1897
|
+
else
|
1898
|
+
s = +1
|
1899
|
+
end
|
1900
|
+
if m!=0 && e1.kind_of?(Numeric)
|
1901
|
+
# normalize
|
1902
|
+
nn = significand_digits
|
1903
|
+
while m >= (1 << nn)
|
1904
|
+
m >>= 1
|
1905
|
+
e += 1
|
1906
|
+
end
|
1907
|
+
while m>0 && m < (1 << (nn-1))
|
1908
|
+
m <<= 1
|
1909
|
+
e -= 1
|
1910
|
+
end
|
1911
|
+
end
|
1912
|
+
[s,m,e]
|
1913
|
+
end
|
1914
|
+
|
1915
|
+
|
1916
|
+
end
|
1917
|
+
|
1918
|
+
|
1919
|
+
|
1920
|
+
module_function
|
1921
|
+
|
1922
|
+
def define(*arguments)
|
1923
|
+
raise "Invalid number of arguments for Flt definitions." if arguments.size<2 || arguments.size>3
|
1924
|
+
if arguments.first.kind_of?(Class)
|
1925
|
+
base,name,parameters = arguments
|
1926
|
+
elsif arguments[1].kind_of?(Class)
|
1927
|
+
name,base,parameters = arguments
|
1928
|
+
else
|
1929
|
+
name,parameters = arguments
|
1930
|
+
base = parameters[:base] || FormatBase
|
1931
|
+
end
|
1932
|
+
Flt.const_set name, cls=Class.new(base)
|
1933
|
+
cls.define parameters
|
1934
|
+
constructor = lambda { |*args| cls.new(*args) }
|
1935
|
+
Flt.send :define_method,name,constructor
|
1936
|
+
Flt.send :module_function, name
|
1937
|
+
yield cls if block_given?
|
1938
|
+
end
|
1939
|
+
|
1940
|
+
|
1941
|
+
|
1942
|
+
def convert_bytes(bytes,from_format,to_format)
|
1943
|
+
from_format.from_bytes(bytes).convert_to(to_format)
|
1944
|
+
end
|
1945
|
+
|
1946
|
+
|
1947
|
+
|
1948
|
+
|
1949
|
+
end
|
1950
|
+
|