flt 1.3.0 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
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