10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
# File 'lib/linear_solver.rb', line 10
def self.solve_with_stopper(goal, starting_value, stopping_comparator, &block)
raise StandardError unless block_given?
return 0.0 if stopping_comparator.call(block.call(0.0), goal)
starting_value = 1 if starting_value == 0
starting_value = starting_value.to_f
goal = goal.to_f
block.call(0) < goal ? input = starting_value.abs : input = -(starting_value.abs)
upper_bounds_counter = 0
if input < 0
while block.call(input) > goal && upper_bounds_counter < 10000
input *= 2
upper_bounds_counter += 1
end
else
while block.call(input) < goal && upper_bounds_counter < 10000
input *= 2
upper_bounds_counter += 1
end
end
raise CalculationUnsolvableError.new("Upper bound reached, goal: #{goal}, starting value: #{starting_value}, input: #{input}") if upper_bounds_counter >= 10000
output = block.call(input)
unless stopping_comparator.call(output, goal)
difference = input.abs
asymptote_counter = 0
begin
difference /= 2
input += difference if output < goal
input -= difference if output > goal
asymptote_counter += 1
output = block.call(input)
end until (stopping_comparator.call(output, goal) || asymptote_counter == 10000)
raise CalculationUnsolvableError.new("Lower bound asymptote reached, goal: #{goal}, starting value: #{starting_value}, input: #{input}") if asymptote_counter == 10000
end
return input
end
|