funset.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. #Copyright (c) 2008, Riccardo De Maria
  2. #All rights reserved.
  3. import math
  4. from .pol import pol, phorner
  5. pi=math.pi
  6. """ The idea is that you evaluate a+x being x a small quantity,
  7. then you rewrite f(a+x) so that you have a combination of
  8. g_i(a) and g_k(x h_l(a) ).
  9. g_i(a) and h_l(a) can be evaluated exactly by usual math libraries
  10. g_k(x) because are proportianal to x are well approximated
  11. by a taylor expansion.
  12. """
  13. def sqrt(c):
  14. """Square root of a polynomial
  15. >>> from pol import *
  16. >>> print sqrt(pol('1+x'))**2
  17. 1.0 + x
  18. >>> print sqrt(pol('1j+x'))**2
  19. 1j -1j*x
  20. """
  21. if not isinstance(c,pol): return math.sqrt(c)
  22. a0,p=c.separate(); p/=a0
  23. lst=[math.sqrt(a0)]
  24. for n in range(1,c.order+1):
  25. lst.append(-lst[-1]/2/n*(2*n-3))
  26. return phorner(lst,p)
  27. def exp(c):
  28. """Exponential of a polynomial
  29. exp(a+x) = exp(a)exp(x)
  30. >>> from pol import *
  31. >>> print log(exp(pol('1+x')))
  32. 1.0 + x
  33. """
  34. if not isinstance(c,pol): return math.exp(c)
  35. a0,p=c.separate();
  36. lst=[exp(a0)]
  37. for n in range(1,c.order+1):
  38. lst.append(lst[-1]/n)
  39. return phorner(lst,p)
  40. def log(c):
  41. """Logarithm of a polynomial
  42. log(a+x)=log(a)-log(1+x/a)
  43. >>> from pol import *
  44. >>> print log(exp(pol('1+x')))
  45. 1.0 + x
  46. """
  47. if not isinstance(c,pol): return math.log(c)
  48. a0,p=c.separate(); p/=a0
  49. lst=[log(a0),1.]
  50. for n in range(2,c.order+1):
  51. lst.append( -lst[-1]/n*(n-1) )
  52. return phorner(lst,p)
  53. def sin(c):
  54. """
  55. sin(a+x)= sin(a) cos(x) + cos(a) sin(x)
  56. """
  57. if not isinstance(c,pol): return math.sin(c)
  58. a0,p=c.separate();
  59. lst=[math.sin(a0),math.cos(a0)]
  60. for n in range(2,c.order+1):
  61. lst.append( -lst[-2]/n/(n-1))
  62. return phorner(lst,p)
  63. def cos(c):
  64. """
  65. cos(a+x)= cos(a) cos(x) - sin(a) sin(x)
  66. """
  67. if not isinstance(c,pol): return math.cos(c)
  68. a0,p=c.separate();
  69. lst=[math.cos(a0),-math.sin(a0)]
  70. for n in range(2,c.order+1):
  71. lst.append( -lst[-2]/n/(n-1))
  72. return phorner(lst,p)
  73. def tan(y):
  74. """Compute Tan
  75. """
  76. return sin(y)/cos(y)
  77. def sinh(c):
  78. """Compute Sinh using a Taylor expansion
  79. """
  80. if not isinstance(c,pol): return math.sinh(c)
  81. a0,p=c.separate();
  82. lst=[math.sinh(a0),math.cosh(a0)]
  83. for n in range(2,c.order+1):
  84. lst.append( lst[-2]/n/(n-1))
  85. return phorner(lst,p)
  86. def cosh(c):
  87. """Compute Cosh using a Taylor expansion
  88. """
  89. if not isinstance(c,pol): return math.cosh(c)
  90. a0,p=c.separate();
  91. lst=[math.cosh(a0),math.sinh(a0)]
  92. for n in range(2,c.order+1):
  93. lst.append( lst[-2]/n/(n-1))
  94. return phorner(lst,p)
  95. def isqrt(c):
  96. if not isinstance(c,pol): return 1/math.sqrt(c)
  97. a0,p=c.separate(); p/=a0
  98. lst=[1/math.sqrt(a0)]
  99. for n in range(1,c.order+1):
  100. lst.append(-lst[-1]/a0/2/n*(2*n-1))
  101. return phorner(lst,p)
  102. #def asin_t(c):
  103. # """Compute ArcSin using a Taylor expansion
  104. # >>> from pol import *
  105. # >>> x,y=mkpol('x,y')
  106. # >>> asin(sin(.7+x+y))
  107. # 0.7 + x + y
  108. # """
  109. # p=c.copy()
  110. # x=pol('x')
  111. # return pisqrt(1-x**2).int(x)(x=p)
  112. def asin(y):
  113. """Compute ArcSin
  114. >>> from pol import *
  115. >>> x,y=mkpol('x,y')
  116. >>> asin(sin(.4+x+y))
  117. 0.4 + x + y
  118. """
  119. x0=pol(math.asin(y.zero()))
  120. for i in range(y.order):
  121. x0=x0 + (y-sin(x0))/cos(x0)
  122. return x0
  123. def acos(y):
  124. """Compute ArcCos
  125. >>> from pol import *
  126. >>> x,y=mkpol('x,y')
  127. >>> acos(cos(.4+x+y))
  128. 0.4 + x + y
  129. """
  130. x0=pol(math.acos(y.zero()))
  131. for i in range(y.order):
  132. x0=x0 + -(y-cos(x0))/sin(x0)
  133. return x0
  134. def atan(y):
  135. """Compute ArcTan using Newton method
  136. x=f(y); y=g(x)
  137. x0=f(y0); x0=x0 +(y-g(x0))/g'(x)
  138. >>> from pol import *
  139. >>> p=pol('.4+x+y')
  140. >>> print tan(atan(p))
  141. 0.4 + x + y
  142. >>> print atan(tan(p))
  143. 0.4 + x + y
  144. """
  145. x0=pol(math.atan(y.zero()))
  146. for i in range(y.order):
  147. x0=x0 + (y-tan(x0))*cos(x0)**2
  148. return x0
  149. def asinh(y):
  150. """Compute ArcSinh
  151. >>> from pol import *
  152. >>> x,y=mkpol('x,y')
  153. >>> asinh(sinh(.4+x+y))
  154. 0.4 + x + y
  155. """
  156. x0=pol(log(y+sqrt(y**2+1)))
  157. for i in range(y.order):
  158. x0=x0 + (y-sinh(x0))/cosh(x0)
  159. return x0
  160. def acosh(y):
  161. """Compute ArcCosh
  162. >>> from pol import *
  163. >>> x,y=mkpol('x,y')
  164. >>> acosh(cosh(1.4+x+y))
  165. 1.4 + x + y
  166. """
  167. x0=pol(log(y+sqrt(y**2-1)))
  168. for i in range(y.order):
  169. x0=x0 + (y-cosh(x0))/sinh(x0)
  170. return x0
  171. def newton(f,y,x0):
  172. """Inverse polynomial using newton method EXPERIMENTAL
  173. >>> f=pol('1+x**2')
  174. >>> f(x=newton(f,pol('2+x'),1))
  175. 2.0 + x
  176. """
  177. for i in range(y.order):
  178. x0=x0+ ( y-f(x=x0) ) / f.der('x')(x=x0)
  179. return x0
  180. #if __name__=='__main__':
  181. # import doctest
  182. # doctest.testmod()
  183. # import profile
  184. # pol.order=9
  185. # profile.run('pol("sqrt(1+x+y+z+px+py+pz)")',sort='time')