nio 0.2.3 → 0.2.4
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 +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
|
+
|