diff options
author | shigek <shigek@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2003-07-18 15:26:37 +0000 |
---|---|---|
committer | shigek <shigek@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2003-07-18 15:26:37 +0000 |
commit | 1bb3071bde8344427a5fe3f5998dc491d2630d2b (patch) | |
tree | 8310d06d0fd319977dbc2b560d230c48f48f03da /ext/bigdecimal/lib/bigdecimal/newton.rb | |
parent | e242cf9defb5442ef223535abe93399352cf139e (diff) |
As discussed in ruby-dev ML:
lib directory moved.
util.rb created instead of bigdecimal-rational.rb
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4093 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext/bigdecimal/lib/bigdecimal/newton.rb')
-rw-r--r-- | ext/bigdecimal/lib/bigdecimal/newton.rb | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/ext/bigdecimal/lib/bigdecimal/newton.rb b/ext/bigdecimal/lib/bigdecimal/newton.rb new file mode 100644 index 0000000000..67a92474ac --- /dev/null +++ b/ext/bigdecimal/lib/bigdecimal/newton.rb @@ -0,0 +1,75 @@ +# +# newton.rb +# +# Solves nonlinear algebraic equation system f = 0 by Newton's method. +# (This program is not dependent on BigDecimal) +# +# To call: +# n = nlsolve(f,x) +# where n is the number of iterations required. +# x is the solution vector. +# f is the object to be solved which must have following methods. +# +# f ... Object to compute Jacobian matrix of the equation systems. +# [Methods required for f] +# f.values(x) returns values of all functions at x. +# f.zero returns 0.0 +# f.one returns 1.0 +# f.two returns 1.0 +# f.ten returns 10.0 +# f.eps convergence criterion +# x ... initial values +# +require "ludcmp" +require "jacobian" + +module Newton + include LUSolve + include Jacobian + + def norm(fv,zero=0.0) + s = zero + n = fv.size + for i in 0...n do + s += fv[i]*fv[i] + end + s + end + + def nlsolve(f,x) + nRetry = 0 + n = x.size + + f0 = f.values(x) + zero = f.zero + one = f.one + two = f.two + p5 = one/two + d = norm(f0,zero) + minfact = f.ten*f.ten*f.ten + minfact = one/minfact + e = f.eps + while d >= e do + nRetry += 1 + # Not yet converged. => Compute Jacobian matrix + dfdx = jacobian(f,f0,x) + # Solve dfdx*dx = -f0 to estimate dx + dx = lusolve(dfdx,f0,ludecomp(dfdx,n,zero,one),zero) + fact = two + xs = x.dup + begin + fact *= p5 + if fact < minfact then + raize "Failed to reduce function values." + end + for i in 0...n do + x[i] = xs[i] - dx[i]*fact + end + f0 = f.values(x) + dn = norm(f0,zero) + end while(dn>=d) + d = dn + end + nRetry + end +end |