%%cython

cpdef noop():
    pass

%load_ext Cython

%%cython
cimport numpy

cpdef cysum(numpy.ndarray[double] A):
    """Compute the sum of an array"""
    cdef double a=0
    for i in range(A.shape[0]):
        a += A[i]
    return a


def pysum(A):
    """Compute the sum of an array"""
    a = 0
    for i in range(A.shape[0]):
        a += A[i]
    return a


import numpy as np

for sz in (100, 1000, 10000):
    A = np.random.random(sz)
    print("Python %i" % sz, end=' ')
    %timeit pysum(A)
    print("np.sum %i" % sz, end=' ')
    %timeit A.sum()
    print("Cython %i" % sz, end=' ')
    %timeit cysum(A)


"""
Explanation: Customizing IPython - Extensions
Extensions are just Python modules with a special function:
python
def load_ipython_extension(ip):
    do_anything()
%load_ext module imports the module, and calls module.load_ipython_extension(ip)
with the IPython instance.
This allows modules or standalone extensions to manipulate IPython.
Most often, extensions define new magics or work with the interactive namespace.
Cython is an example of a package that can be used as an IPython extension.
This defines a few magics for executing Cython code interactively.
End of explanation
"""


import Cython

Cython.load_ipython_extension??

from Cython.Build.IpythonMagic import CythonMagics
CythonMagics??

"""
Explanation: Let's see what Cython's load_ipython_extension function looks like
End of explanation
"""


%pycat soln/mymagics.py

"""
Explanation: Our own extension
Loading an extension can do as much or as little as you want.
Since we have been defining our timer magics, let's create an extension to make them available in any IPython session.
End of explanation
"""


%install_ext soln/mymagics.py

%load_ext mymagics

import time
%tic
time.sleep(0.1)
%toc

%nbrun _Sample

"""
Explanation: %install_ext is a function that can take any file path or URL, and puts the target into IPYTHONDIR/extensions
End of explanation
"""


