rubysl-mathn 1.0.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 467e937606c8e419d779633cb724dd5327bfeeff
4
- data.tar.gz: 1bcc431f67bb1a5581d5574aa816a7a58eea7971
3
+ metadata.gz: 2c8f404bbf236fce57e1e6de091af800546663ff
4
+ data.tar.gz: dd52a75c76ebd8bbc4f8bfbcf23a6cff75b5fbc6
5
5
  SHA512:
6
- metadata.gz: d3d2f5ab89cab030c46699a7500a816980b5742b6148bb50c63c74cd4cf9bff608e4f520dcd416dd0a1f285251325ece2b646e81675d34447099b29e41ff2d22
7
- data.tar.gz: 7f4f2d6254a66cdb96c398e8800f11d7da0440680ce5dce5591874cf27d9edef8be03a73182696e0464c9082cb9a3575298b4d62dc86189ecab6715146391f9f
6
+ metadata.gz: de4d0b8516c0e11d67c45b04c654b10b68768807993354eeef2fb47a32f26608d18a93ebee4516cd50f80611f6cdb8d55a40c7088c854f71aa05dd52ee40b8d3
7
+ data.tar.gz: f62b3e29787871eb7b598fea8603a408e5e04b4a8bc4ec1ca67143ecb3974a32c383a2f83aa39b7e656443aee8a9107a766b7fb5038caf3c9e275a15bb118afd
@@ -1,8 +1,7 @@
1
1
  language: ruby
2
- before_install:
3
- - gem update --system
4
- - gem --version
5
- - gem install rubysl-bundler
6
- script: bundle exec mspec spec
2
+ env:
3
+ - RUBYLIB=lib
4
+ script: bundle exec mspec
7
5
  rvm:
8
- - rbx-nightly-18mode
6
+ - 1.9.3
7
+ - rbx-nightly-19mode
@@ -1,198 +1,142 @@
1
+ #--
2
+ # $Release Version: 0.5 $
3
+ # $Revision: 1.1.1.1.4.1 $
4
+
5
+ ##
6
+ # = mathn
7
+ #
8
+ # mathn is a library for changing the way Ruby does math. If you need
9
+ # more precise rounding with multiple division or exponentiation
10
+ # operations, then mathn is the right tool.
11
+ #
12
+ # Without mathn:
13
+ #
14
+ # 3 / 2 => 1 # Integer
15
+ #
16
+ # With mathn:
17
+ #
18
+ # 3 / 2 => 3/2 # Rational
1
19
  #
2
- # mathn.rb -
3
- # $Release Version: 0.5 $
4
- # $Revision: 1.1.1.1.4.1 $
5
- # $Date: 1998/01/16 12:36:05 $
6
- # by Keiju ISHITSUKA(SHL Japan Inc.)
20
+ # mathn features late rounding and lacks truncation of intermediate results:
7
21
  #
8
- # --
22
+ # Without mathn:
9
23
  #
24
+ # 20 / 9 * 3 * 14 / 7 * 3 / 2 # => 18
10
25
  #
26
+ # With mathn:
11
27
  #
28
+ # 20 / 9 * 3 * 14 / 7 * 3 / 2 # => 20
29
+ #
30
+ #
31
+ # When you require 'mathn', the libraries for Prime, CMath, Matrix and Vector
32
+ # are also loaded.
33
+ #
34
+ # == Copyright
35
+ #
36
+ # Author: Keiju ISHITSUKA (SHL Japan Inc.)
37
+ #--
38
+ # class Numeric follows to make this documentation findable in a reasonable
39
+ # location
12
40
 
13
- require "complex.rb"
14
- require "rational.rb"
15
- require "matrix.rb"
41
+ class Numeric; end
16
42
 
17
- class Integer
43
+ require "cmath.rb"
44
+ require "matrix.rb"
45
+ require "prime.rb"
18
46
 
19
- def gcd2(int)
20
- a = self.abs
21
- b = int.abs
22
- a, b = b, a if a < b
47
+ unless defined?(Math.exp!)
48
+ Object.instance_eval{remove_const :Math}
49
+ Math = CMath # :nodoc:
50
+ end
23
51
 
24
- pd_a = a.prime_division
25
- pd_b = b.prime_division
52
+ ##
53
+ # When mathn is required, Fixnum's division and exponentiation are enhanced to
54
+ # return more precise values from mathematical expressions.
55
+ #
56
+ # 2/3*3 # => 0
57
+ # require 'mathn'
58
+ # 2/3*3 # => 2
26
59
 
