_trigonometric_special.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. r"""A module for special angle forumlas for trigonometric functions
  2. TODO
  3. ====
  4. This module should be developed in the future to contain direct squrae root
  5. representation of
  6. .. math
  7. F(\frac{n}{m} \pi)
  8. for every
  9. - $m \in \{ 3, 5, 17, 257, 65537 \}$
  10. - $n \in \mathbb{N}$, $0 \le n < m$
  11. - $F \in \{\sin, \cos, \tan, \csc, \sec, \cot\}$
  12. Without multi-step rewrites
  13. (e.g. $\tan \to \cos/\sin \to \cos/\sqrt \to \ sqrt$)
  14. or using chebyshev identities
  15. (e.g. $\cos \to \cos + \cos^2 + \cdots \to \sqrt{} + \sqrt{}^2 + \cdots $),
  16. which are trivial to implement in sympy,
  17. and had used to give overly complicated expressions.
  18. The reference can be found below, if anyone may need help implementing them.
  19. References
  20. ==========
  21. .. [*] Gottlieb, Christian. (1999). The Simple and straightforward construction
  22. of the regular 257-gon. The Mathematical Intelligencer. 21. 31-37.
  23. 10.1007/BF03024829.
  24. .. [*] https://resources.wolframcloud.com/FunctionRepository/resources/Cos2PiOverFermatPrime
  25. """
  26. from __future__ import annotations
  27. from typing import Callable
  28. from functools import reduce
  29. from sympy.core.expr import Expr
  30. from sympy.core.singleton import S
  31. from sympy.core.numbers import igcdex, Integer
  32. from sympy.functions.elementary.miscellaneous import sqrt
  33. from sympy.core.cache import cacheit
  34. def migcdex(*x: int) -> tuple[tuple[int, ...], int]:
  35. r"""Compute extended gcd for multiple integers.
  36. Explanation
  37. ===========
  38. Given the integers $x_1, \cdots, x_n$ and
  39. an extended gcd for multiple arguments are defined as a solution
  40. $(y_1, \cdots, y_n), g$ for the diophantine equation
  41. $x_1 y_1 + \cdots + x_n y_n = g$ such that
  42. $g = \gcd(x_1, \cdots, x_n)$.
  43. Examples
  44. ========
  45. >>> from sympy.functions.elementary._trigonometric_special import migcdex
  46. >>> migcdex()
  47. ((), 0)
  48. >>> migcdex(4)
  49. ((1,), 4)
  50. >>> migcdex(4, 6)
  51. ((-1, 1), 2)
  52. >>> migcdex(6, 10, 15)
  53. ((1, 1, -1), 1)
  54. """
  55. if not x:
  56. return (), 0
  57. if len(x) == 1:
  58. return (1,), x[0]
  59. if len(x) == 2:
  60. u, v, h = igcdex(x[0], x[1])
  61. return (u, v), h
  62. y, g = migcdex(*x[1:])
  63. u, v, h = igcdex(x[0], g)
  64. return (u, *(v * i for i in y)), h
  65. def ipartfrac(*denoms: int) -> tuple[int, ...]:
  66. r"""Compute the the partial fraction decomposition.
  67. Explanation
  68. ===========
  69. Given a rational number $\frac{1}{q_1 \cdots q_n}$ where all
  70. $q_1, \cdots, q_n$ are pairwise coprime,
  71. A partial fraction decomposition is defined as
  72. .. math::
  73. \frac{1}{q_1 \cdots q_n} = \frac{p_1}{q_1} + \cdots + \frac{p_n}{q_n}
  74. And it can be derived from solving the following diophantine equation for
  75. the $p_1, \cdots, p_n$
  76. .. math::
  77. 1 = p_1 \prod_{i \ne 1}q_i + \cdots + p_n \prod_{i \ne n}q_i
  78. Where $q_1, \cdots, q_n$ being pairwise coprime implies
  79. $\gcd(\prod_{i \ne 1}q_i, \cdots, \prod_{i \ne n}q_i) = 1$,
  80. which guarantees the existance of the solution.
  81. It is sufficient to compute partial fraction decomposition only
  82. for numerator $1$ because partial fraction decomposition for any
  83. $\frac{n}{q_1 \cdots q_n}$ can be easily computed by multiplying
  84. the result by $n$ afterwards.
  85. Parameters
  86. ==========
  87. denoms : int
  88. The pairwise coprime integer denominators $q_i$ which defines the
  89. rational number $\frac{1}{q_1 \cdots q_n}$
  90. Returns
  91. =======
  92. tuple[int, ...]
  93. The list of numerators which semantically corresponds to $p_i$ of the
  94. partial fraction decomposition
  95. $\frac{1}{q_1 \cdots q_n} = \frac{p_1}{q_1} + \cdots + \frac{p_n}{q_n}$
  96. Examples
  97. ========
  98. >>> from sympy import Rational, Mul
  99. >>> from sympy.functions.elementary._trigonometric_special import ipartfrac
  100. >>> denoms = 2, 3, 5
  101. >>> numers = ipartfrac(2, 3, 5)
  102. >>> numers
  103. (1, 7, -14)
  104. >>> Rational(1, Mul(*denoms))
  105. 1/30
  106. >>> out = 0
  107. >>> for n, d in zip(numers, denoms):
  108. ... out += Rational(n, d)
  109. >>> out
  110. 1/30
  111. """
  112. if not denoms:
  113. return ()
  114. def mul(x: int, y: int) -> int:
  115. return x * y
  116. denom = reduce(mul, denoms)
  117. a = [denom // x for x in denoms]
  118. h, _ = migcdex(*a)
  119. return h
  120. def fermat_coords(n: int) -> list[int] | None:
  121. """If n can be factored in terms of Fermat primes with
  122. multiplicity of each being 1, return those primes, else
  123. None
  124. """
  125. primes = []
  126. for p in [3, 5, 17, 257, 65537]:
  127. quotient, remainder = divmod(n, p)
  128. if remainder == 0:
  129. n = quotient
  130. primes.append(p)
  131. if n == 1:
  132. return primes
  133. return None
  134. @cacheit
  135. def cos_3() -> Expr:
  136. r"""Computes $\cos \frac{\pi}{3}$ in square roots"""
  137. return S.Half
  138. @cacheit
  139. def cos_5() -> Expr:
  140. r"""Computes $\cos \frac{\pi}{5}$ in square roots"""
  141. return (sqrt(5) + 1) / 4
  142. @cacheit
  143. def cos_17() -> Expr:
  144. r"""Computes $\cos \frac{\pi}{17}$ in square roots"""
  145. return sqrt(
  146. (15 + sqrt(17)) / 32 + sqrt(2) * (sqrt(17 - sqrt(17)) +
  147. sqrt(sqrt(2) * (-8 * sqrt(17 + sqrt(17)) - (1 - sqrt(17))
  148. * sqrt(17 - sqrt(17))) + 6 * sqrt(17) + 34)) / 32)
  149. @cacheit
  150. def cos_257() -> Expr:
  151. r"""Computes $\cos \frac{\pi}{257}$ in square roots
  152. References
  153. ==========
  154. .. [*] https://math.stackexchange.com/questions/516142/how-does-cos2-pi-257-look-like-in-real-radicals
  155. .. [*] https://r-knott.surrey.ac.uk/Fibonacci/simpleTrig.html
  156. """
  157. def f1(a: Expr, b: Expr) -> tuple[Expr, Expr]:
  158. return (a + sqrt(a**2 + b)) / 2, (a - sqrt(a**2 + b)) / 2
  159. def f2(a: Expr, b: Expr) -> Expr:
  160. return (a - sqrt(a**2 + b))/2
  161. t1, t2 = f1(S.NegativeOne, Integer(256))
  162. z1, z3 = f1(t1, Integer(64))
  163. z2, z4 = f1(t2, Integer(64))
  164. y1, y5 = f1(z1, 4*(5 + t1 + 2*z1))
  165. y6, y2 = f1(z2, 4*(5 + t2 + 2*z2))
  166. y3, y7 = f1(z3, 4*(5 + t1 + 2*z3))
  167. y8, y4 = f1(z4, 4*(5 + t2 + 2*z4))
  168. x1, x9 = f1(y1, -4*(t1 + y1 + y3 + 2*y6))
  169. x2, x10 = f1(y2, -4*(t2 + y2 + y4 + 2*y7))
  170. x3, x11 = f1(y3, -4*(t1 + y3 + y5 + 2*y8))
  171. x4, x12 = f1(y4, -4*(t2 + y4 + y6 + 2*y1))
  172. x5, x13 = f1(y5, -4*(t1 + y5 + y7 + 2*y2))
  173. x6, x14 = f1(y6, -4*(t2 + y6 + y8 + 2*y3))
  174. x15, x7 = f1(y7, -4*(t1 + y7 + y1 + 2*y4))
  175. x8, x16 = f1(y8, -4*(t2 + y8 + y2 + 2*y5))
  176. v1 = f2(x1, -4*(x1 + x2 + x3 + x6))
  177. v2 = f2(x2, -4*(x2 + x3 + x4 + x7))
  178. v3 = f2(x8, -4*(x8 + x9 + x10 + x13))
  179. v4 = f2(x9, -4*(x9 + x10 + x11 + x14))
  180. v5 = f2(x10, -4*(x10 + x11 + x12 + x15))
  181. v6 = f2(x16, -4*(x16 + x1 + x2 + x5))
  182. u1 = -f2(-v1, -4*(v2 + v3))
  183. u2 = -f2(-v4, -4*(v5 + v6))
  184. w1 = -2*f2(-u1, -4*u2)
  185. return sqrt(sqrt(2)*sqrt(w1 + 4)/8 + S.Half)
  186. def cos_table() -> dict[int, Callable[[], Expr]]:
  187. r"""Lazily evaluated table for $\cos \frac{\pi}{n}$ in square roots for
  188. $n \in \{3, 5, 17, 257, 65537\}$.
  189. Notes
  190. =====
  191. 65537 is the only other known Fermat prime and it is nearly impossible to
  192. build in the current SymPy due to performance issues.
  193. References
  194. ==========
  195. https://r-knott.surrey.ac.uk/Fibonacci/simpleTrig.html
  196. """
  197. return {
  198. 3: cos_3,
  199. 5: cos_5,
  200. 17: cos_17,
  201. 257: cos_257
  202. }