bigdecimal 3.1.4-java

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e9fced8ced07121aeb95b8d3d0dfe0a341025ffda5382115e50b2f2e247b4cc5
4
+ data.tar.gz: eb74b46e55565a8d7d0669bf7bf42824498be32d3e0c514378b65d399b84cff3
5
+ SHA512:
6
+ metadata.gz: e343e759448c7e3d25fa27557f7ee791e2269e8146813ece216da77923474be65407381aca04ba42f59795001058e38ff3efd7ed01c93e04f44824d6781ddc54
7
+ data.tar.gz: 211ca130d2b9cf5677eee155d4ef56d8483f60eb15855dfdbc65a0cdf343238efdcb8d66ef2d1e6d82111434e00c7283380dd2c5e29c27c0fcad0706396eb817
@@ -0,0 +1,54 @@
1
+ # coding: utf-8
2
+
3
+ name = File.basename(__FILE__, '.*')
4
+ source_version = ["", "ext/#{name}/"].find do |dir|
5
+ begin
6
+ break File.foreach(File.join(__dir__, "#{dir}#{name}.c")) {|line|
7
+ break $1.sub("-", ".") if /^#define\s+#{name.upcase}_VERSION\s+"(.+)"/o =~ line
8
+ }
9
+ rescue Errno::ENOENT
10
+ end
11
+ end or raise "can't find #{name.upcase}_VERSION"
12
+
13
+ Gem::Specification.new do |s|
14
+ s.name = name
15
+ s.version = source_version
16
+ s.authors = ["Kenta Murata", "Zachary Scott", "Shigeo Kobayashi"]
17
+ s.email = ["mrkn@mrkn.jp"]
18
+
19
+ s.summary = "Arbitrary-precision decimal floating-point number library."
20
+ s.description = "This library provides arbitrary-precision decimal floating-point number class."
21
+ s.homepage = "https://github.com/ruby/bigdecimal"
22
+ s.licenses = ["Ruby", "BSD-2-Clause"]
23
+
24
+ s.require_paths = %w[lib]
25
+ s.files = %w[
26
+ bigdecimal.gemspec
27
+ lib/bigdecimal.rb
28
+ lib/bigdecimal/jacobian.rb
29
+ lib/bigdecimal/ludcmp.rb
30
+ lib/bigdecimal/math.rb
31
+ lib/bigdecimal/newton.rb
32
+ lib/bigdecimal/util.rb
33
+ sample/linear.rb
34
+ sample/nlsolve.rb
35
+ sample/pi.rb
36
+ ]
37
+ if Gem::Platform === s.platform and s.platform =~ 'java' or RUBY_ENGINE == 'jruby'
38
+ s.platform = 'java'
39
+ else
40
+ s.extensions = %w[ext/bigdecimal/extconf.rb]
41
+ s.files += %w[
42
+ ext/bigdecimal/bigdecimal.c
43
+ ext/bigdecimal/bigdecimal.h
44
+ ext/bigdecimal/bits.h
45
+ ext/bigdecimal/feature.h
46
+ ext/bigdecimal/missing.c
47
+ ext/bigdecimal/missing.h
48
+ ext/bigdecimal/missing/dtoa.c
49
+ ext/bigdecimal/static_assert.h
50
+ ]
51
+ end
52
+
53
+ s.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
54
+ end
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: false
2
+
3
+ require 'bigdecimal'
4
+
5
+ # require 'bigdecimal/jacobian'
6
+ #
7
+ # Provides methods to compute the Jacobian matrix of a set of equations at a
8
+ # point x. In the methods below:
9
+ #
10
+ # f is an Object which is used to compute the Jacobian matrix of the equations.
11
+ # It must provide the following methods:
12
+ #
13
+ # f.values(x):: returns the values of all functions at x
14
+ #
15
+ # f.zero:: returns 0.0
16
+ # f.one:: returns 1.0
17
+ # f.two:: returns 2.0
18
+ # f.ten:: returns 10.0
19
+ #
20
+ # f.eps:: returns the convergence criterion (epsilon value) used to determine whether two values are considered equal. If |a-b| < epsilon, the two values are considered equal.
21
+ #
22
+ # x is the point at which to compute the Jacobian.
23
+ #
24
+ # fx is f.values(x).
25
+ #
26
+ module Jacobian
27
+ module_function
28
+
29
+ # Determines the equality of two numbers by comparing to zero, or using the epsilon value
30
+ def isEqual(a,b,zero=0.0,e=1.0e-8)
31
+ aa = a.abs
32
+ bb = b.abs
33
+ if aa == zero && bb == zero then
34
+ true
35
+ else
36
+ if ((a-b)/(aa+bb)).abs < e then
37
+ true
38
+ else
39
+ false
40
+ end
41
+ end
42
+ end
43
+
44
+
45
+ # Computes the derivative of +f[i]+ at +x[i]+.
46
+ # +fx+ is the value of +f+ at +x+.
47
+ def dfdxi(f,fx,x,i)
48
+ nRetry = 0
49
+ n = x.size
50
+ xSave = x[i]
51
+ ok = 0
52
+ ratio = f.ten*f.ten*f.ten
53
+ dx = x[i].abs/ratio
54
+ dx = fx[i].abs/ratio if isEqual(dx,f.zero,f.zero,f.eps)
55
+ dx = f.one/f.ten if isEqual(dx,f.zero,f.zero,f.eps)
56
+ until ok>0 do
57
+ deriv = []
58
+ nRetry += 1
59
+ if nRetry > 100
60
+ raise "Singular Jacobian matrix. No change at x[" + i.to_s + "]"
61
+ end
62
+ dx = dx*f.two
63
+ x[i] += dx
64
+ fxNew = f.values(x)
65
+ for j in 0...n do
66
+ if !isEqual(fxNew[j],fx[j],f.zero,f.eps) then
67
+ ok += 1
68
+ deriv <<= (fxNew[j]-fx[j])/dx
69
+ else
70
+ deriv <<= f.zero
71
+ end
72
+ end
73
+ x[i] = xSave
74
+ end
75
+ deriv
76
+ end
77
+
78
+ # Computes the Jacobian of +f+ at +x+. +fx+ is the value of +f+ at +x+.
79
+ def jacobian(f,fx,x)
80
+ n = x.size
81
+ dfdx = Array.new(n*n)
82
+ for i in 0...n do
83
+ df = dfdxi(f,fx,x,i)
84
+ for j in 0...n do
85
+ dfdx[j*n+i] = df[j]
86
+ end
87
+ end
88
+ dfdx
89
+ end
90
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: false
2
+ require 'bigdecimal'
3
+
4
+ #
5
+ # Solves a*x = b for x, using LU decomposition.
6
+ #
7
+ module LUSolve
8
+ module_function
9
+
10
+ # Performs LU decomposition of the n by n matrix a.
11
+ def ludecomp(a,n,zero=0,one=1)
12
+ prec = BigDecimal.limit(nil)
13
+ ps = []
14
+ scales = []
15
+ for i in 0...n do # pick up largest(abs. val.) element in each row.
16
+ ps <<= i
17
+ nrmrow = zero
18
+ ixn = i*n
19
+ for j in 0...n do
20
+ biggst = a[ixn+j].abs
21
+ nrmrow = biggst if biggst>nrmrow
22
+ end
23
+ if nrmrow>zero then
24
+ scales <<= one.div(nrmrow,prec)
25
+ else
26
+ raise "Singular matrix"
27
+ end
28
+ end
29
+ n1 = n - 1
30
+ for k in 0...n1 do # Gaussian elimination with partial pivoting.
31
+ biggst = zero;
32
+ for i in k...n do
33
+ size = a[ps[i]*n+k].abs*scales[ps[i]]
34
+ if size>biggst then
35
+ biggst = size
36
+ pividx = i
37
+ end
38
+ end
39
+ raise "Singular matrix" if biggst<=zero
40
+ if pividx!=k then
41
+ j = ps[k]
42
+ ps[k] = ps[pividx]
43
+ ps[pividx] = j
44
+ end
45
+ pivot = a[ps[k]*n+k]
46
+ for i in (k+1)...n do
47
+ psin = ps[i]*n
48
+ a[psin+k] = mult = a[psin+k].div(pivot,prec)
49
+ if mult!=zero then
50
+ pskn = ps[k]*n
51
+ for j in (k+1)...n do
52
+ a[psin+j] -= mult.mult(a[pskn+j],prec)
53
+ end
54
+ end
55
+ end
56
+ end
57
+ raise "Singular matrix" if a[ps[n1]*n+n1] == zero
58
+ ps
59
+ end
60
+
61
+ # Solves a*x = b for x, using LU decomposition.
62
+ #
63
+ # a is a matrix, b is a constant vector, x is the solution vector.
64
+ #
65
+ # ps is the pivot, a vector which indicates the permutation of rows performed
66
+ # during LU decomposition.
67
+ def lusolve(a,b,ps,zero=0.0)
68
+ prec = BigDecimal.limit(nil)
69
+ n = ps.size
70
+ x = []
71
+ for i in 0...n do
72
+ dot = zero
73
+ psin = ps[i]*n
74
+ for j in 0...i do
75
+ dot = a[psin+j].mult(x[j],prec) + dot
76
+ end
77
+ x <<= b[ps[i]] - dot
78
+ end
79
+ (n-1).downto(0) do |i|
80
+ dot = zero
81
+ psin = ps[i]*n
82
+ for j in (i+1)...n do
83
+ dot = a[psin+j].mult(x[j],prec) + dot
84
+ end
85
+ x[i] = (x[i]-dot).div(a[psin+i],prec)
86
+ end
87
+ x
88
+ end
89
+ end
@@ -0,0 +1,232 @@
1
+ # frozen_string_literal: false
2
+ require 'bigdecimal'
3
+
4
+ #
5
+ #--
6
+ # Contents:
7
+ # sqrt(x, prec)
8
+ # sin (x, prec)
9
+ # cos (x, prec)
10
+ # atan(x, prec) Note: |x|<1, x=0.9999 may not converge.
11
+ # PI (prec)
12
+ # E (prec) == exp(1.0,prec)
13
+ #
14
+ # where:
15
+ # x ... BigDecimal number to be computed.
16
+ # |x| must be small enough to get convergence.
17
+ # prec ... Number of digits to be obtained.
18
+ #++
19
+ #
20
+ # Provides mathematical functions.
21
+ #
22
+ # Example:
23
+ #
24
+ # require "bigdecimal/math"
25
+ #
26
+ # include BigMath
27
+ #
28
+ # a = BigDecimal((PI(100)/2).to_s)
29
+ # puts sin(a,100) # => 0.99999999999999999999......e0
30
+ #
31
+ module BigMath
32
+ module_function
33
+
34
+ # call-seq:
35
+ # sqrt(decimal, numeric) -> BigDecimal
36
+ #
37
+ # Computes the square root of +decimal+ to the specified number of digits of
38
+ # precision, +numeric+.
39
+ #
40
+ # BigMath.sqrt(BigDecimal('2'), 16).to_s
41
+ # #=> "0.1414213562373095048801688724e1"
42
+ #
43
+ def sqrt(x, prec)
44
+ x.sqrt(prec)
45
+ end
46
+
47
+ # call-seq:
48
+ # sin(decimal, numeric) -> BigDecimal
49
+ #
50
+ # Computes the sine of +decimal+ to the specified number of digits of
51
+ # precision, +numeric+.
52
+ #
53
+ # If +decimal+ is Infinity or NaN, returns NaN.
54
+ #
55
+ # BigMath.sin(BigMath.PI(5)/4, 5).to_s
56
+ # #=> "0.70710678118654752440082036563292800375e0"
57
+ #
58
+ def sin(x, prec)
59
+ raise ArgumentError, "Zero or negative precision for sin" if prec <= 0
60
+ return BigDecimal("NaN") if x.infinite? || x.nan?
61
+ n = prec + BigDecimal.double_fig
62
+ one = BigDecimal("1")
63
+ two = BigDecimal("2")
64
+ x = -x if neg = x < 0
65
+ if x > (twopi = two * BigMath.PI(prec))
66
+ if x > 30
67
+ x %= twopi
68
+ else
69
+ x -= twopi while x > twopi
70
+ end
71
+ end
72
+ x1 = x
73
+ x2 = x.mult(x,n)
74
+ sign = 1
75
+ y = x
76
+ d = y
77
+ i = one
78
+ z = one
79
+ while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0)
80
+ m = BigDecimal.double_fig if m < BigDecimal.double_fig
81
+ sign = -sign
82
+ x1 = x2.mult(x1,n)
83
+ i += two
84
+ z *= (i-one) * i
85
+ d = sign * x1.div(z,m)
86
+ y += d
87
+ end
88
+ neg ? -y : y
89
+ end
90
+
91
+ # call-seq:
92
+ # cos(decimal, numeric) -> BigDecimal
93
+ #
94
+ # Computes the cosine of +decimal+ to the specified number of digits of
95
+ # precision, +numeric+.
96
+ #
97
+ # If +decimal+ is Infinity or NaN, returns NaN.
98
+ #
99
+ # BigMath.cos(BigMath.PI(4), 16).to_s
100
+ # #=> "-0.999999999999999999999999999999856613163740061349e0"
101
+ #
102
+ def cos(x, prec)
103
+ raise ArgumentError, "Zero or negative precision for cos" if prec <= 0
104
+ return BigDecimal("NaN") if x.infinite? || x.nan?
105
+ n = prec + BigDecimal.double_fig
106
+ one = BigDecimal("1")
107
+ two = BigDecimal("2")
108
+ x = -x if x < 0
109
+ if x > (twopi = two * BigMath.PI(prec))
110
+ if x > 30
111
+ x %= twopi
112
+ else
113
+ x -= twopi while x > twopi
114
+ end
115
+ end
116
+ x1 = one
117
+ x2 = x.mult(x,n)
118
+ sign = 1
119
+ y = one
120
+ d = y
121
+ i = BigDecimal("0")
122
+ z = one
123
+ while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0)
124
+ m = BigDecimal.double_fig if m < BigDecimal.double_fig
125
+ sign = -sign
126
+ x1 = x2.mult(x1,n)
127
+ i += two
128
+ z *= (i-one) * i
129
+ d = sign * x1.div(z,m)
130
+ y += d
131
+ end
132
+ y
133
+ end
134
+
135
+ # call-seq:
136
+ # atan(decimal, numeric) -> BigDecimal
137
+ #
138
+ # Computes the arctangent of +decimal+ to the specified number of digits of
139
+ # precision, +numeric+.
140
+ #
141
+ # If +decimal+ is NaN, returns NaN.
142
+ #
143
+ # BigMath.atan(BigDecimal('-1'), 16).to_s
144
+ # #=> "-0.785398163397448309615660845819878471907514682065e0"
145
+ #
146
+ def atan(x, prec)
147
+ raise ArgumentError, "Zero or negative precision for atan" if prec <= 0
148
+ return BigDecimal("NaN") if x.nan?
149
+ pi = PI(prec)
150
+ x = -x if neg = x < 0
151
+ return pi.div(neg ? -2 : 2, prec) if x.infinite?
152
+ return pi / (neg ? -4 : 4) if x.round(prec) == 1
153
+ x = BigDecimal("1").div(x, prec) if inv = x > 1
154
+ x = (-1 + sqrt(1 + x**2, prec))/x if dbl = x > 0.5
155
+ n = prec + BigDecimal.double_fig
156
+ y = x
157
+ d = y
158
+ t = x
159
+ r = BigDecimal("3")
160
+ x2 = x.mult(x,n)
161
+ while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0)
162
+ m = BigDecimal.double_fig if m < BigDecimal.double_fig
163
+ t = -t.mult(x2,n)
164
+ d = t.div(r,m)
165
+ y += d
166
+ r += 2
167
+ end
168
+ y *= 2 if dbl
169
+ y = pi / 2 - y if inv
170
+ y = -y if neg
171
+ y
172
+ end
173
+
174
+ # call-seq:
175
+ # PI(numeric) -> BigDecimal
176
+ #
177
+ # Computes the value of pi to the specified number of digits of precision,
178
+ # +numeric+.
179
+ #
180
+ # BigMath.PI(10).to_s
181
+ # #=> "0.3141592653589793238462643388813853786957412e1"
182
+ #
183
+ def PI(prec)
184
+ raise ArgumentError, "Zero or negative precision for PI" if prec <= 0
185
+ n = prec + BigDecimal.double_fig
186
+ zero = BigDecimal("0")
187
+ one = BigDecimal("1")
188
+ two = BigDecimal("2")
189
+
190
+ m25 = BigDecimal("-0.04")
191
+ m57121 = BigDecimal("-57121")
192
+
193
+ pi = zero
194
+
195
+ d = one
196
+ k = one
197
+ t = BigDecimal("-80")
198
+ while d.nonzero? && ((m = n - (pi.exponent - d.exponent).abs) > 0)
199
+ m = BigDecimal.double_fig if m < BigDecimal.double_fig
200
+ t = t*m25
201
+ d = t.div(k,m)
202
+ k = k+two
203
+ pi = pi + d
204
+ end
205
+
206
+ d = one
207
+ k = one
208
+ t = BigDecimal("956")
209
+ while d.nonzero? && ((m = n - (pi.exponent - d.exponent).abs) > 0)
210
+ m = BigDecimal.double_fig if m < BigDecimal.double_fig
211
+ t = t.div(m57121,n)
212
+ d = t.div(k,m)
213
+ pi = pi + d
214
+ k = k+two
215
+ end
216
+ pi
217
+ end
218
+
219
+ # call-seq:
220
+ # E(numeric) -> BigDecimal
221
+ #
222
+ # Computes e (the base of natural logarithms) to the specified number of
223
+ # digits of precision, +numeric+.
224
+ #
225
+ # BigMath.E(10).to_s
226
+ # #=> "0.271828182845904523536028752390026306410273e1"
227
+ #
228
+ def E(prec)
229
+ raise ArgumentError, "Zero or negative precision for E" if prec <= 0
230
+ BigMath.exp(1, prec)
231
+ end
232
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: false
2
+ require "bigdecimal/ludcmp"
3
+ require "bigdecimal/jacobian"
4
+
5
+ #
6
+ # newton.rb
7
+ #
8
+ # Solves the nonlinear algebraic equation system f = 0 by Newton's method.
9
+ # This program is not dependent on BigDecimal.
10
+ #
11
+ # To call:
12
+ # n = nlsolve(f,x)
13
+ # where n is the number of iterations required,
14
+ # x is the initial value vector
15
+ # f is an Object which is used to compute the values of the equations to be solved.
16
+ # It must provide the following methods:
17
+ #
18
+ # f.values(x):: returns the values of all functions at x
19
+ #
20
+ # f.zero:: returns 0.0
21
+ # f.one:: returns 1.0
22
+ # f.two:: returns 2.0
23
+ # f.ten:: returns 10.0
24
+ #
25
+ # f.eps:: returns the convergence criterion (epsilon value) used to determine whether two values are considered equal. If |a-b| < epsilon, the two values are considered equal.
26
+ #
27
+ # On exit, x is the solution vector.
28
+ #
29
+ module Newton
30
+ include LUSolve
31
+ include Jacobian
32
+ module_function
33
+
34
+ def norm(fv,zero=0.0) # :nodoc:
35
+ s = zero
36
+ n = fv.size
37
+ for i in 0...n do
38
+ s += fv[i]*fv[i]
39
+ end
40
+ s
41
+ end
42
+
43
+ # See also Newton
44
+ def nlsolve(f,x)
45
+ nRetry = 0
46
+ n = x.size
47
+
48
+ f0 = f.values(x)
49
+ zero = f.zero
50
+ one = f.one
51
+ two = f.two
52
+ p5 = one/two
53
+ d = norm(f0,zero)
54
+ minfact = f.ten*f.ten*f.ten
55
+ minfact = one/minfact
56
+ e = f.eps
57
+ while d >= e do
58
+ nRetry += 1
59
+ # Not yet converged. => Compute Jacobian matrix
60
+ dfdx = jacobian(f,f0,x)
61
+ # Solve dfdx*dx = -f0 to estimate dx
62
+ dx = lusolve(dfdx,f0,ludecomp(dfdx,n,zero,one),zero)
63
+ fact = two
64
+ xs = x.dup
65
+ begin
66
+ fact *= p5
67
+ if fact < minfact then
68
+ raise "Failed to reduce function values."
69
+ end
70
+ for i in 0...n do
71
+ x[i] = xs[i] - dx[i]*fact
72
+ end
73
+ f0 = f.values(x)
74
+ dn = norm(f0,zero)
75
+ end while(dn>=d)
76
+ d = dn
77
+ end
78
+ nRetry
79
+ end
80
+ end
@@ -0,0 +1,185 @@
1
+ # frozen_string_literal: false
2
+ #
3
+ #--
4
+ # bigdecimal/util extends various native classes to provide the #to_d method,
5
+ # and provides BigDecimal#to_d and BigDecimal#to_digits.
6
+ #++
7
+
8
+ require 'bigdecimal'
9
+
10
+ class Integer < Numeric
11
+ # call-seq:
12
+ # int.to_d -> bigdecimal
13
+ #
14
+ # Returns the value of +int+ as a BigDecimal.
15
+ #
16
+ # require 'bigdecimal'
17
+ # require 'bigdecimal/util'
18
+ #
19
+ # 42.to_d # => 0.42e2
20
+ #
21
+ # See also BigDecimal::new.
22
+ #
23
+ def to_d
24
+ BigDecimal(self)
25
+ end
26
+ end
27
+
28
+
29
+ class Float < Numeric
30
+ # call-seq:
31
+ # float.to_d -> bigdecimal
32
+ # float.to_d(precision) -> bigdecimal
33
+ #
34
+ # Returns the value of +float+ as a BigDecimal.
35
+ # The +precision+ parameter is used to determine the number of
36
+ # significant digits for the result. When +precision+ is set to +0+,
37
+ # the number of digits to represent the float being converted is determined
38
+ # automatically.
39
+ # The default +precision+ is +0+.
40
+ #
41
+ # require 'bigdecimal'
42
+ # require 'bigdecimal/util'
43
+ #
44
+ # 0.5.to_d # => 0.5e0
45
+ # 1.234.to_d # => 0.1234e1
46
+ # 1.234.to_d(2) # => 0.12e1
47
+ #
48
+ # See also BigDecimal::new.
49
+ #
50
+ def to_d(precision=0)
51
+ BigDecimal(self, precision)
52
+ end
53
+ end
54
+
55
+
56
+ class String
57
+ # call-seq:
58
+ # str.to_d -> bigdecimal
59
+ #
60
+ # Returns the result of interpreting leading characters in +str+
61
+ # as a BigDecimal.
62
+ #
63
+ # require 'bigdecimal'
64
+ # require 'bigdecimal/util'
65
+ #
66
+ # "0.5".to_d # => 0.5e0
67
+ # "123.45e1".to_d # => 0.12345e4
68
+ # "45.67 degrees".to_d # => 0.4567e2
69
+ #
70
+ # See also BigDecimal::new.
71
+ #
72
+ def to_d
73
+ BigDecimal.interpret_loosely(self)
74
+ end
75
+ end
76
+
77
+
78
+ class BigDecimal < Numeric
79
+ # call-seq:
80
+ # a.to_digits -> string
81
+ #
82
+ # Converts a BigDecimal to a String of the form "nnnnnn.mmm".
83
+ # This method is deprecated; use BigDecimal#to_s("F") instead.
84
+ #
85
+ # require 'bigdecimal/util'
86
+ #
87
+ # d = BigDecimal("3.14")
88
+ # d.to_digits # => "3.14"
89
+ #
90
+ def to_digits
91
+ if self.nan? || self.infinite? || self.zero?
92
+ self.to_s
93
+ else
94
+ i = self.to_i.to_s
95
+ _,f,_,z = self.frac.split
96
+ i + "." + ("0"*(-z)) + f
97
+ end
98
+ end
99
+
100
+ # call-seq:
101
+ # a.to_d -> bigdecimal
102
+ #
103
+ # Returns self.
104
+ #
105
+ # require 'bigdecimal/util'
106
+ #
107
+ # d = BigDecimal("3.14")
108
+ # d.to_d # => 0.314e1
109
+ #
110
+ def to_d
111
+ self
112
+ end
113
+ end
114
+
115
+
116
+ class Rational < Numeric
117
+ # call-seq:
118
+ # rat.to_d(precision) -> bigdecimal
119
+ #
120
+ # Returns the value as a BigDecimal.
121
+ #
122
+ # The required +precision+ parameter is used to determine the number of
123
+ # significant digits for the result.
124
+ #
125
+ # require 'bigdecimal'
126
+ # require 'bigdecimal/util'
127
+ #
128
+ # Rational(22, 7).to_d(3) # => 0.314e1
129
+ #
130
+ # See also BigDecimal::new.
131
+ #
132
+ def to_d(precision)
133
+ BigDecimal(self, precision)
134
+ end
135
+ end
136
+
137
+
138
+ class Complex < Numeric
139
+ # call-seq:
140
+ # cmp.to_d -> bigdecimal
141
+ # cmp.to_d(precision) -> bigdecimal
142
+ #
143
+ # Returns the value as a BigDecimal.
144
+ #
145
+ # The +precision+ parameter is required for a rational complex number.
146
+ # This parameter is used to determine the number of significant digits
147
+ # for the result.
148
+ #
149
+ # require 'bigdecimal'
150
+ # require 'bigdecimal/util'
151
+ #
152
+ # Complex(0.1234567, 0).to_d(4) # => 0.1235e0
153
+ # Complex(Rational(22, 7), 0).to_d(3) # => 0.314e1
154
+ #
155
+ # See also BigDecimal::new.
156
+ #
157
+ def to_d(*args)
158
+ BigDecimal(self) unless self.imag.zero? # to raise eerror
159
+
160
+ if args.length == 0
161
+ case self.real
162
+ when Rational
163
+ BigDecimal(self.real) # to raise error
164
+ end
165
+ end
166
+ self.real.to_d(*args)
167
+ end
168
+ end
169
+
170
+
171
+ class NilClass
172
+ # call-seq:
173
+ # nil.to_d -> bigdecimal
174
+ #
175
+ # Returns nil represented as a BigDecimal.
176
+ #
177
+ # require 'bigdecimal'
178
+ # require 'bigdecimal/util'
179
+ #
180
+ # nil.to_d # => 0.0
181
+ #
182
+ def to_d
183
+ BigDecimal(0)
184
+ end
185
+ end
data/lib/bigdecimal.rb ADDED
@@ -0,0 +1,5 @@
1
+ if RUBY_ENGINE == 'jruby'
2
+ JRuby::Util.load_ext("org.jruby.ext.bigdecimal.BigDecimalLibrary")
3
+ else
4
+ require 'bigdecimal.so'
5
+ end
data/sample/linear.rb ADDED
@@ -0,0 +1,74 @@
1
+ #!/usr/local/bin/ruby
2
+ # frozen_string_literal: false
3
+
4
+ #
5
+ # linear.rb
6
+ #
7
+ # Solves linear equation system(A*x = b) by LU decomposition method.
8
+ # where A is a coefficient matrix,x is an answer vector,b is a constant vector.
9
+ #
10
+ # USAGE:
11
+ # ruby linear.rb [input file solved]
12
+ #
13
+
14
+ # :stopdoc:
15
+ require "bigdecimal"
16
+ require "bigdecimal/ludcmp"
17
+
18
+ #
19
+ # NOTE:
20
+ # Change following BigDecimal.limit() if needed.
21
+ BigDecimal.limit(100)
22
+ #
23
+
24
+ include LUSolve
25
+ def rd_order(na)
26
+ printf("Number of equations ?") if(na <= 0)
27
+ n = ARGF.gets().to_i
28
+ end
29
+
30
+ na = ARGV.size
31
+ zero = BigDecimal("0.0")
32
+ one = BigDecimal("1.0")
33
+
34
+ while (n=rd_order(na))>0
35
+ a = []
36
+ as= []
37
+ b = []
38
+ if na <= 0
39
+ # Read data from console.
40
+ printf("\nEnter coefficient matrix element A[i,j]\n")
41
+ for i in 0...n do
42
+ for j in 0...n do
43
+ printf("A[%d,%d]? ",i,j); s = ARGF.gets
44
+ a << BigDecimal(s)
45
+ as << BigDecimal(s)
46
+ end
47
+ printf("Contatant vector element b[%d] ? ",i)
48
+ b << BigDecimal(ARGF.gets)
49
+ end
50
+ else
51
+ # Read data from specified file.
52
+ printf("Coefficient matrix and constant vector.\n")
53
+ for i in 0...n do
54
+ s = ARGF.gets
55
+ printf("%d) %s",i,s)
56
+ s = s.split
57
+ for j in 0...n do
58
+ a << BigDecimal(s[j])
59
+ as << BigDecimal(s[j])
60
+ end
61
+ b << BigDecimal(s[n])
62
+ end
63
+ end
64
+ x = lusolve(a,b,ludecomp(a,n,zero,one),zero)
65
+ printf("Answer(x[i] & (A*x-b)[i]) follows\n")
66
+ for i in 0...n do
67
+ printf("x[%d]=%s ",i,x[i].to_s)
68
+ s = zero
69
+ for j in 0...n do
70
+ s = s + as[i*n+j]*x[j]
71
+ end
72
+ printf(" & %s\n",(s-b[i]).to_s)
73
+ end
74
+ end
data/sample/nlsolve.rb ADDED
@@ -0,0 +1,40 @@
1
+ #!/usr/local/bin/ruby
2
+ # frozen_string_literal: false
3
+
4
+ #
5
+ # nlsolve.rb
6
+ # An example for solving nonlinear algebraic equation system.
7
+ #
8
+
9
+ require "bigdecimal"
10
+ require "bigdecimal/newton"
11
+ include Newton
12
+
13
+ class Function # :nodoc: all
14
+ def initialize()
15
+ @zero = BigDecimal("0.0")
16
+ @one = BigDecimal("1.0")
17
+ @two = BigDecimal("2.0")
18
+ @ten = BigDecimal("10.0")
19
+ @eps = BigDecimal("1.0e-16")
20
+ end
21
+ def zero;@zero;end
22
+ def one ;@one ;end
23
+ def two ;@two ;end
24
+ def ten ;@ten ;end
25
+ def eps ;@eps ;end
26
+ def values(x) # <= defines functions solved
27
+ f = []
28
+ f1 = x[0]*x[0] + x[1]*x[1] - @two # f1 = x**2 + y**2 - 2 => 0
29
+ f2 = x[0] - x[1] # f2 = x - y => 0
30
+ f <<= f1
31
+ f <<= f2
32
+ f
33
+ end
34
+ end
35
+
36
+ f = BigDecimal.limit(100)
37
+ f = Function.new
38
+ x = [f.zero,f.zero] # Initial values
39
+ n = nlsolve(f,x)
40
+ p x
data/sample/pi.rb ADDED
@@ -0,0 +1,21 @@
1
+ #!/usr/local/bin/ruby
2
+ # frozen_string_literal: false
3
+
4
+ #
5
+ # pi.rb
6
+ #
7
+ # Calculates 3.1415.... (the number of times that a circle's diameter
8
+ # will fit around the circle) using J. Machin's formula.
9
+ #
10
+
11
+ require "bigdecimal"
12
+ require "bigdecimal/math.rb"
13
+
14
+ include BigMath
15
+
16
+ if ARGV.size == 1
17
+ print "PI("+ARGV[0]+"):\n"
18
+ p PI(ARGV[0].to_i)
19
+ else
20
+ print "TRY: ruby pi.rb 1000 \n"
21
+ end
metadata ADDED
@@ -0,0 +1,57 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bigdecimal
3
+ version: !ruby/object:Gem::Version
4
+ version: 3.1.4
5
+ platform: java
6
+ authors:
7
+ - Kenta Murata
8
+ - Zachary Scott
9
+ - Shigeo Kobayashi
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2023-09-05 00:00:00.000000000 Z
14
+ dependencies: []
15
+ description: This library provides arbitrary-precision decimal floating-point number
16
+ class.
17
+ email:
18
+ - mrkn@mrkn.jp
19
+ executables: []
20
+ extensions: []
21
+ extra_rdoc_files: []
22
+ files:
23
+ - bigdecimal.gemspec
24
+ - lib/bigdecimal.rb
25
+ - lib/bigdecimal/jacobian.rb
26
+ - lib/bigdecimal/ludcmp.rb
27
+ - lib/bigdecimal/math.rb
28
+ - lib/bigdecimal/newton.rb
29
+ - lib/bigdecimal/util.rb
30
+ - sample/linear.rb
31
+ - sample/nlsolve.rb
32
+ - sample/pi.rb
33
+ homepage: https://github.com/ruby/bigdecimal
34
+ licenses:
35
+ - Ruby
36
+ - BSD-2-Clause
37
+ metadata: {}
38
+ post_install_message:
39
+ rdoc_options: []
40
+ require_paths:
41
+ - lib
42
+ required_ruby_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 2.5.0
47
+ required_rubygems_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ requirements: []
53
+ rubygems_version: 3.3.26
54
+ signing_key:
55
+ specification_version: 4
56
+ summary: Arbitrary-precision decimal floating-point number library.
57
+ test_files: []