27
- gcd = 1
28
- for pair in pd_a
29
- as = pd_b.assoc(pair[0])
30
- if as
31
- gcd *= as[0] ** [as[1], pair[1]].min
32
- end
33
- end
34
- return gcd
35
- end
60
+ class Fixnum
61
+ remove_method :/
36
62
 
37
- def Integer.from_prime_division(pd)
38
- value = 1
39
- for prime, index in pd
40
- value *= prime**index
41
- end
42
- value
43
- end
63
+ ##
64
+ # +/+ defines the Rational division for Fixnum.
65
+ #
66
+ # 1/3 # => (1/3)
44
67
 
45
- def prime_division
46
- raise ZeroDivisionError if self == 0
47
- ps = Prime.new
48
- value = self
49
- if value < 0
50
- value = -value
51
- pv = [[-1, 1]]
52
- else
53
- pv = []
54
- end
55
- for prime in ps
56
- count = 0
57
- while (value1, mod = value.divmod(prime)
58
- mod) == 0
59
- value = value1
60
- count += 1
61
- end
62
- if count != 0
63
- pv.push [prime, count]
64
- end
65
- break if prime * prime >= value
66
- end
67
- if value > 1
68
- pv.push [value, 1]
69
- end
70
- return pv
71
- end
72
- end
68
+ alias / quo
73
69
 
74
- class Prime
75
- include Enumerable
70
+ alias power! ** unless method_defined? :power!
76
71
 
77
- def initialize
78
- @seed = 1
79
- @primes = []
80
- @counts = []
81
- end
72
+ ##
73
+ # Exponentiate by +other+
82
74
 
83
- def succ
84
- i = -1
85
- size = @primes.size
86
- while i < size
87
- if i == -1
88
- @seed += 1
89
- i += 1
90
- else
91
- while @seed > @counts[i]
92
- @counts[i] += @primes[i]
93
- end
94
- if @seed != @counts[i]
95
- i += 1
96
- else
97
- i = -1
98
- end
99
- end
75
+ def ** (other)
76
+ if self < 0 && other.round != other
77
+ Complex(self, 0.0) ** other
78
+ else
79
+ power!(other)
100
80
  end
101
- @primes.push @seed
102
- @counts.push @seed + @seed
103
- return @seed
104
81
  end
105
- alias next succ
106
82
 
107
- def each
108
- loop do
109
- yield succ
110
- end
111
- end
112
83
  end
113
84
 
114
- class Fixnum
115
- alias / quo
116
- end
85
+ ##
86
+ # When mathn is required Bignum's division and exponentiation are enhanced to
87
+ # return more precise values from mathematical expressions.
117
88
 
118
89
  class Bignum
119
- alias / quo
120
- end
90
+ remove_method :/
121
91
 
122
- class Rational
123
- Unify = true
92
+ ##
93
+ # +/+ defines the Rational division for Bignum.
94
+ #
95
+ # (2**72) / ((2**70) * 3) # => 4/3
124
96
 
125
- def inspect
126
- format "%s/%s", numerator.inspect, denominator.inspect
127
- end
97
+ alias / quo
128
98
 
129
- alias power! **
99
+ alias power! ** unless method_defined? :power!
130
100
 
131
- def ** (other)
132
- if other.kind_of?(Rational)
133
- other2 = other
134
- if self < 0
135
- return Complex.new!(self, 0) ** other
136
- elsif other == 0
137
- return Rational(1,1)
138
- elsif self == 0
139
- return Rational(0,1)
140
- elsif self == 1
141
- return Rational(1,1)
142
- end
101
+ ##
102
+ # Exponentiate by +other+
143
103
 
144
- npd = numerator.prime_division
145
- dpd = denominator.prime_division
146
- if other < 0
147
- other = -other
148
- npd, dpd = dpd, npd
149
- end
104
+ def ** (other)
105
+ if self < 0 && other.round != other
106
+ Complex(self, 0.0) ** other
107
+ else
108
+ power!(other)
109
+ end
110
+ end
150
111
 
151
- for elm in npd
152
- elm[1] = elm[1] * other
153
- if !elm[1].kind_of?(Integer) and elm[1].denominator != 1
154
- return Float(self) ** other2
155
- end
156
- elm[1] = elm[1].to_i
157
- end
112
+ end
158
113
 
