#!/usr/bin/env ruby
# Ruby/GSL implementation of GSL "roots/test.c"
require("rbgsl")
require("./gsl_test2.rb")
include GSL::Test
include Math
EPSREL = 10.0*GSL::DBL_EPSILON
EPSABS = 10.0*GSL::DBL_EPSILON
MAX_ITERATIONS = 150
def WITHIN_TOL(a, b, epsrel, epsabs)
(a - b).abs < epsrel*GSL::MIN(a.abs, b.abs) + epsabs
end
def test_f(type, desc, f, lower, upper, correct)
s = GSL::Root::FSolver.alloc(type)
s.set(f, lower, upper)
iter = 0
begin
iter += 1
s.iterate
r = s.root
a = s.x_lower
b = s.x_upper
if a > b
GSL::Test::test(GSL::FAILURE, "interval is invalid (#{a},#{b})")
end
if r < a or r > b
GSL::Test::test(GSL::FAILURE, "r lies outside interval #{r} (#{a},#{b})")
end
status = GSL::Root::test_interval(a, b, EPSABS, EPSREL)
end while status == GSL::CONTINUE and iter < MAX_ITERATIONS
GSL::Test::test(status, "#{s.name}, #{desc} (#{s.root} obs vs #{correct} expected)")
if iter == MAX_ITERATIONS
GSL::Test::test(GSL::FAILURE, "exceeded maximum number of iterations")
end
if !WITHIN_TOL(r, correct, EPSREL, EPSABS)
GSL::Test::test(GSL::FAILURE, "incorrect precision (#{r} obs vs #{correct} expected)")
end
end
def test_fdf(type, desc, fdf, root, correct)
s = GSL::Root::FdfSolver.alloc(type)
s.set(fdf, root)
iter = 0
begin
iter += 1
prev = s.root
s.iterate
status = GSL::Root::test_delta(s.root, prev, EPSABS, EPSREL)
end while status == GSL::CONTINUE and iter < MAX_ITERATIONS
GSL::Test::test(status, "#{s.name} #{desc} (#{s.root} obs vs #{correct} expected)")
if iter == MAX_ITERATIONS
GSL::Test::test(GSL::FAILURE, "exceeded maximum number of iterations")
end
if !WITHIN_TOL(s.root, correct, EPSREL, EPSABS)
GSL::Test::test(GSL::FAILURE, "incorrect precision (#{r} obs vs #{correct} expected)")
end
end
func1 = GSL::Function.alloc { |x| pow(x, 20.0) - 1 }
func1_fdf = Proc.new { |x| 20.0*pow(x, 19.0) }
fdf1 = GSL::Function_fdf.alloc(func1.f, func1_fdf)
fsolvers = ["bisection", "brent", "falsepos"]
fsolvers.each do |type|
test_f(type, "x^20 - 1 [0.1, 2]", func1, 0.1, 2.0, 1.0)
end
fdfsolvers = ["newton", "secant", "steffenson"]
fdfsolvers = ["newton", "steffenson"]
fdfsolvers.each do |type|
test_fdf(type, "x^{20} - 1 {0.9}", fdf1, 0.9, 1.0)
end
syntax highlighted by Code2HTML, v. 0.9.1