flt 1.3.2 → 1.3.3
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 +5 -0
- data/README.rdoc +1 -0
- data/lib/flt/support.rb +112 -30
- data/lib/flt/version.rb +1 -1
- data/test/test_formatter.rb +197 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a623d39842de7043c3004b02fe86bf20b4fb6491
|
4
|
+
data.tar.gz: a21afce102fa26145f8f24b8661d6b9bfddb2ae4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bfe19f6b32df81f96b39d1b58b8845c402c66fc3f20b0e4e6cbc45cc4593f1d5e3d37aea6c0f3cbf02a15ef30aae75805ffefb740099fd41bc729f99f0de9bf3
|
7
|
+
data.tar.gz: e4077b0fdcd3ecd337af25b8fec87c47cde43003b89dff3c8621fe4f434589a0f73a726aa32389e40251b47c714db07f94d6845de62bc550cdc9f441a85d1321
|
data/History.txt
CHANGED
data/README.rdoc
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
= Introduction
|
2
2
|
{<img src="https://badge.fury.io/rb/flt.svg" alt="Gem Version" />}[http://badge.fury.io/rb/flt]
|
3
|
+
{<img src="https://travis-ci.org/jgoizueta/flt.svg?branch=master" alt="Build tests" />}[https://travis-ci.org/jgoizueta/flt]
|
3
4
|
|
4
5
|
This library provides arbitrary precision floating-point types for Ruby. All types and
|
5
6
|
functions are within a namespace called Flt. Decimal and Binary floating point numbers
|
data/lib/flt/support.rb
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
module Flt
|
2
2
|
module Support
|
3
|
+
|
4
|
+
class InfiniteLoopError < StandardError
|
5
|
+
end
|
6
|
+
|
3
7
|
# This class assigns bit-values to a set of symbols
|
4
8
|
# so they can be used as flags and stored as an integer.
|
5
9
|
# fv = FlagValues.new(:flag1, :flag2, :flag3)
|
@@ -353,23 +357,22 @@ module Flt
|
|
353
357
|
round_mode
|
354
358
|
end
|
355
359
|
|
356
|
-
|
357
360
|
# Floating-point reading and printing (from/to text literals).
|
358
361
|
#
|
359
|
-
# Here are methods for floating-point reading using algorithms by William D. Clinger and
|
360
|
-
# printing using algorithms by Robert G. Burger and R. Kent Dybvig.
|
362
|
+
# Here are methods for floating-point reading, using algorithms by William D. Clinger, and
|
363
|
+
# printing, using algorithms by Robert G. Burger and R. Kent Dybvig.
|
361
364
|
#
|
362
|
-
# Reading and printing can also viewed as floating-point conversion
|
363
|
-
# floating-point format (the floating-point numbers) and and a free floating-point format (text)
|
364
|
-
# may use different numerical bases.
|
365
|
+
# Reading and printing can also viewed as floating-point conversion between a fixed-precision
|
366
|
+
# floating-point format (the floating-point numbers) and and a free floating-point format (text),
|
367
|
+
# which may use different numerical bases.
|
365
368
|
#
|
366
|
-
# The Reader class
|
369
|
+
# The Reader class, in the default :free mode, converts a free-form numeric value
|
367
370
|
# (as a text literal, i.e. a free floating-point format, usually in base 10) which is taken
|
368
371
|
# as an exact value, to a correctly-rounded floating-point of specified precision and with a
|
369
372
|
# specified rounding mode. It also has a :fixed mode that uses the Formatter class indirectly.
|
370
373
|
#
|
371
374
|
# The Formatter class implements the Burger-Dybvig printing algorithm which converts a
|
372
|
-
# fixed-precision floating point value and produces a text literal in
|
375
|
+
# fixed-precision floating point value and produces a text literal in some base, usually 10,
|
373
376
|
# (equivalently, it produces a floating-point free-format value) so that it rounds back to
|
374
377
|
# the original value (with some specified rounding-mode or any round-to-nearest mode) and with
|
375
378
|
# the same original precision (e.g. using the Clinger algorithm)
|
@@ -822,14 +825,27 @@ module Flt
|
|
822
825
|
# p is the input floating point precision
|
823
826
|
class Formatter
|
824
827
|
|
825
|
-
# This Object-oriented implementation is slower than the functional one for two reasons:
|
828
|
+
# This Object-oriented implementation is slower than the original functional one for two reasons:
|
826
829
|
# * The overhead of object creation
|
827
830
|
# * The use of instance variables instead of local variables
|
828
831
|
# But if scale is optimized or local variables are used in the inner loops, then this implementation
|
829
832
|
# is on par with the functional one for Float and it is more efficient for Flt types, where the variables
|
830
833
|
# passed as parameters hold larger objects.
|
831
834
|
|
832
|
-
|
835
|
+
# A Formatted object is created to format floating point numbers given:
|
836
|
+
# * The input base in which numbers to be formatted are defined
|
837
|
+
# * The input minimum expeonent
|
838
|
+
# * The output base to which the input is converted.
|
839
|
+
# * The :raise_on_repeat option, true by default specifies that when
|
840
|
+
# an infinite sequence of repeating significant digits is found on the output
|
841
|
+
# (which may occur when using the all-digits options and using directed-rounding)
|
842
|
+
# an InfiniteLoopError exception is raised. If this option is false, then
|
843
|
+
# no exception occurs, and instead of generating an infinite sequence of digits,
|
844
|
+
# the formatter object will have a 'repeat' property which designs the first digit
|
845
|
+
# to be repeated (it is an index into digits). If this equals the size of digits,
|
846
|
+
# it is assumend, that the digit to be repeated is a zero which follows the last
|
847
|
+
# digit present in digits.
|
848
|
+
def initialize(input_b, input_min_e, output_b, options={})
|
833
849
|
@b = input_b
|
834
850
|
@min_e = input_min_e
|
835
851
|
@output_b = output_b
|
@@ -844,35 +860,49 @@ module Flt
|
|
844
860
|
# for round-to-nearest it is atie.
|
845
861
|
# * it is :hi otherwise (the value should be rounded-up except for the :down mode)
|
846
862
|
@round_up = nil
|
863
|
+
|
864
|
+
options = { raise_on_repeat: true }.merge(options)
|
865
|
+
# when significant repeating digits occur (+all+ parameter and directed rounding)
|
866
|
+
# @repeat is set to the index of the first repeating digit in @digits;
|
867
|
+
# (if equal to @digits.size, that would indicate an infinite sequence of significant zeros)
|
868
|
+
@repeat = nil
|
869
|
+
# the :raise_on_repeat options (by default true) causes exceptions when repeating is found
|
870
|
+
@raise_on_repeat = options[:raise_on_repeat]
|
847
871
|
end
|
848
872
|
|
849
|
-
# This method converts v = f*b**e into a sequence of output_b
|
873
|
+
# This method converts v = f*b**e into a sequence of +output_b+-base digits,
|
850
874
|
# so that if the digits are converted back to a floating-point value
|
851
|
-
# of precision p (correctly rounded), the result is v.
|
852
|
-
#
|
875
|
+
# of precision p (correctly rounded), the result is exactly v.
|
876
|
+
#
|
877
|
+
# If +round_mode+ is not nil, then just enough digits to produce v using
|
853
878
|
# that rounding is used; otherwise enough digits to produce v with
|
854
879
|
# any rounding are delivered.
|
855
880
|
#
|
856
881
|
# If the +all+ parameter is true, all significant digits are generated without rounding,
|
857
|
-
#
|
882
|
+
# Significant digits here are all digits that, if used on input, cannot arbitrarily change
|
858
883
|
# while preserving the parsed value of the floating point number. Since the digits are not rounded
|
859
884
|
# more digits may be needed to assure round-trip value preservation.
|
885
|
+
#
|
860
886
|
# This is useful to reflect the precision of the floating point value in the output; in particular
|
861
887
|
# trailing significant zeros are shown. But note that, for directed rounding and base conversion
|
862
|
-
# this may need to produce an infinite number of digits, in which case an exception will be raised
|
863
|
-
#
|
864
|
-
#
|
865
|
-
#
|
888
|
+
# this may need to produce an infinite number of digits, in which case an exception will be raised
|
889
|
+
# unless the :raise_on_repeat option has been set to false in the Formatter object. In that case
|
890
|
+
# the formatter objetct will have a +repeat+ property that specifies the point in the digit
|
891
|
+
# sequence where irepetition starts. The digits from that point to the end to the digits sequence
|
892
|
+
# repeat indefinitely.
|
893
|
+
#
|
894
|
+
# This digit-repetition is specially frequent for the :up rounding mode, in which any number
|
895
|
+
# with a finite numberof nonzero digits equal to or less than the precision will haver and infinite
|
896
|
+
# sequence of zero significant digits.
|
866
897
|
#
|
867
|
-
#
|
868
|
-
# point but beware:
|
869
|
-
#
|
870
|
-
# formatting '0.1' (as a decimal floating-point number) in base 2 with :down rounding
|
898
|
+
# The:down rounding (truncation) could be used to show the exact value of the floating
|
899
|
+
# point but beware: if the value has not an exact representation in the output base this will
|
900
|
+
# lead to an infinite loop or repeating squence.
|
871
901
|
#
|
872
902
|
# When the +all+ parameters is used the result is not rounded (is truncated), and the round_up flag
|
873
903
|
# is set to indicate that nonzero digits exists beyond the returned digits; the possible values
|
874
904
|
# of the round_up flag are:
|
875
|
-
# * nil : the rest of digits are zero (the result is exact)
|
905
|
+
# * nil : the rest of digits are zero or repeat (the result is exact)
|
876
906
|
# * :lo : there exist non-zero digits beyond the significant ones (those returned), but
|
877
907
|
# the value is below the tie (the value must be rounded up only for :up rounding mode)
|
878
908
|
# * :tie : there exists exactly one nonzero digit after the significant and it is radix/2,
|
@@ -883,6 +913,7 @@ module Flt
|
|
883
913
|
# it is the rounding mode that applied to *input* preserves the original floating-point
|
884
914
|
# value (with the same precision as input).
|
885
915
|
# should be rounded-up.
|
916
|
+
#
|
886
917
|
def format(v, f, e, round_mode, p=nil, all=false)
|
887
918
|
context = v.class.context
|
888
919
|
# TODO: consider removing parameters f,e and using v.split instead
|
@@ -976,7 +1007,7 @@ module Flt
|
|
976
1007
|
return @k, @digits
|
977
1008
|
end
|
978
1009
|
|
979
|
-
attr_reader :round_up
|
1010
|
+
attr_reader :round_up, :repeat
|
980
1011
|
|
981
1012
|
|
982
1013
|
# Access rounded result of format operation: scaling (position of radix point) and digits
|
@@ -1078,17 +1109,67 @@ module Flt
|
|
1078
1109
|
@output_b**n
|
1079
1110
|
end
|
1080
1111
|
|
1112
|
+
def start_repetition_dectection
|
1113
|
+
@may_repeat = (@m_p == 0 || @m_m == 0)
|
1114
|
+
@n_iters = 0
|
1115
|
+
@rs = []
|
1116
|
+
end
|
1117
|
+
|
1118
|
+
ITERATIONS_BEFORE_KEEPING_TRACK_OF_REMAINDERS = 10000
|
1119
|
+
|
1120
|
+
# Detect indefinite repetitions in generate_max
|
1121
|
+
# returns the number of digits that are being repeated
|
1122
|
+
# (0 indicates the next digit would repeat and it would be a zero)
|
1123
|
+
def detect_repetitions(r)
|
1124
|
+
return nil unless @may_repeat
|
1125
|
+
@n_iters += 1
|
1126
|
+
if r == 0 && @m_p == 0
|
1127
|
+
repeat_count = 0
|
1128
|
+
elsif (@n_iters > ITERATIONS_BEFORE_KEEPING_TRACK_OF_REMAINDERS)
|
1129
|
+
if @rs.include?(r)
|
1130
|
+
repeat_count = @rs.index(r) - @rs.size
|
1131
|
+
else
|
1132
|
+
@rs << r
|
1133
|
+
end
|
1134
|
+
end
|
1135
|
+
if repeat_count
|
1136
|
+
raise InfiniteLoopError, "Infinite digit sequence." if @raise_on_repeat
|
1137
|
+
repeat_count
|
1138
|
+
else
|
1139
|
+
nil
|
1140
|
+
end
|
1141
|
+
end
|
1142
|
+
|
1143
|
+
def remove_redundant_repetitions
|
1144
|
+
if ITERATIONS_BEFORE_KEEPING_TRACK_OF_REMAINDERS > 0 && @repeat
|
1145
|
+
if @repeat < @digits.size
|
1146
|
+
repeating_digits = @digits[@repeat..-1]
|
1147
|
+
l = repeating_digits.size
|
1148
|
+
pos = @repeat - l
|
1149
|
+
while pos >= 0 && @digits[pos, l] == repeating_digits
|
1150
|
+
pos -= l
|
1151
|
+
end
|
1152
|
+
first_repeat = pos + l
|
1153
|
+
if first_repeat < @repeat
|
1154
|
+
@repeat = first_repeat
|
1155
|
+
@digits = @digits[0, @repeat+l]
|
1156
|
+
end
|
1157
|
+
end
|
1158
|
+
end
|
1159
|
+
@digits
|
1160
|
+
end
|
1161
|
+
|
1081
1162
|
def generate_max
|
1082
1163
|
@round_up = false
|
1083
1164
|
list = []
|
1084
1165
|
r, s, m_p, m_m, = @r, @s, @m_p, @m_m
|
1085
|
-
|
1166
|
+
|
1167
|
+
start_repetition_dectection
|
1168
|
+
|
1086
1169
|
loop do
|
1087
|
-
if
|
1088
|
-
|
1089
|
-
|
1090
|
-
else
|
1091
|
-
n_iters += 1
|
1170
|
+
if repeat_count = detect_repetitions(r)
|
1171
|
+
@repeat = list.size + repeat_count
|
1172
|
+
break
|
1092
1173
|
end
|
1093
1174
|
|
1094
1175
|
d,r = (r*@output_b).divmod(s)
|
@@ -1116,6 +1197,7 @@ module Flt
|
|
1116
1197
|
end
|
1117
1198
|
end
|
1118
1199
|
@digits = list
|
1200
|
+
remove_redundant_repetitions
|
1119
1201
|
end
|
1120
1202
|
|
1121
1203
|
def generate
|
data/lib/flt/version.rb
CHANGED
@@ -0,0 +1,197 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__),'helper.rb'))
|
2
|
+
|
3
|
+
|
4
|
+
class TestExact < Test::Unit::TestCase
|
5
|
+
|
6
|
+
|
7
|
+
def setup
|
8
|
+
initialize_context
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_binary_to_decimal_formatter
|
12
|
+
Flt::BinNum.context = Flt::BinNum::IEEEDoubleContext
|
13
|
+
formatter = Flt::Support::Formatter.new(BinNum.radix, BinNum.context.etiny, 10)
|
14
|
+
|
15
|
+
x = BinNum(0.1)
|
16
|
+
s, f, e = x.split
|
17
|
+
|
18
|
+
digits = formatter.format(x, f, e, :half_even, BinNum.context.precision, false)
|
19
|
+
assert_equal [1], digits
|
20
|
+
|
21
|
+
digits = formatter.format(x, f, e, :half_even, BinNum.context.precision, true)
|
22
|
+
assert_equal [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], digits
|
23
|
+
assert_equal :hi, formatter.round_up
|
24
|
+
|
25
|
+
digits = formatter.format(x, f, e, :up, BinNum.context.precision, false)
|
26
|
+
assert_equal [1], digits
|
27
|
+
|
28
|
+
assert_raise(Flt::Support::InfiniteLoopError) { formatter.format(x, f, e, :up, BinNum.context.precision, true) }
|
29
|
+
|
30
|
+
digits = formatter.format(x, f, e, :down, BinNum.context.precision, false)
|
31
|
+
assert_equal [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
|
32
|
+
digits
|
33
|
+
|
34
|
+
digits = formatter.format(x, f, e, :down, BinNum.context.precision, true)
|
35
|
+
assert_equal [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 1, 1, 1, 5, 1, 2, 3, 1, 2, 5, 7, 8, 2, 7, 0, 2, 1, 1, 8, 1, 5, 8, 3, 4, 0, 4, 5, 4, 1, 0, 1, 5, 6, 2, 5],
|
36
|
+
digits
|
37
|
+
|
38
|
+
x = BinNum(0.5)
|
39
|
+
s, f, e = x.split
|
40
|
+
|
41
|
+
digits = formatter.format(x, f, e, :half_even, BinNum.context.precision, false)
|
42
|
+
assert_equal [5], digits
|
43
|
+
|
44
|
+
digits = formatter.format(x, f, e, :half_even, BinNum.context.precision, true)
|
45
|
+
assert_equal [5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], digits
|
46
|
+
refute formatter.round_up
|
47
|
+
|
48
|
+
digits = formatter.format(x, f, e, :up, BinNum.context.precision, false)
|
49
|
+
assert_equal [5], digits
|
50
|
+
|
51
|
+
assert_raise(Flt::Support::InfiniteLoopError) { formatter.format(x, f, e, :up, BinNum.context.precision, true) }
|
52
|
+
|
53
|
+
digits = formatter.format(x, f, e, :down, BinNum.context.precision, false)
|
54
|
+
assert_equal [5], digits
|
55
|
+
|
56
|
+
digits = formatter.format(x, f, e, :down, BinNum.context.precision, true)
|
57
|
+
assert_equal [5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], digits
|
58
|
+
refute formatter.round_up
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_binary_to_repeating_decimal_formatter
|
62
|
+
Flt::BinNum.context = Flt::BinNum::IEEEDoubleContext
|
63
|
+
formatter = Flt::Support::Formatter.new(BinNum.radix, BinNum.context.etiny, 10, raise_on_repeat: false)
|
64
|
+
|
65
|
+
x = BinNum(0.1)
|
66
|
+
s, f, e = x.split
|
67
|
+
|
68
|
+
digits = formatter.format(x, f, e, :half_even, BinNum.context.precision, false)
|
69
|
+
assert_equal [1], digits
|
70
|
+
|
71
|
+
digits = formatter.format(x, f, e, :half_even, BinNum.context.precision, true)
|
72
|
+
assert_equal [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], digits
|
73
|
+
assert_equal :hi, formatter.round_up
|
74
|
+
refute formatter.repeat
|
75
|
+
|
76
|
+
digits = formatter.format(x, f, e, :up, BinNum.context.precision, false)
|
77
|
+
assert_equal [1], digits
|
78
|
+
|
79
|
+
assert_nothing_raised { formatter.format(x, f, e, :up, BinNum.context.precision, true) }
|
80
|
+
digits = formatter.format(x, f, e, :up, BinNum.context.precision, true)
|
81
|
+
assert_equal [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 1, 1, 1, 5, 1, 2, 3, 1, 2, 5, 7, 8, 2, 7, 0, 2, 1, 1, 8, 1, 5, 8, 3, 4, 0, 4, 5, 4, 1, 0, 1, 5, 6, 2, 5],
|
82
|
+
digits
|
83
|
+
refute formatter.round_up
|
84
|
+
assert_equal 55, formatter.repeat
|
85
|
+
|
86
|
+
digits = formatter.format(x, f, e, :down, BinNum.context.precision, false)
|
87
|
+
assert_equal [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
|
88
|
+
digits
|
89
|
+
|
90
|
+
digits = formatter.format(x, f, e, :down, BinNum.context.precision, true)
|
91
|
+
assert_equal [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 1, 1, 1, 5, 1, 2, 3, 1, 2, 5, 7, 8, 2, 7, 0, 2, 1, 1, 8, 1, 5, 8, 3, 4, 0, 4, 5, 4, 1, 0, 1, 5, 6, 2, 5],
|
92
|
+
digits
|
93
|
+
|
94
|
+
x = BinNum(0.5)
|
95
|
+
s, f, e = x.split
|
96
|
+
|
97
|
+
digits = formatter.format(x, f, e, :half_even, BinNum.context.precision, false)
|
98
|
+
assert_equal [5], digits
|
99
|
+
|
100
|
+
digits = formatter.format(x, f, e, :half_even, BinNum.context.precision, true)
|
101
|
+
assert_equal [5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], digits
|
102
|
+
refute formatter.round_up
|
103
|
+
|
104
|
+
digits = formatter.format(x, f, e, :up, BinNum.context.precision, false)
|
105
|
+
assert_equal [5], digits
|
106
|
+
|
107
|
+
assert_nothing_raised { formatter.format(x, f, e, :up, BinNum.context.precision, true) }
|
108
|
+
digits = formatter.format(x, f, e, :up, BinNum.context.precision, true)
|
109
|
+
assert_equal [5], digits
|
110
|
+
refute formatter.round_up
|
111
|
+
assert_equal 1, formatter.repeat
|
112
|
+
|
113
|
+
digits = formatter.format(x, f, e, :down, BinNum.context.precision, false)
|
114
|
+
assert_equal [5], digits
|
115
|
+
|
116
|
+
digits = formatter.format(x, f, e, :down, BinNum.context.precision, true)
|
117
|
+
assert_equal [5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], digits
|
118
|
+
refute formatter.round_up
|
119
|
+
end
|
120
|
+
|
121
|
+
def test_decimal_to_binary_formatter
|
122
|
+
Flt::DecNum.context.precision = 8
|
123
|
+
formatter = Flt::Support::Formatter.new(DecNum.radix, DecNum.context.etiny, 2)
|
124
|
+
|
125
|
+
x = DecNum('0.1')
|
126
|
+
s, f, e = x.split
|
127
|
+
digits = formatter.format(x, f, e, :half_even, DecNum.context.precision, false)
|
128
|
+
assert_equal [1], digits
|
129
|
+
|
130
|
+
digits = formatter.format(x, f, e, :half_even, DecNum.context.precision, true)
|
131
|
+
assert_equal [0,1], digits
|
132
|
+
assert_equal :hi, formatter.round_up
|
133
|
+
|
134
|
+
x = DecNum('0.1000000')
|
135
|
+
s, f, e = x.split
|
136
|
+
|
137
|
+
digits = formatter.format(x, f, e, :half_even, DecNum.context.precision, false)
|
138
|
+
assert_equal [1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1], digits
|
139
|
+
|
140
|
+
digits = formatter.format(x, f, e, :half_even, DecNum.context.precision, true)
|
141
|
+
assert_equal [1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1], digits
|
142
|
+
assert_equal :hi, formatter.round_up
|
143
|
+
|
144
|
+
digits = formatter.format(x, f, e, :up, DecNum.context.precision, false)
|
145
|
+
assert_equal [1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1], digits
|
146
|
+
|
147
|
+
assert_raise(Support::InfiniteLoopError) { formatter.format(x, f, e, :up, DecNum.context.precision, true) }
|
148
|
+
|
149
|
+
digits = formatter.format(x, f, e, :down, DecNum.context.precision, false)
|
150
|
+
assert_equal [1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1], digits
|
151
|
+
|
152
|
+
assert_raise(Support::InfiniteLoopError) { formatter.format(x, f, e, :down, DecNum.context.precision, true) }
|
153
|
+
end
|
154
|
+
|
155
|
+
def test_decimal_to_repeating_binary_formatter
|
156
|
+
Flt::DecNum.context.precision = 8
|
157
|
+
formatter = Flt::Support::Formatter.new(DecNum.radix, DecNum.context.etiny, 2, raise_on_repeat: false)
|
158
|
+
|
159
|
+
x = DecNum('0.1')
|
160
|
+
s, f, e = x.split
|
161
|
+
digits = formatter.format(x, f, e, :half_even, DecNum.context.precision, false)
|
162
|
+
assert_equal [1], digits
|
163
|
+
|
164
|
+
digits = formatter.format(x, f, e, :half_even, DecNum.context.precision, true)
|
165
|
+
assert_equal [0,1], digits
|
166
|
+
assert_equal :hi, formatter.round_up
|
167
|
+
|
168
|
+
x = DecNum('0.1000000')
|
169
|
+
s, f, e = x.split
|
170
|
+
|
171
|
+
digits = formatter.format(x, f, e, :half_even, DecNum.context.precision, false)
|
172
|
+
assert_equal [1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1], digits
|
173
|
+
|
174
|
+
digits = formatter.format(x, f, e, :half_even, DecNum.context.precision, true)
|
175
|
+
assert_equal [1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1], digits
|
176
|
+
assert_equal :hi, formatter.round_up
|
177
|
+
|
178
|
+
digits = formatter.format(x, f, e, :up, DecNum.context.precision, false)
|
179
|
+
assert_equal [1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1], digits
|
180
|
+
|
181
|
+
assert_nothing_raised { formatter.format(x, f, e, :up, DecNum.context.precision, true) }
|
182
|
+
digits = formatter.format(x, f, e, :up, DecNum.context.precision, true)
|
183
|
+
assert_equal [1, 1, 0, 0], digits
|
184
|
+
refute formatter.round_up
|
185
|
+
assert_equal 0, formatter.repeat
|
186
|
+
|
187
|
+
digits = formatter.format(x, f, e, :down, DecNum.context.precision, false)
|
188
|
+
assert_equal [1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1], digits
|
189
|
+
|
190
|
+
assert_nothing_raised { formatter.format(x, f, e, :down, DecNum.context.precision, true) }
|
191
|
+
digits = formatter.format(x, f, e, :down, DecNum.context.precision, true)
|
192
|
+
assert_equal [1, 1, 0, 0], digits
|
193
|
+
refute formatter.round_up
|
194
|
+
assert_equal 0, formatter.repeat
|
195
|
+
end
|
196
|
+
|
197
|
+
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.3
|
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-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -87,6 +87,7 @@ files:
|
|
87
87
|
- test/test_epsilon.rb
|
88
88
|
- test/test_exact.rb
|
89
89
|
- test/test_flags.rb
|
90
|
+
- test/test_formatter.rb
|
90
91
|
- test/test_multithreading.rb
|
91
92
|
- test/test_num_constructor.rb
|
92
93
|
- test/test_odd_even.rb
|
@@ -137,6 +138,7 @@ test_files:
|
|
137
138
|
- test/test_epsilon.rb
|
138
139
|
- test/test_exact.rb
|
139
140
|
- test/test_flags.rb
|
141
|
+
- test/test_formatter.rb
|
140
142
|
- test/test_multithreading.rb
|
141
143
|
- test/test_num_constructor.rb
|
142
144
|
- test/test_odd_even.rb
|