function _rk(a, c, b, bp) {
return function (f, T, y0, options){
const t0 = T[0];
const tf = T[1];
const steps = 1;
const tol = options.tol ? options.tol : 1e-4;
const maxStep = options.maxStep;
const minStep = options.minStep;
const minDelta = options.minDelta ? options.minDelta : 0.2;
const maxDelta = options.maxDelta ? options.maxDelta : 5;
const maxIter = options.maxIter ? options.maxIter : 10_000;
let h = options.firstStep ?
options.firstStep :
math.divide(math.subtract(tf, t0), steps);
const t = [t0];
const y = [y0];
const delta_b = math.subtract(b, bp);
let n = 0;
let iter = 0;
while (ongoing(t[n], tf, h) && iter < maxIter) {
const k = [];
h = trimStep(t[n], tf, h);
k.push(f(t[n], y[n]));
for (let i = 1; i < c.length; ++i) {
k.push(
f(
math.add(t[n], math.multiply(c[i], h)),
math.add(y[n], math.multiply(h, a[i], k))
)
);
}
const TE = math.max(
math.abs(
math.map(math.multiply(delta_b, k), (X) =>
math.isUnit(X) ? X.value : X
)
)
);
if (TE < tol && tol / TE > 1 / 4) {
t.push(math.add(t[n], h));
y.push(math.add(y[n], math.multiply(h, b, k)));
n ++;
}
const delta = 0.84 * (tol / TE) ** (1 / 5);
if (delta < minDelta) {
h = math.multiply(h, minDelta);
} else if (delta > maxDelta) {
h = math.multiply(h, maxDelta);
} else {
h = math.multiply(h, delta);
}
if (maxStep && math.larger(math.abs(h), math.abs(maxStep))) {
h = math.isPositive(h) ? math.abs(maxStep) : math.multiply(-1, math.abs(maxStep));
} else if (minStep && math.smaller(math.abs(h), math.abs(minStep))) {
h = math.isPositive(h) ? math.abs(minStep) : math.multiply(-1, math.abs(minStep));
}
iter++;
}
return { t, y };
}
}