class Silicium::NumericalIntegration
A class providing numerical integration methods
Public Class Methods
Computes integral by the Left Rectangles method from a
to b
of block
with accuracy eps
# File lib/numerical_integration.rb, line 58 def self.left_rect_integration(a, b, eps = 0.0001, &block) wrapper_method([a, b], eps, :left_rect_integration_n, &block) end
Computes integral by the Left Rectangles method from a
to b
of block
with n
segmentations
# File lib/numerical_integration.rb, line 65 def self.left_rect_integration_n(a, b, n, &block) dx = (b - a) / n.to_f amount_calculation(a, [0, n], dx, &block) end
Computes integral by the Middle Rectangles method from a
to b
of block
with accuracy eps
# File lib/numerical_integration.rb, line 102 def self.middle_rectangles(a, b, eps = 0.0001, &block) wrapper_method([a, b], eps, :middle_rectangles_with_a_segment, &block) end
Computes integral by the Middle Rectangles method from a
to b
of block
with n
segmentations
# File lib/numerical_integration.rb, line 88 def self.middle_rectangles_with_a_segment(a, b, n, &block) dx = (b - a) / n.to_f result = 0 i = 0 n.times do result += block.call(a + dx * (i + 1 / 2)) * dx i += 1 end result end
Computes integral by the Right Rectangles method from a
to b
of block
with accuracy eps
# File lib/numerical_integration.rb, line 73 def self.right_rect_integration(a, b, eps = 0.0001, &block) wrapper_method([a, b], eps, :right_rect_integration_n, &block) end
Computes integral by the Right Rectangles method from a
to b
of block
with n
segmentations
# File lib/numerical_integration.rb, line 80 def self.right_rect_integration_n(a, b, n, &block) dx = (b - a) / n.to_f amount_calculation(a, [1, n + 1], dx, &block) end
Computes integral by the Simpson's rule from a
to b
of block
with accuracy eps
# File lib/numerical_integration.rb, line 51 def self.simpson_integration(a, b, eps = 0.0001, &block) wrapper_method([a, b], eps, :simpson_integration_with_a_segment, &block) end
Computes integral by the Simpson's rule from a
to b
of block
with n
segmentations
# File lib/numerical_integration.rb, line 36 def self.simpson_integration_with_a_segment(a, b, n, &block) dx = (b - a) / n.to_f result = 0 i = 0 while i < n result += (block.call(a + i * dx) + 4 * block.call(((a + i * dx) + (a + (i + 1) * dx)) / 2.0) + block.call(a + (i + 1) * dx)) / 6.0 * dx i += 1 end result end
Computes integral by the 3/8 rule from a
to b
of block
with accuracy eps
# File lib/numerical_integration.rb, line 13 def self.three_eights_integration(a, b, eps = 0.0001, &block) wrapper_method([a, b], eps, :three_eights_integration_n, &block) end
Computes integral by the 3/8 rule from a
to b
of block
with n
segmentations
# File lib/numerical_integration.rb, line 20 def self.three_eights_integration_n(a, b, n, &block) dx = (b - a) / n.to_f result = 0 x = a n.times do result += (block.call(x) + 3 * block.call((2 * x + x + dx) / 3.0) + 3 * block.call((x + 2 * (x + dx)) / 3.0) + block.call(x + dx)) / 8.0 * dx x += dx end result end
Computes integral by the Trapezoid method from a
to b
of block
with accuracy eps
# File lib/numerical_integration.rb, line 124 def self.trapezoid(a, b, eps = 0.0001, &block) wrapper_method([a, b], eps, :trapezoid_with_a_segment ,&block) end
Computes integral by the Trapezoid method from a
to b
of block
with n
segmentations
# File lib/numerical_integration.rb, line 109 def self.trapezoid_with_a_segment(a, b, n, &block) dx = (b - a) / n.to_f result = 0 i = 1 (n - 1).times do result += block.call(a + dx * i) i += 1 end result += (block.call(a) + block.call(b)) / 2.0 result * dx end
Private Class Methods
Computes the sum of n rectangles on a segment of length dx at points of the form a + i * dx @param [Numeric] a - first division point @param [Array] i_n number of divisions @param [Numeric] dx - length of integration segment @param [Block] block - integrated function as Block
# File lib/numerical_integration.rb, line 173 def self.amount_calculation(a, i_n, dx, &block) result = 0 while i_n[0] < i_n[1] result += block.call(a + i_n[0] * dx) i_n[0] += 1 end result * dx end
# File lib/numerical_integration.rb, line 157 def self.check_value(value) if value.nan? raise IntegralDoesntExistError, 'We have not-a-number result :(' end if value == Float::INFINITY raise IntegralDoesntExistError, 'We have infinity :(' end end
Wrapper method for num_integratons methods @param [Array] a_b integration range @param [Numeric] eps @param [Proc] proc - integration Proc @param [Block] block - integrated function as Block
# File lib/numerical_integration.rb, line 136 def self.wrapper_method(a_b, eps, method_name, &block) n = 1 max_it = 10_000 begin begin result = send(method_name, a_b[0], a_b[1], n, &block) check_value(result) n *= 5 raise NumberofIterOutofRangeError if n > max_it result1 = send(method_name, a_b[0], a_b[1], n, &block) check_value(result1) end until (result - result1).abs < eps rescue Math::DomainError raise IntegralDoesntExistError, 'Domain error in math function' rescue ZeroDivisionError raise IntegralDoesntExistError, 'Divide by zero' end (result + result1) / 2.0 end