159
- for elm in dpd
160
- elm[1] = elm[1] * other
161
- if !elm[1].kind_of?(Integer) and elm[1].denominator != 1
162
- return Float(self) ** other2
163
- end
164
- elm[1] = elm[1].to_i
165
- end
114
+ ##
115
+ # When mathn is required Rational is changed to simplify the use of Rational
116
+ # operations.
117
+ #
118
+ # Normal behaviour:
119
+ #
120
+ # Rational.new!(1,3) ** 2 # => Rational(1, 9)
121
+ # (1 / 3) ** 2 # => 0
122
+ #
123
+ # require 'mathn' behaviour:
124
+ #
125
+ # (1 / 3) ** 2 # => 1/9
166
126
 
167
- num = Integer.from_prime_division(npd)
168
- den = Integer.from_prime_division(dpd)
169
-
170
- Rational(num,den)
171
-
172
- elsif other.kind_of?(Integer)
173
- if other > 0
174
- num = numerator ** other
175
- den = denominator ** other
176
- elsif other < 0
177
- num = denominator ** -other
178
- den = numerator ** -other
179
- elsif other == 0
180
- num = 1
181
- den = 1
182
- end
183
- Rational.new!(num, den)
184
- elsif other.kind_of?(Float)
185
- Float(self) ** other
186
- else
187
- x , y = other.coerce(self)
188
- x ** y
189
- end
190
- end
127
+ class Rational
128
+ remove_method :**
129
+
130
+ ##
131
+ # Exponentiate by +other+
132
+ #
133
+ # (1/3) ** 2 # => 1/9
191
134
 
192
- def power2(other)
135
+ def ** (other)
193
136
  if other.kind_of?(Rational)
137
+ other2 = other
194
138
  if self < 0
195
- return Complex(self, 0) ** other
139
+ return Complex(self, 0.0) ** other
196
140
  elsif other == 0
197
141
  return Rational(1,1)
198
142
  elsif self == 0
@@ -201,16 +145,32 @@ class Rational
201
145
  return Rational(1,1)
202
146
  end
203
147
 
204
- dem = nil
205
- x = self.denominator.to_f.to_i
206
- neard = self.denominator.to_f ** (1.0/other.denominator.to_f)
207
- loop do
208
- if (neard**other.denominator == self.denominator)
209
- dem = neaed
210
- break
148
+ npd = numerator.prime_division
149
+ dpd = denominator.prime_division
150
+ if other < 0
151
+ other = -other
152
+ npd, dpd = dpd, npd
153
+ end
154
+
155
+ for elm in npd
156
+ elm[1] = elm[1] * other
157
+ if !elm[1].kind_of?(Integer) and elm[1].denominator != 1
158
+ return Float(self) ** other2
211
159
  end
160
+ elm[1] = elm[1].to_i
212
161
  end
213
- nearn = self.numerator.to_f ** (1.0/other.denominator.to_f)
162
+
163
+ for elm in dpd
164
+ elm[1] = elm[1] * other
165
+ if !elm[1].kind_of?(Integer) and elm[1].denominator != 1
166
+ return Float(self) ** other2
167
+ end
168
+ elm[1] = elm[1].to_i
169
+ end
170
+
171
+ num = Integer.from_prime_division(npd)
172
+ den = Integer.from_prime_division(dpd)
173
+
214
174
  Rational(num,den)
215
175
 
216
176
  elsif other.kind_of?(Integer)
@@ -224,7 +184,7 @@ class Rational
224
184
  num = 1
225
185
  den = 1
226
186
  end
227
- Rational.new!(num, den)
187
+ Rational(num, den)
228
188
  elsif other.kind_of?(Float)
229
189
  Float(self) ** other
230
190
  else
@@ -234,23 +194,50 @@ class Rational
234
194
  end
235
195
  end
236
196
 
197
+ ##
198
+ # When mathn is required, the Math module changes as follows:
199
+ #
200
+ # Standard Math module behaviour:
201
+ # Math.sqrt(4/9) # => 0.0
202
+ # Math.sqrt(4.0/9.0) # => 0.666666666666667
203
+ # Math.sqrt(- 4/9) # => Errno::EDOM: Numerical argument out of domain - sqrt
204
+ #
205
+ # After require 'mathn', this is changed to:
206
+ #
207
+ # require 'mathn'
208
+ # Math.sqrt(4/9) # => 2/3
209
+ # Math.sqrt(4.0/9.0) # => 0.666666666666667
210
+ # Math.sqrt(- 4/9) # => Complex(0, 2/3)
211
+
237
212
  module Math
