residue_ntheory.py 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573
  1. from __future__ import annotations
  2. from sympy.core.function import Function
  3. from sympy.core.numbers import igcd, igcdex, mod_inverse
  4. from sympy.core.power import isqrt
  5. from sympy.core.singleton import S
  6. from sympy.polys import Poly
  7. from sympy.polys.domains import ZZ
  8. from sympy.polys.galoistools import gf_crt1, gf_crt2, linear_congruence
  9. from .primetest import isprime
  10. from .factor_ import factorint, trailing, totient, multiplicity, perfect_power
  11. from sympy.utilities.misc import as_int
  12. from sympy.core.random import _randint, randint
  13. from itertools import cycle, product
  14. def n_order(a, n):
  15. """Returns the order of ``a`` modulo ``n``.
  16. The order of ``a`` modulo ``n`` is the smallest integer
  17. ``k`` such that ``a**k`` leaves a remainder of 1 with ``n``.
  18. Parameters
  19. ==========
  20. a : integer
  21. n : integer, n > 1. a and n should be relatively prime
  22. Examples
  23. ========
  24. >>> from sympy.ntheory import n_order
  25. >>> n_order(3, 7)
  26. 6
  27. >>> n_order(4, 7)
  28. 3
  29. """
  30. from collections import defaultdict
  31. a, n = as_int(a), as_int(n)
  32. if n <= 1:
  33. raise ValueError("n should be an integer greater than 1")
  34. a = a % n
  35. # Trivial
  36. if a == 1:
  37. return 1
  38. if igcd(a, n) != 1:
  39. raise ValueError("The two numbers should be relatively prime")
  40. # We want to calculate
  41. # order = totient(n), factors = factorint(order)
  42. factors = defaultdict(int)
  43. for px, kx in factorint(n).items():
  44. if kx > 1:
  45. factors[px] += kx - 1
  46. for py, ky in factorint(px - 1).items():
  47. factors[py] += ky
  48. order = 1
  49. for px, kx in factors.items():
  50. order *= px**kx
  51. # Now the `order` is the order of the group.
  52. # The order of `a` divides the order of the group.
  53. for p, e in factors.items():
  54. for _ in range(e):
  55. if pow(a, order // p, n) == 1:
  56. order //= p
  57. else:
  58. break
  59. return order
  60. def _primitive_root_prime_iter(p):
  61. """
  62. Generates the primitive roots for a prime ``p``
  63. Examples
  64. ========
  65. >>> from sympy.ntheory.residue_ntheory import _primitive_root_prime_iter
  66. >>> list(_primitive_root_prime_iter(19))
  67. [2, 3, 10, 13, 14, 15]
  68. References
  69. ==========
  70. .. [1] W. Stein "Elementary Number Theory" (2011), page 44
  71. """
  72. # it is assumed that p is an int
  73. v = [(p - 1) // i for i in factorint(p - 1).keys()]
  74. a = 2
  75. while a < p:
  76. for pw in v:
  77. # a TypeError below may indicate that p was not an int
  78. if pow(a, pw, p) == 1:
  79. break
  80. else:
  81. yield a
  82. a += 1
  83. def primitive_root(p):
  84. """
  85. Returns the smallest primitive root or None.
  86. Parameters
  87. ==========
  88. p : positive integer
  89. Examples
  90. ========
  91. >>> from sympy.ntheory.residue_ntheory import primitive_root
  92. >>> primitive_root(19)
  93. 2
  94. References
  95. ==========
  96. .. [1] W. Stein "Elementary Number Theory" (2011), page 44
  97. .. [2] P. Hackman "Elementary Number Theory" (2009), Chapter C
  98. """
  99. p = as_int(p)
  100. if p < 1:
  101. raise ValueError('p is required to be positive')
  102. if p <= 2:
  103. return 1
  104. f = factorint(p)
  105. if len(f) > 2:
  106. return None
  107. if len(f) == 2:
  108. if 2 not in f or f[2] > 1:
  109. return None
  110. # case p = 2*p1**k, p1 prime
  111. for p1, e1 in f.items():
  112. if p1 != 2:
  113. break
  114. i = 1
  115. while i < p:
  116. i += 2
  117. if i % p1 == 0:
  118. continue
  119. if is_primitive_root(i, p):
  120. return i
  121. else:
  122. if 2 in f:
  123. if p == 4:
  124. return 3
  125. return None
  126. p1, n = list(f.items())[0]
  127. if n > 1:
  128. # see Ref [2], page 81
  129. g = primitive_root(p1)
  130. if is_primitive_root(g, p1**2):
  131. return g
  132. else:
  133. for i in range(2, g + p1 + 1):
  134. if igcd(i, p) == 1 and is_primitive_root(i, p):
  135. return i
  136. return next(_primitive_root_prime_iter(p))
  137. def is_primitive_root(a, p):
  138. """
  139. Returns True if ``a`` is a primitive root of ``p``.
  140. ``a`` is said to be the primitive root of ``p`` if gcd(a, p) == 1 and
  141. totient(p) is the smallest positive number s.t.
  142. a**totient(p) cong 1 mod(p)
  143. Parameters
  144. ==========
  145. a : integer
  146. p : integer, p > 1. a and p should be relatively prime
  147. Examples
  148. ========
  149. >>> from sympy.ntheory import is_primitive_root, n_order, totient
  150. >>> is_primitive_root(3, 10)
  151. True
  152. >>> is_primitive_root(9, 10)
  153. False
  154. >>> n_order(3, 10) == totient(10)
  155. True
  156. >>> n_order(9, 10) == totient(10)
  157. False
  158. """
  159. a, p = as_int(a), as_int(p)
  160. if p <= 1:
  161. raise ValueError("p should be an integer greater than 1")
  162. a = a % p
  163. if igcd(a, p) != 1:
  164. raise ValueError("The two numbers should be relatively prime")
  165. # Primitive root of p exist only for
  166. # p = 2, 4, q**e, 2*q**e (q is odd prime)
  167. if p <= 4:
  168. # The primitive root is only p-1.
  169. return a == p - 1
  170. t = trailing(p)
  171. if t > 1:
  172. return False
  173. q = p >> t
  174. if isprime(q):
  175. group_order = q - 1
  176. factors = set(factorint(q - 1).keys())
  177. else:
  178. m = perfect_power(q)
  179. if not m:
  180. return False
  181. q, e = m
  182. if not isprime(q):
  183. return False
  184. group_order = q**(e - 1)*(q - 1)
  185. factors = set(factorint(q - 1).keys())
  186. factors.add(q)
  187. return all(pow(a, group_order // prime, p) != 1 for prime in factors)
  188. def _sqrt_mod_tonelli_shanks(a, p):
  189. """
  190. Returns the square root in the case of ``p`` prime with ``p == 1 (mod 8)``
  191. References
  192. ==========
  193. .. [1] R. Crandall and C. Pomerance "Prime Numbers", 2nt Ed., page 101
  194. """
  195. s = trailing(p - 1)
  196. t = p >> s
  197. # find a non-quadratic residue
  198. while 1:
  199. d = randint(2, p - 1)
  200. r = legendre_symbol(d, p)
  201. if r == -1:
  202. break
  203. #assert legendre_symbol(d, p) == -1
  204. A = pow(a, t, p)
  205. D = pow(d, t, p)
  206. m = 0
  207. for i in range(s):
  208. adm = A*pow(D, m, p) % p
  209. adm = pow(adm, 2**(s - 1 - i), p)
  210. if adm % p == p - 1:
  211. m += 2**i
  212. #assert A*pow(D, m, p) % p == 1
  213. x = pow(a, (t + 1)//2, p)*pow(D, m//2, p) % p
  214. return x
  215. def sqrt_mod(a, p, all_roots=False):
  216. """
  217. Find a root of ``x**2 = a mod p``.
  218. Parameters
  219. ==========
  220. a : integer
  221. p : positive integer
  222. all_roots : if True the list of roots is returned or None
  223. Notes
  224. =====
  225. If there is no root it is returned None; else the returned root
  226. is less or equal to ``p // 2``; in general is not the smallest one.
  227. It is returned ``p // 2`` only if it is the only root.
  228. Use ``all_roots`` only when it is expected that all the roots fit
  229. in memory; otherwise use ``sqrt_mod_iter``.
  230. Examples
  231. ========
  232. >>> from sympy.ntheory import sqrt_mod
  233. >>> sqrt_mod(11, 43)
  234. 21
  235. >>> sqrt_mod(17, 32, True)
  236. [7, 9, 23, 25]
  237. """
  238. if all_roots:
  239. return sorted(sqrt_mod_iter(a, p))
  240. try:
  241. p = abs(as_int(p))
  242. it = sqrt_mod_iter(a, p)
  243. r = next(it)
  244. if r > p // 2:
  245. return p - r
  246. elif r < p // 2:
  247. return r
  248. else:
  249. try:
  250. r = next(it)
  251. if r > p // 2:
  252. return p - r
  253. except StopIteration:
  254. pass
  255. return r
  256. except StopIteration:
  257. return None
  258. def _product(*iters):
  259. """
  260. Cartesian product generator
  261. Notes
  262. =====
  263. Unlike itertools.product, it works also with iterables which do not fit
  264. in memory. See https://bugs.python.org/issue10109
  265. Author: Fernando Sumudu
  266. with small changes
  267. """
  268. inf_iters = tuple(cycle(enumerate(it)) for it in iters)
  269. num_iters = len(inf_iters)
  270. cur_val = [None]*num_iters
  271. first_v = True
  272. while True:
  273. i, p = 0, num_iters
  274. while p and not i:
  275. p -= 1
  276. i, cur_val[p] = next(inf_iters[p])
  277. if not p and not i:
  278. if first_v:
  279. first_v = False
  280. else:
  281. break
  282. yield cur_val
  283. def sqrt_mod_iter(a, p, domain=int):
  284. """
  285. Iterate over solutions to ``x**2 = a mod p``.
  286. Parameters
  287. ==========
  288. a : integer
  289. p : positive integer
  290. domain : integer domain, ``int``, ``ZZ`` or ``Integer``
  291. Examples
  292. ========
  293. >>> from sympy.ntheory.residue_ntheory import sqrt_mod_iter
  294. >>> list(sqrt_mod_iter(11, 43))
  295. [21, 22]
  296. """
  297. a, p = as_int(a), abs(as_int(p))
  298. if isprime(p):
  299. a = a % p
  300. if a == 0:
  301. res = _sqrt_mod1(a, p, 1)
  302. else:
  303. res = _sqrt_mod_prime_power(a, p, 1)
  304. if res:
  305. if domain is ZZ:
  306. yield from res
  307. else:
  308. for x in res:
  309. yield domain(x)
  310. else:
  311. f = factorint(p)
  312. v = []
  313. pv = []
  314. for px, ex in f.items():
  315. if a % px == 0:
  316. rx = _sqrt_mod1(a, px, ex)
  317. if not rx:
  318. return
  319. else:
  320. rx = _sqrt_mod_prime_power(a, px, ex)
  321. if not rx:
  322. return
  323. v.append(rx)
  324. pv.append(px**ex)
  325. mm, e, s = gf_crt1(pv, ZZ)
  326. if domain is ZZ:
  327. for vx in _product(*v):
  328. r = gf_crt2(vx, pv, mm, e, s, ZZ)
  329. yield r
  330. else:
  331. for vx in _product(*v):
  332. r = gf_crt2(vx, pv, mm, e, s, ZZ)
  333. yield domain(r)
  334. def _sqrt_mod_prime_power(a, p, k):
  335. """
  336. Find the solutions to ``x**2 = a mod p**k`` when ``a % p != 0``
  337. Parameters
  338. ==========
  339. a : integer
  340. p : prime number
  341. k : positive integer
  342. Examples
  343. ========
  344. >>> from sympy.ntheory.residue_ntheory import _sqrt_mod_prime_power
  345. >>> _sqrt_mod_prime_power(11, 43, 1)
  346. [21, 22]
  347. References
  348. ==========
  349. .. [1] P. Hackman "Elementary Number Theory" (2009), page 160
  350. .. [2] http://www.numbertheory.org/php/squareroot.html
  351. .. [3] [Gathen99]_
  352. """
  353. pk = p**k
  354. a = a % pk
  355. if k == 1:
  356. if p == 2:
  357. return [ZZ(a)]
  358. if not (a % p < 2 or pow(a, (p - 1) // 2, p) == 1):
  359. return None
  360. if p % 4 == 3:
  361. res = pow(a, (p + 1) // 4, p)
  362. elif p % 8 == 5:
  363. sign = pow(a, (p - 1) // 4, p)
  364. if sign == 1:
  365. res = pow(a, (p + 3) // 8, p)
  366. else:
  367. b = pow(4*a, (p - 5) // 8, p)
  368. x = (2*a*b) % p
  369. if pow(x, 2, p) == a:
  370. res = x
  371. else:
  372. res = _sqrt_mod_tonelli_shanks(a, p)
  373. # ``_sqrt_mod_tonelli_shanks(a, p)`` is not deterministic;
  374. # sort to get always the same result
  375. return sorted([ZZ(res), ZZ(p - res)])
  376. if k > 1:
  377. # see Ref.[2]
  378. if p == 2:
  379. if a % 8 != 1:
  380. return None
  381. if k <= 3:
  382. s = set()
  383. for i in range(0, pk, 4):
  384. s.add(1 + i)
  385. s.add(-1 + i)
  386. return list(s)
  387. # according to Ref.[2] for k > 2 there are two solutions
  388. # (mod 2**k-1), that is four solutions (mod 2**k), which can be
  389. # obtained from the roots of x**2 = 0 (mod 8)
  390. rv = [ZZ(1), ZZ(3), ZZ(5), ZZ(7)]
  391. # hensel lift them to solutions of x**2 = 0 (mod 2**k)
  392. # if r**2 - a = 0 mod 2**nx but not mod 2**(nx+1)
  393. # then r + 2**(nx - 1) is a root mod 2**(nx+1)
  394. n = 3
  395. res = []
  396. for r in rv:
  397. nx = n
  398. while nx < k:
  399. r1 = (r**2 - a) >> nx
  400. if r1 % 2:
  401. r = r + (1 << (nx - 1))
  402. #assert (r**2 - a)% (1 << (nx + 1)) == 0
  403. nx += 1
  404. if r not in res:
  405. res.append(r)
  406. x = r + (1 << (k - 1))
  407. #assert (x**2 - a) % pk == 0
  408. if x < (1 << nx) and x not in res:
  409. if (x**2 - a) % pk == 0:
  410. res.append(x)
  411. return res
  412. rv = _sqrt_mod_prime_power(a, p, 1)
  413. if not rv:
  414. return None
  415. r = rv[0]
  416. fr = r**2 - a
  417. # hensel lifting with Newton iteration, see Ref.[3] chapter 9
  418. # with f(x) = x**2 - a; one has f'(a) != 0 (mod p) for p != 2
  419. n = 1
  420. px = p
  421. while 1:
  422. n1 = n
  423. n1 *= 2
  424. if n1 > k:
  425. break
  426. n = n1
  427. px = px**2
  428. frinv = igcdex(2*r, px)[0]
  429. r = (r - fr*frinv) % px
  430. fr = r**2 - a
  431. if n < k:
  432. px = p**k
  433. frinv = igcdex(2*r, px)[0]
  434. r = (r - fr*frinv) % px
  435. return [r, px - r]
  436. def _sqrt_mod1(a, p, n):
  437. """
  438. Find solution to ``x**2 == a mod p**n`` when ``a % p == 0``
  439. see http://www.numbertheory.org/php/squareroot.html
  440. """
  441. pn = p**n
  442. a = a % pn
  443. if a == 0:
  444. # case gcd(a, p**k) = p**n
  445. m = n // 2
  446. if n % 2 == 1:
  447. pm1 = p**(m + 1)
  448. def _iter0a():
  449. i = 0
  450. while i < pn:
  451. yield i
  452. i += pm1
  453. return _iter0a()
  454. else:
  455. pm = p**m
  456. def _iter0b():
  457. i = 0
  458. while i < pn:
  459. yield i
  460. i += pm
  461. return _iter0b()
  462. # case gcd(a, p**k) = p**r, r < n
  463. f = factorint(a)
  464. r = f[p]
  465. if r % 2 == 1:
  466. return None
  467. m = r // 2
  468. a1 = a >> r
  469. if p == 2:
  470. if n - r == 1:
  471. pnm1 = 1 << (n - m + 1)
  472. pm1 = 1 << (m + 1)
  473. def _iter1():
  474. k = 1 << (m + 2)
  475. i = 1 << m
  476. while i < pnm1:
  477. j = i
  478. while j < pn:
  479. yield j
  480. j += k
  481. i += pm1
  482. return _iter1()
  483. if n - r == 2:
  484. res = _sqrt_mod_prime_power(a1, p, n - r)
  485. if res is None:
  486. return None
  487. pnm = 1 << (n - m)
  488. def _iter2():
  489. s = set()
  490. for r in res:
  491. i = 0
  492. while i < pn:
  493. x = (r << m) + i
  494. if x not in s:
  495. s.add(x)
  496. yield x
  497. i += pnm
  498. return _iter2()
  499. if n - r > 2:
  500. res = _sqrt_mod_prime_power(a1, p, n - r)
  501. if res is None:
  502. return None
  503. pnm1 = 1 << (n - m - 1)
  504. def _iter3():
  505. s = set()
  506. for r in res:
  507. i = 0
  508. while i < pn:
  509. x = ((r << m) + i) % pn
  510. if x not in s:
  511. s.add(x)
  512. yield x
  513. i += pnm1
  514. return _iter3()
  515. else:
  516. m = r // 2
  517. a1 = a // p**r
  518. res1 = _sqrt_mod_prime_power(a1, p, n - r)
  519. if res1 is None:
  520. return None
  521. pm = p**m
  522. pnr = p**(n-r)
  523. pnm = p**(n-m)
  524. def _iter4():
  525. s = set()
  526. pm = p**m
  527. for rx in res1:
  528. i = 0
  529. while i < pnm:
  530. x = ((rx + i) % pn)
  531. if x not in s:
  532. s.add(x)
  533. yield x*pm
  534. i += pnr
  535. return _iter4()
  536. def is_quad_residue(a, p):
  537. """
  538. Returns True if ``a`` (mod ``p``) is in the set of squares mod ``p``,
  539. i.e a % p in set([i**2 % p for i in range(p)]).
  540. Examples
  541. ========
  542. If ``p`` is an odd
  543. prime, an iterative method is used to make the determination:
  544. >>> from sympy.ntheory import is_quad_residue
  545. >>> sorted(set([i**2 % 7 for i in range(7)]))
  546. [0, 1, 2, 4]
  547. >>> [j for j in range(7) if is_quad_residue(j, 7)]
  548. [0, 1, 2, 4]
  549. See Also
  550. ========
  551. legendre_symbol, jacobi_symbol
  552. """
  553. a, p = as_int(a), as_int(p)
  554. if p < 1:
  555. raise ValueError('p must be > 0')
  556. if a >= p or a < 0:
  557. a = a % p
  558. if a < 2 or p < 3:
  559. return True
  560. if not isprime(p):
  561. if p % 2 and jacobi_symbol(a, p) == -1:
  562. return False
  563. r = sqrt_mod(a, p)
  564. if r is None:
  565. return False
  566. else:
  567. return True
  568. return pow(a, (p - 1) // 2, p) == 1
  569. def is_nthpow_residue(a, n, m):
  570. """
  571. Returns True if ``x**n == a (mod m)`` has solutions.
  572. References
  573. ==========
  574. .. [1] P. Hackman "Elementary Number Theory" (2009), page 76
  575. """
  576. a = a % m
  577. a, n, m = as_int(a), as_int(n), as_int(m)
  578. if m <= 0:
  579. raise ValueError('m must be > 0')
  580. if n < 0:
  581. raise ValueError('n must be >= 0')
  582. if n == 0:
  583. if m == 1:
  584. return False
  585. return a == 1
  586. if a == 0:
  587. return True
  588. if n == 1:
  589. return True
  590. if n == 2:
  591. return is_quad_residue(a, m)
  592. return _is_nthpow_residue_bign(a, n, m)
  593. def _is_nthpow_residue_bign(a, n, m):
  594. r"""Returns True if `x^n = a \pmod{n}` has solutions for `n > 2`."""
  595. # assert n > 2
  596. # assert a > 0 and m > 0
  597. if primitive_root(m) is None or igcd(a, m) != 1:
  598. # assert m >= 8
  599. for prime, power in factorint(m).items():
  600. if not _is_nthpow_residue_bign_prime_power(a, n, prime, power):
  601. return False
  602. return True
  603. f = totient(m)
  604. k = int(f // igcd(f, n))
  605. return pow(a, k, int(m)) == 1
  606. def _is_nthpow_residue_bign_prime_power(a, n, p, k):
  607. r"""Returns True/False if a solution for `x^n = a \pmod{p^k}`
  608. does/does not exist."""
  609. # assert a > 0
  610. # assert n > 2
  611. # assert p is prime
  612. # assert k > 0
  613. if a % p:
  614. if p != 2:
  615. return _is_nthpow_residue_bign(a, n, pow(p, k))
  616. if n & 1:
  617. return True
  618. c = trailing(n)
  619. return a % pow(2, min(c + 2, k)) == 1
  620. else:
  621. a %= pow(p, k)
  622. if not a:
  623. return True
  624. mu = multiplicity(p, a)
  625. if mu % n:
  626. return False
  627. pm = pow(p, mu)
  628. return _is_nthpow_residue_bign_prime_power(a//pm, n, p, k - mu)
  629. def _nthroot_mod2(s, q, p):
  630. f = factorint(q)
  631. v = []
  632. for b, e in f.items():
  633. v.extend([b]*e)
  634. for qx in v:
  635. s = _nthroot_mod1(s, qx, p, False)
  636. return s
  637. def _nthroot_mod1(s, q, p, all_roots):
  638. """
  639. Root of ``x**q = s mod p``, ``p`` prime and ``q`` divides ``p - 1``
  640. References
  641. ==========
  642. .. [1] A. M. Johnston "A Generalized qth Root Algorithm"
  643. """
  644. g = primitive_root(p)
  645. if not isprime(q):
  646. r = _nthroot_mod2(s, q, p)
  647. else:
  648. f = p - 1
  649. assert (p - 1) % q == 0
  650. # determine k
  651. k = 0
  652. while f % q == 0:
  653. k += 1
  654. f = f // q
  655. # find z, x, r1
  656. f1 = igcdex(-f, q)[0] % q
  657. z = f*f1
  658. x = (1 + z) // q
  659. r1 = pow(s, x, p)
  660. s1 = pow(s, f, p)
  661. h = pow(g, f*q, p)
  662. t = discrete_log(p, s1, h)
  663. g2 = pow(g, z*t, p)
  664. g3 = igcdex(g2, p)[0]
  665. r = r1*g3 % p
  666. #assert pow(r, q, p) == s
  667. res = [r]
  668. h = pow(g, (p - 1) // q, p)
  669. #assert pow(h, q, p) == 1
  670. hx = r
  671. for i in range(q - 1):
  672. hx = (hx*h) % p
  673. res.append(hx)
  674. if all_roots:
  675. res.sort()
  676. return res
  677. return min(res)
  678. def _help(m, prime_modulo_method, diff_method, expr_val):
  679. """
  680. Helper function for _nthroot_mod_composite and polynomial_congruence.
  681. Parameters
  682. ==========
  683. m : positive integer
  684. prime_modulo_method : function to calculate the root of the congruence
  685. equation for the prime divisors of m
  686. diff_method : function to calculate derivative of expression at any
  687. given point
  688. expr_val : function to calculate value of the expression at any
  689. given point
  690. """
  691. from sympy.ntheory.modular import crt
  692. f = factorint(m)
  693. dd = {}
  694. for p, e in f.items():
  695. tot_roots = set()
  696. if e == 1:
  697. tot_roots.update(prime_modulo_method(p))
  698. else:
  699. for root in prime_modulo_method(p):
  700. diff = diff_method(root, p)
  701. if diff != 0:
  702. ppow = p
  703. m_inv = mod_inverse(diff, p)
  704. for j in range(1, e):
  705. ppow *= p
  706. root = (root - expr_val(root, ppow) * m_inv) % ppow
  707. tot_roots.add(root)
  708. else:
  709. new_base = p
  710. roots_in_base = {root}
  711. while new_base < pow(p, e):
  712. new_base *= p
  713. new_roots = set()
  714. for k in roots_in_base:
  715. if expr_val(k, new_base)!= 0:
  716. continue
  717. while k not in new_roots:
  718. new_roots.add(k)
  719. k = (k + (new_base // p)) % new_base
  720. roots_in_base = new_roots
  721. tot_roots = tot_roots | roots_in_base
  722. if tot_roots == set():
  723. return []
  724. dd[pow(p, e)] = tot_roots
  725. a = []
  726. m = []
  727. for x, y in dd.items():
  728. m.append(x)
  729. a.append(list(y))
  730. return sorted({crt(m, list(i))[0] for i in product(*a)})
  731. def _nthroot_mod_composite(a, n, m):
  732. """
  733. Find the solutions to ``x**n = a mod m`` when m is not prime.
  734. """
  735. return _help(m,
  736. lambda p: nthroot_mod(a, n, p, True),
  737. lambda root, p: (pow(root, n - 1, p) * (n % p)) % p,
  738. lambda root, p: (pow(root, n, p) - a) % p)
  739. def nthroot_mod(a, n, p, all_roots=False):
  740. """
  741. Find the solutions to ``x**n = a mod p``.
  742. Parameters
  743. ==========
  744. a : integer
  745. n : positive integer
  746. p : positive integer
  747. all_roots : if False returns the smallest root, else the list of roots
  748. Examples
  749. ========
  750. >>> from sympy.ntheory.residue_ntheory import nthroot_mod
  751. >>> nthroot_mod(11, 4, 19)
  752. 8
  753. >>> nthroot_mod(11, 4, 19, True)
  754. [8, 11]
  755. >>> nthroot_mod(68, 3, 109)
  756. 23
  757. """
  758. a = a % p
  759. a, n, p = as_int(a), as_int(n), as_int(p)
  760. if n == 2:
  761. return sqrt_mod(a, p, all_roots)
  762. # see Hackman "Elementary Number Theory" (2009), page 76
  763. if not isprime(p):
  764. return _nthroot_mod_composite(a, n, p)
  765. if a % p == 0:
  766. return [0]
  767. if not is_nthpow_residue(a, n, p):
  768. return [] if all_roots else None
  769. if (p - 1) % n == 0:
  770. return _nthroot_mod1(a, n, p, all_roots)
  771. # The roots of ``x**n - a = 0 (mod p)`` are roots of
  772. # ``gcd(x**n - a, x**(p - 1) - 1) = 0 (mod p)``
  773. pa = n
  774. pb = p - 1
  775. b = 1
  776. if pa < pb:
  777. a, pa, b, pb = b, pb, a, pa
  778. while pb:
  779. # x**pa - a = 0; x**pb - b = 0
  780. # x**pa - a = x**(q*pb + r) - a = (x**pb)**q * x**r - a =
  781. # b**q * x**r - a; x**r - c = 0; c = b**-q * a mod p
  782. q, r = divmod(pa, pb)
  783. c = pow(b, q, p)
  784. c = igcdex(c, p)[0]
  785. c = (c * a) % p
  786. pa, pb = pb, r
  787. a, b = b, c
  788. if pa == 1:
  789. if all_roots:
  790. res = [a]
  791. else:
  792. res = a
  793. elif pa == 2:
  794. return sqrt_mod(a, p, all_roots)
  795. else:
  796. res = _nthroot_mod1(a, pa, p, all_roots)
  797. return res
  798. def quadratic_residues(p) -> list[int]:
  799. """
  800. Returns the list of quadratic residues.
  801. Examples
  802. ========
  803. >>> from sympy.ntheory.residue_ntheory import quadratic_residues
  804. >>> quadratic_residues(7)
  805. [0, 1, 2, 4]
  806. """
  807. p = as_int(p)
  808. r = {pow(i, 2, p) for i in range(p // 2 + 1)}
  809. return sorted(r)
  810. def legendre_symbol(a, p):
  811. r"""
  812. Returns the Legendre symbol `(a / p)`.
  813. For an integer ``a`` and an odd prime ``p``, the Legendre symbol is
  814. defined as
  815. .. math ::
  816. \genfrac(){}{}{a}{p} = \begin{cases}
  817. 0 & \text{if } p \text{ divides } a\\
  818. 1 & \text{if } a \text{ is a quadratic residue modulo } p\\
  819. -1 & \text{if } a \text{ is a quadratic nonresidue modulo } p
  820. \end{cases}
  821. Parameters
  822. ==========
  823. a : integer
  824. p : odd prime
  825. Examples
  826. ========
  827. >>> from sympy.ntheory import legendre_symbol
  828. >>> [legendre_symbol(i, 7) for i in range(7)]
  829. [0, 1, 1, -1, 1, -1, -1]
  830. >>> sorted(set([i**2 % 7 for i in range(7)]))
  831. [0, 1, 2, 4]
  832. See Also
  833. ========
  834. is_quad_residue, jacobi_symbol
  835. """
  836. a, p = as_int(a), as_int(p)
  837. if not isprime(p) or p == 2:
  838. raise ValueError("p should be an odd prime")
  839. a = a % p
  840. if not a:
  841. return 0
  842. if pow(a, (p - 1) // 2, p) == 1:
  843. return 1
  844. return -1
  845. def jacobi_symbol(m, n):
  846. r"""
  847. Returns the Jacobi symbol `(m / n)`.
  848. For any integer ``m`` and any positive odd integer ``n`` the Jacobi symbol
  849. is defined as the product of the Legendre symbols corresponding to the
  850. prime factors of ``n``:
  851. .. math ::
  852. \genfrac(){}{}{m}{n} =
  853. \genfrac(){}{}{m}{p^{1}}^{\alpha_1}
  854. \genfrac(){}{}{m}{p^{2}}^{\alpha_2}
  855. ...
  856. \genfrac(){}{}{m}{p^{k}}^{\alpha_k}
  857. \text{ where } n =
  858. p_1^{\alpha_1}
  859. p_2^{\alpha_2}
  860. ...
  861. p_k^{\alpha_k}
  862. Like the Legendre symbol, if the Jacobi symbol `\genfrac(){}{}{m}{n} = -1`
  863. then ``m`` is a quadratic nonresidue modulo ``n``.
  864. But, unlike the Legendre symbol, if the Jacobi symbol
  865. `\genfrac(){}{}{m}{n} = 1` then ``m`` may or may not be a quadratic residue
  866. modulo ``n``.
  867. Parameters
  868. ==========
  869. m : integer
  870. n : odd positive integer
  871. Examples
  872. ========
  873. >>> from sympy.ntheory import jacobi_symbol, legendre_symbol
  874. >>> from sympy import S
  875. >>> jacobi_symbol(45, 77)
  876. -1
  877. >>> jacobi_symbol(60, 121)
  878. 1
  879. The relationship between the ``jacobi_symbol`` and ``legendre_symbol`` can
  880. be demonstrated as follows:
  881. >>> L = legendre_symbol
  882. >>> S(45).factors()
  883. {3: 2, 5: 1}
  884. >>> jacobi_symbol(7, 45) == L(7, 3)**2 * L(7, 5)**1
  885. True
  886. See Also
  887. ========
  888. is_quad_residue, legendre_symbol
  889. """
  890. m, n = as_int(m), as_int(n)
  891. if n < 0 or not n % 2:
  892. raise ValueError("n should be an odd positive integer")
  893. if m < 0 or m > n:
  894. m %= n
  895. if not m:
  896. return int(n == 1)
  897. if n == 1 or m == 1:
  898. return 1
  899. if igcd(m, n) != 1:
  900. return 0
  901. j = 1
  902. while m != 0:
  903. while m % 2 == 0 and m > 0:
  904. m >>= 1
  905. if n % 8 in [3, 5]:
  906. j = -j
  907. m, n = n, m
  908. if m % 4 == n % 4 == 3:
  909. j = -j
  910. m %= n
  911. return j
  912. class mobius(Function):
  913. """
  914. Mobius function maps natural number to {-1, 0, 1}
  915. It is defined as follows:
  916. 1) `1` if `n = 1`.
  917. 2) `0` if `n` has a squared prime factor.
  918. 3) `(-1)^k` if `n` is a square-free positive integer with `k`
  919. number of prime factors.
  920. It is an important multiplicative function in number theory
  921. and combinatorics. It has applications in mathematical series,
  922. algebraic number theory and also physics (Fermion operator has very
  923. concrete realization with Mobius Function model).
  924. Parameters
  925. ==========
  926. n : positive integer
  927. Examples
  928. ========
  929. >>> from sympy.ntheory import mobius
  930. >>> mobius(13*7)
  931. 1
  932. >>> mobius(1)
  933. 1
  934. >>> mobius(13*7*5)
  935. -1
  936. >>> mobius(13**2)
  937. 0
  938. References
  939. ==========
  940. .. [1] https://en.wikipedia.org/wiki/M%C3%B6bius_function
  941. .. [2] Thomas Koshy "Elementary Number Theory with Applications"
  942. """
  943. @classmethod
  944. def eval(cls, n):
  945. if n.is_integer:
  946. if n.is_positive is not True:
  947. raise ValueError("n should be a positive integer")
  948. else:
  949. raise TypeError("n should be an integer")
  950. if n.is_prime:
  951. return S.NegativeOne
  952. elif n is S.One:
  953. return S.One
  954. elif n.is_Integer:
  955. a = factorint(n)
  956. if any(i > 1 for i in a.values()):
  957. return S.Zero
  958. return S.NegativeOne**len(a)
  959. def _discrete_log_trial_mul(n, a, b, order=None):
  960. """
  961. Trial multiplication algorithm for computing the discrete logarithm of
  962. ``a`` to the base ``b`` modulo ``n``.
  963. The algorithm finds the discrete logarithm using exhaustive search. This
  964. naive method is used as fallback algorithm of ``discrete_log`` when the
  965. group order is very small.
  966. Examples
  967. ========
  968. >>> from sympy.ntheory.residue_ntheory import _discrete_log_trial_mul
  969. >>> _discrete_log_trial_mul(41, 15, 7)
  970. 3
  971. See Also
  972. ========
  973. discrete_log
  974. References
  975. ==========
  976. .. [1] "Handbook of applied cryptography", Menezes, A. J., Van, O. P. C., &
  977. Vanstone, S. A. (1997).
  978. """
  979. a %= n
  980. b %= n
  981. if order is None:
  982. order = n
  983. x = 1
  984. for i in range(order):
  985. if x == a:
  986. return i
  987. x = x * b % n
  988. raise ValueError("Log does not exist")
  989. def _discrete_log_shanks_steps(n, a, b, order=None):
  990. """
  991. Baby-step giant-step algorithm for computing the discrete logarithm of
  992. ``a`` to the base ``b`` modulo ``n``.
  993. The algorithm is a time-memory trade-off of the method of exhaustive
  994. search. It uses `O(sqrt(m))` memory, where `m` is the group order.
  995. Examples
  996. ========
  997. >>> from sympy.ntheory.residue_ntheory import _discrete_log_shanks_steps
  998. >>> _discrete_log_shanks_steps(41, 15, 7)
  999. 3
  1000. See Also
  1001. ========
  1002. discrete_log
  1003. References
  1004. ==========
  1005. .. [1] "Handbook of applied cryptography", Menezes, A. J., Van, O. P. C., &
  1006. Vanstone, S. A. (1997).
  1007. """
  1008. a %= n
  1009. b %= n
  1010. if order is None:
  1011. order = n_order(b, n)
  1012. m = isqrt(order) + 1
  1013. T = {}
  1014. x = 1
  1015. for i in range(m):
  1016. T[x] = i
  1017. x = x * b % n
  1018. z = mod_inverse(b, n)
  1019. z = pow(z, m, n)
  1020. x = a
  1021. for i in range(m):
  1022. if x in T:
  1023. return i * m + T[x]
  1024. x = x * z % n
  1025. raise ValueError("Log does not exist")
  1026. def _discrete_log_pollard_rho(n, a, b, order=None, retries=10, rseed=None):
  1027. """
  1028. Pollard's Rho algorithm for computing the discrete logarithm of ``a`` to
  1029. the base ``b`` modulo ``n``.
  1030. It is a randomized algorithm with the same expected running time as
  1031. ``_discrete_log_shanks_steps``, but requires a negligible amount of memory.
  1032. Examples
  1033. ========
  1034. >>> from sympy.ntheory.residue_ntheory import _discrete_log_pollard_rho
  1035. >>> _discrete_log_pollard_rho(227, 3**7, 3)
  1036. 7
  1037. See Also
  1038. ========
  1039. discrete_log
  1040. References
  1041. ==========
  1042. .. [1] "Handbook of applied cryptography", Menezes, A. J., Van, O. P. C., &
  1043. Vanstone, S. A. (1997).
  1044. """
  1045. a %= n
  1046. b %= n
  1047. if order is None:
  1048. order = n_order(b, n)
  1049. randint = _randint(rseed)
  1050. for i in range(retries):
  1051. aa = randint(1, order - 1)
  1052. ba = randint(1, order - 1)
  1053. xa = pow(b, aa, n) * pow(a, ba, n) % n
  1054. c = xa % 3
  1055. if c == 0:
  1056. xb = a * xa % n
  1057. ab = aa
  1058. bb = (ba + 1) % order
  1059. elif c == 1:
  1060. xb = xa * xa % n
  1061. ab = (aa + aa) % order
  1062. bb = (ba + ba) % order
  1063. else:
  1064. xb = b * xa % n
  1065. ab = (aa + 1) % order
  1066. bb = ba
  1067. for j in range(order):
  1068. c = xa % 3
  1069. if c == 0:
  1070. xa = a * xa % n
  1071. ba = (ba + 1) % order
  1072. elif c == 1:
  1073. xa = xa * xa % n
  1074. aa = (aa + aa) % order
  1075. ba = (ba + ba) % order
  1076. else:
  1077. xa = b * xa % n
  1078. aa = (aa + 1) % order
  1079. c = xb % 3
  1080. if c == 0:
  1081. xb = a * xb % n
  1082. bb = (bb + 1) % order
  1083. elif c == 1:
  1084. xb = xb * xb % n
  1085. ab = (ab + ab) % order
  1086. bb = (bb + bb) % order
  1087. else:
  1088. xb = b * xb % n
  1089. ab = (ab + 1) % order
  1090. c = xb % 3
  1091. if c == 0:
  1092. xb = a * xb % n
  1093. bb = (bb + 1) % order
  1094. elif c == 1:
  1095. xb = xb * xb % n
  1096. ab = (ab + ab) % order
  1097. bb = (bb + bb) % order
  1098. else:
  1099. xb = b * xb % n
  1100. ab = (ab + 1) % order
  1101. if xa == xb:
  1102. r = (ba - bb) % order
  1103. try:
  1104. e = mod_inverse(r, order) * (ab - aa) % order
  1105. if (pow(b, e, n) - a) % n == 0:
  1106. return e
  1107. except ValueError:
  1108. pass
  1109. break
  1110. raise ValueError("Pollard's Rho failed to find logarithm")
  1111. def _discrete_log_pohlig_hellman(n, a, b, order=None):
  1112. """
  1113. Pohlig-Hellman algorithm for computing the discrete logarithm of ``a`` to
  1114. the base ``b`` modulo ``n``.
  1115. In order to compute the discrete logarithm, the algorithm takes advantage
  1116. of the factorization of the group order. It is more efficient when the
  1117. group order factors into many small primes.
  1118. Examples
  1119. ========
  1120. >>> from sympy.ntheory.residue_ntheory import _discrete_log_pohlig_hellman
  1121. >>> _discrete_log_pohlig_hellman(251, 210, 71)
  1122. 197
  1123. See Also
  1124. ========
  1125. discrete_log
  1126. References
  1127. ==========
  1128. .. [1] "Handbook of applied cryptography", Menezes, A. J., Van, O. P. C., &
  1129. Vanstone, S. A. (1997).
  1130. """
  1131. from .modular import crt
  1132. a %= n
  1133. b %= n
  1134. if order is None:
  1135. order = n_order(b, n)
  1136. f = factorint(order)
  1137. l = [0] * len(f)
  1138. for i, (pi, ri) in enumerate(f.items()):
  1139. for j in range(ri):
  1140. gj = pow(b, l[i], n)
  1141. aj = pow(a * mod_inverse(gj, n), order // pi**(j + 1), n)
  1142. bj = pow(b, order // pi, n)
  1143. cj = discrete_log(n, aj, bj, pi, True)
  1144. l[i] += cj * pi**j
  1145. d, _ = crt([pi**ri for pi, ri in f.items()], l)
  1146. return d
  1147. def discrete_log(n, a, b, order=None, prime_order=None):
  1148. """
  1149. Compute the discrete logarithm of ``a`` to the base ``b`` modulo ``n``.
  1150. This is a recursive function to reduce the discrete logarithm problem in
  1151. cyclic groups of composite order to the problem in cyclic groups of prime
  1152. order.
  1153. It employs different algorithms depending on the problem (subgroup order
  1154. size, prime order or not):
  1155. * Trial multiplication
  1156. * Baby-step giant-step
  1157. * Pollard's Rho
  1158. * Pohlig-Hellman
  1159. Examples
  1160. ========
  1161. >>> from sympy.ntheory import discrete_log
  1162. >>> discrete_log(41, 15, 7)
  1163. 3
  1164. References
  1165. ==========
  1166. .. [1] https://mathworld.wolfram.com/DiscreteLogarithm.html
  1167. .. [2] "Handbook of applied cryptography", Menezes, A. J., Van, O. P. C., &
  1168. Vanstone, S. A. (1997).
  1169. """
  1170. n, a, b = as_int(n), as_int(a), as_int(b)
  1171. if order is None:
  1172. order = n_order(b, n)
  1173. if prime_order is None:
  1174. prime_order = isprime(order)
  1175. if order < 1000:
  1176. return _discrete_log_trial_mul(n, a, b, order)
  1177. elif prime_order:
  1178. if order < 1000000000000:
  1179. return _discrete_log_shanks_steps(n, a, b, order)
  1180. return _discrete_log_pollard_rho(n, a, b, order)
  1181. return _discrete_log_pohlig_hellman(n, a, b, order)
  1182. def quadratic_congruence(a, b, c, p):
  1183. """
  1184. Find the solutions to ``a x**2 + b x + c = 0 mod p.
  1185. Parameters
  1186. ==========
  1187. a : int
  1188. b : int
  1189. c : int
  1190. p : int
  1191. A positive integer.
  1192. """
  1193. a = as_int(a)
  1194. b = as_int(b)
  1195. c = as_int(c)
  1196. p = as_int(p)
  1197. a = a % p
  1198. b = b % p
  1199. c = c % p
  1200. if a == 0:
  1201. return linear_congruence(b, -c, p)
  1202. if p == 2:
  1203. roots = []
  1204. if c % 2 == 0:
  1205. roots.append(0)
  1206. if (a + b + c) % 2 == 0:
  1207. roots.append(1)
  1208. return roots
  1209. if isprime(p):
  1210. inv_a = mod_inverse(a, p)
  1211. b *= inv_a
  1212. c *= inv_a
  1213. if b % 2 == 1:
  1214. b = b + p
  1215. d = ((b * b) // 4 - c) % p
  1216. y = sqrt_mod(d, p, all_roots=True)
  1217. res = set()
  1218. for i in y:
  1219. res.add((i - b // 2) % p)
  1220. return sorted(res)
  1221. y = sqrt_mod(b * b - 4 * a * c, 4 * a * p, all_roots=True)
  1222. res = set()
  1223. for i in y:
  1224. root = linear_congruence(2 * a, i - b, 4 * a * p)
  1225. for j in root:
  1226. res.add(j % p)
  1227. return sorted(res)
  1228. def _polynomial_congruence_prime(coefficients, p):
  1229. """A helper function used by polynomial_congruence.
  1230. It returns the root of a polynomial modulo prime number
  1231. by naive search from [0, p).
  1232. Parameters
  1233. ==========
  1234. coefficients : list of integers
  1235. p : prime number
  1236. """
  1237. roots = []
  1238. rank = len(coefficients)
  1239. for i in range(0, p):
  1240. f_val = 0
  1241. for coeff in range(0,rank - 1):
  1242. f_val = (f_val + pow(i, int(rank - coeff - 1), p) * coefficients[coeff]) % p
  1243. f_val = f_val + coefficients[-1]
  1244. if f_val % p == 0:
  1245. roots.append(i)
  1246. return roots
  1247. def _diff_poly(root, coefficients, p):
  1248. """A helper function used by polynomial_congruence.
  1249. It returns the derivative of the polynomial evaluated at the
  1250. root (mod p).
  1251. Parameters
  1252. ==========
  1253. coefficients : list of integers
  1254. p : prime number
  1255. root : integer
  1256. """
  1257. diff = 0
  1258. rank = len(coefficients)
  1259. for coeff in range(0, rank - 1):
  1260. if not coefficients[coeff]:
  1261. continue
  1262. diff = (diff + pow(root, rank - coeff - 2, p)*(rank - coeff - 1)*
  1263. coefficients[coeff]) % p
  1264. return diff % p
  1265. def _val_poly(root, coefficients, p):
  1266. """A helper function used by polynomial_congruence.
  1267. It returns value of the polynomial at root (mod p).
  1268. Parameters
  1269. ==========
  1270. coefficients : list of integers
  1271. p : prime number
  1272. root : integer
  1273. """
  1274. rank = len(coefficients)
  1275. f_val = 0
  1276. for coeff in range(0, rank - 1):
  1277. f_val = (f_val + pow(root, rank - coeff - 1, p)*
  1278. coefficients[coeff]) % p
  1279. f_val = f_val + coefficients[-1]
  1280. return f_val % p
  1281. def _valid_expr(expr):
  1282. """
  1283. return coefficients of expr if it is a univariate polynomial
  1284. with integer coefficients else raise a ValueError.
  1285. """
  1286. if not expr.is_polynomial():
  1287. raise ValueError("The expression should be a polynomial")
  1288. polynomial = Poly(expr)
  1289. if not polynomial.is_univariate:
  1290. raise ValueError("The expression should be univariate")
  1291. if not polynomial.domain == ZZ:
  1292. raise ValueError("The expression should should have integer coefficients")
  1293. return polynomial.all_coeffs()
  1294. def polynomial_congruence(expr, m):
  1295. """
  1296. Find the solutions to a polynomial congruence equation modulo m.
  1297. Parameters
  1298. ==========
  1299. coefficients : Coefficients of the Polynomial
  1300. m : positive integer
  1301. Examples
  1302. ========
  1303. >>> from sympy.ntheory import polynomial_congruence
  1304. >>> from sympy.abc import x
  1305. >>> expr = x**6 - 2*x**5 -35
  1306. >>> polynomial_congruence(expr, 6125)
  1307. [3257]
  1308. """
  1309. coefficients = _valid_expr(expr)
  1310. coefficients = [num % m for num in coefficients]
  1311. rank = len(coefficients)
  1312. if rank == 3:
  1313. return quadratic_congruence(*coefficients, m)
  1314. if rank == 2:
  1315. return quadratic_congruence(0, *coefficients, m)
  1316. if coefficients[0] == 1 and 1 + coefficients[-1] == sum(coefficients):
  1317. return nthroot_mod(-coefficients[-1], rank - 1, m, True)
  1318. if isprime(m):
  1319. return _polynomial_congruence_prime(coefficients, m)
  1320. return _help(m,
  1321. lambda p: _polynomial_congruence_prime(coefficients, p),
  1322. lambda root, p: _diff_poly(root, coefficients, p),
  1323. lambda root, p: _val_poly(root, coefficients, p))