flt 1.3.3 → 1.3.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.
- 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
|