module NumberRefinements
Float.prepend self
Integer.prepend self
BigDecimal.prepend self
def + other
zero? && [Vector, Matrix].any? { other.is_a? _1 } ? other : super
end
end
class Vector
def self.build(...)
new Array.new(...)
end
def to_ary
to_a
end
end
class Array
def inner other
zip(other).sum { _1 * _2 }
end
end
class Canvas
attr_accessor :bitmap, :color
def initialize
@bitmap = Bitmap.new 1024, 768
@color = Color.new 255, 255, 255
end
def trace t, ret
block = ->y { @bitmap.set_pixel t*128, 200*(y+2), @color }
ret.is_a?(Enumerable) ? ret.each(&block) : block.(ret)
end
end
$canvas = Canvas.new
def runge_kutta initial, max_t, dt, (*pyramid, coefs), func
(0..max_t).step(dt).reduce initial do |ret, t|
$canvas&.trace t, ret
coefs.zip(pyramid).each_with_object([]).sum do |(coef, row), ary|
coef * ary.push(func.(t, row.inner(ary) * dt + ret)).last
end * dt + ret#p(ret)
end
end
def div x0, dx, f
f0 = f.(x0)
n = x0.size
Vector.build n do |i|
(f.(x0 + Vector.basis(size: n, index: i) * dx) - f0) / dx
end
end
def solve_hamiltonian n, x0, t, dt, hamiltonian
runge_kutta Vector[*x0], t, dt, CLASSIC_4TH, ->t, x do
dxdt = div x, 1e-5, ->qp { hamiltonian.(t, qp) }
Vector[*dxdt[n...n*2], *dxdt[0...n].map(&:-@)]
end
end
BigDecimal.limit 25
include RGSS
Graphics.resize_screen 1024, 768
rgss_main do
Thread.start do
Sprite.new.bitmap = $canvas.bitmap
rgss_stop
end
end
alias ` BigDecimal
#METHODS.each do |method|
# p runge_kutta `1`, `1`, `1e-4`, method, ->t,x { x*t }
#end