flt 1.3.0 → 1.3.1
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 +7 -0
- data/.gitignore +28 -0
- data/Gemfile +3 -0
- data/History.txt +4 -0
- data/Manifest.txt +1 -2
- data/{README.txt → README.rdoc} +24 -15
- data/Rakefile +15 -30
- data/expand.rb +177 -0
- data/flt.gemspec +23 -0
- data/lib/flt.rb +1 -1
- data/lib/flt/float.rb +1 -1
- data/lib/flt/num.rb +88 -27
- data/lib/flt/sugar.rb +3 -0
- data/lib/flt/tolerance.rb +1 -1
- data/lib/flt/version.rb +1 -7
- data/test/test_define_conversions.rb +4 -4
- data/test/test_sugar.rb +5 -5
- metadata +64 -87
- data/tasks/ann.rake +0 -80
- data/tasks/bones.rake +0 -20
- data/tasks/gem.rake +0 -192
- data/tasks/git.rake +0 -40
- data/tasks/manifest.rake +0 -48
- data/tasks/notes.rake +0 -27
- data/tasks/post_load.rake +0 -39
- data/tasks/rdoc.rake +0 -50
- data/tasks/rubyforge.rake +0 -55
- data/tasks/setup.rb +0 -279
- data/tasks/spec.rake +0 -54
- data/tasks/svn.rake +0 -47
- data/tasks/test.rake +0 -40
data/lib/flt/float.rb
CHANGED
data/lib/flt/num.rb
CHANGED
@@ -3,19 +3,21 @@
|
|
3
3
|
#--
|
4
4
|
# =Notes on the representation of Flt::Num numbers.
|
5
5
|
#
|
6
|
-
# @sign is +1 for plus and -1 for minus
|
7
|
-
# @coeff is the integral significand stored as an integer (so leading zeros cannot be kept)
|
8
|
-
# @exp is the exponent to be applied to @coeff as an integer or one of :inf, :nan, :snan for special values
|
6
|
+
# * @sign is +1 for plus and -1 for minus
|
7
|
+
# * @coeff is the integral significand stored as an integer (so leading zeros cannot be kept)
|
8
|
+
# * @exp is the exponent to be applied to @coeff as an integer or one of :inf, :nan, :snan for special values
|
9
9
|
#
|
10
|
+
# The value represented is @sign*@coeff*b**@exp with b = num_class.radix the radix for the the Num-derived class.
|
11
|
+
|
10
12
|
# The original Python Decimal representation has these slots:
|
11
|
-
# _sign is 1 for minus, 0 for plus
|
12
|
-
# _int is the integral significand as a string of digits (leading zeroes are not kept)
|
13
|
-
# _exp is the exponent as an integer or 'F' for infinity, 'n' for NaN , 'N' for sNaN
|
14
|
-
# _is_especial is true for special values (infinity, NaN, sNaN)
|
13
|
+
# * _sign is 1 for minus, 0 for plus
|
14
|
+
# * _int is the integral significand as a string of digits (leading zeroes are not kept)
|
15
|
+
# * _exp is the exponent as an integer or 'F' for infinity, 'n' for NaN , 'N' for sNaN
|
16
|
+
# * _is_especial is true for special values (infinity, NaN, sNaN)
|
15
17
|
# An additional class _WorkRep is used in Python for non-special decimal values with:
|
16
|
-
# sign
|
17
|
-
# int (significand as an integer)
|
18
|
-
# exp
|
18
|
+
# * sign
|
19
|
+
# * int (significand as an integer)
|
20
|
+
# * exp
|
19
21
|
#
|
20
22
|
# =Exponent values
|
21
23
|
#
|
@@ -24,9 +26,15 @@
|
|
24
26
|
#
|
25
27
|
# The reduce operation (originally called 'normalize') removes trailing 0s and increments the exponent if necessary;
|
26
28
|
# the representation is rescaled to use the maximum exponent possible (while maintaining an integral significand.)
|
29
|
+
# So, a reduced number uses as few digits as possible to retain it's value; information about digit significance
|
30
|
+
# is lost.
|
27
31
|
#
|
28
|
-
# A classical floating-point normalize
|
29
|
-
# rescaling to the minimum exponent
|
32
|
+
# A classical floating-point normalize operation would remove leading 0s and decrement the exponent instead,
|
33
|
+
# rescaling to the minimum exponent that maintains the significand value under some conventional limit
|
34
|
+
# (1 for fractional normalization; the radix for scientific or adjusted normalization and the maximum
|
35
|
+
# integral significand with as many digits as determined by the context precision for integral normalization.)
|
36
|
+
# So, normalization is meaningful given some fixed limited precision, as given by the context precision in our case.
|
37
|
+
# Normalization uses all the available precision digits and loses information about digit significance too.
|
30
38
|
#
|
31
39
|
# The logb and adjusted operations return the exponent that applies to the most significand digit (logb as a Decimal
|
32
40
|
# and adjusted as an integer.) This is the normalized scientific exponent.
|
@@ -40,15 +48,25 @@
|
|
40
48
|
# The number of (kept) significand digits is s = a - e + 1
|
41
49
|
# where a is the adjusted exponent and e is the internal exponent (the unnormalized integral exponent.)
|
42
50
|
#
|
43
|
-
# The number of significant digits (excluding leading and trailing zeroes) is sr = a - re + 1
|
51
|
+
# The number of significant digits (excluding leading and trailing zeroes) is sr = a - re + 1 = s + e - re
|
44
52
|
# where re is the internal exponent of the reduced value.
|
45
53
|
#
|
46
|
-
# The normalized integral exponent is e - (p - s) = a - p + 1
|
54
|
+
# The normalized integral exponent is ei = e - (p - s) = a - p + 1
|
47
55
|
# where p is the fixed precision.
|
48
56
|
#
|
49
|
-
# The normalized fractional exponent is e + s = a + 1
|
57
|
+
# The normalized fractional exponent is ef = e + s = a + 1
|
58
|
+
#
|
59
|
+
# For context c and a number x we have:
|
60
|
+
# * e == x.exponent == x.to_int_scale.last == x.integral_exponent
|
61
|
+
# * ei == c.normalized_integral_exponent(x) == c.normalize(x).exponent == c.to_normalized_int_scale(x).last
|
62
|
+
# * a == c.adjusted_exponent == c.scientific_exponent == c.logb(x).to_i == c.a
|
63
|
+
# * re == c.reduce(x).exponent.to_i == c.reduced_exponent # the first uses c because it rounds to it
|
64
|
+
# * s == x.number_of_digits == x.digits.size
|
65
|
+
# * sr == c.reduce(x).number_of_digits
|
66
|
+
# * p == c.precision
|
67
|
+
# * ne == x.fractional_exponent
|
50
68
|
#
|
51
|
-
# ==Example: 0.
|
69
|
+
# ==Example: 0.0120400
|
52
70
|
#
|
53
71
|
# * The integral significand is 120400 and the internal exponent that applies to it is e = -7
|
54
72
|
# * The number of significand digits is s = 6
|
@@ -60,13 +78,25 @@
|
|
60
78
|
#
|
61
79
|
# ==Exponent limits
|
62
80
|
#
|
63
|
-
#
|
64
|
-
#
|
65
|
-
#
|
66
|
-
#
|
67
|
-
#
|
68
|
-
#
|
69
|
-
#
|
81
|
+
# A context defines the limits for adjusted (scientific) exponents, emin, emax, and equivalently,
|
82
|
+
# the limits for internal (integral) exponents, etiny, etop. The emin, emax are the limits of the exponent
|
83
|
+
# shown in scientific notation (except for subnormal numbers) and are use to define the context exponent
|
84
|
+
# limits. We have etiny == emin-p+1 and etop==emax-p+1 where p is the context precision.
|
85
|
+
#
|
86
|
+
# For a given context a number with an integral significand not exceeding the context precision in number of digits
|
87
|
+
# and with integral exponents e in the range:
|
88
|
+
# etiny <= e <= etop
|
89
|
+
# is always valid.
|
90
|
+
# The adjusted exponent, a, of valid normal numbers within the context must verify:
|
91
|
+
# emin <= a <= emax
|
92
|
+
# If the significand is normalized (uses the full precision of the context)
|
93
|
+
# the internal exponent cannot exceed etop. Significands with less digits than the context precision
|
94
|
+
# can have internal exponents greater than etop withoug causing overflow:
|
95
|
+
# +DecNum(1,context.emax) == DecNum(10**(context.precision-1),context.etop)
|
96
|
+
# The maximum finite value, which has a normalized (full precision) significand has internal exponent e==etop.
|
97
|
+
# The minimum normal value and all adjusted subnormal values have e==etiny, but non-adjusted subnormal values
|
98
|
+
# can have e<etiny: +DecNum(10,context.etiny-1) == Decimal(1,context.etiny) == context.minimum_nonzero
|
99
|
+
# Subnormal numbers have adjusted exponents in the range: context.etiny <= a < context.emin
|
70
100
|
#
|
71
101
|
# =Interoperatibility with other numeric types
|
72
102
|
#
|
@@ -96,7 +126,6 @@
|
|
96
126
|
#++
|
97
127
|
|
98
128
|
require 'flt/support'
|
99
|
-
require 'flt/version'
|
100
129
|
|
101
130
|
require 'bigdecimal'
|
102
131
|
require 'forwardable'
|
@@ -933,7 +962,7 @@ class Num < Numeric
|
|
933
962
|
# Maximum finite number
|
934
963
|
def maximum_finite(sign=+1)
|
935
964
|
return exception(InvalidOperation, "Exact context maximum finite value") if exact?
|
936
|
-
# equals
|
965
|
+
# equals Num(+1, 1, emax+1) - Num(+1, 1, etop)
|
937
966
|
# equals Num.infinity.next_minus(self)
|
938
967
|
Num(sign, num_class.int_radix_power(precision)-1, etop)
|
939
968
|
end
|
@@ -2260,6 +2289,24 @@ class Num < Numeric
|
|
2260
2289
|
return Num(dup.sign, coeff/num_class.int_radix_power(nd-end_d), exp)
|
2261
2290
|
end
|
2262
2291
|
|
2292
|
+
# Exponent corresponding to the integral significand with all trailing digits removed.
|
2293
|
+
# Does not use any context; equals the value of self.reduce.exponent (but as an integer rather than a Num)
|
2294
|
+
# except for special values and when the number is rounded under the context or exceeds its limits.
|
2295
|
+
def reduced_exponent
|
2296
|
+
if self.special? || self.zero?
|
2297
|
+
0
|
2298
|
+
else
|
2299
|
+
exp = self.exponent
|
2300
|
+
dgs = self.digits
|
2301
|
+
nd = dgs.size # self.number_of_digits
|
2302
|
+
while dgs[nd-1]==0
|
2303
|
+
exp += 1
|
2304
|
+
nd -= 1
|
2305
|
+
end
|
2306
|
+
exp
|
2307
|
+
end
|
2308
|
+
end
|
2309
|
+
|
2263
2310
|
# Normalizes (changes quantum) so that the coefficient has precision digits, unless it is subnormal.
|
2264
2311
|
# For surnormal numbers the Subnormal flag is raised an a subnormal is returned with the smallest
|
2265
2312
|
# possible exponent.
|
@@ -2641,6 +2688,21 @@ class Num < Numeric
|
|
2641
2688
|
def ==(other)
|
2642
2689
|
(self<=>other) == 0
|
2643
2690
|
end
|
2691
|
+
|
2692
|
+
# For MRI this is unnecesary, but it is needed for Rubinius because of the coercion done in Numeric#< etc.
|
2693
|
+
def <=(other)
|
2694
|
+
(self<=>other) <= 0
|
2695
|
+
end
|
2696
|
+
def <(other)
|
2697
|
+
(self<=>other) < 0
|
2698
|
+
end
|
2699
|
+
def >=(other)
|
2700
|
+
(self<=>other) >= 0
|
2701
|
+
end
|
2702
|
+
def >(other)
|
2703
|
+
(self<=>other) > 0
|
2704
|
+
end
|
2705
|
+
|
2644
2706
|
include Comparable
|
2645
2707
|
|
2646
2708
|
def hash
|
@@ -4205,7 +4267,6 @@ class Num < Numeric
|
|
4205
4267
|
(1...t).to_a.reverse.each do |k|
|
4206
4268
|
w = _div_nearest(m, k) - _div_nearest(yshift*w, m)
|
4207
4269
|
end
|
4208
|
-
|
4209
4270
|
return _div_nearest(w*y, m)
|
4210
4271
|
end
|
4211
4272
|
|
@@ -4493,4 +4554,4 @@ class Num < Numeric
|
|
4493
4554
|
|
4494
4555
|
end # Num
|
4495
4556
|
|
4496
|
-
end # Flt
|
4557
|
+
end # Flt
|
data/lib/flt/sugar.rb
CHANGED
@@ -102,6 +102,9 @@ end
|
|
102
102
|
|
103
103
|
# Shortcut to define DecNums, e.g. 1._234567890123456789 produces Flt::DecNum('1.234567890123456789')
|
104
104
|
# Based on http://coderrr.wordpress.com/2009/12/22/get-arbitrarily-precise-bigdecimals-in-ruby-for-just-one-extra-character/
|
105
|
+
# There's a problem with negative numbers with a null integer part: -0._1 is parsed as (-0)._1 and -0 is 0.
|
106
|
+
# The problem cannot be solved by redefinition of -@ for integers because -0 is interpreted as 0 by the Ruby parser
|
107
|
+
# (no runtime method call is involved). Such numbers have to be entered as -(0._1)
|
105
108
|
class Integer
|
106
109
|
def method_missing(m, *a, &b)
|
107
110
|
return Flt::DecNum("#{self}.#{$1.tr('_','')}") if m.to_s =~ /^_(\d[_\d]*)$/
|
data/lib/flt/tolerance.rb
CHANGED
data/lib/flt/version.rb
CHANGED
@@ -55,7 +55,7 @@ class TestDefineConversions < Test::Unit::TestCase
|
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
|
-
assert_raise(TypeError) { DecNum('0') == BigDecimal.new('0') }
|
58
|
+
assert_raise(TypeError, RuntimeError) { DecNum('0') == BigDecimal.new('0') }
|
59
59
|
unless Num < Numeric
|
60
60
|
# BigDecimal#eql? is weird
|
61
61
|
assert_not_equal BigDecimal.new('0'), DecNum('0')
|
@@ -64,11 +64,11 @@ class TestDefineConversions < Test::Unit::TestCase
|
|
64
64
|
assert_not_equal BigDecimal.new('1.2345'), DecNum('0.0012345000E3')
|
65
65
|
assert_raise(TypeError) { BigDecimal.new('7')+DecNum('0.1') }
|
66
66
|
end
|
67
|
-
assert_raise(TypeError) { DecNum('7')+BigDecimal.new('0.1') }
|
68
|
-
assert_raise(TypeError) { DecNum(BigDecimal.new('1.1')) }
|
67
|
+
assert_raise(TypeError, RuntimeError) { DecNum('7')+BigDecimal.new('0.1') }
|
68
|
+
assert_raise(TypeError, RuntimeError) { DecNum(BigDecimal.new('1.1')) }
|
69
69
|
|
70
70
|
['0.1', '-0.1', '0.0', '1234567.1234567', '-1234567.1234567', '1.234E7', '1.234E-7'].each do |n|
|
71
|
-
assert_raise(TypeError) { DecNum(n).convert_to(BigDecimal) }
|
71
|
+
assert_raise(TypeError, RuntimeError) { DecNum(n).convert_to(BigDecimal) }
|
72
72
|
end
|
73
73
|
|
74
74
|
end
|
data/test/test_sugar.rb
CHANGED
@@ -14,11 +14,11 @@ class TestSugar < Test::Unit::TestCase
|
|
14
14
|
123456789123._01234567890123456789012345678901234567890123456789
|
15
15
|
assert_equal Flt::DecNum('-123456789123.01234567890123456789012345678901234567890123456789'),
|
16
16
|
-123456789123._01234567890123456789012345678901234567890123456789
|
17
|
-
assert_raise(NoMethodError){3._x}
|
18
|
-
assert_raise(NoMethodError){3._3233x}
|
19
|
-
assert_raise(NoMethodError){3._3233x34333}
|
20
|
-
assert_raise(NoMethodError){3.__}
|
21
|
-
assert_raise(NoMethodError){3._}
|
17
|
+
assert_raise(NoMethodError,NameError){3._x}
|
18
|
+
assert_raise(NoMethodError,NameError){3._3233x}
|
19
|
+
assert_raise(NoMethodError,NameError){3._3233x34333}
|
20
|
+
assert_raise(NoMethodError,NameError){3.__}
|
21
|
+
assert_raise(NoMethodError,NameError){3._}
|
22
22
|
assert_equal Flt::DecNum, 10._32_23.class
|
23
23
|
assert_equal Flt::DecNum('10.3223'), 10._32_23
|
24
24
|
assert_equal Flt::DecNum('3.01234567890123456789012345678901234567890123456789'),
|
metadata
CHANGED
@@ -1,55 +1,60 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: flt
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease: false
|
6
|
-
segments:
|
7
|
-
- 1
|
8
|
-
- 3
|
9
|
-
- 0
|
10
|
-
version: 1.3.0
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.3.1
|
11
5
|
platform: ruby
|
12
|
-
authors:
|
6
|
+
authors:
|
13
7
|
- Javier Goizueta
|
14
8
|
autorequire:
|
15
9
|
bindir: bin
|
16
10
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
11
|
+
date: 2014-05-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.6'
|
20
|
+
type: :development
|
23
21
|
prerelease: false
|
24
|
-
|
25
|
-
|
26
|
-
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
27
31
|
- - ">="
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
|
30
|
-
segments:
|
31
|
-
- 2
|
32
|
-
- 1
|
33
|
-
- 1
|
34
|
-
version: 2.1.1
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
35
34
|
type: :development
|
36
|
-
|
37
|
-
|
38
|
-
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: Decimal and binary arbitrary precision floating point numbers in pure
|
42
|
+
Ruby.
|
43
|
+
email:
|
44
|
+
- jgoizueta@gmail.com
|
39
45
|
executables: []
|
40
|
-
|
41
46
|
extensions: []
|
42
|
-
|
43
|
-
|
44
|
-
-
|
45
|
-
-
|
46
|
-
- README.txt
|
47
|
-
files:
|
47
|
+
extra_rdoc_files: []
|
48
|
+
files:
|
49
|
+
- ".gitignore"
|
50
|
+
- Gemfile
|
48
51
|
- History.txt
|
49
52
|
- License.txt
|
50
53
|
- Manifest.txt
|
51
|
-
- README.
|
54
|
+
- README.rdoc
|
52
55
|
- Rakefile
|
56
|
+
- expand.rb
|
57
|
+
- flt.gemspec
|
53
58
|
- lib/flt.rb
|
54
59
|
- lib/flt/b.rb
|
55
60
|
- lib/flt/bigdecimal.rb
|
@@ -67,19 +72,6 @@ files:
|
|
67
72
|
- lib/flt/trigonometry.rb
|
68
73
|
- lib/flt/version.rb
|
69
74
|
- setup.rb
|
70
|
-
- tasks/ann.rake
|
71
|
-
- tasks/bones.rake
|
72
|
-
- tasks/gem.rake
|
73
|
-
- tasks/git.rake
|
74
|
-
- tasks/manifest.rake
|
75
|
-
- tasks/notes.rake
|
76
|
-
- tasks/post_load.rake
|
77
|
-
- tasks/rdoc.rake
|
78
|
-
- tasks/rubyforge.rake
|
79
|
-
- tasks/setup.rb
|
80
|
-
- tasks/spec.rake
|
81
|
-
- tasks/svn.rake
|
82
|
-
- tasks/test.rake
|
83
75
|
- test/all_tests.rb
|
84
76
|
- test/generate_trig_data.rb
|
85
77
|
- test/helper.rb
|
@@ -105,50 +97,35 @@ files:
|
|
105
97
|
- test/test_tol.rb
|
106
98
|
- test/test_trig.rb
|
107
99
|
- test/test_ulp.rb
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
100
|
+
homepage: http://github.com/jgoizueta/flt
|
101
|
+
licenses:
|
102
|
+
- MIT
|
103
|
+
metadata: {}
|
112
104
|
post_install_message:
|
113
|
-
rdoc_options:
|
114
|
-
|
115
|
-
- README.txt
|
116
|
-
- --title
|
117
|
-
- Ruby Flt Documentation
|
118
|
-
- --opname
|
119
|
-
- index.html
|
120
|
-
- --line-numbers
|
121
|
-
- --inline-source
|
122
|
-
- --main
|
123
|
-
- README.txt
|
124
|
-
require_paths:
|
105
|
+
rdoc_options: []
|
106
|
+
require_paths:
|
125
107
|
- lib
|
126
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
127
|
-
|
128
|
-
requirements:
|
108
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
129
110
|
- - ">="
|
130
|
-
- !ruby/object:Gem::Version
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
version: "0"
|
135
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
136
|
-
none: false
|
137
|
-
requirements:
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0'
|
113
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
138
115
|
- - ">="
|
139
|
-
- !ruby/object:Gem::Version
|
140
|
-
|
141
|
-
segments:
|
142
|
-
- 0
|
143
|
-
version: "0"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
144
118
|
requirements: []
|
145
|
-
|
146
|
-
|
147
|
-
rubygems_version: 1.3.7
|
119
|
+
rubyforge_project:
|
120
|
+
rubygems_version: 2.2.2
|
148
121
|
signing_key:
|
149
|
-
specification_version:
|
122
|
+
specification_version: 4
|
150
123
|
summary: Floating Point Numbers
|
151
|
-
test_files:
|
124
|
+
test_files:
|
125
|
+
- test/all_tests.rb
|
126
|
+
- test/generate_trig_data.rb
|
127
|
+
- test/helper.rb
|
128
|
+
- test/reader.rb
|
152
129
|
- test/test_basic.rb
|
153
130
|
- test/test_bin.rb
|
154
131
|
- test/test_bin_arithmetic.rb
|