flt 1.3.3 → 1.3.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/History.txt +9 -0
- data/lib/flt/float.rb +23 -0
- data/lib/flt/num.rb +169 -26
- data/lib/flt/support.rb +50 -38
- data/lib/flt/version.rb +1 -1
- data/test/test_base_digits.rb +55 -0
- data/test/test_basic.rb +20 -0
- data/test/test_exact.rb +18 -0
- data/test/test_hex_format.rb +44 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 58bd070debe5638c64334230eb8e5d87176001bd
|
4
|
+
data.tar.gz: 71adc3e996232e211bd521ee64ef14b1e6f3f100
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 19c292ce44adafdf320693681e5e563cf5a73763941ca3de66cf6de654ad50db9b2f69409acb91f78ae1a18f6509399331fd0bf742da51acf28ddc79115c639d
|
7
|
+
data.tar.gz: 6c060e62ce10a9489bfae7d7cb5105845bdc4ff04cfc0e790e64962315690707a3efd8a4b831d63cc2bffc680587315ebb0a72c6643d5f0f191e189e490d31e8
|
data/History.txt
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
== 1.3.4 2014-10-27
|
2
|
+
|
3
|
+
* New features
|
4
|
+
- Context methods necessary_digits and representable_digits
|
5
|
+
- Assign :exact as the precision value to define an :exact context
|
6
|
+
- Constructors for nan, infinite, zero replicated in context
|
7
|
+
- Hexadecimal (%A) representation of binary floating point numbers
|
8
|
+
- Support.adjust_digits (to be used in Numerals gem)
|
9
|
+
|
1
10
|
== 1.3.3 2014-10-13
|
2
11
|
|
3
12
|
Formatter has a new raise_on_repeat options
|
data/lib/flt/float.rb
CHANGED
@@ -127,6 +127,10 @@ class Flt::FloatContext
|
|
127
127
|
(sign < 0) ? -1.0/0.0 : 1.0/0.0 # Ruby 1.9.2: (sing < 0) ? -Float::INFINITY : Float::INFINITY
|
128
128
|
end
|
129
129
|
|
130
|
+
def one_half
|
131
|
+
0.5
|
132
|
+
end
|
133
|
+
|
130
134
|
def int_radix_power(n)
|
131
135
|
1 << n
|
132
136
|
end
|
@@ -475,6 +479,25 @@ class Flt::FloatContext
|
|
475
479
|
end
|
476
480
|
end
|
477
481
|
|
482
|
+
def representable_digits(b)
|
483
|
+
if b == 10
|
484
|
+
Float::DIG
|
485
|
+
elsif b == radix
|
486
|
+
precision
|
487
|
+
else
|
488
|
+
((precision-1)*log(radix, b)).floor
|
489
|
+
end
|
490
|
+
end
|
491
|
+
|
492
|
+
def necessary_digits(b)
|
493
|
+
if b == 10
|
494
|
+
Float::DECIMAL_DIG
|
495
|
+
elsif b == radix
|
496
|
+
precision
|
497
|
+
else
|
498
|
+
(precision*log(radix, b)).ceil + 1
|
499
|
+
end
|
500
|
+
end
|
478
501
|
|
479
502
|
end
|
480
503
|
|
data/lib/flt/num.rb
CHANGED
@@ -580,7 +580,7 @@ class Num < Numeric
|
|
580
580
|
# If 0 is set the precision turns to be exact.
|
581
581
|
def precision=(n)
|
582
582
|
@precision = n
|
583
|
-
@exact = false
|
583
|
+
@exact = false
|
584
584
|
update_precision
|
585
585
|
n
|
586
586
|
end
|
@@ -624,9 +624,12 @@ class Num < Numeric
|
|
624
624
|
@clamp = options[:clamp ] unless options[:clamp ].nil?
|
625
625
|
@exact = options[:exact ] unless options[:exact ].nil?
|
626
626
|
@angle = options[:angle ] unless options[:angle ].nil?
|
627
|
-
@precision += options[:extra_precision] unless options[:extra_precision].nil?
|
628
627
|
update_precision
|
628
|
+
if options[:extra_precision] && !@exact
|
629
|
+
@precision += options[:extra_precision]
|
630
|
+
end
|
629
631
|
end
|
632
|
+
self
|
630
633
|
end
|
631
634
|
|
632
635
|
attr_reader :coercible_type_handlers, :conversions
|
@@ -1148,6 +1151,56 @@ class Num < Numeric
|
|
1148
1151
|
_convert(x).zero?
|
1149
1152
|
end
|
1150
1153
|
|
1154
|
+
# Maximum number of base b digits that can be stored in a context floating point number
|
1155
|
+
# and then preserved when converted back to base b.
|
1156
|
+
#
|
1157
|
+
# To store a base b number in a floating point number and be able to get then back exactly
|
1158
|
+
# the number cannot have more than these significant digits.
|
1159
|
+
def representable_digits(b)
|
1160
|
+
unless exact?
|
1161
|
+
if b == radix
|
1162
|
+
precision
|
1163
|
+
else
|
1164
|
+
((precision-1)*log(radix, b)).floor
|
1165
|
+
end
|
1166
|
+
end
|
1167
|
+
end
|
1168
|
+
|
1169
|
+
# Mininum number of base b digits necessary to store any context floating point number
|
1170
|
+
# while being able to convert the digits back to the same exact context floating point number
|
1171
|
+
#
|
1172
|
+
# To convert any floating point number to base b and be able to round the result back to
|
1173
|
+
# the same floating point number, at least this many base b digits are needed.
|
1174
|
+
def necessary_digits(b)
|
1175
|
+
unless exact?
|
1176
|
+
if b == radix
|
1177
|
+
precision
|
1178
|
+
else
|
1179
|
+
(precision*log(radix, b)).ceil + 1
|
1180
|
+
end
|
1181
|
+
end
|
1182
|
+
end
|
1183
|
+
|
1184
|
+
# A floating-point number with value zero and the specified sign
|
1185
|
+
def zero(sign = +1)
|
1186
|
+
num_class.zero(sign)
|
1187
|
+
end
|
1188
|
+
|
1189
|
+
# A floating-point infinite number with the specified sign
|
1190
|
+
def infinity(sign = +1)
|
1191
|
+
num_class.infinity(sign)
|
1192
|
+
end
|
1193
|
+
|
1194
|
+
# A floating-point NaN (not a number)
|
1195
|
+
def nan
|
1196
|
+
num_class.nan
|
1197
|
+
end
|
1198
|
+
|
1199
|
+
# One half: 1/2
|
1200
|
+
def one_half
|
1201
|
+
num_class.one_half
|
1202
|
+
end
|
1203
|
+
|
1151
1204
|
private
|
1152
1205
|
|
1153
1206
|
def _convert(x)
|
@@ -1164,13 +1217,14 @@ class Num < Numeric
|
|
1164
1217
|
elsif @emin && !@emax
|
1165
1218
|
@emax = 1 - @emin
|
1166
1219
|
end
|
1167
|
-
if @exact || @precision==0
|
1220
|
+
if @exact || @precision == 0 || @precision == :exact
|
1168
1221
|
quiet = (@exact == :quiet)
|
1169
1222
|
@exact = true
|
1170
1223
|
@precision = 0
|
1171
1224
|
@traps << Inexact unless quiet
|
1172
1225
|
@ignored_flags[Inexact] = false
|
1173
1226
|
else
|
1227
|
+
@exact = false
|
1174
1228
|
@traps[Inexact] = false
|
1175
1229
|
end
|
1176
1230
|
end
|
@@ -1398,7 +1452,7 @@ class Num < Numeric
|
|
1398
1452
|
options.delete(:exponent) || 0]
|
1399
1453
|
end
|
1400
1454
|
mode ||= options && options.delete(:mode)
|
1401
|
-
base = (options && options.delete(:base))
|
1455
|
+
base = (options && options.delete(:base))
|
1402
1456
|
context = options if context.nil? && options && !options.empty?
|
1403
1457
|
context = define_context(context)
|
1404
1458
|
|
@@ -1434,7 +1488,7 @@ class Num < Numeric
|
|
1434
1488
|
@sign,@coeff,@exp = context.exception(ConversionSyntax, "no trailing or leading whitespace is permitted").split
|
1435
1489
|
return
|
1436
1490
|
end
|
1437
|
-
m = _parser(arg)
|
1491
|
+
m = _parser(arg, base: base)
|
1438
1492
|
if m.nil?
|
1439
1493
|
@sign,@coeff,@exp = context.exception(ConversionSyntax, "Invalid literal for DecNum: #{arg.inspect}").split
|
1440
1494
|
return
|
@@ -1449,12 +1503,18 @@ class Num < Numeric
|
|
1449
1503
|
intpart = ''
|
1450
1504
|
fracpart = m.onlyfrac
|
1451
1505
|
end
|
1506
|
+
fracpart ||= ''
|
1507
|
+
base = m.base
|
1452
1508
|
exp = m.exp.to_i
|
1453
|
-
|
1454
|
-
|
1455
|
-
|
1509
|
+
coeff = (intpart+fracpart).to_i(base)
|
1510
|
+
if m.exp_base && m.exp_base != base
|
1511
|
+
# The exponent uses a different base;
|
1512
|
+
# compute exponent in base; assume base = exp_base**k
|
1513
|
+
k = Math.log(base, m.exp_base).round
|
1514
|
+
exp -= fracpart.size*k
|
1515
|
+
base = m.exp_base
|
1456
1516
|
else
|
1457
|
-
|
1517
|
+
exp -= fracpart.size
|
1458
1518
|
end
|
1459
1519
|
|
1460
1520
|
if false
|
@@ -3656,14 +3716,27 @@ class Num < Numeric
|
|
3656
3716
|
# If it is not passed and :all_digits is true, then :rounding or the context rounding mode
|
3657
3717
|
# will be used.
|
3658
3718
|
#
|
3659
|
-
# Note that when :base
|
3719
|
+
# Note that when :base is different from the floating point radix,
|
3720
|
+
# we're regarding the floating point number x
|
3660
3721
|
# as an approximation with x.number_of_digits precision and showing that
|
3661
3722
|
# inexact value in decimal without introducing additional precision.
|
3662
|
-
#
|
3723
|
+
#
|
3724
|
+
# If the exact value of the number expressed in other base is desired (we consider
|
3663
3725
|
# the Flt an exact number), this can be done with Num.convert_exact.
|
3726
|
+
#
|
3727
|
+
# The :hex_bin option produces the %A/%a format of printf, which sho2 the significand
|
3728
|
+
# as an hexadecimal number and the binary exponent in decimal.
|
3729
|
+
#
|
3664
3730
|
def format(num_context, options={})
|
3665
3731
|
# TODO: support options (base, all_digits, any_rounding, eng) and context options in the same hash
|
3666
3732
|
output_radix = options[:base] || 10
|
3733
|
+
output_exp_radix = options[:exp_base]
|
3734
|
+
if output_radix == :hex_bin
|
3735
|
+
output_radix = 16
|
3736
|
+
output_exp_radix = 2
|
3737
|
+
first_digit_1 = true
|
3738
|
+
end
|
3739
|
+
output_exp_radix ||= output_radix
|
3667
3740
|
rounding = options[:rounding]
|
3668
3741
|
all_digits = options[:all_digits]
|
3669
3742
|
eng = options[:eng]
|
@@ -3686,12 +3759,40 @@ class Num < Numeric
|
|
3686
3759
|
rounding ||= context.rounding
|
3687
3760
|
output_rounding ||= rounding
|
3688
3761
|
|
3689
|
-
if output_radix
|
3762
|
+
if output_radix != output_exp_radix
|
3763
|
+
k = Math.log(output_radix, output_exp_radix).round
|
3764
|
+
if output_radix != output_exp_radix**k
|
3765
|
+
raise "When different bases are used for the coefficient and exponent, the first must be a power of the second"
|
3766
|
+
end
|
3767
|
+
end
|
3768
|
+
|
3769
|
+
if output_exp_radix == num_class.radix && !all_digits && output_radix != output_exp_radix
|
3770
|
+
if first_digit_1
|
3771
|
+
# make the first digit a 1
|
3772
|
+
c = @coeff
|
3773
|
+
exp = integral_exponent
|
3774
|
+
nb = _nbits(c)
|
3775
|
+
r = (nb % k)
|
3776
|
+
d = (k + 1 - r) % k
|
3777
|
+
if d != 0
|
3778
|
+
c <<= d
|
3779
|
+
exp -= d
|
3780
|
+
end
|
3781
|
+
else
|
3782
|
+
c = @coeff
|
3783
|
+
exp = integral_exponent
|
3784
|
+
end
|
3785
|
+
ds = c.to_s(output_radix)
|
3786
|
+
n_ds = ds.size
|
3787
|
+
leftdigits = exp + n_ds
|
3788
|
+
exp_radix = num_class.radix
|
3789
|
+
elsif output_radix == num_class.radix && !all_digits && output_radix == output_exp_radix
|
3690
3790
|
# show exactly inner representation and precision
|
3691
3791
|
ds = @coeff.to_s(output_radix)
|
3692
3792
|
n_ds = ds.size
|
3693
3793
|
exp = integral_exponent
|
3694
3794
|
leftdigits = exp + n_ds
|
3795
|
+
exp_radix = num_class.radix
|
3695
3796
|
else
|
3696
3797
|
p = self.number_of_digits # context.precision
|
3697
3798
|
formatter = Flt::Support::Formatter.new(num_class.radix, context.etiny, output_radix)
|
@@ -3702,17 +3803,51 @@ class Num < Numeric
|
|
3702
3803
|
n_ds = ds.size
|
3703
3804
|
exp = dec_pos - n_ds
|
3704
3805
|
leftdigits = dec_pos
|
3806
|
+
exp_radix = output_radix
|
3705
3807
|
end
|
3706
3808
|
|
3707
|
-
# TODO:
|
3708
|
-
if
|
3709
|
-
|
3710
|
-
|
3711
|
-
|
3712
|
-
|
3713
|
-
|
3809
|
+
# TODO: this doesn't need to be so ugly...
|
3810
|
+
if output_exp_radix == 2 && output_radix == 16
|
3811
|
+
a_format = true
|
3812
|
+
digits_prefix = "0x"
|
3813
|
+
exp_letter = (context.capitals ? 'P' : 'p')
|
3814
|
+
show_exp = true
|
3815
|
+
else
|
3816
|
+
a_format = false
|
3817
|
+
digits_prefix = ""
|
3818
|
+
exp_letter = (context.capitals ? 'E' : 'e')
|
3819
|
+
show_exp = false
|
3820
|
+
end
|
3821
|
+
|
3822
|
+
if output_exp_radix != exp_radix
|
3823
|
+
# k = Math.log(exp_radix, output_exp_radix).round
|
3824
|
+
if leftdigits != 1
|
3825
|
+
exp += (ds.size - 1)
|
3826
|
+
leftdigits = 1
|
3827
|
+
dotplace = 1
|
3828
|
+
end
|
3829
|
+
exp *= k
|
3830
|
+
elsif a_format
|
3831
|
+
# k = Math.log(output_radix, output_exp_radix).round
|
3832
|
+
if leftdigits != 1
|
3833
|
+
exp += (ds.size - 1)*4
|
3834
|
+
leftdigits = 1
|
3835
|
+
dotplace = 1
|
3836
|
+
ds = ds[0...-1] while ds[-1,1] == '0' && ds.size>1
|
3837
|
+
n_ds = ds.size
|
3838
|
+
end
|
3714
3839
|
else
|
3715
|
-
|
3840
|
+
# TODO: DRY (this code is duplicated in num_class#format)
|
3841
|
+
if exp<=0 && leftdigits>-6
|
3842
|
+
dotplace = leftdigits
|
3843
|
+
elsif !eng
|
3844
|
+
dotplace = 1
|
3845
|
+
elsif @coeff==0
|
3846
|
+
dotplace = (leftdigits+1)%3 - 1
|
3847
|
+
else
|
3848
|
+
dotplace = (leftdigits-1)%3 + 1
|
3849
|
+
end
|
3850
|
+
exp = leftdigits-dotplace
|
3716
3851
|
end
|
3717
3852
|
|
3718
3853
|
if dotplace <=0
|
@@ -3726,14 +3861,13 @@ class Num < Numeric
|
|
3726
3861
|
fracpart = '.' + ds[dotplace..-1]
|
3727
3862
|
end
|
3728
3863
|
|
3729
|
-
if
|
3864
|
+
if exp == 0 && !show_exp
|
3730
3865
|
e = ''
|
3731
3866
|
else
|
3732
|
-
e =
|
3867
|
+
e = exp_letter + "%+d"%(exp)
|
3733
3868
|
end
|
3734
3869
|
|
3735
|
-
sgn + intpart + fracpart + e
|
3736
|
-
|
3870
|
+
sgn + digits_prefix + intpart + fracpart + e
|
3737
3871
|
end
|
3738
3872
|
|
3739
3873
|
# Auxiliar Methods
|
@@ -4017,11 +4151,20 @@ class Num < Numeric
|
|
4017
4151
|
end
|
4018
4152
|
|
4019
4153
|
# Parse numeric text literals (internal use)
|
4020
|
-
def _parser(txt)
|
4154
|
+
def _parser(txt, options={})
|
4155
|
+
base = options[:base]
|
4021
4156
|
md = /^\s*([-+])?(?:(?:(\d+)(?:\.(\d*))?|\.(\d+))(?:E([-+]?\d+))?|Inf(?:inity)?|(s)?NaN(\d*))\s*$/i.match(txt)
|
4022
4157
|
if md
|
4158
|
+
base ||= 10
|
4023
4159
|
OpenStruct.new :sign=>md[1], :int=>md[2], :frac=>md[3], :onlyfrac=>md[4], :exp=>md[5],
|
4024
|
-
:signal=>md[6], :diag=>md[7]
|
4160
|
+
:signal=>md[6], :diag=>md[7], :base=>base
|
4161
|
+
else
|
4162
|
+
md = /^\s*([-+])?0x(?:(?:([\da-f]+)(?:\.([\da-f]*))?|\.([\da-f]+))(?:P([-+]?\d+))?)\s*$/i.match(txt)
|
4163
|
+
if md
|
4164
|
+
base = 16
|
4165
|
+
OpenStruct.new :sign=>md[1], :int=>md[2], :frac=>md[3], :onlyfrac=>md[4], :exp=>md[5],
|
4166
|
+
:signal=>nil, :diag=>nil, :base=>base, :exp_base=>2
|
4167
|
+
end
|
4025
4168
|
end
|
4026
4169
|
end
|
4027
4170
|
|
data/lib/flt/support.rb
CHANGED
@@ -357,6 +357,51 @@ module Flt
|
|
357
357
|
round_mode
|
358
358
|
end
|
359
359
|
|
360
|
+
# Adjust truncated digits based on the rounding mode (:round_mode option)
|
361
|
+
# and on the information about the following digits contained in the :round_up
|
362
|
+
# parameter (nil for only zeros, :lo for nonzero values below tie, :tie for a :tie
|
363
|
+
# and :hi for nonzero digits over the tie). Other parameters: :negative to consider
|
364
|
+
# the number negative, :base the base of the number.
|
365
|
+
def adjust_digits(dec_pos, digits, options={})
|
366
|
+
round_mode = options[:round_mode]
|
367
|
+
negative = options[:negative]
|
368
|
+
round_up = options[:round_up]
|
369
|
+
base = options[:base]
|
370
|
+
round_mode = simplified_round_mode(round_mode, negative)
|
371
|
+
|
372
|
+
increment = (round_up && (round_mode != :down)) &&
|
373
|
+
((round_mode == :up) ||
|
374
|
+
(round_up == :hi) ||
|
375
|
+
((round_up == :tie) &&
|
376
|
+
((round_mode==:half_up) ||
|
377
|
+
((round_mode==:half_even) && ((digits.last % 2)==1)))))
|
378
|
+
|
379
|
+
if increment
|
380
|
+
digits = digits.dup
|
381
|
+
# carry = increment ? 1 : 0
|
382
|
+
# digits = digits.reverse.map{|d| d += carry; d>=base ? 0 : (carry=0;d)}.reverse
|
383
|
+
# if carry != 0
|
384
|
+
# digits.unshift carry
|
385
|
+
# dec_pos += 1
|
386
|
+
# end
|
387
|
+
i = digits.size - 1
|
388
|
+
while i>=0
|
389
|
+
digits[i] += 1
|
390
|
+
if digits[i] == base
|
391
|
+
digits[i] = 0
|
392
|
+
else
|
393
|
+
break
|
394
|
+
end
|
395
|
+
i -= 1
|
396
|
+
end
|
397
|
+
if i<0
|
398
|
+
dec_pos += 1
|
399
|
+
digits.unshift 1
|
400
|
+
end
|
401
|
+
end
|
402
|
+
[dec_pos, digits]
|
403
|
+
end
|
404
|
+
|
360
405
|
# Floating-point reading and printing (from/to text literals).
|
361
406
|
#
|
362
407
|
# Here are methods for floating-point reading, using algorithms by William D. Clinger, and
|
@@ -1009,47 +1054,14 @@ module Flt
|
|
1009
1054
|
|
1010
1055
|
attr_reader :round_up, :repeat
|
1011
1056
|
|
1012
|
-
|
1013
1057
|
# Access rounded result of format operation: scaling (position of radix point) and digits
|
1014
1058
|
def adjusted_digits(round_mode)
|
1015
|
-
round_mode = Support.simplified_round_mode(round_mode, @minus)
|
1016
1059
|
if @adjusted_digits.nil? && !@digits.nil?
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
# increment = (@round_up == :tie) || (@round_up == :hi) # old behaviour (:half_up)
|
1023
|
-
if increment
|
1024
|
-
base = @output_b
|
1025
|
-
dec_pos = @k
|
1026
|
-
digits = @digits.dup
|
1027
|
-
# carry = increment ? 1 : 0
|
1028
|
-
# digits = digits.reverse.map{|d| d += carry; d>=base ? 0 : (carry=0;d)}.reverse
|
1029
|
-
# if carry != 0
|
1030
|
-
# digits.unshift carry
|
1031
|
-
# dec_pos += 1
|
1032
|
-
# end
|
1033
|
-
i = digits.size - 1
|
1034
|
-
while i>=0
|
1035
|
-
digits[i] += 1
|
1036
|
-
if digits[i] == base
|
1037
|
-
digits[i] = 0
|
1038
|
-
else
|
1039
|
-
break
|
1040
|
-
end
|
1041
|
-
i -= 1
|
1042
|
-
end
|
1043
|
-
if i<0
|
1044
|
-
dec_pos += 1
|
1045
|
-
digits.unshift 1
|
1046
|
-
end
|
1047
|
-
@adjusted_k = dec_pos
|
1048
|
-
@adjusted_digits = digits
|
1049
|
-
else
|
1050
|
-
@adjusted_k = @k
|
1051
|
-
@adjusted_digits = @digits
|
1052
|
-
end
|
1060
|
+
@adjusted_k, @adjusted_digits = Support.adjust_digits(@k, @digits,
|
1061
|
+
:round_mode => round_mode,
|
1062
|
+
:negative => @minus,
|
1063
|
+
:round_up => @round_up,
|
1064
|
+
:base => @output_b)
|
1053
1065
|
end
|
1054
1066
|
return @adjusted_k, @adjusted_digits
|
1055
1067
|
end
|
data/lib/flt/version.rb
CHANGED
@@ -0,0 +1,55 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__),'helper.rb'))
|
2
|
+
|
3
|
+
|
4
|
+
class TestBaseDigits < Test::Unit::TestCase
|
5
|
+
|
6
|
+
|
7
|
+
def test_number_of_digits_in_other_base
|
8
|
+
|
9
|
+
assert_equal Float::DIG, Float.context.representable_digits(10)
|
10
|
+
assert_equal Float::DECIMAL_DIG, Float.context.necessary_digits(10)
|
11
|
+
|
12
|
+
if defined?(BinNum::FloatContext)
|
13
|
+
assert_equal Float::DIG, BinNum::FloatContext.representable_digits(10)
|
14
|
+
assert_equal Float::DECIMAL_DIG, BinNum::FloatContext.necessary_digits(10)
|
15
|
+
end
|
16
|
+
|
17
|
+
assert_equal 6, BinNum::IEEESingleContext.representable_digits(10)
|
18
|
+
assert_equal 9, BinNum::IEEESingleContext.necessary_digits(10)
|
19
|
+
|
20
|
+
assert_equal 15, BinNum::IEEEDoubleContext.representable_digits(10)
|
21
|
+
assert_equal 17, BinNum::IEEEDoubleContext.necessary_digits(10)
|
22
|
+
|
23
|
+
assert_equal 18, BinNum::IEEEExtendedContext.representable_digits(10)
|
24
|
+
assert_equal 21, BinNum::IEEEExtendedContext.necessary_digits(10)
|
25
|
+
|
26
|
+
|
27
|
+
[10,15,20,100].each do |precision|
|
28
|
+
DecNum.context(precision: precision) do
|
29
|
+
assert_equal precision, DecNum.context.representable_digits(10)
|
30
|
+
assert_equal precision, DecNum.context.necessary_digits(10)
|
31
|
+
end
|
32
|
+
|
33
|
+
BinNum.context(precision: precision) do
|
34
|
+
assert_equal precision, BinNum.context.representable_digits(2)
|
35
|
+
assert_equal precision, BinNum.context.necessary_digits(2)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
DecNum.context(exact: true) do
|
40
|
+
assert_nil DecNum.context.representable_digits(10)
|
41
|
+
assert_nil DecNum.context.necessary_digits(10)
|
42
|
+
assert_nil DecNum.context.representable_digits(2)
|
43
|
+
assert_nil DecNum.context.necessary_digits(2)
|
44
|
+
end
|
45
|
+
|
46
|
+
BinNum.context(exact: true) do
|
47
|
+
assert_nil BinNum.context.representable_digits(10)
|
48
|
+
assert_nil BinNum.context.necessary_digits(10)
|
49
|
+
assert_nil BinNum.context.representable_digits(2)
|
50
|
+
assert_nil BinNum.context.necessary_digits(2)
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
data/test/test_basic.rb
CHANGED
@@ -381,6 +381,26 @@ class TestBasic < Test::Unit::TestCase
|
|
381
381
|
assert_equal(-1, neg.sign)
|
382
382
|
end
|
383
383
|
|
384
|
+
def test_special_constructors
|
385
|
+
[DecNum, BinNum, Float].each do |num_class|
|
386
|
+
context = num_class.context
|
387
|
+
assert context.nan.nan?
|
388
|
+
assert context.zero.zero?
|
389
|
+
assert_equal +1, context.sign(context.zero)
|
390
|
+
assert context.zero(+1).zero?
|
391
|
+
assert_equal +1, context.sign(context.zero(+1))
|
392
|
+
assert context.zero(-1).zero?
|
393
|
+
assert_equal -1, context.sign(context.zero(-1))
|
394
|
+
assert context.infinity.infinite?
|
395
|
+
assert_equal +1, context.sign(context.infinity)
|
396
|
+
assert context.infinity(+1).infinite?
|
397
|
+
assert_equal +1, context.sign(context.infinity(+1))
|
398
|
+
assert context.infinity(-1).infinite?
|
399
|
+
assert_equal -1, context.sign(context.infinity(-1))
|
400
|
+
assert_equal context.Num(1)/2, context.one_half
|
401
|
+
end
|
402
|
+
end
|
403
|
+
|
384
404
|
def test_context_parameters
|
385
405
|
#DecNum.context = DecNum.Context
|
386
406
|
DecNum.context.precision = 3
|
data/test/test_exact.rb
CHANGED
@@ -144,4 +144,22 @@ class TestExact < Test::Unit::TestCase
|
|
144
144
|
|
145
145
|
end
|
146
146
|
|
147
|
+
def test_exact_precision
|
148
|
+
DecNum.context.precision = 10
|
149
|
+
refute DecNum.context.exact?
|
150
|
+
assert_equal 10, DecNum.context.precision
|
151
|
+
DecNum.context(exact: true) do
|
152
|
+
assert DecNum.context.exact?
|
153
|
+
assert_equal 0, DecNum.context.precision
|
154
|
+
end
|
155
|
+
refute DecNum.context.exact?
|
156
|
+
assert_equal 10, DecNum.context.precision
|
157
|
+
DecNum.context(precision: :exact) do
|
158
|
+
assert DecNum.context.exact?
|
159
|
+
assert_equal 0, DecNum.context.precision
|
160
|
+
end
|
161
|
+
refute DecNum.context.exact?
|
162
|
+
assert_equal 10, DecNum.context.precision
|
163
|
+
end
|
164
|
+
|
147
165
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__),'helper.rb'))
|
2
|
+
|
3
|
+
class TestHexFormat< Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@hex_test_data = [0.1, 1.0/3, 0.1e10, 1e10/3.0, 0.1e-10, 1e-10/3.0, 123456.789,
|
7
|
+
-0.1, -1.0/3, -0.1e10, -1e10/3.0, -0.1e-10, -1e-10/3.0, -123456.789,
|
8
|
+
Float::MAX, -Float::MIN, Float::MIN_D, Float::MAX_D, Float::MIN_D,
|
9
|
+
-Float::MIN_D, -Float::MAX_D, -Float::MIN_D,
|
10
|
+
Float.context.next_plus(0.1), Float.context.next_minus(0.1),
|
11
|
+
-Float.context.next_plus(0.1), -Float.context.next_minus(0.1),
|
12
|
+
0.5, Float.context.next_plus(0.5), Float.context.next_minus(0.5),
|
13
|
+
-0.5, -Float.context.next_plus(0.5), -Float.context.next_minus(0.5),
|
14
|
+
1E22, -1E22, 64.1, -64.1]
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_hex_input
|
18
|
+
if RUBY_VERSION >= "1.9.2" # luckily there's no 1.9.10!
|
19
|
+
BinNum.context(BinNum::FloatContext) do
|
20
|
+
@hex_test_data.each do |number|
|
21
|
+
hex_upcase = "%A" % number
|
22
|
+
hex_downcase = "%a" % number
|
23
|
+
assert_equal number, BinNum(hex_upcase).to_f, "Read #{hex_upcase} (number)"
|
24
|
+
assert_equal number, BinNum(hex_downcase).to_f, "Read #{hex_downcase} (number)"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_hex_output
|
31
|
+
if RUBY_VERSION >= "1.9.2" # luckily there's no 1.9.10!
|
32
|
+
BinNum.context(BinNum::FloatContext) do
|
33
|
+
@hex_test_data.each do |number|
|
34
|
+
hex_upcase = "%A" % number
|
35
|
+
number = BinNum(number)
|
36
|
+
# text = number.to_s(:base => :hex_bin, :all_digits => false, :output_rounding => BinNum.context.rounding)
|
37
|
+
text = number.to_s(:base => :hex_bin, :all_digits => false, :output_rounding => nil)
|
38
|
+
assert_equal hex_upcase, text.upcase, "Write #{hex_upcase} (number)"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Javier Goizueta
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-10-
|
11
|
+
date: 2014-10-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -76,6 +76,7 @@ files:
|
|
76
76
|
- test/generate_trig_data.rb
|
77
77
|
- test/helper.rb
|
78
78
|
- test/reader.rb
|
79
|
+
- test/test_base_digits.rb
|
79
80
|
- test/test_basic.rb
|
80
81
|
- test/test_bin.rb
|
81
82
|
- test/test_bin_arithmetic.rb
|
@@ -88,6 +89,7 @@ files:
|
|
88
89
|
- test/test_exact.rb
|
89
90
|
- test/test_flags.rb
|
90
91
|
- test/test_formatter.rb
|
92
|
+
- test/test_hex_format.rb
|
91
93
|
- test/test_multithreading.rb
|
92
94
|
- test/test_num_constructor.rb
|
93
95
|
- test/test_odd_even.rb
|
@@ -127,6 +129,7 @@ test_files:
|
|
127
129
|
- test/generate_trig_data.rb
|
128
130
|
- test/helper.rb
|
129
131
|
- test/reader.rb
|
132
|
+
- test/test_base_digits.rb
|
130
133
|
- test/test_basic.rb
|
131
134
|
- test/test_bin.rb
|
132
135
|
- test/test_bin_arithmetic.rb
|
@@ -139,6 +142,7 @@ test_files:
|
|
139
142
|
- test/test_exact.rb
|
140
143
|
- test/test_flags.rb
|
141
144
|
- test/test_formatter.rb
|
145
|
+
- test/test_hex_format.rb
|
142
146
|
- test/test_multithreading.rb
|
143
147
|
- test/test_num_constructor.rb
|
144
148
|
- test/test_odd_even.rb
|