Task: Numerical integration_Adaptive Simpson's method





Java: import java.util.function.Function;

public class NumericalIntegrationAdaptiveSimpsons {

    public static void main(String[] args) {
        Function<Double,Double> f = x -> sin(x);
        System.out.printf("integrate sin(x), x = 0 .. Pi = %2.12f.  Function calls = %d%n", quadratureAdaptiveSimpsons(f, 0, Math.PI, 1e-8), functionCount);
        functionCount = 0;
        System.out.printf("integrate sin(x), x = 0 .. 1 = %2.12f.  Function calls = %d%n", quadratureAdaptiveSimpsons(f, 0, 1, 1e-8), functionCount);
    }
    
    private static double quadratureAdaptiveSimpsons(Function<Double,Double> function, double a, double b, double error) {
        double fa = function.apply(a);
        double fb = function.apply(b);
        Triple t =  quadratureAdaptiveSimpsonsOne(function, a, fa, b ,fb);
        return quadratureAdaptiveSimpsonsRecursive(function, a, fa, b, fb, error, t.s, t.x, t.fx);
    }
    
    private static double quadratureAdaptiveSimpsonsRecursive(Function<Double,Double> function, double a, double fa, double b, double fb, double error, double whole, double m, double fm) {
        Triple left  = quadratureAdaptiveSimpsonsOne(function, a, fa, m, fm);
        Triple right = quadratureAdaptiveSimpsonsOne(function, m, fm, b, fb);
        double delta = left.s + right.s - whole;
        if ( Math.abs(delta) <= 15*error ) {
            return left.s + right.s + delta / 15;
        }
        return quadratureAdaptiveSimpsonsRecursive(function, a, fa, m, fm, error/2, left.s, left.x, left.fx) +
               quadratureAdaptiveSimpsonsRecursive(function, m, fm, b, fb, error/2, right.s, right.x, right.fx);
    }
    
    private static Triple quadratureAdaptiveSimpsonsOne(Function<Double,Double> function, double a, double fa, double b, double fb) {
        double m = (a + b) / 2;
        double fm = function.apply(m);
        return new Triple(m, fm, Math.abs(b-a) / 6 * (fa + 4*fm + fb));
    }
    
    private static class Triple {
        double x, fx, s;
        private Triple(double m, double fm, double s) {
            this.x = m;
            this.fx = fm;
            this.s = s;
        }
    }
    
    private static int functionCount = 0;
    
    private static double sin(double x) {
        functionCount++;
        return Math.sin(x);
    }
    
}



Python: 



import math

import collections
triple = collections.namedtuple('triple', 'm fm simp')

def _quad_simpsons_mem(f: callable, a: float , fa: float, b: float, fb: float)->tuple:
    
    m = a + (b - a) / 2
    fm = f(m)
    simp = abs(b - a) / 6 * (fa + 4*fm + fb)
    return triple(m, fm, simp,)
 
def _quad_asr(f: callable, a: float, fa: float, b: float, fb: float, eps: float, whole: float, m: float, fm: float)->float:
    
    lt = _quad_simpsons_mem(f, a, fa, m, fm)
    rt = _quad_simpsons_mem(f, m, fm, b, fb)
    delta = lt.simp + rt.simp - whole
    return (lt.simp + rt.simp + delta/15
        if (abs(delta) <= eps * 15) else
            _quad_asr(f, a, fa, m, fm, eps/2, lt.simp, lt.m, lt.fm) +
            _quad_asr(f, m, fm, b, fb, eps/2, rt.simp, rt.m, rt.fm)
    )

def quad_asr(f: callable, a: float, b: float, eps: float)->float:
    
    fa = f(a)
    fb = f(b)
    t = _quad_simpsons_mem(f, a, fa, b, fb)
    return _quad_asr(f, a, fa, b, fb, eps, t.simp, t.m, t.fm)

def main():
    (a, b,) = (0.0, 1.0,)
    sinx = quad_asr(math.sin, a, b, 1e-09);
    print("Simpson's integration of sine from {} to {} = {}\n".format(a, b, sinx))

main()