nio 0.2.3 → 0.2.4
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +8 -0
- data/Manifest.txt +1 -2
- data/README.txt +519 -560
- data/Rakefile +1 -0
- data/lib/nio.rb +6 -7
- data/lib/nio/fmt.rb +378 -437
- data/lib/nio/repdec.rb +31 -31
- data/lib/nio/rtnlzr.rb +88 -81
- data/lib/nio/sugar.rb +69 -99
- data/lib/nio/version.rb +1 -1
- data/tasks/nuweb.rake +53 -33
- data/test/{test_helper.rb → helper.rb} +5 -0
- data/test/test_fmt.rb +98 -100
- data/test/test_repdec.rb +3 -5
- data/test/test_rtnlzr.rb +66 -44
- data/test/test_tools.rb +2 -2
- metadata +17 -7
- data/lib/nio/flttol.rb +0 -669
data/Rakefile
CHANGED
data/lib/nio.rb
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
$:.unshift File.dirname(__FILE__)
|
2
|
-
|
3
|
-
require 'nio/version'
|
4
|
-
require 'nio/tools'
|
5
|
-
require 'nio/
|
6
|
-
require 'nio/
|
7
|
-
require 'nio/
|
8
|
-
require 'nio/fmt'
|
2
|
+
|
3
|
+
require 'nio/version'
|
4
|
+
require 'nio/tools'
|
5
|
+
require 'nio/repdec'
|
6
|
+
require 'nio/rtnlzr'
|
7
|
+
require 'nio/fmt'
|
data/lib/nio/fmt.rb
CHANGED
@@ -18,10 +18,12 @@ require 'rational'
|
|
18
18
|
|
19
19
|
require 'bigdecimal'
|
20
20
|
|
21
|
+
require 'flt'
|
22
|
+
|
21
23
|
module Nio
|
22
24
|
|
23
25
|
# positional notation, unformatted numeric literal: used as intermediate form
|
24
|
-
class NeutralNum
|
26
|
+
class NeutralNum
|
25
27
|
include StateEquivalent
|
26
28
|
def initialize(s='',d='',p=nil,r=nil,dgs=DigitsDef.base(10), inexact=false, round=:inf)
|
27
29
|
set s,d,p,r,dgs,dgs, inexact, round
|
@@ -40,7 +42,7 @@ module Nio
|
|
40
42
|
@inexact = inexact
|
41
43
|
@special = nil
|
42
44
|
@rounding = rounding
|
43
|
-
trimZeros unless inexact
|
45
|
+
trimZeros unless inexact
|
44
46
|
self
|
45
47
|
end
|
46
48
|
# set infinite (:inf) and invalid (:nan) numbers
|
@@ -84,7 +86,7 @@ module Nio
|
|
84
86
|
# in Ruby 1.6.8 Float,BigNum,Fixnum doesn't respond to dup
|
85
87
|
n.set @sign.dup, @digits.dup, @dec_pos, @rep_pos, @dgs.dup, @inexact, @rounding
|
86
88
|
end
|
87
|
-
return n
|
89
|
+
return n
|
88
90
|
end
|
89
91
|
|
90
92
|
def zero?
|
@@ -119,7 +121,8 @@ module Nio
|
|
119
121
|
adj = 0
|
120
122
|
dv = :tie
|
121
123
|
if @inexact && n==@digits.size
|
122
|
-
|
124
|
+
# TODO: the combination of the value true with the values of Formatter#round_up makes this ugly
|
125
|
+
dv = @inexact.is_a?(Symbol) ? @inexact : :lo
|
123
126
|
else
|
124
127
|
v = dig_value(n)
|
125
128
|
v2 = 2*v
|
@@ -128,15 +131,19 @@ module Nio
|
|
128
131
|
elsif v2 > @base # v>(@base/2)
|
129
132
|
dv = :hi
|
130
133
|
else
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
134
|
+
if @inexact
|
135
|
+
dv = :hi
|
136
|
+
else
|
137
|
+
|
138
|
+
(n+1...@digits.length).each do |i|
|
139
|
+
if dig_value(i)>0
|
140
|
+
dv = :hi
|
141
|
+
break
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
dv = :hi if dv==:tie && @rep_pos<=n
|
140
147
|
end
|
141
148
|
end
|
142
149
|
|
@@ -149,10 +156,10 @@ module Nio
|
|
149
156
|
adj = +1 if (dig_value(n-1)%2)!=0
|
150
157
|
elsif dir==:zero # towards zero
|
151
158
|
adj=0
|
152
|
-
# elsif dir==:odd
|
159
|
+
# elsif dir==:odd
|
153
160
|
# adj = +1 unless (dig_value(n-1)%2)!=0
|
154
161
|
end
|
155
|
-
end
|
162
|
+
end
|
156
163
|
|
157
164
|
if n>@digits.length
|
158
165
|
(@digits.length...n).each do |i|
|
@@ -175,17 +182,17 @@ module Nio
|
|
175
182
|
adj = +1
|
176
183
|
end
|
177
184
|
if i<0
|
178
|
-
prefix = dig_char(v)+prefix
|
185
|
+
prefix = dig_char(v)+prefix
|
179
186
|
elsif i<@digits.length
|
180
187
|
@digits[i] = dig_char(v)
|
181
188
|
end
|
182
189
|
i += -1
|
183
|
-
end
|
190
|
+
end
|
184
191
|
|
185
192
|
if n<0
|
186
|
-
@digits = ""
|
193
|
+
@digits = ""
|
187
194
|
else
|
188
|
-
@digits = @digits[0...n]
|
195
|
+
@digits = @digits[0...n]
|
189
196
|
end
|
190
197
|
@rep_pos = @digits.length
|
191
198
|
|
@@ -205,10 +212,10 @@ module Nio
|
|
205
212
|
return nn
|
206
213
|
end
|
207
214
|
|
208
|
-
def trimTrailZeros()
|
215
|
+
def trimTrailZeros()
|
209
216
|
i = @digits.length
|
210
217
|
while i>0 && dig_value(i-1)==0
|
211
|
-
i -= 1
|
218
|
+
i -= 1
|
212
219
|
end
|
213
220
|
if @rep_pos>=i
|
214
221
|
@digits = @digits[0...i]
|
@@ -240,7 +247,7 @@ module Nio
|
|
240
247
|
|
241
248
|
end
|
242
249
|
|
243
|
-
def trimZeros()
|
250
|
+
def trimZeros()
|
244
251
|
trimLeadZeros
|
245
252
|
trimTrailZeros
|
246
253
|
end
|
@@ -249,11 +256,11 @@ module Nio
|
|
249
256
|
|
250
257
|
def dig_value(i)
|
251
258
|
v = 0
|
252
|
-
if i>=@rep_pos
|
259
|
+
if i>=@rep_pos
|
253
260
|
i -= @digits.length
|
254
261
|
i %= @digits.length - @rep_pos if @rep_pos<@digits.length
|
255
262
|
i += @rep_pos
|
256
|
-
end
|
263
|
+
end
|
257
264
|
if i>=0 && i<@digits.length
|
258
265
|
v = @dgs.digit_value(@digits[i]) #digcode_value(@digits[i])
|
259
266
|
end
|
@@ -302,8 +309,8 @@ module Nio
|
|
302
309
|
n.ip = 0
|
303
310
|
n.d = text_to_digits(dig_char(0)*(-dec_pos) + digits)
|
304
311
|
elsif dec_pos >= digits.length
|
305
|
-
n.ip = digits.to_i(@base)
|
306
|
-
if rep_pos<dec_pos
|
312
|
+
n.ip = digits.to_i(@base)
|
313
|
+
if rep_pos<dec_pos
|
307
314
|
i=0
|
308
315
|
(dec_pos-digits.length).times do
|
309
316
|
n.ip *= @base
|
@@ -326,22 +333,22 @@ module Nio
|
|
326
333
|
else
|
327
334
|
n.ip = digits[0...dec_pos].to_i(@base)
|
328
335
|
n.d = text_to_digits(digits[dec_pos..-1])
|
329
|
-
if rep_pos<dec_pos
|
336
|
+
if rep_pos<dec_pos
|
330
337
|
new_rep_pos = n.d.size + dec_pos
|
331
338
|
n.d += text_to_digits(digits[rep_pos..-1])
|
332
339
|
self.rep_pos = new_rep_pos
|
333
340
|
puts "--rep_pos=#{rep_pos}"
|
334
|
-
end
|
341
|
+
end
|
335
342
|
end
|
336
343
|
n.sign = -1 if sign=='-'
|
337
|
-
n.rep_i = rep_pos - dec_pos
|
344
|
+
n.rep_i = rep_pos - dec_pos
|
338
345
|
end
|
339
346
|
n.normalize!(!inexact) # keep trailing zeros for inexact numbers
|
340
347
|
return n
|
341
348
|
end
|
342
349
|
protected
|
343
350
|
def text_to_digits(txt)
|
344
|
-
#txt.split('').collect{|c| @dgs.digit_value(c)}
|
351
|
+
#txt.split('').collect{|c| @dgs.digit_value(c)}
|
345
352
|
ds = []
|
346
353
|
txt.each_byte{|b| ds << @dgs.digit_value(b)}
|
347
354
|
ds
|
@@ -364,7 +371,7 @@ module Nio
|
|
364
371
|
else
|
365
372
|
num = nil
|
366
373
|
end
|
367
|
-
|
374
|
+
|
368
375
|
else
|
369
376
|
base_dgs ||= DigitsDef.base(@radix)
|
370
377
|
# assert base_dgs.radix == @radix
|
@@ -376,7 +383,7 @@ module Nio
|
|
376
383
|
num.set signch, decimals, dec_pos, rep_pos, base_dgs
|
377
384
|
end
|
378
385
|
return num
|
379
|
-
|
386
|
+
end
|
380
387
|
end
|
381
388
|
|
382
389
|
# A Fmt object defines a numeric format.
|
@@ -392,7 +399,7 @@ module Nio
|
|
392
399
|
# - #width() and the shortcut #pad0s()
|
393
400
|
# * numerical base
|
394
401
|
# - #base()
|
395
|
-
# * repeating numerals
|
402
|
+
# * repeating numerals
|
396
403
|
# - #rep()
|
397
404
|
#
|
398
405
|
# Note that for every aspect there are also corresponding _mutator_
|
@@ -461,12 +468,12 @@ module Nio
|
|
461
468
|
@nan_txt = 'NAN'
|
462
469
|
@inf_txt = 'Infinity'
|
463
470
|
|
464
|
-
yield self if block_given?
|
471
|
+
yield self if block_given?
|
465
472
|
end
|
466
473
|
|
467
474
|
# Defines the separators used in numerals. This is relevant to
|
468
|
-
# both input and output.
|
469
|
-
#
|
475
|
+
# both input and output.
|
476
|
+
#
|
470
477
|
# The first argument is the radix point separator (usually
|
471
478
|
# a point or a comma; by default it is a point.)
|
472
479
|
#
|
@@ -495,12 +502,12 @@ module Nio
|
|
495
502
|
set! :grp_sep=>grp_sep, :grp=>grp
|
496
503
|
end
|
497
504
|
|
498
|
-
# This is a shortcut to return a new default Fmt object
|
505
|
+
# This is a shortcut to return a new default Fmt object
|
499
506
|
# and define the separators as with #sep().
|
500
507
|
def Fmt.sep(dec_sep,grp_sep=nil,grp=nil)
|
501
508
|
Fmt.default.sep(dec_sep,grp_sep,grp)
|
502
509
|
end
|
503
|
-
# This is a shortcut to return a new default Fmt object
|
510
|
+
# This is a shortcut to return a new default Fmt object
|
504
511
|
# and define the grouping as with #grouping().
|
505
512
|
def Fmt.grouping(grp=[3],grp_sep=nil)
|
506
513
|
Fmt.default.grouping(grp,grp_sep)
|
@@ -526,10 +533,10 @@ module Nio
|
|
526
533
|
# - <tt>:round</tt> rounding mode applied to conversions
|
527
534
|
# (this is relevant for both input and output). It must be one of:
|
528
535
|
# [<tt>:inf</tt>]
|
529
|
-
# rounds to nearest with ties toward infinite;
|
536
|
+
# rounds to nearest with ties toward infinite;
|
530
537
|
# 1.5 is rounded to 2, -1.5 to -2
|
531
538
|
# [<tt>:zero</tt>]
|
532
|
-
# rounds to nearest with ties toward zero;
|
539
|
+
# rounds to nearest with ties toward zero;
|
533
540
|
# 1.5 is rounded to 1, -1.5 to 2
|
534
541
|
# [<tt>:even</tt>]
|
535
542
|
# rounds to the nearest with ties toward an even digit;
|
@@ -544,7 +551,7 @@ module Nio
|
|
544
551
|
# significant and insignificant digits.
|
545
552
|
# [<tt>:simplify</tt>]
|
546
553
|
# the value is simplified, if possible to a simpler (rational) value.
|
547
|
-
# - <tt>:show_all_digits</tt> if true, this forces to show digits that
|
554
|
+
# - <tt>:show_all_digits</tt> if true, this forces to show digits that
|
548
555
|
# would otherwise not be shown in the <tt>:gen</tt> format: trailing
|
549
556
|
# zeros of exact types or non-signficative digits of inexact types.
|
550
557
|
# - <tt>:nonsignficative_digits</tt> assigns a character to display
|
@@ -562,18 +569,18 @@ module Nio
|
|
562
569
|
# to change the precision only. Refer to #mode().
|
563
570
|
def prec(precision,mode=nil, options={})
|
564
571
|
dup.prec! precision, mode, options
|
565
|
-
end
|
572
|
+
end
|
566
573
|
# This is the mutator version of #prec().
|
567
574
|
def prec!(precision,mode=:gen, options={})
|
568
575
|
set! options.merge(:mode=>mode, :ndig=>precision)
|
569
576
|
end
|
570
577
|
|
571
|
-
# This is a shortcut to return a new default Fmt object
|
578
|
+
# This is a shortcut to return a new default Fmt object
|
572
579
|
# and define the formatting mode as with #mode()
|
573
580
|
def Fmt.mode(mode,ndig=nil,options={})
|
574
581
|
Fmt.default.mode(mode,ndig,options)
|
575
582
|
end
|
576
|
-
# This is a shortcut to return a new default Fmt object
|
583
|
+
# This is a shortcut to return a new default Fmt object
|
577
584
|
# and define the formatting mode as with #prec()
|
578
585
|
def Fmt.prec(ndig,mode=nil,options={})
|
579
586
|
Fmt.default.prec(ndig,mode,options)
|
@@ -592,7 +599,7 @@ module Nio
|
|
592
599
|
|
593
600
|
# This controls the display of the digits that are not necessary
|
594
601
|
# to specify the value unambiguosly (e.g. trailing zeros).
|
595
|
-
#
|
602
|
+
#
|
596
603
|
# The true (default) value forces the display of the requested number of digits
|
597
604
|
# and false will display only necessary digits.
|
598
605
|
def show_all_digits(ad=true)
|
@@ -640,22 +647,22 @@ module Nio
|
|
640
647
|
set! :sci_format=>n
|
641
648
|
end
|
642
649
|
|
643
|
-
# This is a shortcut to return a new default Fmt object
|
650
|
+
# This is a shortcut to return a new default Fmt object
|
644
651
|
# and define show_all_digits
|
645
652
|
def Fmt.show_all_digits(v=true)
|
646
653
|
Fmt.default.show_all_digits(v)
|
647
654
|
end
|
648
|
-
# This is a shortcut to return a new default Fmt object
|
655
|
+
# This is a shortcut to return a new default Fmt object
|
649
656
|
# and define approx_mode
|
650
657
|
def Fmt.approx_mode(v)
|
651
658
|
Fmt.default.approx_mode(v)
|
652
659
|
end
|
653
|
-
# This is a shortcut to return a new default Fmt object
|
660
|
+
# This is a shortcut to return a new default Fmt object
|
654
661
|
# and define insignificant digits
|
655
662
|
def Fmt.insignificant_digits(v='#')
|
656
663
|
Fmt.default.insignificant_digits(v)
|
657
664
|
end
|
658
|
-
# This is a shortcut to return a new default Fmt object
|
665
|
+
# This is a shortcut to return a new default Fmt object
|
659
666
|
# and define sci_digits
|
660
667
|
def Fmt.sci_digits(v=-1)
|
661
668
|
Fmt.default.sci_digits(v)
|
@@ -683,12 +690,12 @@ module Nio
|
|
683
690
|
self
|
684
691
|
end
|
685
692
|
|
686
|
-
# This is a shortcut to return a new default Fmt object
|
693
|
+
# This is a shortcut to return a new default Fmt object
|
687
694
|
# and define show_plus
|
688
695
|
def Fmt.show_plus(v=true)
|
689
696
|
Fmt.default.show_plus(v)
|
690
697
|
end
|
691
|
-
# This is a shortcut to return a new default Fmt object
|
698
|
+
# This is a shortcut to return a new default Fmt object
|
692
699
|
# and define show_exp_plus
|
693
700
|
def Fmt.show_exp_plus(v=true)
|
694
701
|
Fmt.default.show_exp_plus(v)
|
@@ -701,7 +708,7 @@ module Nio
|
|
701
708
|
# [<tt>:suffix</tt>] is the suffix used to indicate a implicit repeating decimal
|
702
709
|
# [<tt>:rep</tt>]
|
703
710
|
# if this parameter is greater than zero, on output the repeating section
|
704
|
-
# is repeated the indicated number of times followed by the suffix;
|
711
|
+
# is repeated the indicated number of times followed by the suffix;
|
705
712
|
# otherwise the delimited notation is used.
|
706
713
|
# [<tt>:read</tt>]
|
707
714
|
# (true/false) determines if repeating decimals are
|
@@ -710,20 +717,20 @@ module Nio
|
|
710
717
|
dup.rep!(*params)
|
711
718
|
end
|
712
719
|
# This is the mutator version of #rep().
|
713
|
-
def rep!(*params)
|
720
|
+
def rep!(*params)
|
714
721
|
|
715
722
|
params << {} if params.size==0
|
716
723
|
if params[0].kind_of?(Hash)
|
717
724
|
params = params[0]
|
718
|
-
else
|
719
|
-
begch,endch,autoch,rep,read = *params
|
725
|
+
else
|
726
|
+
begch,endch,autoch,rep,read = *params
|
720
727
|
params = {:begin=>begch,:end=>endch,:suffix=>autoch,:nreps=>rep,:read=>read}
|
721
728
|
end
|
722
729
|
|
723
730
|
set! params
|
724
731
|
end
|
725
732
|
|
726
|
-
# This is a shortcut to return a new default Fmt object
|
733
|
+
# This is a shortcut to return a new default Fmt object
|
727
734
|
# and define the repeating decimals mode as with #rep()
|
728
735
|
def Fmt.rep(*params)
|
729
736
|
Fmt.default.rep(*params)
|
@@ -822,7 +829,7 @@ module Nio
|
|
822
829
|
|
823
830
|
# Method used internally to format a neutral numeral
|
824
831
|
def nio_write_formatted(neutral) # :nodoc:
|
825
|
-
str = ''
|
832
|
+
str = ''
|
826
833
|
if neutral.special?
|
827
834
|
str << neutral.sign
|
828
835
|
case neutral.special
|
@@ -830,9 +837,9 @@ module Nio
|
|
830
837
|
str << @inf_txt
|
831
838
|
when :nan
|
832
839
|
str << @nan_txt
|
833
|
-
end
|
840
|
+
end
|
834
841
|
else
|
835
|
-
zero = get_base_digits(neutral.base).digit_char(0).chr
|
842
|
+
zero = get_base_digits(neutral.base).digit_char(0).chr
|
836
843
|
neutral = neutral.dup
|
837
844
|
round! neutral
|
838
845
|
if neutral.zero?
|
@@ -861,7 +868,7 @@ module Nio
|
|
861
868
|
end
|
862
869
|
end
|
863
870
|
exp = neutral.dec_pos - integral_digits
|
864
|
-
|
871
|
+
|
865
872
|
case actual_mode
|
866
873
|
when :gen # general (automatic)
|
867
874
|
# @ndig means significant digits
|
@@ -870,7 +877,7 @@ module Nio
|
|
870
877
|
trim_trail_zeros = !@all_digits # true
|
871
878
|
end
|
872
879
|
|
873
|
-
case actual_mode
|
880
|
+
case actual_mode
|
874
881
|
when :fix, :sig #, :gen
|
875
882
|
|
876
883
|
|
@@ -903,7 +910,7 @@ module Nio
|
|
903
910
|
digits = neutral.digits + ns_digits
|
904
911
|
if neutral.dec_pos<=0
|
905
912
|
str << zero+@dec_sep+zero*(-neutral.dec_pos) + digits
|
906
|
-
elsif neutral.dec_pos >= digits.length
|
913
|
+
elsif neutral.dec_pos >= digits.length
|
907
914
|
str << group(digits + zero*(neutral.dec_pos-digits.length))
|
908
915
|
else
|
909
916
|
str << group(digits[0...neutral.dec_pos]) + @dec_sep + digits[neutral.dec_pos..-1]
|
@@ -917,7 +924,7 @@ module Nio
|
|
917
924
|
#puts str
|
918
925
|
end
|
919
926
|
|
920
|
-
|
927
|
+
|
921
928
|
when :sci
|
922
929
|
|
923
930
|
|
@@ -935,7 +942,7 @@ module Nio
|
|
935
942
|
if @ndig==:exact
|
936
943
|
neutral.sign = '+'
|
937
944
|
neutral.dec_pos-=exp
|
938
|
-
str << neutral.to_RepDec.getS(@rep_n, getRepDecOpt(neutral.base))
|
945
|
+
str << neutral.to_RepDec.getS(@rep_n, getRepDecOpt(neutral.base))
|
939
946
|
else
|
940
947
|
ns_digits = ''
|
941
948
|
|
@@ -951,7 +958,7 @@ module Nio
|
|
951
958
|
str << ((integral_digits<1) ? zero : digits[0...integral_digits])
|
952
959
|
str << @dec_sep
|
953
960
|
str << digits[integral_digits...@ndig]
|
954
|
-
pad_right =(@ndig+1-str.length)
|
961
|
+
pad_right =(@ndig+1-str.length)
|
955
962
|
str << zero*pad_right if pad_right>0 && !neutral.inexact? # maybe we didn't have enought digits
|
956
963
|
end
|
957
964
|
|
@@ -967,7 +974,7 @@ module Nio
|
|
967
974
|
str << (exp<0 ? (@minus_symbol || '-') : (@plus_symbol || '+'))
|
968
975
|
end
|
969
976
|
str << exp.abs.to_s
|
970
|
-
|
977
|
+
|
971
978
|
end
|
972
979
|
|
973
980
|
end
|
@@ -985,7 +992,7 @@ module Nio
|
|
985
992
|
case @adjust
|
986
993
|
when :internal
|
987
994
|
sign = ''
|
988
|
-
if str[0,1]=='+' || str[0,1]=='-'
|
995
|
+
if str[0,1]=='+' || str[0,1]=='-'
|
989
996
|
sign = str[0,1]
|
990
997
|
str = str[1...str.length]
|
991
998
|
end
|
@@ -997,7 +1004,7 @@ module Nio
|
|
997
1004
|
when :left
|
998
1005
|
str = str + @fill_char*l
|
999
1006
|
end
|
1000
|
-
end
|
1007
|
+
end
|
1001
1008
|
end
|
1002
1009
|
|
1003
1010
|
return str
|
@@ -1013,14 +1020,14 @@ module Nio
|
|
1013
1020
|
def nio_read_formatted(txt) # :nodoc:
|
1014
1021
|
txt = txt.dup
|
1015
1022
|
num = nil
|
1016
|
-
|
1023
|
+
|
1017
1024
|
base = nil
|
1018
1025
|
|
1019
1026
|
base ||= get_base
|
1020
|
-
|
1021
|
-
zero = get_base_digits(base).digit_char(0).chr
|
1022
|
-
txt.tr!(@non_sig,zero) # we don't simply remove it because it may be before the radix point
|
1023
|
-
|
1027
|
+
|
1028
|
+
zero = get_base_digits(base).digit_char(0).chr
|
1029
|
+
txt.tr!(@non_sig,zero) # we don't simply remove it because it may be before the radix point
|
1030
|
+
|
1024
1031
|
exp = 0
|
1025
1032
|
x_char = get_exp_char(base)
|
1026
1033
|
|
@@ -1028,8 +1035,8 @@ module Nio
|
|
1028
1035
|
exp_i = txt.index(x_char.downcase) if exp_i===nil
|
1029
1036
|
if exp_i!=nil
|
1030
1037
|
exp = txt[exp_i+1...txt.length].to_i
|
1031
|
-
txt = txt[0...exp_i]
|
1032
|
-
end
|
1038
|
+
txt = txt[0...exp_i]
|
1039
|
+
end
|
1033
1040
|
|
1034
1041
|
|
1035
1042
|
opt = getRepDecOpt(base)
|
@@ -1051,7 +1058,7 @@ module Nio
|
|
1051
1058
|
return num
|
1052
1059
|
end
|
1053
1060
|
|
1054
|
-
|
1061
|
+
|
1055
1062
|
@@fmts = {
|
1056
1063
|
:def=>Fmt.new.freeze
|
1057
1064
|
}
|
@@ -1076,7 +1083,7 @@ module Nio
|
|
1076
1083
|
def self.[](tag)
|
1077
1084
|
@@fmts[tag.to_sym]
|
1078
1085
|
end
|
1079
|
-
|
1086
|
+
|
1080
1087
|
protected
|
1081
1088
|
|
1082
1089
|
@@valid_properties = nil
|
@@ -1097,7 +1104,7 @@ module Nio
|
|
1097
1104
|
|
1098
1105
|
@@valid_properties ||= instance_variables.collect{|v| v[1..-1].to_sym}
|
1099
1106
|
|
1100
|
-
|
1107
|
+
|
1101
1108
|
properties.each do |k,v|
|
1102
1109
|
al = ALIAS_PROPERTIES[k]
|
1103
1110
|
if al
|
@@ -1107,16 +1114,16 @@ module Nio
|
|
1107
1114
|
raise InvalidOption, "Invalid option: #{k}"
|
1108
1115
|
end
|
1109
1116
|
end
|
1110
|
-
|
1117
|
+
|
1111
1118
|
|
1112
|
-
if properties[:grp_sep].nil? && !properties[:dec_sep].nil? && properties[:dec_sep]!=@dec_sep && properties[:dec_sep]==@grp_sep
|
1113
|
-
properties[:grp_sep] = properties[:dec_sep]=='.' ? ',' : '.'
|
1119
|
+
if properties[:grp_sep].nil? && !properties[:dec_sep].nil? && properties[:dec_sep]!=@dec_sep && properties[:dec_sep]==@grp_sep
|
1120
|
+
properties[:grp_sep] = properties[:dec_sep]=='.' ? ',' : '.'
|
1114
1121
|
end
|
1115
1122
|
|
1116
1123
|
if properties[:all_digits].nil? && (properties[:ndig] || properties[:mode])
|
1117
1124
|
ndig = properties[:ndig] || @ndig
|
1118
1125
|
mode = properties[:mode] || @mode
|
1119
|
-
properties[:all_digits] = ndig!=:exact && mode!=:gen
|
1126
|
+
properties[:all_digits] = ndig!=:exact && mode!=:gen
|
1120
1127
|
end
|
1121
1128
|
|
1122
1129
|
if !properties[:all_digits].nil? && properties[:non_sig].nil?
|
@@ -1131,12 +1138,12 @@ module Nio
|
|
1131
1138
|
properties[:base_digits] = DigitsDef.base(base, !uppercase)
|
1132
1139
|
end
|
1133
1140
|
|
1134
|
-
|
1141
|
+
|
1135
1142
|
properties.each do |k,v|
|
1136
1143
|
instance_variable_set "@#{k}", v unless v.nil?
|
1137
1144
|
end
|
1138
|
-
|
1139
|
-
self
|
1145
|
+
|
1146
|
+
self
|
1140
1147
|
end
|
1141
1148
|
|
1142
1149
|
def set(properties={}) # :nodoc:
|
@@ -1149,7 +1156,7 @@ module Nio
|
|
1149
1156
|
puts " #{nd} ndpos=#{neutral.dec_pos} ndlen=#{neutral.digits.length}"
|
1150
1157
|
neutral.dec_pos>nd || ([neutral.digits.length,nd].min-neutral.dec_pos)>nd
|
1151
1158
|
else
|
1152
|
-
exp<-4 || exp>=nd
|
1159
|
+
exp<-4 || exp>=nd
|
1153
1160
|
end
|
1154
1161
|
end
|
1155
1162
|
|
@@ -1162,7 +1169,7 @@ module Nio
|
|
1162
1169
|
rd_opt.grp_sep = @grp_sep
|
1163
1170
|
rd_opt.grp = @grp
|
1164
1171
|
rd_opt.inf_txt = @inf_txt
|
1165
|
-
rd_opt.nan_txt = @nan_txt
|
1172
|
+
rd_opt.nan_txt = @nan_txt
|
1166
1173
|
rd_opt.set_digits(get_base_digits(base))
|
1167
1174
|
# if base && (base != get_base_digits.radix)
|
1168
1175
|
# rd_opt.set_digits(get_base_digits(base))
|
@@ -1197,11 +1204,11 @@ module Nio
|
|
1197
1204
|
|
1198
1205
|
module ClassMethods
|
1199
1206
|
# This is the method available in all formattable clases
|
1200
|
-
# to read a formatted value from a text string into
|
1207
|
+
# to read a formatted value from a text string into
|
1201
1208
|
# a value the class, according to the optional format passed.
|
1202
1209
|
def nio_read(txt,fmt=Fmt.default)
|
1203
1210
|
neutral = fmt.nio_read_formatted(txt)
|
1204
|
-
nio_read_neutral neutral
|
1211
|
+
nio_read_neutral neutral
|
1205
1212
|
end
|
1206
1213
|
end
|
1207
1214
|
|
@@ -1210,14 +1217,14 @@ module Nio
|
|
1210
1217
|
def nio_round(fmt=Fmt.default)
|
1211
1218
|
neutral = nio_write_neutral(fmt)
|
1212
1219
|
fmt.round! neutral
|
1213
|
-
self.class.nio_read_neutral neutral
|
1220
|
+
self.class.nio_read_neutral neutral
|
1214
1221
|
end
|
1215
1222
|
|
1216
1223
|
def self.append_features(mod) # :nodoc:
|
1217
1224
|
super
|
1218
1225
|
mod.extend ClassMethods
|
1219
1226
|
end
|
1220
|
-
|
1227
|
+
|
1221
1228
|
end
|
1222
1229
|
|
1223
1230
|
Fmt[:comma] = Fmt.sep(',','.')
|
@@ -1262,283 +1269,21 @@ module Nio
|
|
1262
1269
|
|
1263
1270
|
def nio_float_to_bigdecimal(x,prec) # :nodoc:
|
1264
1271
|
if prec.nil?
|
1265
|
-
x = Fmt.convert(x,BigDecimal,:approx)
|
1272
|
+
x = Fmt.convert(x,BigDecimal,:approx)
|
1266
1273
|
elsif prec==:exact
|
1267
|
-
x = Fmt.convert(x,BigDecimal,:exact)
|
1274
|
+
x = Fmt.convert(x,BigDecimal,:exact)
|
1268
1275
|
else
|
1269
1276
|
x = BigDecimal(x.nio_write(Nio::Fmt.new.prec(prec,:sig)))
|
1270
1277
|
end
|
1271
1278
|
x
|
1272
1279
|
end
|
1273
|
-
|
1274
|
-
|
1275
|
-
module Clinger # :nodoc: all
|
1276
|
-
module_function
|
1277
|
-
|
1278
|
-
def algM(f,e,round_mode,eb=10,beta=Float::RADIX,n=Float::MANT_DIG,min_e=Float::MIN_EXP-Float::MANT_DIG,max_e=Float::MAX_EXP-Float::MANT_DIG)
|
1279
|
-
|
1280
|
-
if e<0
|
1281
|
-
u,v,k = f,eb**(-e),0
|
1282
|
-
else
|
1283
|
-
u,v,k = f*(eb**e),1,0
|
1284
|
-
end
|
1285
|
-
|
1286
|
-
loop do
|
1287
|
-
x = u.div(v)
|
1288
|
-
# overflow if k>=max_e
|
1289
|
-
if (x>=beta**(n-1) && x<beta**n) || k==min_e || k==max_e
|
1290
|
-
return ratio_float(u,v,k,round_mode,beta,n)
|
1291
|
-
elsif x<beta**(n-1)
|
1292
|
-
u *= beta
|
1293
|
-
k -= 1
|
1294
|
-
elsif x>=beta**n
|
1295
|
-
v *= beta
|
1296
|
-
k += 1
|
1297
|
-
end
|
1298
|
-
end
|
1299
|
-
|
1300
|
-
end
|
1301
|
-
|
1302
|
-
def ratio_float(u,v,k,round_mode,beta=Float::RADIX,n=Float::MANT_DIG)
|
1303
|
-
q,r = u.divmod(v)
|
1304
|
-
v_r = v-r
|
1305
|
-
z = Math.ldexp(q,k)
|
1306
|
-
if r<v_r
|
1307
|
-
z
|
1308
|
-
elsif r>v_r
|
1309
|
-
nextfloat z
|
1310
|
-
elsif (round_mode==:even && q.even?) || (round_mode==:zero)
|
1311
|
-
z
|
1312
|
-
else
|
1313
|
-
nextfloat z
|
1314
|
-
end
|
1315
|
-
end
|
1316
|
-
|
1317
|
-
# valid only for non-negative x
|
1318
|
-
def nextfloat(x)
|
1319
|
-
f,e = Math.frexp(x)
|
1320
|
-
e = Float::MIN_EXP if f==0
|
1321
|
-
e = [Float::MIN_EXP,e].max
|
1322
|
-
dx = Math.ldexp(1,e-Float::MANT_DIG) #Math.ldexp(Math.ldexp(1.0,-Float::MANT_DIG),e)
|
1323
|
-
if f==(1.0 - Math.ldexp(1,-Float::MANT_DIG))
|
1324
|
-
x + dx*2
|
1325
|
-
else
|
1326
|
-
x + dx
|
1327
|
-
end
|
1328
|
-
end
|
1329
|
-
|
1330
|
-
# valid only for non-negative x
|
1331
|
-
def prevfloat(x)
|
1332
|
-
f,e = Math.frexp(x)
|
1333
|
-
e = Float::MIN_EXP if f==0
|
1334
|
-
e = [Float::MIN_EXP,e].max
|
1335
|
-
dx = Math.ldexp(1,e-Float::MANT_DIG) #Math.ldexp(Math.ldexp(1.0,-Float::MANT_DIG),e)
|
1336
|
-
if e==Float::MIN_EXP || f!=0.5 #0.5==Math.ldexp(2**(bits-1),-Float::MANT_DIG)
|
1337
|
-
x - dx
|
1338
|
-
else
|
1339
|
-
x - dx/2 # x - Math.ldexp(Math.ldexp(1.0,-Float::MANT_DIG),e-1)
|
1340
|
-
end
|
1341
|
-
end
|
1342
|
-
|
1343
|
-
end
|
1344
|
-
|
1345
|
-
module BurgerDybvig # :nodoc: all
|
1346
|
-
module_function
|
1347
|
-
|
1348
|
-
def float_to_digits(v,f,e,round_mode,min_e,p,b,_B)
|
1349
|
-
|
1350
|
-
case round_mode
|
1351
|
-
when :even
|
1352
|
-
roundl = roundh = f.even?
|
1353
|
-
when :inf
|
1354
|
-
roundl = true
|
1355
|
-
roundh = false
|
1356
|
-
when :zero
|
1357
|
-
roundl = false
|
1358
|
-
roundh = true
|
1359
|
-
else
|
1360
|
-
# here we don't assume any rounding in the floating point numbers
|
1361
|
-
# the result is valid for any rounding but may produce more digits
|
1362
|
-
# than stricly necessary for specifica rounding modes.
|
1363
|
-
roundl = false
|
1364
|
-
roundh = false
|
1365
|
-
end
|
1366
|
-
|
1367
|
-
if e >= 0
|
1368
|
-
if f != exptt(b,p-1)
|
1369
|
-
be = exptt(b,e)
|
1370
|
-
r,s,m_p,m_m,k = scale(f*be*2,2,be,be,0,_B,roundl ,roundh,v)
|
1371
|
-
else
|
1372
|
-
be = exptt(b,e)
|
1373
|
-
be1 = be*b
|
1374
|
-
r,s,m_p,m_m,k = scale(f*be1*2,b*2,be1,be,0,_B,roundl ,roundh,v)
|
1375
|
-
end
|
1376
|
-
else
|
1377
|
-
if e==min_e or f != exptt(b,p-1)
|
1378
|
-
r,s,m_p,m_m,k = scale(f*2,exptt(b,-e)*2,1,1,0,_B,roundl ,roundh,v)
|
1379
|
-
else
|
1380
|
-
r,s,m_p,m_m,k = scale(f*b*2,exptt(b,1-e)*2,b,1,0,_B,roundl ,roundh,v)
|
1381
|
-
end
|
1382
|
-
end
|
1383
|
-
[k]+generate(r,s,m_p,m_m,_B,roundl ,roundh)
|
1384
|
-
end
|
1385
|
-
|
1386
|
-
def scale(r,s,m_p,m_m,k,_B,low_ok ,high_ok,v)
|
1387
|
-
return scale2(r,s,m_p,m_m,k,_B,low_ok ,high_ok) if v==0
|
1388
|
-
est = (logB(_B,v)-1E-10).ceil.to_i
|
1389
|
-
if est>=0
|
1390
|
-
fixup(r,s*exptt(_B,est),m_p,m_m,est,_B,low_ok,high_ok)
|
1391
|
-
else
|
1392
|
-
sc = exptt(_B,-est)
|
1393
|
-
fixup(r*sc,s,m_p*sc,m_m*sc,est,_B,low_ok,high_ok)
|
1394
|
-
end
|
1395
|
-
end
|
1396
|
-
|
1397
|
-
def fixup(r,s,m_p,m_m,k,_B,low_ok,high_ok)
|
1398
|
-
if (high_ok ? (r+m_p >= s) : (r+m_p > s)) # too low?
|
1399
|
-
[r,s*_B,m_p,m_m,k+1]
|
1400
|
-
else
|
1401
|
-
[r,s,m_p,m_m,k]
|
1402
|
-
end
|
1403
|
-
end
|
1404
1280
|
|
1405
|
-
def scale2(r,s,m_p,m_m,k,_B,low_ok ,high_ok)
|
1406
|
-
loop do
|
1407
|
-
if (high_ok ? (r+m_p >= s) : (r+m_p > s)) # k is too low
|
1408
|
-
s *= _B
|
1409
|
-
k += 1
|
1410
|
-
elsif (high_ok ? ((r+m_p)*_B<s) : ((r+m_p)*_B<=s)) # k is too high
|
1411
|
-
r *= _B
|
1412
|
-
m_p *= _B
|
1413
|
-
m_m *= _B
|
1414
|
-
k -= 1
|
1415
|
-
else
|
1416
|
-
break
|
1417
|
-
end
|
1418
|
-
end
|
1419
|
-
[r,s,m_p,m_m,k]
|
1420
|
-
end
|
1421
1281
|
|
1422
|
-
def generate(r,s,m_p,m_m,_B,low_ok ,high_ok)
|
1423
|
-
list = []
|
1424
|
-
loop do
|
1425
|
-
d,r = (r*_B).divmod(s)
|
1426
|
-
m_p *= _B
|
1427
|
-
m_m *= _B
|
1428
|
-
tc1 = low_ok ? (r<=m_m) : (r<m_m)
|
1429
|
-
tc2 = high_ok ? (r+m_p >= s) : (r+m_p > s)
|
1430
|
-
|
1431
|
-
if not tc1
|
1432
|
-
if not tc2
|
1433
|
-
list << d
|
1434
|
-
else
|
1435
|
-
list << d+1
|
1436
|
-
break
|
1437
|
-
end
|
1438
|
-
else
|
1439
|
-
if not tc2
|
1440
|
-
list << d
|
1441
|
-
break
|
1442
|
-
else
|
1443
|
-
if r*2 < s
|
1444
|
-
list << d
|
1445
|
-
break
|
1446
|
-
else
|
1447
|
-
list << d+1
|
1448
|
-
break
|
1449
|
-
end
|
1450
|
-
end
|
1451
|
-
end
|
1452
|
-
|
1453
|
-
end
|
1454
|
-
list
|
1455
|
-
end
|
1456
|
-
|
1457
|
-
$exptt_table = Array.new(326)
|
1458
|
-
(0...326).each{|i| $exptt_table[i]=10**i}
|
1459
|
-
def exptt(_B, k)
|
1460
|
-
if _B==10 && k>=0 && k<326
|
1461
|
-
$exptt_table[k]
|
1462
|
-
else
|
1463
|
-
_B**k
|
1464
|
-
end
|
1465
|
-
end
|
1466
|
-
|
1467
|
-
$logB_table = Array.new(37)
|
1468
|
-
(2...37).each{|b| $logB_table[b]=1.0/Math.log(b)}
|
1469
|
-
def logB(_B, x)
|
1470
|
-
if _B>=2 && _B<37
|
1471
|
-
Math.log(x)*$logB_table[_B]
|
1472
|
-
else
|
1473
|
-
Math.log(x)/Math.log(_B)
|
1474
|
-
end
|
1475
|
-
end
|
1476
|
-
|
1477
|
-
def float_to_digits_max(v,f,e,round_mode,min_e,p,b,_B)
|
1478
|
-
|
1479
|
-
case round_mode
|
1480
|
-
when :even
|
1481
|
-
roundl = roundh = f.even?
|
1482
|
-
when :inf
|
1483
|
-
roundl = true
|
1484
|
-
roundh = false
|
1485
|
-
when :zero
|
1486
|
-
roundl = false
|
1487
|
-
roundh = true
|
1488
|
-
else
|
1489
|
-
# here we don't assume any rounding in the floating point numbers
|
1490
|
-
# the result is valid for any rounding but may produce more digits
|
1491
|
-
# than stricly necessary for specifica rounding modes.
|
1492
|
-
roundl = false
|
1493
|
-
roundh = false
|
1494
|
-
end
|
1495
|
-
|
1496
|
-
if e >= 0
|
1497
|
-
if f != exptt(b,p-1)
|
1498
|
-
be = exptt(b,e)
|
1499
|
-
r,s,m_p,m_m,k = scale(f*be*2,2,be,be,0,_B,roundl ,roundh,v)
|
1500
|
-
else
|
1501
|
-
be = exptt(b,e)
|
1502
|
-
be1 = be*b
|
1503
|
-
r,s,m_p,m_m,k = scale(f*be1*2,b*2,be1,be,0,_B,roundl ,roundh,v)
|
1504
|
-
end
|
1505
|
-
else
|
1506
|
-
if e==min_e or f != exptt(b,p-1)
|
1507
|
-
r,s,m_p,m_m,k = scale(f*2,exptt(b,-e)*2,1,1,0,_B,roundl ,roundh,v)
|
1508
|
-
else
|
1509
|
-
r,s,m_p,m_m,k = scale(f*b*2,exptt(b,1-e)*2,b,1,0,_B,roundl ,roundh,v)
|
1510
|
-
end
|
1511
|
-
end
|
1512
|
-
[k]+generate_max(r,s,m_p,m_m,_B,roundl ,roundh)
|
1513
|
-
end
|
1514
|
-
|
1515
|
-
def generate_max(r,s,m_p,m_m,_B,low_ok ,high_ok)
|
1516
|
-
list = [false]
|
1517
|
-
loop do
|
1518
|
-
d,r = (r*_B).divmod(s)
|
1519
|
-
m_p *= _B
|
1520
|
-
m_m *= _B
|
1521
|
-
|
1522
|
-
list << d
|
1523
|
-
|
1524
|
-
tc1 = low_ok ? (r<=m_m) : (r<m_m)
|
1525
|
-
tc2 = high_ok ? (r+m_p >= s) : (r+m_p > s)
|
1526
|
-
|
1527
|
-
if tc1 && tc2
|
1528
|
-
list[0] = true if r*2 >= s
|
1529
|
-
break
|
1530
|
-
end
|
1531
|
-
end
|
1532
|
-
list
|
1533
|
-
end
|
1534
|
-
|
1535
|
-
end
|
1536
|
-
|
1537
1282
|
end
|
1538
1283
|
|
1539
1284
|
class Float
|
1540
1285
|
include Nio::Formattable
|
1541
|
-
def self.nio_read_neutral(neutral)
|
1286
|
+
def self.nio_read_neutral(neutral)
|
1542
1287
|
x = nil
|
1543
1288
|
|
1544
1289
|
honor_rounding = true
|
@@ -1550,13 +1295,13 @@ class Float
|
|
1550
1295
|
when :inf
|
1551
1296
|
x = (neutral.sign=='-' ? -1.0 : +1.0)/0.0
|
1552
1297
|
end
|
1553
|
-
elsif neutral.rep_pos<neutral.digits.length
|
1298
|
+
elsif neutral.rep_pos<neutral.digits.length
|
1554
1299
|
|
1555
1300
|
x,y = neutral.to_RepDec.getQ
|
1556
1301
|
x = Float(x)/y
|
1557
1302
|
|
1558
1303
|
else
|
1559
|
-
nd = neutral.base==10 ? Float::DIG : ((Float::MANT_DIG-1)*Math.log(2)/Math.log(neutral.base)).floor
|
1304
|
+
nd = neutral.base==10 ? Float::DIG : ((Float::MANT_DIG-1)*Math.log(2)/Math.log(neutral.base)).floor
|
1560
1305
|
k = neutral.dec_pos-neutral.digits.length
|
1561
1306
|
if !honor_rounding && (neutral.digits.length<=nd && k.abs<=15)
|
1562
1307
|
x = neutral.digits.to_i(neutral.base).to_f
|
@@ -1576,24 +1321,62 @@ class Float
|
|
1576
1321
|
f = neutral.digits.to_i(neutral.base)
|
1577
1322
|
e = neutral.dec_pos-neutral.digits.length
|
1578
1323
|
|
1579
|
-
rounding = neutral.rounding
|
1324
|
+
rounding = case neutral.rounding
|
1325
|
+
when :even
|
1326
|
+
:half_even
|
1327
|
+
when :zero
|
1328
|
+
:half_down
|
1329
|
+
when :inf
|
1330
|
+
:half_up
|
1331
|
+
when :truncate
|
1332
|
+
:down
|
1333
|
+
when :directed_up
|
1334
|
+
:up
|
1335
|
+
when :floor
|
1336
|
+
:floor
|
1337
|
+
when :ceil
|
1338
|
+
:ceil
|
1339
|
+
else
|
1340
|
+
nil
|
1341
|
+
end
|
1580
1342
|
|
1581
|
-
|
1582
|
-
|
1343
|
+
reader = Flt::Support::Reader.new(:mode=>:fixed)
|
1344
|
+
sign = neutral.sign == '-' ? -1 : +1
|
1345
|
+
x = reader.read(Float.context, rounding, sign, f, e, neutral.base)
|
1346
|
+
exact = reader.exact?
|
1583
1347
|
|
1584
1348
|
else
|
1585
1349
|
|
1586
1350
|
f = neutral.digits.to_i(neutral.base)
|
1587
1351
|
e = neutral.dec_pos-neutral.digits.length
|
1588
1352
|
|
1589
|
-
rounding = neutral.rounding
|
1353
|
+
rounding = case neutral.rounding
|
1354
|
+
when :even
|
1355
|
+
:half_even
|
1356
|
+
when :zero
|
1357
|
+
:half_down
|
1358
|
+
when :inf
|
1359
|
+
:half_up
|
1360
|
+
when :truncate
|
1361
|
+
:down
|
1362
|
+
when :directed_up
|
1363
|
+
:up
|
1364
|
+
when :floor
|
1365
|
+
:floor
|
1366
|
+
when :ceil
|
1367
|
+
:ceil
|
1368
|
+
else
|
1369
|
+
nil
|
1370
|
+
end
|
1590
1371
|
|
1591
|
-
|
1592
|
-
|
1372
|
+
reader = Flt::Support::Reader.new(:mode=>:fixed)
|
1373
|
+
sign = neutral.sign == '-' ? -1 : +1
|
1374
|
+
x = reader.read(Float.context, rounding, sign, f, e, neutral.base)
|
1375
|
+
exact = reader.exact?
|
1593
1376
|
|
1594
1377
|
end
|
1595
1378
|
end
|
1596
|
-
|
1379
|
+
|
1597
1380
|
return x
|
1598
1381
|
end
|
1599
1382
|
def nio_write_neutral(fmt)
|
@@ -1609,7 +1392,7 @@ class Float
|
|
1609
1392
|
if fmt.get_ndig==:exact && fmt.get_approx==:simplify
|
1610
1393
|
|
1611
1394
|
if x!=0
|
1612
|
-
q = x.nio_r(
|
1395
|
+
q = x.nio_r(Flt.Tolerance(Float::DIG, :sig_decimals))
|
1613
1396
|
if q!=0
|
1614
1397
|
neutral = q.nio_write_neutral(fmt)
|
1615
1398
|
converted = true if neutral.digits.length<=Float::DIG
|
@@ -1620,11 +1403,11 @@ class Float
|
|
1620
1403
|
neutral = x.nio_xr.nio_write_neutral(fmt)
|
1621
1404
|
converted = true
|
1622
1405
|
end
|
1623
|
-
if !converted
|
1406
|
+
if !converted
|
1624
1407
|
if fmt.get_base==10 && false
|
1625
1408
|
txt = format "%.*e",Float::DECIMAL_DIG-1,x # note that spec. e output precision+1 significant digits
|
1626
1409
|
|
1627
|
-
sign = '+'
|
1410
|
+
sign = '+'
|
1628
1411
|
if txt[0,1]=='-'
|
1629
1412
|
sign = '-'
|
1630
1413
|
txt = txt[1...txt.length]
|
@@ -1636,12 +1419,12 @@ class Float
|
|
1636
1419
|
exp_i = txt.index(x_char.downcase) if exp_i===nil
|
1637
1420
|
if exp_i!=nil
|
1638
1421
|
exp = txt[exp_i+1...txt.length].to_i
|
1639
|
-
txt = txt[0...exp_i]
|
1640
|
-
end
|
1422
|
+
txt = txt[0...exp_i]
|
1423
|
+
end
|
1641
1424
|
|
1642
1425
|
dec_pos = txt.index '.'
|
1643
1426
|
if dec_pos==nil
|
1644
|
-
dec_pos = txt.length
|
1427
|
+
dec_pos = txt.length
|
1645
1428
|
else
|
1646
1429
|
txt[dec_pos]=''
|
1647
1430
|
end
|
@@ -1654,7 +1437,6 @@ class Float
|
|
1654
1437
|
if !converted
|
1655
1438
|
|
1656
1439
|
sign = x<0 ? '-' : '+'
|
1657
|
-
x = -x if sign=='-'
|
1658
1440
|
f,e = Math.frexp(x)
|
1659
1441
|
if e < Float::MIN_EXP
|
1660
1442
|
# denormalized number
|
@@ -1668,48 +1450,51 @@ class Float
|
|
1668
1450
|
f = f.to_i
|
1669
1451
|
inexact = true
|
1670
1452
|
|
1671
|
-
rounding = fmt.get_round
|
1672
|
-
|
1673
|
-
|
1674
|
-
|
1675
|
-
|
1676
|
-
|
1453
|
+
rounding = case fmt.get_round
|
1454
|
+
when :even
|
1455
|
+
:half_even
|
1456
|
+
when :zero
|
1457
|
+
:half_down
|
1458
|
+
when :inf
|
1459
|
+
:half_up
|
1460
|
+
when :truncate
|
1461
|
+
:down
|
1462
|
+
when :directed_up
|
1463
|
+
:up
|
1464
|
+
when :floor
|
1465
|
+
:floor
|
1466
|
+
when :ceil
|
1467
|
+
:ceil
|
1677
1468
|
else
|
1678
|
-
|
1679
|
-
dec_pos,*digits = Nio::BurgerDybvig::float_to_digits(x,f,e,rounding,Float::MIN_EXP-Float::MANT_DIG,Float::MANT_DIG,Float::RADIX,fmt.get_base)
|
1469
|
+
nil
|
1680
1470
|
end
|
1471
|
+
|
1472
|
+
|
1473
|
+
# Note: it is assumed that fmt will be used for for input too, otherwise
|
1474
|
+
# rounding should be Float.context.rounding (input rounding for Float) rather than fmt.get_round (output)
|
1475
|
+
formatter = Flt::Support::Formatter.new(Float::RADIX, Float::MIN_EXP-Float::MANT_DIG, fmt.get_base)
|
1476
|
+
formatter.format(x, f, e, rounding, Float::MANT_DIG, fmt.get_all_digits?)
|
1477
|
+
inexact = formatter.round_up if formatter.round_up.is_a?(Symbol)
|
1478
|
+
dec_pos, digits = formatter.digits
|
1681
1479
|
txt = ''
|
1682
1480
|
digits.each{|d| txt << fmt.get_base_digits.digit_char(d)}
|
1683
1481
|
neutral.set sign, txt, dec_pos, nil, fmt.get_base_digits, inexact, fmt.get_round
|
1684
1482
|
|
1685
1483
|
end
|
1686
1484
|
end
|
1687
|
-
|
1485
|
+
|
1688
1486
|
return neutral
|
1689
|
-
end
|
1690
|
-
end
|
1691
|
-
|
1692
|
-
class Numeric
|
1693
|
-
unless method_defined?(:even?)
|
1694
|
-
def even?
|
1695
|
-
self.modulo(2)==0
|
1696
|
-
end
|
1697
|
-
end
|
1698
|
-
unless method_defined?(:odd?)
|
1699
|
-
def odd?
|
1700
|
-
self.modulo(2)!=0
|
1701
|
-
end
|
1702
1487
|
end
|
1703
1488
|
end
|
1704
1489
|
|
1705
1490
|
class Integer
|
1706
1491
|
include Nio::Formattable
|
1707
|
-
def self.nio_read_neutral(neutral)
|
1492
|
+
def self.nio_read_neutral(neutral)
|
1708
1493
|
x = nil
|
1709
1494
|
|
1710
1495
|
if neutral.special?
|
1711
1496
|
raise Nio::InvalidFormat,"Invalid integer numeral"
|
1712
|
-
elsif neutral.rep_pos<neutral.digits.length
|
1497
|
+
elsif neutral.rep_pos<neutral.digits.length
|
1713
1498
|
return Rational.nio_read_neutral(neutral).to_i
|
1714
1499
|
else
|
1715
1500
|
digits = neutral.digits
|
@@ -1719,18 +1504,18 @@ class Integer
|
|
1719
1504
|
elsif neutral.dec_pos <= digits.length
|
1720
1505
|
digits = digits[0...neutral.dec_pos]
|
1721
1506
|
else
|
1722
|
-
digits = digits + '0'*(neutral.dec_pos-digits.length)
|
1507
|
+
digits = digits + '0'*(neutral.dec_pos-digits.length)
|
1723
1508
|
end
|
1724
1509
|
|
1725
1510
|
x = digits.to_i(neutral.base)
|
1726
1511
|
# this was formely needed because we didn't adust the digits
|
1727
1512
|
# if neutral.dec_pos != neutral.digits.length
|
1728
1513
|
# # with rational included, negative powers of ten are rational numbers
|
1729
|
-
# x = (x*((neutral.base)**(neutral.dec_pos-neutral.digits.length))).to_i
|
1514
|
+
# x = (x*((neutral.base)**(neutral.dec_pos-neutral.digits.length))).to_i
|
1730
1515
|
# end
|
1731
1516
|
x = -x if neutral.sign=='-'
|
1732
1517
|
end
|
1733
|
-
|
1518
|
+
|
1734
1519
|
return x
|
1735
1520
|
end
|
1736
1521
|
def nio_write_neutral(fmt)
|
@@ -1739,16 +1524,16 @@ class Integer
|
|
1739
1524
|
|
1740
1525
|
sign = x<0 ? '-' : '+'
|
1741
1526
|
txt = x.abs.to_s(fmt.get_base)
|
1742
|
-
dec_pos = rep_pos = txt.length
|
1527
|
+
dec_pos = rep_pos = txt.length
|
1743
1528
|
neutral.set sign, txt, dec_pos, nil, fmt.get_base_digits, false ,fmt.get_round
|
1744
|
-
|
1529
|
+
|
1745
1530
|
return neutral
|
1746
1531
|
end
|
1747
1532
|
end
|
1748
1533
|
|
1749
1534
|
class Rational
|
1750
1535
|
include Nio::Formattable
|
1751
|
-
def self.nio_read_neutral(neutral)
|
1536
|
+
def self.nio_read_neutral(neutral)
|
1752
1537
|
x = nil
|
1753
1538
|
|
1754
1539
|
if neutral.special?
|
@@ -1761,7 +1546,7 @@ class Rational
|
|
1761
1546
|
else
|
1762
1547
|
x = Rational(*neutral.to_RepDec.getQ)
|
1763
1548
|
end
|
1764
|
-
|
1549
|
+
|
1765
1550
|
return x
|
1766
1551
|
end
|
1767
1552
|
def nio_write_neutral(fmt)
|
@@ -1769,7 +1554,7 @@ class Rational
|
|
1769
1554
|
x = self
|
1770
1555
|
|
1771
1556
|
if x.denominator==0
|
1772
|
-
if x.numerator>0
|
1557
|
+
if x.numerator>0
|
1773
1558
|
neutral.set_special(:inf)
|
1774
1559
|
elsif x.numerator<0
|
1775
1560
|
neutral.set_special(:inf,'-')
|
@@ -1786,7 +1571,7 @@ class Rational
|
|
1786
1571
|
neutral = rd.to_NeutralNum(fmt.get_base_digits)
|
1787
1572
|
neutral.rounding = fmt.get_round
|
1788
1573
|
end
|
1789
|
-
|
1574
|
+
|
1790
1575
|
return neutral
|
1791
1576
|
end
|
1792
1577
|
end
|
@@ -1794,7 +1579,7 @@ end
|
|
1794
1579
|
if defined? BigDecimal
|
1795
1580
|
class BigDecimal
|
1796
1581
|
include Nio::Formattable
|
1797
|
-
def self.nio_read_neutral(neutral)
|
1582
|
+
def self.nio_read_neutral(neutral)
|
1798
1583
|
x = nil
|
1799
1584
|
|
1800
1585
|
if neutral.special?
|
@@ -1804,7 +1589,7 @@ class BigDecimal
|
|
1804
1589
|
when :inf
|
1805
1590
|
x = BigDecimal(neutral.sign=='-' ? '-1.0' : '+1.0')/0
|
1806
1591
|
end
|
1807
|
-
elsif neutral.rep_pos<neutral.digits.length
|
1592
|
+
elsif neutral.rep_pos<neutral.digits.length
|
1808
1593
|
|
1809
1594
|
x,y = neutral.to_RepDec.getQ
|
1810
1595
|
x = BigDecimal(x.to_s)/y
|
@@ -1819,12 +1604,12 @@ class BigDecimal
|
|
1819
1604
|
str += "E#{(neutral.dec_pos-neutral.digits.length)}"
|
1820
1605
|
x = BigDecimal(str)
|
1821
1606
|
else
|
1822
|
-
x = BigDecimal(neutral.digits.to_i(neutral.base).to_s)
|
1607
|
+
x = BigDecimal(neutral.digits.to_i(neutral.base).to_s)
|
1823
1608
|
x *= BigDecimal(neutral.base.to_s)**(neutral.dec_pos-neutral.digits.length)
|
1824
1609
|
x = -x if neutral.sign=='-'
|
1825
1610
|
end
|
1826
1611
|
end
|
1827
|
-
|
1612
|
+
|
1828
1613
|
return x
|
1829
1614
|
end
|
1830
1615
|
def nio_write_neutral(fmt)
|
@@ -1835,26 +1620,26 @@ class BigDecimal
|
|
1835
1620
|
neutral.set_special(:nan)
|
1836
1621
|
elsif x.infinite?
|
1837
1622
|
neutral.set_special(:inf, x<0 ? '-' : '+')
|
1838
|
-
else
|
1623
|
+
else
|
1839
1624
|
converted = false
|
1840
1625
|
if fmt.get_ndig==:exact && fmt.get_approx==:simplify
|
1841
1626
|
|
1842
1627
|
prc = [x.precs[0],20].max
|
1843
|
-
neutral = x.nio_r(
|
1628
|
+
neutral = x.nio_r(Flt.Tolerance(prc, :sig_decimals)).nio_write_neutral(fmt)
|
1844
1629
|
converted = true if neutral.digits.length<prc
|
1845
1630
|
|
1846
1631
|
elsif fmt.get_approx==:exact && fmt.get_base!=10
|
1847
1632
|
neutral = x.nio_xr.nio_write_neutral(fmt)
|
1848
1633
|
converted = true
|
1849
1634
|
end
|
1850
|
-
if !converted
|
1851
|
-
if fmt.get_base==10
|
1635
|
+
if !converted
|
1636
|
+
if fmt.get_base==10
|
1852
1637
|
# Don't use x.to_s because of bugs in BigDecimal in Ruby 1.9 revisions 20359-20797
|
1853
1638
|
# x.to_s('F') is not affected by that problem, but produces innecesary long strings
|
1854
1639
|
sgn,ds,b,e = x.split
|
1855
1640
|
txt = "#{sgn<0 ? '-' : ''}0.#{ds}E#{e}"
|
1856
1641
|
|
1857
|
-
sign = '+'
|
1642
|
+
sign = '+'
|
1858
1643
|
if txt[0,1]=='-'
|
1859
1644
|
sign = '-'
|
1860
1645
|
txt = txt[1...txt.length]
|
@@ -1866,12 +1651,12 @@ class BigDecimal
|
|
1866
1651
|
exp_i = txt.index(x_char.downcase) if exp_i===nil
|
1867
1652
|
if exp_i!=nil
|
1868
1653
|
exp = txt[exp_i+1...txt.length].to_i
|
1869
|
-
txt = txt[0...exp_i]
|
1870
|
-
end
|
1654
|
+
txt = txt[0...exp_i]
|
1655
|
+
end
|
1871
1656
|
|
1872
1657
|
dec_pos = txt.index '.'
|
1873
1658
|
if dec_pos==nil
|
1874
|
-
dec_pos = txt.length
|
1659
|
+
dec_pos = txt.length
|
1875
1660
|
else
|
1876
1661
|
txt[dec_pos]=''
|
1877
1662
|
end
|
@@ -1880,41 +1665,197 @@ class BigDecimal
|
|
1880
1665
|
|
1881
1666
|
converted = true
|
1882
1667
|
end
|
1883
|
-
end
|
1668
|
+
end
|
1884
1669
|
if !converted
|
1885
1670
|
|
1886
|
-
|
1887
|
-
|
1888
|
-
|
1889
|
-
|
1890
|
-
|
1891
|
-
|
1892
|
-
|
1893
|
-
|
1894
|
-
|
1895
|
-
|
1671
|
+
x = Flt::DecNum(x.to_s)
|
1672
|
+
|
1673
|
+
min_exp = num_class.context.etiny
|
1674
|
+
n = x.number_of_digits
|
1675
|
+
s,f,e = x.split
|
1676
|
+
b = num_class.radix
|
1677
|
+
if s < 0
|
1678
|
+
sign = '-'
|
1679
|
+
else
|
1680
|
+
sign = '+'
|
1681
|
+
end
|
1682
|
+
prc = x.number_of_digits
|
1683
|
+
f = num_class.int_mult_radix_power(f, prc-n)
|
1684
|
+
e -= (prc-n)
|
1896
1685
|
|
1897
1686
|
inexact = true
|
1898
1687
|
|
1899
|
-
rounding = fmt.get_round
|
1900
|
-
|
1901
|
-
|
1902
|
-
|
1903
|
-
|
1904
|
-
|
1688
|
+
rounding = case fmt.get_round
|
1689
|
+
when :even
|
1690
|
+
:half_even
|
1691
|
+
when :zero
|
1692
|
+
:half_down
|
1693
|
+
when :inf
|
1694
|
+
:half_up
|
1695
|
+
when :truncate
|
1696
|
+
:down
|
1697
|
+
when :directed_up
|
1698
|
+
:up
|
1699
|
+
when :floor
|
1700
|
+
:floor
|
1701
|
+
when :ceil
|
1702
|
+
:ceil
|
1905
1703
|
else
|
1906
|
-
|
1907
|
-
dec_pos,*digits = Nio::BurgerDybvig::float_to_digits(x,f_i,e,rounding,[e,min_exp].min,prc,b,fmt.get_base)
|
1704
|
+
nil
|
1908
1705
|
end
|
1706
|
+
|
1707
|
+
|
1708
|
+
# TODO: use Num#format instead
|
1709
|
+
# Note: it is assumed that fmt will be used for for input too, otherwise
|
1710
|
+
# rounding should be Float.context.rounding (input rounding for Float) rather than fmt.get_round (output)
|
1711
|
+
formatter = Flt::Support::Formatter.new(num_class.radix, num_class.context.etiny, fmt.get_base)
|
1712
|
+
formatter.format(x, f, e, rounding, prc, fmt.get_all_digits?)
|
1713
|
+
inexact = formatter.round_up if formatter.round_up.is_a?(Symbol)
|
1714
|
+
dec_pos,digits = formatter.digits
|
1909
1715
|
txt = ''
|
1910
1716
|
digits.each{|d| txt << fmt.get_base_digits.digit_char(d)}
|
1911
1717
|
neutral.set sign, txt, dec_pos, nil, fmt.get_base_digits, inexact, fmt.get_round
|
1912
1718
|
|
1719
|
+
|
1913
1720
|
end
|
1914
1721
|
end
|
1915
|
-
|
1722
|
+
|
1916
1723
|
return neutral
|
1917
1724
|
end
|
1918
1725
|
end
|
1919
1726
|
end
|
1920
1727
|
|
1728
|
+
class Flt::Num
|
1729
|
+
include Nio::Formattable
|
1730
|
+
def self.nio_read_neutral(neutral)
|
1731
|
+
x = nil
|
1732
|
+
|
1733
|
+
if neutral.special?
|
1734
|
+
case neutral.special
|
1735
|
+
when :nan
|
1736
|
+
x = num_class.nan
|
1737
|
+
when :inf
|
1738
|
+
x = num_class.infinity(neutral.sign=='-' ? '-1.0' : '+1.0')
|
1739
|
+
end
|
1740
|
+
elsif neutral.rep_pos<neutral.digits.length
|
1741
|
+
|
1742
|
+
# uses num_clas.context.precision TODO: ?
|
1743
|
+
x = num_class.new Rational(*neutral.to_RepDec.getQ)
|
1744
|
+
|
1745
|
+
else
|
1746
|
+
if neutral.base==num_class.radix
|
1747
|
+
if neutral.base==10
|
1748
|
+
str = neutral.sign
|
1749
|
+
str += neutral.digits
|
1750
|
+
str += "E#{(neutral.dec_pos-neutral.digits.length)}"
|
1751
|
+
x = num_class.new(str)
|
1752
|
+
else
|
1753
|
+
f = neutral.digits.to_i(neutral.base)
|
1754
|
+
e = neutral.dec_pos-neutral.digits.length
|
1755
|
+
s = neutral.sign=='-' ? -1 : +1
|
1756
|
+
x = num_class.Num(s, f, e)
|
1757
|
+
end
|
1758
|
+
else
|
1759
|
+
# uses num_clas.context.precision TODO: ?
|
1760
|
+
if num_class.respond_to?(:power)
|
1761
|
+
x = num_class.Num(neutral.digits.to_i(neutral.base).to_s)
|
1762
|
+
x *= num_class.Num(neutral.base.to_s)**(neutral.dec_pos-neutral.digits.length)
|
1763
|
+
x = -x if neutral.sign=='-'
|
1764
|
+
else
|
1765
|
+
|
1766
|
+
# uses num_clas.context.precision TODO: ?
|
1767
|
+
x = num_class.new Rational(*neutral.to_RepDec.getQ)
|
1768
|
+
|
1769
|
+
end
|
1770
|
+
end
|
1771
|
+
end
|
1772
|
+
|
1773
|
+
return x
|
1774
|
+
end
|
1775
|
+
def nio_write_neutral(fmt)
|
1776
|
+
neutral = Nio::NeutralNum.new
|
1777
|
+
x = self
|
1778
|
+
|
1779
|
+
if x.nan?
|
1780
|
+
neutral.set_special(:nan)
|
1781
|
+
elsif x.infinite?
|
1782
|
+
neutral.set_special(:inf, x<0 ? '-' : '+')
|
1783
|
+
else
|
1784
|
+
converted = false
|
1785
|
+
if fmt.get_ndig==:exact && fmt.get_approx==:simplify
|
1786
|
+
|
1787
|
+
neutral = x.nio_r(Flt.Tolerance('0.5', :ulps)).nio_write_neutral(fmt)
|
1788
|
+
# TODO: find better method to accept the conversion
|
1789
|
+
prc = (fmt.get_base==num_class.radix) ? x.number_of_digits : x.coefficient.to_s(fmt.get_base).length
|
1790
|
+
prc = [prc, 8].max
|
1791
|
+
converted = true if neutral.digits.length<prc
|
1792
|
+
|
1793
|
+
elsif fmt.get_approx==:exact && fmt.get_base!=num_class.radix
|
1794
|
+
# TODO: num_class.context(:precision=>fmt....
|
1795
|
+
neutral = x.to_r.nio_write_neutral(fmt)
|
1796
|
+
converted = true
|
1797
|
+
end
|
1798
|
+
if !converted
|
1799
|
+
if fmt.get_base==num_class.radix
|
1800
|
+
sign = x.sign==-1 ? '-' : '+'
|
1801
|
+
txt = x.coefficient.to_s(fmt.get_base) # TODO: can use x.digits directly?
|
1802
|
+
dec_pos = rep_pos = x.fractional_exponent
|
1803
|
+
neutral.set sign, txt, dec_pos, nil, fmt.get_base_digits, false ,fmt.get_round
|
1804
|
+
converted = true
|
1805
|
+
end
|
1806
|
+
end
|
1807
|
+
if !converted
|
1808
|
+
|
1809
|
+
min_exp = num_class.context.etiny
|
1810
|
+
n = x.number_of_digits
|
1811
|
+
s,f,e = x.split
|
1812
|
+
b = num_class.radix
|
1813
|
+
if s < 0
|
1814
|
+
sign = '-'
|
1815
|
+
else
|
1816
|
+
sign = '+'
|
1817
|
+
end
|
1818
|
+
prc = x.number_of_digits
|
1819
|
+
f = num_class.int_mult_radix_power(f, prc-n)
|
1820
|
+
e -= (prc-n)
|
1821
|
+
|
1822
|
+
inexact = true
|
1823
|
+
|
1824
|
+
rounding = case fmt.get_round
|
1825
|
+
when :even
|
1826
|
+
:half_even
|
1827
|
+
when :zero
|
1828
|
+
:half_down
|
1829
|
+
when :inf
|
1830
|
+
:half_up
|
1831
|
+
when :truncate
|
1832
|
+
:down
|
1833
|
+
when :directed_up
|
1834
|
+
:up
|
1835
|
+
when :floor
|
1836
|
+
:floor
|
1837
|
+
when :ceil
|
1838
|
+
:ceil
|
1839
|
+
else
|
1840
|
+
nil
|
1841
|
+
end
|
1842
|
+
|
1843
|
+
|
1844
|
+
# TODO: use Num#format instead
|
1845
|
+
# Note: it is assumed that fmt will be used for for input too, otherwise
|
1846
|
+
# rounding should be Float.context.rounding (input rounding for Float) rather than fmt.get_round (output)
|
1847
|
+
formatter = Flt::Support::Formatter.new(num_class.radix, num_class.context.etiny, fmt.get_base)
|
1848
|
+
formatter.format(x, f, e, rounding, prc, fmt.get_all_digits?)
|
1849
|
+
inexact = formatter.round_up if formatter.round_up.is_a?(Symbol)
|
1850
|
+
dec_pos,digits = formatter.digits
|
1851
|
+
txt = ''
|
1852
|
+
digits.each{|d| txt << fmt.get_base_digits.digit_char(d)}
|
1853
|
+
neutral.set sign, txt, dec_pos, nil, fmt.get_base_digits, inexact, fmt.get_round
|
1854
|
+
|
1855
|
+
end
|
1856
|
+
end
|
1857
|
+
|
1858
|
+
return neutral
|
1859
|
+
end
|
1860
|
+
end
|
1861
|
+
|