#!/usr/bin/ruby

#
## https://rosettacode.org/wiki/Runge-Kutta_method
#

func runge_kutta(yp) {
    func (t, y, δt) {
        var a = (δt * yp(t, y));
        var b = (δt * yp(t + δt/2, y + a/2));
        var c = (δt * yp(t + δt/2, y + b/2));
        var d = (δt * yp(t + δt, y + c));
        (a + 2*(b + c) + d) / 6;
    }
}

define δt = 0.1;
var δy = runge_kutta(func(t, y) { t * y.sqrt });

var(t, y) = (0, 1);
loop {
    t.is_int &&
        printf("y(%2d) = %12f ± %e\n", t, y, abs(y - ((t**2 + 4)**2 / 16)));
    t <= 10 || break;
    y += δy(t, y, δt);
    t += δt;
}