factorials.py 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133
  1. from __future__ import annotations
  2. from functools import reduce
  3. from sympy.core import S, sympify, Dummy, Mod
  4. from sympy.core.cache import cacheit
  5. from sympy.core.function import DefinedFunction, ArgumentIndexError, PoleError
  6. from sympy.core.logic import fuzzy_and
  7. from sympy.core.numbers import Integer, pi, I
  8. from sympy.core.relational import Eq
  9. from sympy.external.gmpy import gmpy as _gmpy
  10. from sympy.ntheory import sieve
  11. from sympy.ntheory.residue_ntheory import binomial_mod
  12. from sympy.polys.polytools import Poly
  13. from math import factorial as _factorial, prod, sqrt as _sqrt
  14. class CombinatorialFunction(DefinedFunction):
  15. """Base class for combinatorial functions. """
  16. def _eval_simplify(self, **kwargs):
  17. from sympy.simplify.combsimp import combsimp
  18. # combinatorial function with non-integer arguments is
  19. # automatically passed to gammasimp
  20. expr = combsimp(self)
  21. measure = kwargs['measure']
  22. if measure(expr) <= kwargs['ratio']*measure(self):
  23. return expr
  24. return self
  25. ###############################################################################
  26. ######################## FACTORIAL and MULTI-FACTORIAL ########################
  27. ###############################################################################
  28. class factorial(CombinatorialFunction):
  29. r"""Implementation of factorial function over nonnegative integers.
  30. By convention (consistent with the gamma function and the binomial
  31. coefficients), factorial of a negative integer is complex infinity.
  32. The factorial is very important in combinatorics where it gives
  33. the number of ways in which `n` objects can be permuted. It also
  34. arises in calculus, probability, number theory, etc.
  35. There is strict relation of factorial with gamma function. In
  36. fact `n! = gamma(n+1)` for nonnegative integers. Rewrite of this
  37. kind is very useful in case of combinatorial simplification.
  38. Computation of the factorial is done using two algorithms. For
  39. small arguments a precomputed look up table is used. However for bigger
  40. input algorithm Prime-Swing is used. It is the fastest algorithm
  41. known and computes `n!` via prime factorization of special class
  42. of numbers, called here the 'Swing Numbers'.
  43. Examples
  44. ========
  45. >>> from sympy import Symbol, factorial, S
  46. >>> n = Symbol('n', integer=True)
  47. >>> factorial(0)
  48. 1
  49. >>> factorial(7)
  50. 5040
  51. >>> factorial(-2)
  52. zoo
  53. >>> factorial(n)
  54. factorial(n)
  55. >>> factorial(2*n)
  56. factorial(2*n)
  57. >>> factorial(S(1)/2)
  58. factorial(1/2)
  59. See Also
  60. ========
  61. factorial2, RisingFactorial, FallingFactorial
  62. """
  63. def fdiff(self, argindex=1):
  64. from sympy.functions.special.gamma_functions import (gamma, polygamma)
  65. if argindex == 1:
  66. return gamma(self.args[0] + 1)*polygamma(0, self.args[0] + 1)
  67. else:
  68. raise ArgumentIndexError(self, argindex)
  69. _small_swing = [
  70. 1, 1, 1, 3, 3, 15, 5, 35, 35, 315, 63, 693, 231, 3003, 429, 6435, 6435, 109395,
  71. 12155, 230945, 46189, 969969, 88179, 2028117, 676039, 16900975, 1300075,
  72. 35102025, 5014575, 145422675, 9694845, 300540195, 300540195
  73. ]
  74. _small_factorials: list[int] = []
  75. @classmethod
  76. def _swing(cls, n):
  77. if n < 33:
  78. return cls._small_swing[n]
  79. else:
  80. N, primes = int(_sqrt(n)), []
  81. for prime in sieve.primerange(3, N + 1):
  82. p, q = 1, n
  83. while True:
  84. q //= prime
  85. if q > 0:
  86. if q & 1 == 1:
  87. p *= prime
  88. else:
  89. break
  90. if p > 1:
  91. primes.append(p)
  92. for prime in sieve.primerange(N + 1, n//3 + 1):
  93. if (n // prime) & 1 == 1:
  94. primes.append(prime)
  95. L_product = prod(sieve.primerange(n//2 + 1, n + 1))
  96. R_product = prod(primes)
  97. return L_product*R_product
  98. @classmethod
  99. def _recursive(cls, n):
  100. if n < 2:
  101. return 1
  102. else:
  103. return (cls._recursive(n//2)**2)*cls._swing(n)
  104. @classmethod
  105. def eval(cls, n):
  106. n = sympify(n)
  107. if n.is_Number:
  108. if n.is_zero:
  109. return S.One
  110. elif n is S.Infinity:
  111. return S.Infinity
  112. elif n.is_Integer:
  113. if n.is_negative:
  114. return S.ComplexInfinity
  115. else:
  116. n = n.p
  117. if n < 20:
  118. if not cls._small_factorials:
  119. result = 1
  120. for i in range(1, 20):
  121. result *= i
  122. cls._small_factorials.append(result)
  123. result = cls._small_factorials[n-1]
  124. # GMPY factorial is faster, use it when available
  125. #
  126. # XXX: There is a sympy.external.gmpy.factorial function
  127. # which provides gmpy.fac if available or the flint version
  128. # if flint is used. It could be used here to avoid the
  129. # conditional logic but it needs to be checked whether the
  130. # pure Python fallback used there is as fast as the
  131. # fallback used here (perhaps the fallback here should be
  132. # moved to sympy.external.ntheory).
  133. elif _gmpy is not None:
  134. result = _gmpy.fac(n)
  135. else:
  136. bits = bin(n).count('1')
  137. result = cls._recursive(n)*2**(n - bits)
  138. return Integer(result)
  139. def _facmod(self, n, q):
  140. res, N = 1, int(_sqrt(n))
  141. # Exponent of prime p in n! is e_p(n) = [n/p] + [n/p**2] + ...
  142. # for p > sqrt(n), e_p(n) < sqrt(n), the primes with [n/p] = m,
  143. # occur consecutively and are grouped together in pw[m] for
  144. # simultaneous exponentiation at a later stage
  145. pw = [1]*N
  146. m = 2 # to initialize the if condition below
  147. for prime in sieve.primerange(2, n + 1):
  148. if m > 1:
  149. m, y = 0, n // prime
  150. while y:
  151. m += y
  152. y //= prime
  153. if m < N:
  154. pw[m] = pw[m]*prime % q
  155. else:
  156. res = res*pow(prime, m, q) % q
  157. for ex, bs in enumerate(pw):
  158. if ex == 0 or bs == 1:
  159. continue
  160. if bs == 0:
  161. return 0
  162. res = res*pow(bs, ex, q) % q
  163. return res
  164. def _eval_Mod(self, q):
  165. n = self.args[0]
  166. if n.is_integer and n.is_nonnegative and q.is_integer:
  167. aq = abs(q)
  168. d = aq - n
  169. if d.is_nonpositive:
  170. return S.Zero
  171. else:
  172. isprime = aq.is_prime
  173. if d == 1:
  174. # Apply Wilson's theorem (if a natural number n > 1
  175. # is a prime number, then (n-1)! = -1 mod n) and
  176. # its inverse (if n > 4 is a composite number, then
  177. # (n-1)! = 0 mod n)
  178. if isprime:
  179. return -1 % q
  180. elif isprime is False and (aq - 6).is_nonnegative:
  181. return S.Zero
  182. elif n.is_Integer and q.is_Integer:
  183. n, d, aq = map(int, (n, d, aq))
  184. if isprime and (d - 1 < n):
  185. fc = self._facmod(d - 1, aq)
  186. fc = pow(fc, aq - 2, aq)
  187. if d%2:
  188. fc = -fc
  189. else:
  190. fc = self._facmod(n, aq)
  191. return fc % q
  192. def _eval_rewrite_as_gamma(self, n, piecewise=True, **kwargs):
  193. from sympy.functions.special.gamma_functions import gamma
  194. return gamma(n + 1)
  195. def _eval_rewrite_as_Product(self, n, **kwargs):
  196. from sympy.concrete.products import Product
  197. if n.is_nonnegative and n.is_integer:
  198. i = Dummy('i', integer=True)
  199. return Product(i, (i, 1, n))
  200. def _eval_is_integer(self):
  201. if self.args[0].is_integer and self.args[0].is_nonnegative:
  202. return True
  203. def _eval_is_positive(self):
  204. if self.args[0].is_integer and self.args[0].is_nonnegative:
  205. return True
  206. def _eval_is_even(self):
  207. x = self.args[0]
  208. if x.is_integer and x.is_nonnegative:
  209. return (x - 2).is_nonnegative
  210. def _eval_is_composite(self):
  211. x = self.args[0]
  212. if x.is_integer and x.is_nonnegative:
  213. return (x - 3).is_nonnegative
  214. def _eval_is_real(self):
  215. x = self.args[0]
  216. if x.is_nonnegative or x.is_noninteger:
  217. return True
  218. def _eval_as_leading_term(self, x, logx, cdir):
  219. arg = self.args[0].as_leading_term(x)
  220. arg0 = arg.subs(x, 0)
  221. if arg0.is_zero:
  222. return S.One
  223. elif not arg0.is_infinite:
  224. return self.func(arg)
  225. raise PoleError("Cannot expand %s around 0" % (self))
  226. class MultiFactorial(CombinatorialFunction):
  227. pass
  228. class subfactorial(CombinatorialFunction):
  229. r"""The subfactorial counts the derangements of $n$ items and is
  230. defined for non-negative integers as:
  231. .. math:: !n = \begin{cases} 1 & n = 0 \\ 0 & n = 1 \\
  232. (n-1)(!(n-1) + !(n-2)) & n > 1 \end{cases}
  233. It can also be written as ``int(round(n!/exp(1)))`` but the
  234. recursive definition with caching is implemented for this function.
  235. An interesting analytic expression is the following [2]_
  236. .. math:: !x = \Gamma(x + 1, -1)/e
  237. which is valid for non-negative integers `x`. The above formula
  238. is not very useful in case of non-integers. `\Gamma(x + 1, -1)` is
  239. single-valued only for integral arguments `x`, elsewhere on the positive
  240. real axis it has an infinite number of branches none of which are real.
  241. References
  242. ==========
  243. .. [1] https://en.wikipedia.org/wiki/Subfactorial
  244. .. [2] https://mathworld.wolfram.com/Subfactorial.html
  245. Examples
  246. ========
  247. >>> from sympy import subfactorial
  248. >>> from sympy.abc import n
  249. >>> subfactorial(n + 1)
  250. subfactorial(n + 1)
  251. >>> subfactorial(5)
  252. 44
  253. See Also
  254. ========
  255. factorial, uppergamma,
  256. sympy.utilities.iterables.generate_derangements
  257. """
  258. @classmethod
  259. @cacheit
  260. def _eval(self, n):
  261. if not n:
  262. return S.One
  263. elif n == 1:
  264. return S.Zero
  265. else:
  266. z1, z2 = 1, 0
  267. for i in range(2, n + 1):
  268. z1, z2 = z2, (i - 1)*(z2 + z1)
  269. return z2
  270. @classmethod
  271. def eval(cls, arg):
  272. if arg.is_Number:
  273. if arg.is_Integer and arg.is_nonnegative:
  274. return cls._eval(arg)
  275. elif arg is S.NaN:
  276. return S.NaN
  277. elif arg is S.Infinity:
  278. return S.Infinity
  279. def _eval_is_even(self):
  280. if self.args[0].is_odd and self.args[0].is_nonnegative:
  281. return True
  282. def _eval_is_integer(self):
  283. if self.args[0].is_integer and self.args[0].is_nonnegative:
  284. return True
  285. def _eval_rewrite_as_factorial(self, arg, **kwargs):
  286. from sympy.concrete.summations import summation
  287. i = Dummy('i')
  288. f = S.NegativeOne**i / factorial(i)
  289. return factorial(arg) * summation(f, (i, 0, arg))
  290. def _eval_rewrite_as_gamma(self, arg, piecewise=True, **kwargs):
  291. from sympy.functions.elementary.exponential import exp
  292. from sympy.functions.special.gamma_functions import (gamma, lowergamma)
  293. return (S.NegativeOne**(arg + 1)*exp(-I*pi*arg)*lowergamma(arg + 1, -1)
  294. + gamma(arg + 1))*exp(-1)
  295. def _eval_rewrite_as_uppergamma(self, arg, **kwargs):
  296. from sympy.functions.special.gamma_functions import uppergamma
  297. return uppergamma(arg + 1, -1)/S.Exp1
  298. def _eval_is_nonnegative(self):
  299. if self.args[0].is_integer and self.args[0].is_nonnegative:
  300. return True
  301. def _eval_is_odd(self):
  302. if self.args[0].is_even and self.args[0].is_nonnegative:
  303. return True
  304. class factorial2(CombinatorialFunction):
  305. r"""The double factorial `n!!`, not to be confused with `(n!)!`
  306. The double factorial is defined for nonnegative integers and for odd
  307. negative integers as:
  308. .. math:: n!! = \begin{cases} 1 & n = 0 \\
  309. n(n-2)(n-4) \cdots 1 & n\ \text{positive odd} \\
  310. n(n-2)(n-4) \cdots 2 & n\ \text{positive even} \\
  311. (n+2)!!/(n+2) & n\ \text{negative odd} \end{cases}
  312. References
  313. ==========
  314. .. [1] https://en.wikipedia.org/wiki/Double_factorial
  315. Examples
  316. ========
  317. >>> from sympy import factorial2, var
  318. >>> n = var('n')
  319. >>> n
  320. n
  321. >>> factorial2(n + 1)
  322. factorial2(n + 1)
  323. >>> factorial2(5)
  324. 15
  325. >>> factorial2(-1)
  326. 1
  327. >>> factorial2(-5)
  328. 1/3
  329. See Also
  330. ========
  331. factorial, RisingFactorial, FallingFactorial
  332. """
  333. @classmethod
  334. def eval(cls, arg):
  335. # TODO: extend this to complex numbers?
  336. if arg.is_Number:
  337. if not arg.is_Integer:
  338. raise ValueError("argument must be nonnegative integer "
  339. "or negative odd integer")
  340. # This implementation is faster than the recursive one
  341. # It also avoids "maximum recursion depth exceeded" runtime error
  342. if arg.is_nonnegative:
  343. if arg.is_even:
  344. k = arg / 2
  345. return 2**k * factorial(k)
  346. return factorial(arg) / factorial2(arg - 1)
  347. if arg.is_odd:
  348. return arg*(S.NegativeOne)**((1 - arg)/2) / factorial2(-arg)
  349. raise ValueError("argument must be nonnegative integer "
  350. "or negative odd integer")
  351. def _eval_is_even(self):
  352. # Double factorial is even for every positive even input
  353. n = self.args[0]
  354. if n.is_integer:
  355. if n.is_odd:
  356. return False
  357. if n.is_even:
  358. if n.is_positive:
  359. return True
  360. if n.is_zero:
  361. return False
  362. def _eval_is_integer(self):
  363. # Double factorial is an integer for every nonnegative input, and for
  364. # -1 and -3
  365. n = self.args[0]
  366. if n.is_integer:
  367. if (n + 1).is_nonnegative:
  368. return True
  369. if n.is_odd:
  370. return (n + 3).is_nonnegative
  371. def _eval_is_odd(self):
  372. # Double factorial is odd for every odd input not smaller than -3, and
  373. # for 0
  374. n = self.args[0]
  375. if n.is_odd:
  376. return (n + 3).is_nonnegative
  377. if n.is_even:
  378. if n.is_positive:
  379. return False
  380. if n.is_zero:
  381. return True
  382. def _eval_is_positive(self):
  383. # Double factorial is positive for every nonnegative input, and for
  384. # every odd negative input which is of the form -1-4k for an
  385. # nonnegative integer k
  386. n = self.args[0]
  387. if n.is_integer:
  388. if (n + 1).is_nonnegative:
  389. return True
  390. if n.is_odd:
  391. return ((n + 1) / 2).is_even
  392. def _eval_rewrite_as_gamma(self, n, piecewise=True, **kwargs):
  393. from sympy.functions.elementary.miscellaneous import sqrt
  394. from sympy.functions.elementary.piecewise import Piecewise
  395. from sympy.functions.special.gamma_functions import gamma
  396. return 2**(n/2)*gamma(n/2 + 1) * Piecewise((1, Eq(Mod(n, 2), 0)),
  397. (sqrt(2/pi), Eq(Mod(n, 2), 1)))
  398. ###############################################################################
  399. ######################## RISING and FALLING FACTORIALS ########################
  400. ###############################################################################
  401. class RisingFactorial(CombinatorialFunction):
  402. r"""
  403. Rising factorial (also called Pochhammer symbol [1]_) is a double valued
  404. function arising in concrete mathematics, hypergeometric functions
  405. and series expansions. It is defined by:
  406. .. math:: \texttt{rf(y, k)} = (x)^k = x \cdot (x+1) \cdots (x+k-1)
  407. where `x` can be arbitrary expression and `k` is an integer. For
  408. more information check "Concrete mathematics" by Graham, pp. 66
  409. or visit https://mathworld.wolfram.com/RisingFactorial.html page.
  410. When `x` is a `~.Poly` instance of degree $\ge 1$ with a single variable,
  411. `(x)^k = x(y) \cdot x(y+1) \cdots x(y+k-1)`, where `y` is the
  412. variable of `x`. This is as described in [2]_.
  413. Examples
  414. ========
  415. >>> from sympy import rf, Poly
  416. >>> from sympy.abc import x
  417. >>> rf(x, 0)
  418. 1
  419. >>> rf(1, 5)
  420. 120
  421. >>> rf(x, 5) == x*(1 + x)*(2 + x)*(3 + x)*(4 + x)
  422. True
  423. >>> rf(Poly(x**3, x), 2)
  424. Poly(x**6 + 3*x**5 + 3*x**4 + x**3, x, domain='ZZ')
  425. Rewriting is complicated unless the relationship between
  426. the arguments is known, but rising factorial can
  427. be rewritten in terms of gamma, factorial, binomial,
  428. and falling factorial.
  429. >>> from sympy import Symbol, factorial, ff, binomial, gamma
  430. >>> n = Symbol('n', integer=True, positive=True)
  431. >>> R = rf(n, n + 2)
  432. >>> for i in (rf, ff, factorial, binomial, gamma):
  433. ... R.rewrite(i)
  434. ...
  435. RisingFactorial(n, n + 2)
  436. FallingFactorial(2*n + 1, n + 2)
  437. factorial(2*n + 1)/factorial(n - 1)
  438. binomial(2*n + 1, n + 2)*factorial(n + 2)
  439. gamma(2*n + 2)/gamma(n)
  440. See Also
  441. ========
  442. factorial, factorial2, FallingFactorial
  443. References
  444. ==========
  445. .. [1] https://en.wikipedia.org/wiki/Pochhammer_symbol
  446. .. [2] Peter Paule, "Greatest Factorial Factorization and Symbolic
  447. Summation", Journal of Symbolic Computation, vol. 20, pp. 235-268,
  448. 1995.
  449. """
  450. @classmethod
  451. def eval(cls, x, k):
  452. x = sympify(x)
  453. k = sympify(k)
  454. if x is S.NaN or k is S.NaN:
  455. return S.NaN
  456. elif x is S.One:
  457. return factorial(k)
  458. elif k.is_Integer:
  459. if k.is_zero:
  460. return S.One
  461. else:
  462. if k.is_positive:
  463. if x is S.Infinity:
  464. return S.Infinity
  465. elif x is S.NegativeInfinity:
  466. if k.is_odd:
  467. return S.NegativeInfinity
  468. else:
  469. return S.Infinity
  470. else:
  471. if isinstance(x, Poly):
  472. gens = x.gens
  473. if len(gens)!= 1:
  474. raise ValueError("rf only defined for "
  475. "polynomials on one generator")
  476. else:
  477. return reduce(lambda r, i:
  478. r*(x.shift(i)),
  479. range(int(k)), 1)
  480. else:
  481. return reduce(lambda r, i: r*(x + i),
  482. range(int(k)), 1)
  483. else:
  484. if x is S.Infinity:
  485. return S.Infinity
  486. elif x is S.NegativeInfinity:
  487. return S.Infinity
  488. else:
  489. if isinstance(x, Poly):
  490. gens = x.gens
  491. if len(gens)!= 1:
  492. raise ValueError("rf only defined for "
  493. "polynomials on one generator")
  494. else:
  495. return 1/reduce(lambda r, i:
  496. r*(x.shift(-i)),
  497. range(1, abs(int(k)) + 1), 1)
  498. else:
  499. return 1/reduce(lambda r, i:
  500. r*(x - i),
  501. range(1, abs(int(k)) + 1), 1)
  502. if k.is_integer == False:
  503. if x.is_integer and x.is_negative:
  504. return S.Zero
  505. def _eval_rewrite_as_gamma(self, x, k, piecewise=True, **kwargs):
  506. from sympy.functions.elementary.piecewise import Piecewise
  507. from sympy.functions.special.gamma_functions import gamma
  508. if not piecewise:
  509. if (x <= 0) == True:
  510. return S.NegativeOne**k*gamma(1 - x) / gamma(-k - x + 1)
  511. return gamma(x + k) / gamma(x)
  512. return Piecewise(
  513. (gamma(x + k) / gamma(x), x > 0),
  514. (S.NegativeOne**k*gamma(1 - x) / gamma(-k - x + 1), True))
  515. def _eval_rewrite_as_FallingFactorial(self, x, k, **kwargs):
  516. return FallingFactorial(x + k - 1, k)
  517. def _eval_rewrite_as_factorial(self, x, k, **kwargs):
  518. from sympy.functions.elementary.piecewise import Piecewise
  519. if x.is_integer and k.is_integer:
  520. return Piecewise(
  521. (factorial(k + x - 1)/factorial(x - 1), x > 0),
  522. (S.NegativeOne**k*factorial(-x)/factorial(-k - x), True))
  523. def _eval_rewrite_as_binomial(self, x, k, **kwargs):
  524. if k.is_integer:
  525. return factorial(k) * binomial(x + k - 1, k)
  526. def _eval_rewrite_as_tractable(self, x, k, limitvar=None, **kwargs):
  527. from sympy.functions.special.gamma_functions import gamma
  528. if limitvar:
  529. k_lim = k.subs(limitvar, S.Infinity)
  530. if k_lim is S.Infinity:
  531. return (gamma(x + k).rewrite('tractable', deep=True) / gamma(x))
  532. elif k_lim is S.NegativeInfinity:
  533. return (S.NegativeOne**k*gamma(1 - x) / gamma(-k - x + 1).rewrite('tractable', deep=True))
  534. return self.rewrite(gamma).rewrite('tractable', deep=True)
  535. def _eval_is_integer(self):
  536. return fuzzy_and((self.args[0].is_integer, self.args[1].is_integer,
  537. self.args[1].is_nonnegative))
  538. class FallingFactorial(CombinatorialFunction):
  539. r"""
  540. Falling factorial (related to rising factorial) is a double valued
  541. function arising in concrete mathematics, hypergeometric functions
  542. and series expansions. It is defined by
  543. .. math:: \texttt{ff(x, k)} = (x)_k = x \cdot (x-1) \cdots (x-k+1)
  544. where `x` can be arbitrary expression and `k` is an integer. For
  545. more information check "Concrete mathematics" by Graham, pp. 66
  546. or [1]_.
  547. When `x` is a `~.Poly` instance of degree $\ge 1$ with single variable,
  548. `(x)_k = x(y) \cdot x(y-1) \cdots x(y-k+1)`, where `y` is the
  549. variable of `x`. This is as described in
  550. >>> from sympy import ff, Poly, Symbol
  551. >>> from sympy.abc import x
  552. >>> n = Symbol('n', integer=True)
  553. >>> ff(x, 0)
  554. 1
  555. >>> ff(5, 5)
  556. 120
  557. >>> ff(x, 5) == x*(x - 1)*(x - 2)*(x - 3)*(x - 4)
  558. True
  559. >>> ff(Poly(x**2, x), 2)
  560. Poly(x**4 - 2*x**3 + x**2, x, domain='ZZ')
  561. >>> ff(n, n)
  562. factorial(n)
  563. Rewriting is complicated unless the relationship between
  564. the arguments is known, but falling factorial can
  565. be rewritten in terms of gamma, factorial and binomial
  566. and rising factorial.
  567. >>> from sympy import factorial, rf, gamma, binomial, Symbol
  568. >>> n = Symbol('n', integer=True, positive=True)
  569. >>> F = ff(n, n - 2)
  570. >>> for i in (rf, ff, factorial, binomial, gamma):
  571. ... F.rewrite(i)
  572. ...
  573. RisingFactorial(3, n - 2)
  574. FallingFactorial(n, n - 2)
  575. factorial(n)/2
  576. binomial(n, n - 2)*factorial(n - 2)
  577. gamma(n + 1)/2
  578. See Also
  579. ========
  580. factorial, factorial2, RisingFactorial
  581. References
  582. ==========
  583. .. [1] https://mathworld.wolfram.com/FallingFactorial.html
  584. .. [2] Peter Paule, "Greatest Factorial Factorization and Symbolic
  585. Summation", Journal of Symbolic Computation, vol. 20, pp. 235-268,
  586. 1995.
  587. """
  588. @classmethod
  589. def eval(cls, x, k):
  590. x = sympify(x)
  591. k = sympify(k)
  592. if x is S.NaN or k is S.NaN:
  593. return S.NaN
  594. elif k.is_integer and x == k:
  595. return factorial(x)
  596. elif k.is_Integer:
  597. if k.is_zero:
  598. return S.One
  599. else:
  600. if k.is_positive:
  601. if x is S.Infinity:
  602. return S.Infinity
  603. elif x is S.NegativeInfinity:
  604. if k.is_odd:
  605. return S.NegativeInfinity
  606. else:
  607. return S.Infinity
  608. else:
  609. if isinstance(x, Poly):
  610. gens = x.gens
  611. if len(gens)!= 1:
  612. raise ValueError("ff only defined for "
  613. "polynomials on one generator")
  614. else:
  615. return reduce(lambda r, i:
  616. r*(x.shift(-i)),
  617. range(int(k)), 1)
  618. else:
  619. return reduce(lambda r, i: r*(x - i),
  620. range(int(k)), 1)
  621. else:
  622. if x is S.Infinity:
  623. return S.Infinity
  624. elif x is S.NegativeInfinity:
  625. return S.Infinity
  626. else:
  627. if isinstance(x, Poly):
  628. gens = x.gens
  629. if len(gens)!= 1:
  630. raise ValueError("rf only defined for "
  631. "polynomials on one generator")
  632. else:
  633. return 1/reduce(lambda r, i:
  634. r*(x.shift(i)),
  635. range(1, abs(int(k)) + 1), 1)
  636. else:
  637. return 1/reduce(lambda r, i: r*(x + i),
  638. range(1, abs(int(k)) + 1), 1)
  639. def _eval_rewrite_as_gamma(self, x, k, piecewise=True, **kwargs):
  640. from sympy.functions.elementary.piecewise import Piecewise
  641. from sympy.functions.special.gamma_functions import gamma
  642. if not piecewise:
  643. if (x < 0) == True:
  644. return S.NegativeOne**k*gamma(k - x) / gamma(-x)
  645. return gamma(x + 1) / gamma(x - k + 1)
  646. return Piecewise(
  647. (gamma(x + 1) / gamma(x - k + 1), x >= 0),
  648. (S.NegativeOne**k*gamma(k - x) / gamma(-x), True))
  649. def _eval_rewrite_as_RisingFactorial(self, x, k, **kwargs):
  650. return rf(x - k + 1, k)
  651. def _eval_rewrite_as_binomial(self, x, k, **kwargs):
  652. if k.is_integer:
  653. return factorial(k) * binomial(x, k)
  654. def _eval_rewrite_as_factorial(self, x, k, **kwargs):
  655. from sympy.functions.elementary.piecewise import Piecewise
  656. if x.is_integer and k.is_integer:
  657. return Piecewise(
  658. (factorial(x)/factorial(-k + x), x >= 0),
  659. (S.NegativeOne**k*factorial(k - x - 1)/factorial(-x - 1), True))
  660. def _eval_rewrite_as_tractable(self, x, k, limitvar=None, **kwargs):
  661. from sympy.functions.special.gamma_functions import gamma
  662. if limitvar:
  663. k_lim = k.subs(limitvar, S.Infinity)
  664. if k_lim is S.Infinity:
  665. return (S.NegativeOne**k*gamma(k - x).rewrite('tractable', deep=True) / gamma(-x))
  666. elif k_lim is S.NegativeInfinity:
  667. return (gamma(x + 1) / gamma(x - k + 1).rewrite('tractable', deep=True))
  668. return self.rewrite(gamma).rewrite('tractable', deep=True)
  669. def _eval_is_integer(self):
  670. return fuzzy_and((self.args[0].is_integer, self.args[1].is_integer,
  671. self.args[1].is_nonnegative))
  672. rf = RisingFactorial
  673. ff = FallingFactorial
  674. ###############################################################################
  675. ########################### BINOMIAL COEFFICIENTS #############################
  676. ###############################################################################
  677. class binomial(CombinatorialFunction):
  678. r"""Implementation of the binomial coefficient. It can be defined
  679. in two ways depending on its desired interpretation:
  680. .. math:: \binom{n}{k} = \frac{n!}{k!(n-k)!}\ \text{or}\
  681. \binom{n}{k} = \frac{(n)_k}{k!}
  682. First, in a strict combinatorial sense it defines the
  683. number of ways we can choose `k` elements from a set of
  684. `n` elements. In this case both arguments are nonnegative
  685. integers and binomial is computed using an efficient
  686. algorithm based on prime factorization.
  687. The other definition is generalization for arbitrary `n`,
  688. however `k` must also be nonnegative. This case is very
  689. useful when evaluating summations.
  690. For the sake of convenience, for negative integer `k` this function
  691. will return zero no matter the other argument.
  692. To expand the binomial when `n` is a symbol, use either
  693. ``expand_func()`` or ``expand(func=True)``. The former will keep
  694. the polynomial in factored form while the latter will expand the
  695. polynomial itself. See examples for details.
  696. Examples
  697. ========
  698. >>> from sympy import Symbol, Rational, binomial, expand_func
  699. >>> n = Symbol('n', integer=True, positive=True)
  700. >>> binomial(15, 8)
  701. 6435
  702. >>> binomial(n, -1)
  703. 0
  704. Rows of Pascal's triangle can be generated with the binomial function:
  705. >>> for N in range(8):
  706. ... print([binomial(N, i) for i in range(N + 1)])
  707. ...
  708. [1]
  709. [1, 1]
  710. [1, 2, 1]
  711. [1, 3, 3, 1]
  712. [1, 4, 6, 4, 1]
  713. [1, 5, 10, 10, 5, 1]
  714. [1, 6, 15, 20, 15, 6, 1]
  715. [1, 7, 21, 35, 35, 21, 7, 1]
  716. As can a given diagonal, e.g. the 4th diagonal:
  717. >>> N = -4
  718. >>> [binomial(N, i) for i in range(1 - N)]
  719. [1, -4, 10, -20, 35]
  720. >>> binomial(Rational(5, 4), 3)
  721. -5/128
  722. >>> binomial(Rational(-5, 4), 3)
  723. -195/128
  724. >>> binomial(n, 3)
  725. binomial(n, 3)
  726. >>> binomial(n, 3).expand(func=True)
  727. n**3/6 - n**2/2 + n/3
  728. >>> expand_func(binomial(n, 3))
  729. n*(n - 2)*(n - 1)/6
  730. In many cases, we can also compute binomial coefficients modulo a
  731. prime p quickly using Lucas' Theorem [2]_, though we need to include
  732. `evaluate=False` to postpone evaluation:
  733. >>> from sympy import Mod
  734. >>> Mod(binomial(156675, 4433, evaluate=False), 10**5 + 3)
  735. 28625
  736. Using a generalisation of Lucas's Theorem given by Granville [3]_,
  737. we can extend this to arbitrary n:
  738. >>> Mod(binomial(10**18, 10**12, evaluate=False), (10**5 + 3)**2)
  739. 3744312326
  740. References
  741. ==========
  742. .. [1] https://www.johndcook.com/blog/binomial_coefficients/
  743. .. [2] https://en.wikipedia.org/wiki/Lucas%27s_theorem
  744. .. [3] Binomial coefficients modulo prime powers, Andrew Granville,
  745. Available: https://web.archive.org/web/20170202003812/http://www.dms.umontreal.ca/~andrew/PDF/BinCoeff.pdf
  746. """
  747. def fdiff(self, argindex=1):
  748. from sympy.functions.special.gamma_functions import polygamma
  749. if argindex == 1:
  750. # https://functions.wolfram.com/GammaBetaErf/Binomial/20/01/01/
  751. n, k = self.args
  752. return binomial(n, k)*(polygamma(0, n + 1) - \
  753. polygamma(0, n - k + 1))
  754. elif argindex == 2:
  755. # https://functions.wolfram.com/GammaBetaErf/Binomial/20/01/02/
  756. n, k = self.args
  757. return binomial(n, k)*(polygamma(0, n - k + 1) - \
  758. polygamma(0, k + 1))
  759. else:
  760. raise ArgumentIndexError(self, argindex)
  761. @classmethod
  762. def _eval(self, n, k):
  763. # n.is_Number and k.is_Integer and k != 1 and n != k
  764. if k.is_Integer:
  765. if n.is_Integer and n >= 0:
  766. n, k = int(n), int(k)
  767. if k > n:
  768. return S.Zero
  769. elif k > n // 2:
  770. k = n - k
  771. # XXX: This conditional logic should be moved to
  772. # sympy.external.gmpy and the pure Python version of bincoef
  773. # should be moved to sympy.external.ntheory.
  774. if _gmpy is not None:
  775. return Integer(_gmpy.bincoef(n, k))
  776. d, result = n - k, 1
  777. for i in range(1, k + 1):
  778. d += 1
  779. result = result * d // i
  780. return Integer(result)
  781. else:
  782. d, result = n - k, 1
  783. for i in range(1, k + 1):
  784. d += 1
  785. result *= d
  786. return result / _factorial(k)
  787. @classmethod
  788. def eval(cls, n, k):
  789. n, k = map(sympify, (n, k))
  790. d = n - k
  791. n_nonneg, n_isint = n.is_nonnegative, n.is_integer
  792. if k.is_zero or ((n_nonneg or n_isint is False)
  793. and d.is_zero):
  794. return S.One
  795. if (k - 1).is_zero or ((n_nonneg or n_isint is False)
  796. and (d - 1).is_zero):
  797. return n
  798. if k.is_integer:
  799. if k.is_negative or (n_nonneg and n_isint and d.is_negative):
  800. return S.Zero
  801. elif n.is_number:
  802. res = cls._eval(n, k)
  803. return res.expand(basic=True) if res else res
  804. elif n_nonneg is False and n_isint:
  805. # a special case when binomial evaluates to complex infinity
  806. return S.ComplexInfinity
  807. elif k.is_number:
  808. from sympy.functions.special.gamma_functions import gamma
  809. return gamma(n + 1)/(gamma(k + 1)*gamma(n - k + 1))
  810. def _eval_Mod(self, q):
  811. n, k = self.args
  812. if any(x.is_integer is False for x in (n, k, q)):
  813. raise ValueError("Integers expected for binomial Mod")
  814. if all(x.is_Integer for x in (n, k, q)):
  815. n, k = map(int, (n, k))
  816. aq, res = abs(q), 1
  817. # handle negative integers k or n
  818. if k < 0:
  819. return S.Zero
  820. if n < 0:
  821. n = -n + k - 1
  822. res = -1 if k%2 else 1
  823. # non negative integers k and n
  824. if k > n:
  825. return S.Zero
  826. isprime = aq.is_prime
  827. aq = int(aq)
  828. if isprime:
  829. if aq < n:
  830. # use Lucas Theorem
  831. N, K = n, k
  832. while N or K:
  833. res = res*binomial(N % aq, K % aq) % aq
  834. N, K = N // aq, K // aq
  835. else:
  836. # use Factorial Modulo
  837. d = n - k
  838. if k > d:
  839. k, d = d, k
  840. kf = 1
  841. for i in range(2, k + 1):
  842. kf = kf*i % aq
  843. df = kf
  844. for i in range(k + 1, d + 1):
  845. df = df*i % aq
  846. res *= df
  847. for i in range(d + 1, n + 1):
  848. res = res*i % aq
  849. res *= pow(kf*df % aq, aq - 2, aq)
  850. res %= aq
  851. elif _sqrt(q) < k and q != 1:
  852. res = binomial_mod(n, k, q)
  853. else:
  854. # Binomial Factorization is performed by calculating the
  855. # exponents of primes <= n in `n! /(k! (n - k)!)`,
  856. # for non-negative integers n and k. As the exponent of
  857. # prime in n! is e_p(n) = [n/p] + [n/p**2] + ...
  858. # the exponent of prime in binomial(n, k) would be
  859. # e_p(n) - e_p(k) - e_p(n - k)
  860. M = int(_sqrt(n))
  861. for prime in sieve.primerange(2, n + 1):
  862. if prime > n - k:
  863. res = res*prime % aq
  864. elif prime > n // 2:
  865. continue
  866. elif prime > M:
  867. if n % prime < k % prime:
  868. res = res*prime % aq
  869. else:
  870. N, K = n, k
  871. exp = a = 0
  872. while N > 0:
  873. a = int((N % prime) < (K % prime + a))
  874. N, K = N // prime, K // prime
  875. exp += a
  876. if exp > 0:
  877. res *= pow(prime, exp, aq)
  878. res %= aq
  879. return S(res % q)
  880. def _eval_expand_func(self, **hints):
  881. """
  882. Function to expand binomial(n, k) when m is positive integer
  883. Also,
  884. n is self.args[0] and k is self.args[1] while using binomial(n, k)
  885. """
  886. n = self.args[0]
  887. if n.is_Number:
  888. return binomial(*self.args)
  889. k = self.args[1]
  890. if (n-k).is_Integer:
  891. k = n - k
  892. if k.is_Integer:
  893. if k.is_zero:
  894. return S.One
  895. elif k.is_negative:
  896. return S.Zero
  897. else:
  898. n, result = self.args[0], 1
  899. for i in range(1, k + 1):
  900. result *= n - k + i
  901. return result / _factorial(k)
  902. else:
  903. return binomial(*self.args)
  904. def _eval_rewrite_as_factorial(self, n, k, **kwargs):
  905. return factorial(n)/(factorial(k)*factorial(n - k))
  906. def _eval_rewrite_as_gamma(self, n, k, piecewise=True, **kwargs):
  907. from sympy.functions.special.gamma_functions import gamma
  908. return gamma(n + 1)/(gamma(k + 1)*gamma(n - k + 1))
  909. def _eval_rewrite_as_tractable(self, n, k, limitvar=None, **kwargs):
  910. return self._eval_rewrite_as_gamma(n, k).rewrite('tractable')
  911. def _eval_rewrite_as_FallingFactorial(self, n, k, **kwargs):
  912. if k.is_integer:
  913. return ff(n, k) / factorial(k)
  914. def _eval_is_integer(self):
  915. n, k = self.args
  916. if n.is_integer and k.is_integer:
  917. return True
  918. elif k.is_integer is False:
  919. return False
  920. def _eval_is_nonnegative(self):
  921. n, k = self.args
  922. if n.is_integer and k.is_integer:
  923. if n.is_nonnegative or k.is_negative or k.is_even:
  924. return True
  925. elif k.is_even is False:
  926. return False
  927. def _eval_as_leading_term(self, x, logx, cdir):
  928. from sympy.functions.special.gamma_functions import gamma
  929. return self.rewrite(gamma)._eval_as_leading_term(x, logx=logx, cdir=cdir)