In [ ]:
import numpy as np
#from numba import jit


def int3points(x1,x2,x3,y1,y2,y3):
    x0 = x1 + 1e-15
    np.reciprocal(x0,out=x0)
    x4 = x2 + 1e-15
    np.reciprocal(x4,out=x4)
    #x4 = 1/(x2+1e-15)
    x5 = x3**2
    x6 = x0*x5
    x7 = x4*x6
    x7 += 1
    x7_ = x0 + x4
    x7_ *= x3
    x7 -= x7_
    x7 += 1e-15
    np.reciprocal(x7,out=x7)
    #x7 = 1/(x7+1e-15)
    #x7 = 1/(-x3*(x0 + x4) + x4*x6 + 1)
    x8 = x1 - x2
    x9 = x8+1e-15
    np.reciprocal(x9,out=x9)
    x10 = x3 - x6
    x10_ = x1*x4
    x11 = x10_*x10
    x11 *= x7
    x11 *= x9
    x12 = x1**2
    x13 = x12+1e-15
    np.reciprocal(x13,out=x13)
    x14 = x2*x9
    x15 = x0*x14
    x16 = x10*x15 
    x16 -= x13*x5
    x16 *= x7
    #x16 = x7*(x10*x15 - x13*x5)
    x17 = x7*y3
    x17 += x16*y1
    x17 -= x11*y2
    #x17 = -x11*y2 + x16*y1 + x7*y3
    x18 = x2**2
    x19 = -x13
    x19 *= x18
    x19 += 1
    #x19 = -x13*x18 + 1
    x20 = x4*x9
    x21 = x7*y3
    x21 += x16*y1
    x21 *= x4
    x21 *= x9
    x21 *= x19
    x21 -= y2*x20
    x21 *= -x1
    x21 -= x15*y1
    x21_ = y2*x10
    x21_ *= x12
    x21_ *= x19
    x21_ *= x7
    x21__ = x18*x8
    x21__ *= x8
    x21__ += 1e-15
    x21_ /= x21__
    x21 += x21_
    #x21 += y2*x10*x12*x19*x7/(x18*x8**2+1e-15)
    x21 /= 2.
    #x21 = (-x1*x4*x9*x19*x7*y3 -x1*x4*x9*x19*x16*y1 + x1*y2*x20 - x15*y1  + y2*x10*x12*x19*x7/(x18*x8**2))/2
    #x21 = (-x1*(x4*x9*x19*(x7*y3 + x16*y1) - y2*x20) - x15*y1  + y2*x10*x12*x19*x7/(x18*x8**2))/2
    x22 = -x19
    x22 *= x20
    x22 += x13
    #x22 = x13 - x19*x20
    x23 = x11*x22
    x23 -= x20
    x23 *= y2
    x23_ = x13*x14
    x23_ += x13
    x23_ -= x16*x22
    x23_ *= y1
    x23 += x23_
    x23_ = -x22
    x23_ *= x7
    x23_ *= y3
    x23 += x23_
    x23 /= 3.
    #x23 = (-x22*x7*y3 + y1*(x13*x14 + x13 - x16*x22) + y2*(x11*x22 - x20))/3
    out = x3 - x1
    out *= x17
    out_ = x1*x23
    out_ += x21
    out_ *= x12
    out -= out_
    out_ = x23*x3
    out_ += x21
    out_ *= x5
    out += out_
    #out = -x12*(x1*x23 + x21) + x17*(x3 - x1) + x5*(x21 + x23*x3)
    return out

def simps(y,x,axis=None):
    assert len(x) == len(y), "sizes of x and y not same {} an {}".format(len(x),len(y))
    assert len(x) >= 4, "not enough points to integrate only {}".format(len(x))
    #arg = np.argsort(x)
    #x = x[arg]
    #y = y[arg]
    #generate the X1,X2,X3
    X1 = x[0:len(x)-2]
    X2 = x[1:len(x)-1]
    X3 = x[2:len(x)]
    Y1 = y[0:len(x)-2]
    Y2 = y[1:len(x)-1]
    Y3 = y[2:len(x)]
    I = int3points(X1,X2,X3,Y1,Y2,Y3)
    #out = (np.sum(I) + (x[1] - x[0])/(x[2] - x[0])*I[0] + (x[-1] - x[-2])/(x[-1] - x[-3])*I[-1])/2.
    out = (np.sum(I) + (x[1] - x[0])*(y[0] + y[1])/2. + (x[-1] - x[-2])*(y[-2] + y[-1])/2.)/2.
    return out

if __name__ == '__main__':
    import numpy as np
    from scipy.integrate import simps as simps_scipy
    import pylab as plt

    def f(x):
        return x**2

    def g(x):
        return np.exp(-(x - 0.5)**2)#/np.sqrt(2*np.pi)

    error1 = []
    error2 = []
    for i in range(4,10,2):
        x = 10**np.linspace(np.log10(0.001),np.log10(1),i)
        #x = np.linspace(0.001,1,i)
        ans = x[-1]**3/3. - x[0]**3/3.
        error1.append(np.abs(simps_scipy(f(x),x) - ans))
        error2.append(np.abs(simps(f(x),x) - ans))

    plt.plot(error1,c='blue')
    plt.plot(error2,c='green')
    plt.yscale('log')
    plt.show()
    from time import clock
    x = 10**np.linspace(np.log10(0.001),np.log10(1),100000)
    y = f(x)
    t1 = clock()
    simps_scipy(y,x)
    print(clock() - t1)
    t1 = clock()
    simps(y,x)
    print(clock() - t1)