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.
data/lib/flt/float.rb CHANGED
@@ -459,7 +459,7 @@ class Flt::FloatContext
459
459
  end
460
460
 
461
461
  def pi
462
- Float::PI
462
+ Math::PI
463
463
  end
464
464
 
465
465
  def eval
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 opwration would remove leading 0s and decrement the exponent instead,
29
- # rescaling to the minimum exponent theat maintains the significand value under some conventional limit (1 or the radix).
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.01204
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
- # The (integral) exponent e must be within this limits: etiny <= e <= etop
64
- # The adjusted exponent a must: emin <= a <= emax
65
- # emin, emax are the limite of the exponent shown in scientific notation and are use to defined
66
- # the exponent limits in the contexts.
67
- # etiny = emin-precision+1 and etop=emax-precision+1 are the limits of the internal exponent.
68
- # Note that for significands with less than precision digits we can use exponents greater than etop
69
- # without causing overflow: +Decimal(+1,1,emax) == Decimal(+1,K,etop) where K=10**(precision-1)
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 +Num(+1, 1, emax)
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
@@ -160,7 +160,7 @@ module Flt
160
160
  end
161
161
 
162
162
  # strongly equals: x == y within tolerance (strict)
163
- def seq?
163
+ def seq?(x, y)
164
164
  (x-y).abs <= relative_to_many(:min, x, y)
165
165
  end
166
166
 
data/lib/flt/version.rb CHANGED
@@ -1,9 +1,3 @@
1
1
  module Flt
2
- module VERSION #:nodoc:
3
- MAJOR = 1
4
- MINOR = 3
5
- TINY = 0
6
-
7
- STRING = [MAJOR, MINOR, TINY].join('.')
8
- end
2
+ VERSION = "1.3.1"
9
3
  end
@@ -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
- hash: 27
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
- date: 2010-06-22 00:00:00 +02:00
19
- default_executable:
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
22
- name: bones
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
- requirement: &id001 !ruby/object:Gem::Requirement
25
- none: false
26
- requirements:
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
- hash: 9
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
- version_requirements: *id001
37
- description: Floating Point Numbers
38
- email: javier@goizueta.info
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
- extra_rdoc_files:
44
- - History.txt
45
- - License.txt
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.txt
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
- has_rdoc: true
109
- homepage: http://flt.rubyforge.org
110
- licenses: []
111
-
100
+ homepage: http://github.com/jgoizueta/flt
101
+ licenses:
102
+ - MIT
103
+ metadata: {}
112
104
  post_install_message:
113
- rdoc_options:
114
- - --main
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
- none: false
128
- requirements:
108
+ required_ruby_version: !ruby/object:Gem::Requirement
109
+ requirements:
129
110
  - - ">="
130
- - !ruby/object:Gem::Version
131
- hash: 3
132
- segments:
133
- - 0
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
- hash: 3
141
- segments:
142
- - 0
143
- version: "0"
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
144
118
  requirements: []
145
-
146
- rubyforge_project: flt
147
- rubygems_version: 1.3.7
119
+ rubyforge_project:
120
+ rubygems_version: 2.2.2
148
121
  signing_key:
149
- specification_version: 3
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