# Source code for numdifftools.test_functions

    """
    Created on 17. mai 2015

    @author: pab
    """
    from __future__ import division
    import numpy as np

    function_names = ['cos', 'sin', 'tan',
                      'cosh', 'sinh', 'tanh',
                      'arcsinh',
                      'exp', 'expm1', 'exp2', 'square',
                      'sqrt',
                      'log', 'log1p', 'log10', 'log2',
                      'arccos', 'arcsin', 'arctan', ]

    def dcos(x):
        return -np.sin(x)

    def ddcos(x):
        return -np.cos(x)

    def get_function(fun_name, n=1):

        sinh, cosh, tanh = np.sinh, np.cosh, np.tanh
        sin, cos, tan = np.sin, np.cos, np.tan
        f_dic = dict(sinh=(sinh, cosh, sinh, cosh, sinh),
                     cosh=(cosh, sinh, cosh, sinh, cosh),
                     arccosh=(np.arccosh,
                              lambda x: 1./np.sqrt(x**2-1),
                              lambda x: -x/(x**2-1)**(1.5),
                              lambda x: -1./(x**2-1)**(1.5) +
                              3*x**2/(x**2-1)**(2.5),
                              ),
                     arcsinh=(np.arcsinh,
                              lambda x: 1./np.sqrt(1+x**2),
                              lambda x: -x/(1+x**2)**(3./2),
                              lambda x: -1./(1+x**2)**(3./2) +
                              3*x**2/(1+x**2)**(5./2),
                              ),
                     arctanh=(np.arctanh,
                              lambda x: 1./(1-x**2),
                              lambda x: 2*x/(1-x**2)**2,
                              lambda x: 2./(1-x**2)**2 +
                              8*x**2/(1-x**2)**3,
                              ),
                     arccos=(np.arccos,
                             lambda x: -1./np.sqrt(1-x**2),
                             lambda x: -x/(1-x**2)**(3./2),
                             lambda x: -1./(1-x**2)**(3./2) -
                             3*x**2/(1-x**2)**(5./2),
                             ),
                     arcsin=(np.arcsin,
                             lambda x: 1./np.sqrt(1-x**2),
                             lambda x: x/(1-x**2)**(3./2),
                             lambda x: 1./(1-x**2)**(3./2) +
                             3*x**2./(1-x**2)**(5./2),
                             ),
                     square=(lambda x: x * x,  # np.square,
                             lambda x: 2 * x,
                             lambda x: 2 * np.ones_like(x)) + (
                             lambda x: np.zeros_like(x),)*15,
                     exp=(np.exp,)*20,
                     expm1=(np.expm1,) + (np.exp,)*20,
                     exp2=(np.exp2,
                           lambda x: np.exp2(x)*np.log(2),
                           lambda x: np.exp2(x)*np.log(2)**2,
                           lambda x: np.exp2(x)*np.log(2)**3,
                           lambda x: np.exp2(x)*np.log(2)**4
                           ),
                     arctan=(np.arctan,
                             lambda x: 1./(1+x**2),
                             lambda x: -2*x/(1+x**2)**2,
                             lambda x: 8.0*x**2/(1+x**2)**3 - 2./(1+x**2)**2,
                             lambda x: 24*x/(1+x**2)**3 - 48*x**3./(1+x**2)**4,
                             ),
                     cos=(cos, dcos, ddcos, sin) * 6,
                     sin=(sin, np.cos, dcos, ddcos) * 6,
                     tan=(tan,
                          lambda x: 1./np.cos(x)**2,
                          lambda x: 2*np.tan(x)/np.cos(x)**2,
                          lambda x: (4*(tan(x)**2 + 1)*tan(x)**2 +
                                     2*(tan(x)**2 + 1)**2),
                          lambda x: (8*(tan(x)**2 + 1)*tan(x)**3 +
                                     16*(tan(x)**2 + 1)**2*tan(x))
                          ),
                     tanh=(tanh,
                           lambda x: 1. / cosh(x) ** 2,
                           lambda x: -2 * sinh(x) / cosh(x) ** 3,
                           lambda x: 4*(tanh(x)/cosh(x))**2 - 2./cosh(x)**4,
                           lambda x: (8*(tanh(x)**2 - 1)*tanh(x)**3 +
                                      16*(tanh(x)**2 - 1)**2*tanh(x))),
                     log1p=(np.log1p,
                            lambda x: 1. / (1+x),
                            lambda x: -1. / (1+x) ** 2,
                            lambda x: 2. / (1+x) ** 3,
                            lambda x: -6. / (1+x) ** 4),
                     log2=(np.log2,
                           lambda x: 1. / (x*np.log(2)),
                           lambda x: -1. / (x ** 2 * np.log(2)),
                           lambda x: 2. / (x ** 3 * np.log(2)),
                           lambda x: -6. / (x ** 4 * np.log(2))),
                     log10=(np.log10,
                            lambda x: 1. / (x * np.log(10)),
                            lambda x: -1. / (x ** 2 * np.log(10)),
                            lambda x: 2. / (x ** 3 * np.log(10)),
                            lambda x: -6. / (x ** 4 * np.log(10))),
                     log=(np.log,
                          lambda x: 1. / x,
                          lambda x: -1. / x ** 2,
                          lambda x: 2. / x ** 3,
                          lambda x: -6. / x ** 4),
                     sqrt=(np.sqrt,
                           lambda x: 0.5/np.sqrt(x),
                           lambda x: -0.25/x**(1.5),
                           lambda x: 1.5*0.25/x**(2.5),
                           lambda x: -2.5*1.5*0.25/x**(3.5)),
                     inv=(lambda x: 1. / x,
                          lambda x: -1. / x ** 2,
                          lambda x: 2. / x ** 3,
                          lambda x: -6. / x ** 4,
                          lambda x: 24. / x ** 5))
        if fun_name == 'all':
            return f_dic.keys()

        funs = f_dic.get(fun_name)
        fun0 = funs[0]
        if n < len(funs):
            return fun0, funs[n]

        return fun0, None

    if __name__ == '__main__':
        pass