123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218 |
- #Copyright (c) 2008, Riccardo De Maria
- #All rights reserved.
- import math
- from .pol import pol, phorner
- pi=math.pi
- """ The idea is that you evaluate a+x being x a small quantity,
- then you rewrite f(a+x) so that you have a combination of
- g_i(a) and g_k(x h_l(a) ).
- g_i(a) and h_l(a) can be evaluated exactly by usual math libraries
- g_k(x) because are proportianal to x are well approximated
- by a taylor expansion.
- """
- def sqrt(c):
- """Square root of a polynomial
- >>> from pol import *
- >>> print sqrt(pol('1+x'))**2
- 1.0 + x
- >>> print sqrt(pol('1j+x'))**2
- 1j -1j*x
- """
- if not isinstance(c,pol): return math.sqrt(c)
- a0,p=c.separate(); p/=a0
- lst=[math.sqrt(a0)]
- for n in range(1,c.order+1):
- lst.append(-lst[-1]/2/n*(2*n-3))
- return phorner(lst,p)
- def exp(c):
- """Exponential of a polynomial
- exp(a+x) = exp(a)exp(x)
- >>> from pol import *
- >>> print log(exp(pol('1+x')))
- 1.0 + x
- """
- if not isinstance(c,pol): return math.exp(c)
- a0,p=c.separate();
- lst=[exp(a0)]
- for n in range(1,c.order+1):
- lst.append(lst[-1]/n)
- return phorner(lst,p)
- def log(c):
- """Logarithm of a polynomial
- log(a+x)=log(a)-log(1+x/a)
- >>> from pol import *
- >>> print log(exp(pol('1+x')))
- 1.0 + x
- """
- if not isinstance(c,pol): return math.log(c)
- a0,p=c.separate(); p/=a0
- lst=[log(a0),1.]
- for n in range(2,c.order+1):
- lst.append( -lst[-1]/n*(n-1) )
- return phorner(lst,p)
- def sin(c):
- """
- sin(a+x)= sin(a) cos(x) + cos(a) sin(x)
- """
- if not isinstance(c,pol): return math.sin(c)
- a0,p=c.separate();
- lst=[math.sin(a0),math.cos(a0)]
- for n in range(2,c.order+1):
- lst.append( -lst[-2]/n/(n-1))
- return phorner(lst,p)
- def cos(c):
- """
- cos(a+x)= cos(a) cos(x) - sin(a) sin(x)
- """
- if not isinstance(c,pol): return math.cos(c)
- a0,p=c.separate();
- lst=[math.cos(a0),-math.sin(a0)]
- for n in range(2,c.order+1):
- lst.append( -lst[-2]/n/(n-1))
- return phorner(lst,p)
- def tan(y):
- """Compute Tan
- """
- return sin(y)/cos(y)
- def sinh(c):
- """Compute Sinh using a Taylor expansion
- """
- if not isinstance(c,pol): return math.sinh(c)
- a0,p=c.separate();
- lst=[math.sinh(a0),math.cosh(a0)]
- for n in range(2,c.order+1):
- lst.append( lst[-2]/n/(n-1))
- return phorner(lst,p)
- def cosh(c):
- """Compute Cosh using a Taylor expansion
- """
- if not isinstance(c,pol): return math.cosh(c)
- a0,p=c.separate();
- lst=[math.cosh(a0),math.sinh(a0)]
- for n in range(2,c.order+1):
- lst.append( lst[-2]/n/(n-1))
- return phorner(lst,p)
- def isqrt(c):
- if not isinstance(c,pol): return 1/math.sqrt(c)
- a0,p=c.separate(); p/=a0
- lst=[1/math.sqrt(a0)]
- for n in range(1,c.order+1):
- lst.append(-lst[-1]/a0/2/n*(2*n-1))
- return phorner(lst,p)
- #def asin_t(c):
- # """Compute ArcSin using a Taylor expansion
- # >>> from pol import *
- # >>> x,y=mkpol('x,y')
- # >>> asin(sin(.7+x+y))
- # 0.7 + x + y
- # """
- # p=c.copy()
- # x=pol('x')
- # return pisqrt(1-x**2).int(x)(x=p)
- def asin(y):
- """Compute ArcSin
- >>> from pol import *
- >>> x,y=mkpol('x,y')
- >>> asin(sin(.4+x+y))
- 0.4 + x + y
- """
- x0=pol(math.asin(y.zero()))
- for i in range(y.order):
- x0=x0 + (y-sin(x0))/cos(x0)
- return x0
- def acos(y):
- """Compute ArcCos
- >>> from pol import *
- >>> x,y=mkpol('x,y')
- >>> acos(cos(.4+x+y))
- 0.4 + x + y
- """
- x0=pol(math.acos(y.zero()))
- for i in range(y.order):
- x0=x0 + -(y-cos(x0))/sin(x0)
- return x0
- def atan(y):
- """Compute ArcTan using Newton method
- x=f(y); y=g(x)
- x0=f(y0); x0=x0 +(y-g(x0))/g'(x)
- >>> from pol import *
- >>> p=pol('.4+x+y')
- >>> print tan(atan(p))
- 0.4 + x + y
- >>> print atan(tan(p))
- 0.4 + x + y
- """
- x0=pol(math.atan(y.zero()))
- for i in range(y.order):
- x0=x0 + (y-tan(x0))*cos(x0)**2
- return x0
- def asinh(y):
- """Compute ArcSinh
- >>> from pol import *
- >>> x,y=mkpol('x,y')
- >>> asinh(sinh(.4+x+y))
- 0.4 + x + y
- """
- x0=pol(log(y+sqrt(y**2+1)))
- for i in range(y.order):
- x0=x0 + (y-sinh(x0))/cosh(x0)
- return x0
- def acosh(y):
- """Compute ArcCosh
- >>> from pol import *
- >>> x,y=mkpol('x,y')
- >>> acosh(cosh(1.4+x+y))
- 1.4 + x + y
- """
- x0=pol(log(y+sqrt(y**2-1)))
- for i in range(y.order):
- x0=x0 + (y-cosh(x0))/sinh(x0)
- return x0
- def newton(f,y,x0):
- """Inverse polynomial using newton method EXPERIMENTAL
- >>> f=pol('1+x**2')
- >>> f(x=newton(f,pol('2+x'),1))
- 2.0 + x
- """
- for i in range(y.order):
- x0=x0+ ( y-f(x=x0) ) / f.der('x')(x=x0)
- return x0
- #if __name__=='__main__':
- # import doctest
- # doctest.testmod()
- # import profile
- # pol.order=9
- # profile.run('pol("sqrt(1+x+y+z+px+py+pz)")',sort='time')
|