213
+ remove_method(:sqrt)
214
+
215
+ ##
216
+ # Computes the square root of +a+. It makes use of Complex and
217
+ # Rational to have no rounding errors if possible.
218
+ #
219
+ # Math.sqrt(4/9) # => 2/3
220
+ # Math.sqrt(- 4/9) # => Complex(0, 2/3)
221
+ # Math.sqrt(4.0/9.0) # => 0.666666666666667
222
+
238
223
  def sqrt(a)
239
224
  if a.kind_of?(Complex)
240
- abs = sqrt(a.real*a.real + a.image*a.image)
241
- # if not abs.kind_of?(Rational)
242
- # return a**Rational(1,2)
243
- # end
225
+ abs = sqrt(a.real*a.real + a.imag*a.imag)
226
+ # if not abs.kind_of?(Rational)
227
+ # return a**Rational(1,2)
228
+ # end
244
229
  x = sqrt((a.real + abs)/Rational(2))
245
230
  y = sqrt((-a.real + abs)/Rational(2))
246
- # if !(x.kind_of?(Rational) and y.kind_of?(Rational))
247
- # return a**Rational(1,2)
248
- # end
249
- if a.image >= 0
231
+ # if !(x.kind_of?(Rational) and y.kind_of?(Rational))
232
+ # return a**Rational(1,2)
233
+ # end
234
+ if a.imag >= 0
250
235
  Complex(x, y)
251
236
  else
252
237
  Complex(x, -y)
253
238
  end
239
+ elsif a.respond_to?(:nan?) and a.nan?
240
+ a
254
241
  elsif a >= 0
255
242
  rsqrt(a)
256
243
  else
@@ -258,6 +245,10 @@ module Math
258
245
  end
259
246
  end
260
247
 
248
+ ##
249
+ # Compute square root of a non negative number. This method is
250
+ # internally used by +Math.sqrt+.
251
+
261
252
  def rsqrt(a)
262
253
  if a.kind_of?(Float)
263
254
  sqrt!(a)
@@ -303,11 +294,34 @@ module Math
303
294
  end
304
295
  end
305
296
 
297
+ class << self
298
+ remove_method(:sqrt)
299
+ end
306
300
  module_function :sqrt
307
301
  module_function :rsqrt
308
302
  end
309
303
 
310
- class Complex
311
- Unify = true
304
+ ##
305
+ # When mathn is required, Float is changed to handle Complex numbers.
306
+
307
+ class Float
308
+ alias power! **
309
+
310
+ ##
311
+ # Exponentiate by +other+
312
+
313
+ def ** (other)
314
+ if self < 0 && other.round != other
315
+ Complex(self, 0.0) ** other
316
+ else
317
+ power!(other)
318
+ end
319
+ end
320
+
312
321
  end
313
322
 
323
+ module Rubinius
324
+ def self.mathn_loaded?
325
+ true
326
+ end
327
+ end
@@ -1,5 +1,5 @@
1
1
  module RubySL
2
2
  module Mathn
3
- VERSION = "1.0.0"
3
+ VERSION = "2.0.0"
4
4
  end
5
5
  end
@@ -19,5 +19,4 @@ Gem::Specification.new do |spec|
19
19
  spec.add_development_dependency "bundler", "~> 1.3"
20
20
  spec.add_development_dependency "rake", "~> 10.0"
21
21
  spec.add_development_dependency "mspec", "~> 1.5"
22
- spec.add_development_dependency "rubysl-prettyprint", "~> 1.0"
23
- end
22
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubysl-mathn
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Shirai
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-09-16 00:00:00.000000000 Z
11
+ date: 2013-09-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,20 +52,6 @@ dependencies:
52
52
  - - ~>
53
53
  - !ruby/object:Gem::Version
54
54
  version: '1.5'
55
- - !ruby/object:Gem::Dependency
56
- name: rubysl-prettyprint
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ~>
60
- - !ruby/object:Gem::Version
61
- version: '1.0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ~>
67
- - !ruby/object:Gem::Version
68
- version: '1.0'
69
55
  description: Ruby standard library mathn.
70
56
  email:
71
57
  - brixen@gmail.com
@@ -122,7 +108,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
122
108
  version: '0'
123
109
  requirements: []
124
110
  rubyforge_project:
125
- rubygems_version: 2.0.3
111
+ rubygems_version: 2.0.7
126
112
  signing_key:
127
113
  specification_version: 4
128
114
  summary: Ruby standard library mathn.
@@ -145,4 +131,3 @@ test_files:
145
131
  - spec/rational/Rational_spec.rb
146
132
  - spec/rational/exponent_spec.rb
147
133
  - spec/rational/inspect_spec.rb
148
- has_rdoc: