Module quagmire.function.math
Copyright 2016-2019 Louis Moresi, Ben Mather, Romain Beucher
This file is part of Quagmire.
Quagmire is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version.
Quagmire is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with Quagmire. If not, see http://www.gnu.org/licenses/.
Expand source code
"""
Copyright 2016-2019 Louis Moresi, Ben Mather, Romain Beucher
This file is part of Quagmire.
Quagmire is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or any later version.
Quagmire is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Quagmire. If not, see <http://www.gnu.org/licenses/>.
"""
import numpy as _np
from .function_classes import LazyEvaluation as _LazyEvaluation
from .function_classes import parameter as _parameter
from .function_classes import convert as _convert
## Functions of a single variable
def _make_npmath_op(op, name, lazyFn, lformat):
lazyFn = _convert(lazyFn)
newLazyFn = _LazyEvaluation()
newLazyFn.coordinate_system = lazyFn.coordinate_system
newLazyFn.evaluate = lambda *args, **kwargs : op(lazyFn.evaluate(*args, **kwargs))
newLazyFn.description = "{}({})".format(name,lazyFn.description)
newLazyFn.latex = lformat.format(lazyFn.latex)
newLazyFn.math = lambda : lformat.format(lazyFn.math())
newLazyFn.dependency_list = lazyFn.dependency_list
return newLazyFn
## Trig
def sin(lazyFn):
newFn = _make_npmath_op(_np.sin, "sin", lazyFn, r"\sin\left({}\right)")
newFn.derivative = lambda dirn : lazyFn.derivative(dirn) * cos( lazyFn )
return newFn
def asin(lazyFn):
newFn = _make_npmath_op(_np.arcsin, "asin", lazyFn, r"\sin^{{-1}}\left({}\right)")
newFn.derivative = lambda dirn : lazyFn.derivative(dirn) / sqrt(_parameter(1.0) - lazyFn**2)
return newFn
def arcsin(lazyFn):
newFn = _make_npmath_op(_np.arcsin, "arcsin", lazyFn, r"\sin^{{-1}}\left({}\right)")
newFn.derivative = lambda dirn : lazyFn.derivative(dirn) / sqrt(_parameter(1.0) - lazyFn**2)
return newFn
def cos(lazyFn):
newFn = _make_npmath_op(_np.cos, "cos", lazyFn, r"\cos\left({}\right)")
newFn.derivative = lambda dirn : -lazyFn.derivative(dirn) * sin( lazyFn )
return newFn
def acos(lazyFn):
newFn = _make_npmath_op(_np.arcsin, "acos", lazyFn, r"\cos^{{-1}}\left({}\right)")
newFn.derivative = lambda dirn : - lazyFn.derivative(dirn) / sqrt(_parameter(1.0) - lazyFn**2)
return newFn
def arccos(lazyFn):
newFn = _make_npmath_op(_np.arcsin, "arccos", lazyFn, r"\cos^{{-1}}\left({}\right)")
newFn.derivative = lambda dirn : - lazyFn.derivative(dirn) / sqrt(_parameter(1.0) - lazyFn**2)
return newFn
def tan(lazyFn):
newFn = _make_npmath_op(_np.tan, "tan", lazyFn, r"\tan\left({}\right)")
newFn.derivative = lambda dirn : lazyFn.derivative(dirn) * (_parameter(1.0) + tan(lazyFn)**2 )
return newFn
def atan(lazyFn):
newFn = _make_npmath_op(_np.arcsin, "atan", lazyFn, r"\tan^{{-1}}\left({}\right)")
newFn.derivative = lambda dirn : lazyFn.derivative(dirn) / (_parameter(1.0) + lazyFn**2)
return newFn
def arctan(lazyFn):
newFn = _make_npmath_op(_np.arcsin, "arctan", lazyFn, r"\tan^{{-1}}\left({}\right)")
newFn.derivative = lambda dirn : lazyFn.derivative(dirn) / (_parameter(1.0) + lazyFn**2)
return newFn
## Hyperbolic
def sinh(lazyFn):
newFn = _make_npmath_op(_np.sinh, "sinh", lazyFn, r"\sinh\left({}\right)")
newFn.derivative = lambda dirn : lazyFn.derivative(dirn) * cosh( lazyFn )
return newFn
def asinh(lazyFn):
newFn = _make_npmath_op(_np.arcsinh, "asinh", lazyFn, r"\sinh^{{-1}}\left({}\right)")
newFn.derivative = lambda dirn : lazyFn.derivative(dirn) / sqrt(_parameter(1.0) + lazyFn**2)
return newFn
def arcsinh(lazyFn):
newFn = _make_npmath_op(_np.arcsinh, "arcsinh", lazyFn, r"\sinh^{{-1}}\left({}\right)")
newFn.derivative = lambda dirn : lazyFn.derivative(dirn) / sqrt(_parameter(1.0) + lazyFn**2)
return newFn
def cosh(lazyFn):
newFn = _make_npmath_op(_np.cosh, "cosh", lazyFn, r"\cosh\left({}\right)")
newFn.derivative = lambda dirn : lazyFn.derivative(dirn) * sinh( lazyFn )
return newFn
def acosh(lazyFn):
newFn = _make_npmath_op(_np.arccosh, "acosh", lazyFn, r"\cosh^{{-1}}\left({}\right)")
newFn.derivative = lambda dirn : lazyFn.derivative(dirn) / sqrt(_parameter(-1.0) + lazyFn**2)
return newFn
def arccosh(lazyFn):
newFn = _make_npmath_op(_np.arccosh, "arccosh", lazyFn, r"\cosh^{{-1}}\left({}\right)")
newFn.derivative = lambda dirn : lazyFn.derivative(dirn) / sqrt(_parameter(-1.0) + lazyFn**2)
return newFn
def tanh(lazyFn):
newFn = _make_npmath_op(_np.tanh, "tanh", lazyFn, r"\tanh\left({}\right)")
newFn.derivative = lambda dirn : lazyFn.derivative(dirn) * (_parameter(1.0) - lazyFn.derivative(dirn)**2)
return newFn
def atanh(lazyFn):
newFn = _make_npmath_op(_np.arctanh, "atanh", lazyFn, r"\tanh^{{-1}}\left({}\right)")
newFn.derivative = lambda dirn : lazyFn.derivative(dirn) / (_parameter(1.0) - lazyFn**2)
return newFn
def arctanh(lazyFn):
newFn = _make_npmath_op(_np.arctanh,"arctanh", lazyFn, r"\tanh^{{-1}}\left({}\right)")
newFn.derivative = lambda dirn : lazyFn.derivative(dirn) / (_parameter(1.0) - lazyFn**2)
return newFn
## exponentiation
def exp(lazyFn):
newFn = _make_npmath_op(_np.exp, "exp", lazyFn, r"\exp\left({}\right)")
newFn.derivative = lambda dirn : lazyFn.derivative(dirn) * exp(lazyFn)
return newFn
def log(lazyFn):
newFn = _make_npmath_op(_np.log, "log", lazyFn, r"\log_e\left({}\right)")
newFn.derivative = lambda dirn : lazyFn.derivative(dirn) / lazyFn
return newFn
def log10(lazyFn):
newFn = _make_npmath_op(_np.log10, "log10",lazyFn, r"\log_{{10}}\left({}\right)")
## See definition of d/dx(log10(x))
newFn.derivative = lambda dirn : _parameter(0.434294481903) * lazyFn.derivative(dirn) / lazyFn
return newFn
def sqrt(lazyFn):
newFn = _make_npmath_op(_np.sqrt, "sqrt", lazyFn, r"\sqrt{{ {} }}")
newFn.derivative = lambda dirn : lazyFn.derivative(dirn) / sqrt(lazyFn)
return newFn
# misc
## Not sure about the absolute value and symbolic derivative
def fabs(lazyFn):
return _make_npmath_op(_np.fabs, "fabs", lazyFn, r"\left|{}\right|")
def degrees(lazyFn):
newFn = _make_npmath_op(_np.degrees, "degrees", lazyFn, r"\frac{{180}}{{\pi}}{}")
newFn.derivative = lambda dirn : _parameter(180.0/_np.pi) * lazyFn.derivative(dirn)
return newFn
def radians(lazyFn):
newFn = _make_npmath_op(_np.radians, "radians", lazyFn, r"\frac{{\pi}}{{180}}{}")
newFn.derivative = lambda dirn : _parameter(_np.pi/180.0) * lazyFn.derivative(dirn)
return newFn
def rad2deg(lazyFn):
return degrees(lazyFn)
def deg2rad(lazyFn):
return radians(lazyFn)
## ?? Are these geometry safe ? Probably not !
def hypot(*args):
"""Lazy evaluation of hypot operator on N fields"""
def _hyp(lazyFn_list, *args, **kwargs):
lazy_ev = []
for lazyFn in lazyFn_list:
lazy_ev.append( lazyFn.evaluate(*args, **kwargs) )
return _np.hypot(*lazy_ev)
lazyFn_list = []
lazyFn_description = ""
lazyFn_dependency = set()
for lazyFn in args:
lazyFn_list.append(lazyFn)
lazyFn_description += "{}^2 + ".format(lazyFn.description)
lazyFn_dependency.union(lazyFn.dependency_list)
lazyFn_description = lazyFn_description[:-3]
newLazyFn = _LazyEvaluation()
newLazyFn.evaluate = lambda *args, **kwargs : _hyp(lazyFn_list, *args, **kwargs)
newLazyFn.description = "sqrt({})".format(lazyFn_description)
newLazyFn.dependency_list = lazyFn_dependency
return newLazyFn
def arctan2(*args):
"""Lazy evaluation of arctan2 operator on N fields"""
def _arctan2(lazyFn_list, *args, **kwargs):
lazy_ev = []
for lazyFn in lazyFn_list:
lazy_ev.append( lazyFn.evaluate(*args, **kwargs) )
return _np.arctan2(*lazy_ev)
lazyFn_list = []
lazyFn_description = ""
lazyFn_dependency = set()
for lazyFn in args:
lazyFn_list.append(lazyFn)
lazyFn_description += "{},".format(lazyFn.description)
lazyFn_dependency.union(lazyFn.dependency_list)
lazyFn_description = lazyFn_description[:-1]
newLazyFn = _LazyEvaluation()
newLazyFn.evaluate = lambda *args, **kwargs : _arctan2(lazyFn_list, *args, **kwargs)
newLazyFn.description = "arctan2({})".format(lazyFn_description)
newLazyFn.dependency_list = lazyFn_dependency
return newLazyFn
Functions
def acos(lazyFn)
-
Expand source code
def acos(lazyFn): newFn = _make_npmath_op(_np.arcsin, "acos", lazyFn, r"\cos^{{-1}}\left({}\right)") newFn.derivative = lambda dirn : - lazyFn.derivative(dirn) / sqrt(_parameter(1.0) - lazyFn**2) return newFn
def acosh(lazyFn)
-
Expand source code
def acosh(lazyFn): newFn = _make_npmath_op(_np.arccosh, "acosh", lazyFn, r"\cosh^{{-1}}\left({}\right)") newFn.derivative = lambda dirn : lazyFn.derivative(dirn) / sqrt(_parameter(-1.0) + lazyFn**2) return newFn
def arccos(lazyFn)
-
Expand source code
def arccos(lazyFn): newFn = _make_npmath_op(_np.arcsin, "arccos", lazyFn, r"\cos^{{-1}}\left({}\right)") newFn.derivative = lambda dirn : - lazyFn.derivative(dirn) / sqrt(_parameter(1.0) - lazyFn**2) return newFn
def arccosh(lazyFn)
-
Expand source code
def arccosh(lazyFn): newFn = _make_npmath_op(_np.arccosh, "arccosh", lazyFn, r"\cosh^{{-1}}\left({}\right)") newFn.derivative = lambda dirn : lazyFn.derivative(dirn) / sqrt(_parameter(-1.0) + lazyFn**2) return newFn
def arcsin(lazyFn)
-
Expand source code
def arcsin(lazyFn): newFn = _make_npmath_op(_np.arcsin, "arcsin", lazyFn, r"\sin^{{-1}}\left({}\right)") newFn.derivative = lambda dirn : lazyFn.derivative(dirn) / sqrt(_parameter(1.0) - lazyFn**2) return newFn
def arcsinh(lazyFn)
-
Expand source code
def arcsinh(lazyFn): newFn = _make_npmath_op(_np.arcsinh, "arcsinh", lazyFn, r"\sinh^{{-1}}\left({}\right)") newFn.derivative = lambda dirn : lazyFn.derivative(dirn) / sqrt(_parameter(1.0) + lazyFn**2) return newFn
def arctan(lazyFn)
-
Expand source code
def arctan(lazyFn): newFn = _make_npmath_op(_np.arcsin, "arctan", lazyFn, r"\tan^{{-1}}\left({}\right)") newFn.derivative = lambda dirn : lazyFn.derivative(dirn) / (_parameter(1.0) + lazyFn**2) return newFn
def arctan2(*args)
-
Lazy evaluation of arctan2 operator on N fields
Expand source code
def arctan2(*args): """Lazy evaluation of arctan2 operator on N fields""" def _arctan2(lazyFn_list, *args, **kwargs): lazy_ev = [] for lazyFn in lazyFn_list: lazy_ev.append( lazyFn.evaluate(*args, **kwargs) ) return _np.arctan2(*lazy_ev) lazyFn_list = [] lazyFn_description = "" lazyFn_dependency = set() for lazyFn in args: lazyFn_list.append(lazyFn) lazyFn_description += "{},".format(lazyFn.description) lazyFn_dependency.union(lazyFn.dependency_list) lazyFn_description = lazyFn_description[:-1] newLazyFn = _LazyEvaluation() newLazyFn.evaluate = lambda *args, **kwargs : _arctan2(lazyFn_list, *args, **kwargs) newLazyFn.description = "arctan2({})".format(lazyFn_description) newLazyFn.dependency_list = lazyFn_dependency return newLazyFn
def arctanh(lazyFn)
-
Expand source code
def arctanh(lazyFn): newFn = _make_npmath_op(_np.arctanh,"arctanh", lazyFn, r"\tanh^{{-1}}\left({}\right)") newFn.derivative = lambda dirn : lazyFn.derivative(dirn) / (_parameter(1.0) - lazyFn**2) return newFn
def asin(lazyFn)
-
Expand source code
def asin(lazyFn): newFn = _make_npmath_op(_np.arcsin, "asin", lazyFn, r"\sin^{{-1}}\left({}\right)") newFn.derivative = lambda dirn : lazyFn.derivative(dirn) / sqrt(_parameter(1.0) - lazyFn**2) return newFn
def asinh(lazyFn)
-
Expand source code
def asinh(lazyFn): newFn = _make_npmath_op(_np.arcsinh, "asinh", lazyFn, r"\sinh^{{-1}}\left({}\right)") newFn.derivative = lambda dirn : lazyFn.derivative(dirn) / sqrt(_parameter(1.0) + lazyFn**2) return newFn
def atan(lazyFn)
-
Expand source code
def atan(lazyFn): newFn = _make_npmath_op(_np.arcsin, "atan", lazyFn, r"\tan^{{-1}}\left({}\right)") newFn.derivative = lambda dirn : lazyFn.derivative(dirn) / (_parameter(1.0) + lazyFn**2) return newFn
def atanh(lazyFn)
-
Expand source code
def atanh(lazyFn): newFn = _make_npmath_op(_np.arctanh, "atanh", lazyFn, r"\tanh^{{-1}}\left({}\right)") newFn.derivative = lambda dirn : lazyFn.derivative(dirn) / (_parameter(1.0) - lazyFn**2) return newFn
def cos(lazyFn)
-
Expand source code
def cos(lazyFn): newFn = _make_npmath_op(_np.cos, "cos", lazyFn, r"\cos\left({}\right)") newFn.derivative = lambda dirn : -lazyFn.derivative(dirn) * sin( lazyFn ) return newFn
def cosh(lazyFn)
-
Expand source code
def cosh(lazyFn): newFn = _make_npmath_op(_np.cosh, "cosh", lazyFn, r"\cosh\left({}\right)") newFn.derivative = lambda dirn : lazyFn.derivative(dirn) * sinh( lazyFn ) return newFn
def deg2rad(lazyFn)
-
Expand source code
def deg2rad(lazyFn): return radians(lazyFn)
def degrees(lazyFn)
-
Expand source code
def degrees(lazyFn): newFn = _make_npmath_op(_np.degrees, "degrees", lazyFn, r"\frac{{180}}{{\pi}}{}") newFn.derivative = lambda dirn : _parameter(180.0/_np.pi) * lazyFn.derivative(dirn) return newFn
def exp(lazyFn)
-
Expand source code
def exp(lazyFn): newFn = _make_npmath_op(_np.exp, "exp", lazyFn, r"\exp\left({}\right)") newFn.derivative = lambda dirn : lazyFn.derivative(dirn) * exp(lazyFn) return newFn
def fabs(lazyFn)
-
Expand source code
def fabs(lazyFn): return _make_npmath_op(_np.fabs, "fabs", lazyFn, r"\left|{}\right|")
def hypot(*args)
-
Lazy evaluation of hypot operator on N fields
Expand source code
def hypot(*args): """Lazy evaluation of hypot operator on N fields""" def _hyp(lazyFn_list, *args, **kwargs): lazy_ev = [] for lazyFn in lazyFn_list: lazy_ev.append( lazyFn.evaluate(*args, **kwargs) ) return _np.hypot(*lazy_ev) lazyFn_list = [] lazyFn_description = "" lazyFn_dependency = set() for lazyFn in args: lazyFn_list.append(lazyFn) lazyFn_description += "{}^2 + ".format(lazyFn.description) lazyFn_dependency.union(lazyFn.dependency_list) lazyFn_description = lazyFn_description[:-3] newLazyFn = _LazyEvaluation() newLazyFn.evaluate = lambda *args, **kwargs : _hyp(lazyFn_list, *args, **kwargs) newLazyFn.description = "sqrt({})".format(lazyFn_description) newLazyFn.dependency_list = lazyFn_dependency return newLazyFn
def log(lazyFn)
-
Expand source code
def log(lazyFn): newFn = _make_npmath_op(_np.log, "log", lazyFn, r"\log_e\left({}\right)") newFn.derivative = lambda dirn : lazyFn.derivative(dirn) / lazyFn return newFn
def log10(lazyFn)
-
Expand source code
def log10(lazyFn): newFn = _make_npmath_op(_np.log10, "log10",lazyFn, r"\log_{{10}}\left({}\right)") ## See definition of d/dx(log10(x)) newFn.derivative = lambda dirn : _parameter(0.434294481903) * lazyFn.derivative(dirn) / lazyFn return newFn
def rad2deg(lazyFn)
-
Expand source code
def rad2deg(lazyFn): return degrees(lazyFn)
def radians(lazyFn)
-
Expand source code
def radians(lazyFn): newFn = _make_npmath_op(_np.radians, "radians", lazyFn, r"\frac{{\pi}}{{180}}{}") newFn.derivative = lambda dirn : _parameter(_np.pi/180.0) * lazyFn.derivative(dirn) return newFn
def sin(lazyFn)
-
Expand source code
def sin(lazyFn): newFn = _make_npmath_op(_np.sin, "sin", lazyFn, r"\sin\left({}\right)") newFn.derivative = lambda dirn : lazyFn.derivative(dirn) * cos( lazyFn ) return newFn
def sinh(lazyFn)
-
Expand source code
def sinh(lazyFn): newFn = _make_npmath_op(_np.sinh, "sinh", lazyFn, r"\sinh\left({}\right)") newFn.derivative = lambda dirn : lazyFn.derivative(dirn) * cosh( lazyFn ) return newFn
def sqrt(lazyFn)
-
Expand source code
def sqrt(lazyFn): newFn = _make_npmath_op(_np.sqrt, "sqrt", lazyFn, r"\sqrt{{ {} }}") newFn.derivative = lambda dirn : lazyFn.derivative(dirn) / sqrt(lazyFn) return newFn
def tan(lazyFn)
-
Expand source code
def tan(lazyFn): newFn = _make_npmath_op(_np.tan, "tan", lazyFn, r"\tan\left({}\right)") newFn.derivative = lambda dirn : lazyFn.derivative(dirn) * (_parameter(1.0) + tan(lazyFn)**2 ) return newFn
def tanh(lazyFn)
-
Expand source code
def tanh(lazyFn): newFn = _make_npmath_op(_np.tanh, "tanh", lazyFn, r"\tanh\left({}\right)") newFn.derivative = lambda dirn : lazyFn.derivative(dirn) * (_parameter(1.0) - lazyFn.derivative(dirn)**2) return newFn