factortools.py 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490
  1. """Polynomial factorization routines in characteristic zero. """
  2. from sympy.polys.galoistools import (
  3. gf_from_int_poly, gf_to_int_poly,
  4. gf_lshift, gf_add_mul, gf_mul,
  5. gf_div, gf_rem,
  6. gf_gcdex,
  7. gf_sqf_p,
  8. gf_factor_sqf, gf_factor)
  9. from sympy.polys.densebasic import (
  10. dup_LC, dmp_LC, dmp_ground_LC,
  11. dup_TC,
  12. dup_convert, dmp_convert,
  13. dup_degree, dmp_degree,
  14. dmp_degree_in, dmp_degree_list,
  15. dmp_from_dict,
  16. dmp_zero_p,
  17. dmp_one,
  18. dmp_nest, dmp_raise,
  19. dup_strip,
  20. dmp_ground,
  21. dup_inflate,
  22. dmp_exclude, dmp_include,
  23. dmp_inject, dmp_eject,
  24. dup_terms_gcd, dmp_terms_gcd)
  25. from sympy.polys.densearith import (
  26. dup_neg, dmp_neg,
  27. dup_add, dmp_add,
  28. dup_sub, dmp_sub,
  29. dup_mul, dmp_mul,
  30. dup_sqr,
  31. dmp_pow,
  32. dup_div, dmp_div,
  33. dup_quo, dmp_quo,
  34. dmp_expand,
  35. dmp_add_mul,
  36. dup_sub_mul, dmp_sub_mul,
  37. dup_lshift,
  38. dup_max_norm, dmp_max_norm,
  39. dup_l1_norm,
  40. dup_mul_ground, dmp_mul_ground,
  41. dup_quo_ground, dmp_quo_ground)
  42. from sympy.polys.densetools import (
  43. dup_clear_denoms, dmp_clear_denoms,
  44. dup_trunc, dmp_ground_trunc,
  45. dup_content,
  46. dup_monic, dmp_ground_monic,
  47. dup_primitive, dmp_ground_primitive,
  48. dmp_eval_tail,
  49. dmp_eval_in, dmp_diff_eval_in,
  50. dmp_compose,
  51. dup_shift, dup_mirror)
  52. from sympy.polys.euclidtools import (
  53. dmp_primitive,
  54. dup_inner_gcd, dmp_inner_gcd)
  55. from sympy.polys.sqfreetools import (
  56. dup_sqf_p,
  57. dup_sqf_norm, dmp_sqf_norm,
  58. dup_sqf_part, dmp_sqf_part)
  59. from sympy.polys.polyutils import _sort_factors
  60. from sympy.polys.polyconfig import query
  61. from sympy.polys.polyerrors import (
  62. ExtraneousFactors, DomainError, CoercionFailed, EvaluationFailed)
  63. from sympy.ntheory import nextprime, isprime, factorint
  64. from sympy.utilities import subsets
  65. from math import ceil as _ceil, log as _log
  66. def dup_trial_division(f, factors, K):
  67. """
  68. Determine multiplicities of factors for a univariate polynomial
  69. using trial division.
  70. """
  71. result = []
  72. for factor in factors:
  73. k = 0
  74. while True:
  75. q, r = dup_div(f, factor, K)
  76. if not r:
  77. f, k = q, k + 1
  78. else:
  79. break
  80. result.append((factor, k))
  81. return _sort_factors(result)
  82. def dmp_trial_division(f, factors, u, K):
  83. """
  84. Determine multiplicities of factors for a multivariate polynomial
  85. using trial division.
  86. """
  87. result = []
  88. for factor in factors:
  89. k = 0
  90. while True:
  91. q, r = dmp_div(f, factor, u, K)
  92. if dmp_zero_p(r, u):
  93. f, k = q, k + 1
  94. else:
  95. break
  96. result.append((factor, k))
  97. return _sort_factors(result)
  98. def dup_zz_mignotte_bound(f, K):
  99. """
  100. The Knuth-Cohen variant of Mignotte bound for
  101. univariate polynomials in `K[x]`.
  102. Examples
  103. ========
  104. >>> from sympy.polys import ring, ZZ
  105. >>> R, x = ring("x", ZZ)
  106. >>> f = x**3 + 14*x**2 + 56*x + 64
  107. >>> R.dup_zz_mignotte_bound(f)
  108. 152
  109. By checking `factor(f)` we can see that max coeff is 8
  110. Also consider a case that `f` is irreducible for example `f = 2*x**2 + 3*x + 4`
  111. To avoid a bug for these cases, we return the bound plus the max coefficient of `f`
  112. >>> f = 2*x**2 + 3*x + 4
  113. >>> R.dup_zz_mignotte_bound(f)
  114. 6
  115. Lastly,To see the difference between the new and the old Mignotte bound
  116. consider the irreducible polynomial::
  117. >>> f = 87*x**7 + 4*x**6 + 80*x**5 + 17*x**4 + 9*x**3 + 12*x**2 + 49*x + 26
  118. >>> R.dup_zz_mignotte_bound(f)
  119. 744
  120. The new Mignotte bound is 744 whereas the old one (SymPy 1.5.1) is 1937664.
  121. References
  122. ==========
  123. ..[1] [Abbott2013]_
  124. """
  125. from sympy.functions.combinatorial.factorials import binomial
  126. d = dup_degree(f)
  127. delta = _ceil(d / 2)
  128. delta2 = _ceil(delta / 2)
  129. # euclidean-norm
  130. eucl_norm = K.sqrt( sum( [cf**2 for cf in f] ) )
  131. # biggest values of binomial coefficients (p. 538 of reference)
  132. t1 = binomial(delta - 1, delta2)
  133. t2 = binomial(delta - 1, delta2 - 1)
  134. lc = K.abs(dup_LC(f, K)) # leading coefficient
  135. bound = t1 * eucl_norm + t2 * lc # (p. 538 of reference)
  136. bound += dup_max_norm(f, K) # add max coeff for irreducible polys
  137. bound = _ceil(bound / 2) * 2 # round up to even integer
  138. return bound
  139. def dmp_zz_mignotte_bound(f, u, K):
  140. """Mignotte bound for multivariate polynomials in `K[X]`. """
  141. a = dmp_max_norm(f, u, K)
  142. b = abs(dmp_ground_LC(f, u, K))
  143. n = sum(dmp_degree_list(f, u))
  144. return K.sqrt(K(n + 1))*2**n*a*b
  145. def dup_zz_hensel_step(m, f, g, h, s, t, K):
  146. """
  147. One step in Hensel lifting in `Z[x]`.
  148. Given positive integer `m` and `Z[x]` polynomials `f`, `g`, `h`, `s`
  149. and `t` such that::
  150. f = g*h (mod m)
  151. s*g + t*h = 1 (mod m)
  152. lc(f) is not a zero divisor (mod m)
  153. lc(h) = 1
  154. deg(f) = deg(g) + deg(h)
  155. deg(s) < deg(h)
  156. deg(t) < deg(g)
  157. returns polynomials `G`, `H`, `S` and `T`, such that::
  158. f = G*H (mod m**2)
  159. S*G + T*H = 1 (mod m**2)
  160. References
  161. ==========
  162. .. [1] [Gathen99]_
  163. """
  164. M = m**2
  165. e = dup_sub_mul(f, g, h, K)
  166. e = dup_trunc(e, M, K)
  167. q, r = dup_div(dup_mul(s, e, K), h, K)
  168. q = dup_trunc(q, M, K)
  169. r = dup_trunc(r, M, K)
  170. u = dup_add(dup_mul(t, e, K), dup_mul(q, g, K), K)
  171. G = dup_trunc(dup_add(g, u, K), M, K)
  172. H = dup_trunc(dup_add(h, r, K), M, K)
  173. u = dup_add(dup_mul(s, G, K), dup_mul(t, H, K), K)
  174. b = dup_trunc(dup_sub(u, [K.one], K), M, K)
  175. c, d = dup_div(dup_mul(s, b, K), H, K)
  176. c = dup_trunc(c, M, K)
  177. d = dup_trunc(d, M, K)
  178. u = dup_add(dup_mul(t, b, K), dup_mul(c, G, K), K)
  179. S = dup_trunc(dup_sub(s, d, K), M, K)
  180. T = dup_trunc(dup_sub(t, u, K), M, K)
  181. return G, H, S, T
  182. def dup_zz_hensel_lift(p, f, f_list, l, K):
  183. r"""
  184. Multifactor Hensel lifting in `Z[x]`.
  185. Given a prime `p`, polynomial `f` over `Z[x]` such that `lc(f)`
  186. is a unit modulo `p`, monic pair-wise coprime polynomials `f_i`
  187. over `Z[x]` satisfying::
  188. f = lc(f) f_1 ... f_r (mod p)
  189. and a positive integer `l`, returns a list of monic polynomials
  190. `F_1,\ F_2,\ \dots,\ F_r` satisfying::
  191. f = lc(f) F_1 ... F_r (mod p**l)
  192. F_i = f_i (mod p), i = 1..r
  193. References
  194. ==========
  195. .. [1] [Gathen99]_
  196. """
  197. r = len(f_list)
  198. lc = dup_LC(f, K)
  199. if r == 1:
  200. F = dup_mul_ground(f, K.gcdex(lc, p**l)[0], K)
  201. return [ dup_trunc(F, p**l, K) ]
  202. m = p
  203. k = r // 2
  204. d = int(_ceil(_log(l, 2)))
  205. g = gf_from_int_poly([lc], p)
  206. for f_i in f_list[:k]:
  207. g = gf_mul(g, gf_from_int_poly(f_i, p), p, K)
  208. h = gf_from_int_poly(f_list[k], p)
  209. for f_i in f_list[k + 1:]:
  210. h = gf_mul(h, gf_from_int_poly(f_i, p), p, K)
  211. s, t, _ = gf_gcdex(g, h, p, K)
  212. g = gf_to_int_poly(g, p)
  213. h = gf_to_int_poly(h, p)
  214. s = gf_to_int_poly(s, p)
  215. t = gf_to_int_poly(t, p)
  216. for _ in range(1, d + 1):
  217. (g, h, s, t), m = dup_zz_hensel_step(m, f, g, h, s, t, K), m**2
  218. return dup_zz_hensel_lift(p, g, f_list[:k], l, K) \
  219. + dup_zz_hensel_lift(p, h, f_list[k:], l, K)
  220. def _test_pl(fc, q, pl):
  221. if q > pl // 2:
  222. q = q - pl
  223. if not q:
  224. return True
  225. return fc % q == 0
  226. def dup_zz_zassenhaus(f, K):
  227. """Factor primitive square-free polynomials in `Z[x]`. """
  228. n = dup_degree(f)
  229. if n == 1:
  230. return [f]
  231. fc = f[-1]
  232. A = dup_max_norm(f, K)
  233. b = dup_LC(f, K)
  234. B = int(abs(K.sqrt(K(n + 1))*2**n*A*b))
  235. C = int((n + 1)**(2*n)*A**(2*n - 1))
  236. gamma = int(_ceil(2*_log(C, 2)))
  237. bound = int(2*gamma*_log(gamma))
  238. a = []
  239. # choose a prime number `p` such that `f` be square free in Z_p
  240. # if there are many factors in Z_p, choose among a few different `p`
  241. # the one with fewer factors
  242. for px in range(3, bound + 1):
  243. if not isprime(px) or b % px == 0:
  244. continue
  245. px = K.convert(px)
  246. F = gf_from_int_poly(f, px)
  247. if not gf_sqf_p(F, px, K):
  248. continue
  249. fsqfx = gf_factor_sqf(F, px, K)[1]
  250. a.append((px, fsqfx))
  251. if len(fsqfx) < 15 or len(a) > 4:
  252. break
  253. p, fsqf = min(a, key=lambda x: len(x[1]))
  254. l = int(_ceil(_log(2*B + 1, p)))
  255. modular = [gf_to_int_poly(ff, p) for ff in fsqf]
  256. g = dup_zz_hensel_lift(p, f, modular, l, K)
  257. sorted_T = range(len(g))
  258. T = set(sorted_T)
  259. factors, s = [], 1
  260. pl = p**l
  261. while 2*s <= len(T):
  262. for S in subsets(sorted_T, s):
  263. # lift the constant coefficient of the product `G` of the factors
  264. # in the subset `S`; if it is does not divide `fc`, `G` does
  265. # not divide the input polynomial
  266. if b == 1:
  267. q = 1
  268. for i in S:
  269. q = q*g[i][-1]
  270. q = q % pl
  271. if not _test_pl(fc, q, pl):
  272. continue
  273. else:
  274. G = [b]
  275. for i in S:
  276. G = dup_mul(G, g[i], K)
  277. G = dup_trunc(G, pl, K)
  278. G = dup_primitive(G, K)[1]
  279. q = G[-1]
  280. if q and fc % q != 0:
  281. continue
  282. H = [b]
  283. S = set(S)
  284. T_S = T - S
  285. if b == 1:
  286. G = [b]
  287. for i in S:
  288. G = dup_mul(G, g[i], K)
  289. G = dup_trunc(G, pl, K)
  290. for i in T_S:
  291. H = dup_mul(H, g[i], K)
  292. H = dup_trunc(H, pl, K)
  293. G_norm = dup_l1_norm(G, K)
  294. H_norm = dup_l1_norm(H, K)
  295. if G_norm*H_norm <= B:
  296. T = T_S
  297. sorted_T = [i for i in sorted_T if i not in S]
  298. G = dup_primitive(G, K)[1]
  299. f = dup_primitive(H, K)[1]
  300. factors.append(G)
  301. b = dup_LC(f, K)
  302. break
  303. else:
  304. s += 1
  305. return factors + [f]
  306. def dup_zz_irreducible_p(f, K):
  307. """Test irreducibility using Eisenstein's criterion. """
  308. lc = dup_LC(f, K)
  309. tc = dup_TC(f, K)
  310. e_fc = dup_content(f[1:], K)
  311. if e_fc:
  312. e_ff = factorint(int(e_fc))
  313. for p in e_ff.keys():
  314. if (lc % p) and (tc % p**2):
  315. return True
  316. def dup_cyclotomic_p(f, K, irreducible=False):
  317. """
  318. Efficiently test if ``f`` is a cyclotomic polynomial.
  319. Examples
  320. ========
  321. >>> from sympy.polys import ring, ZZ
  322. >>> R, x = ring("x", ZZ)
  323. >>> f = x**16 + x**14 - x**10 + x**8 - x**6 + x**2 + 1
  324. >>> R.dup_cyclotomic_p(f)
  325. False
  326. >>> g = x**16 + x**14 - x**10 - x**8 - x**6 + x**2 + 1
  327. >>> R.dup_cyclotomic_p(g)
  328. True
  329. """
  330. if K.is_QQ:
  331. try:
  332. K0, K = K, K.get_ring()
  333. f = dup_convert(f, K0, K)
  334. except CoercionFailed:
  335. return False
  336. elif not K.is_ZZ:
  337. return False
  338. lc = dup_LC(f, K)
  339. tc = dup_TC(f, K)
  340. if lc != 1 or (tc != -1 and tc != 1):
  341. return False
  342. if not irreducible:
  343. coeff, factors = dup_factor_list(f, K)
  344. if coeff != K.one or factors != [(f, 1)]:
  345. return False
  346. n = dup_degree(f)
  347. g, h = [], []
  348. for i in range(n, -1, -2):
  349. g.insert(0, f[i])
  350. for i in range(n - 1, -1, -2):
  351. h.insert(0, f[i])
  352. g = dup_sqr(dup_strip(g), K)
  353. h = dup_sqr(dup_strip(h), K)
  354. F = dup_sub(g, dup_lshift(h, 1, K), K)
  355. if K.is_negative(dup_LC(F, K)):
  356. F = dup_neg(F, K)
  357. if F == f:
  358. return True
  359. g = dup_mirror(f, K)
  360. if K.is_negative(dup_LC(g, K)):
  361. g = dup_neg(g, K)
  362. if F == g and dup_cyclotomic_p(g, K):
  363. return True
  364. G = dup_sqf_part(F, K)
  365. if dup_sqr(G, K) == F and dup_cyclotomic_p(G, K):
  366. return True
  367. return False
  368. def dup_zz_cyclotomic_poly(n, K):
  369. """Efficiently generate n-th cyclotomic polynomial. """
  370. h = [K.one, -K.one]
  371. for p, k in factorint(n).items():
  372. h = dup_quo(dup_inflate(h, p, K), h, K)
  373. h = dup_inflate(h, p**(k - 1), K)
  374. return h
  375. def _dup_cyclotomic_decompose(n, K):
  376. H = [[K.one, -K.one]]
  377. for p, k in factorint(n).items():
  378. Q = [ dup_quo(dup_inflate(h, p, K), h, K) for h in H ]
  379. H.extend(Q)
  380. for i in range(1, k):
  381. Q = [ dup_inflate(q, p, K) for q in Q ]
  382. H.extend(Q)
  383. return H
  384. def dup_zz_cyclotomic_factor(f, K):
  385. """
  386. Efficiently factor polynomials `x**n - 1` and `x**n + 1` in `Z[x]`.
  387. Given a univariate polynomial `f` in `Z[x]` returns a list of factors
  388. of `f`, provided that `f` is in the form `x**n - 1` or `x**n + 1` for
  389. `n >= 1`. Otherwise returns None.
  390. Factorization is performed using cyclotomic decomposition of `f`,
  391. which makes this method much faster that any other direct factorization
  392. approach (e.g. Zassenhaus's).
  393. References
  394. ==========
  395. .. [1] [Weisstein09]_
  396. """
  397. lc_f, tc_f = dup_LC(f, K), dup_TC(f, K)
  398. if dup_degree(f) <= 0:
  399. return None
  400. if lc_f != 1 or tc_f not in [-1, 1]:
  401. return None
  402. if any(bool(cf) for cf in f[1:-1]):
  403. return None
  404. n = dup_degree(f)
  405. F = _dup_cyclotomic_decompose(n, K)
  406. if not K.is_one(tc_f):
  407. return F
  408. else:
  409. H = []
  410. for h in _dup_cyclotomic_decompose(2*n, K):
  411. if h not in F:
  412. H.append(h)
  413. return H
  414. def dup_zz_factor_sqf(f, K):
  415. """Factor square-free (non-primitive) polynomials in `Z[x]`. """
  416. cont, g = dup_primitive(f, K)
  417. n = dup_degree(g)
  418. if dup_LC(g, K) < 0:
  419. cont, g = -cont, dup_neg(g, K)
  420. if n <= 0:
  421. return cont, []
  422. elif n == 1:
  423. return cont, [g]
  424. if query('USE_IRREDUCIBLE_IN_FACTOR'):
  425. if dup_zz_irreducible_p(g, K):
  426. return cont, [g]
  427. factors = None
  428. if query('USE_CYCLOTOMIC_FACTOR'):
  429. factors = dup_zz_cyclotomic_factor(g, K)
  430. if factors is None:
  431. factors = dup_zz_zassenhaus(g, K)
  432. return cont, _sort_factors(factors, multiple=False)
  433. def dup_zz_factor(f, K):
  434. """
  435. Factor (non square-free) polynomials in `Z[x]`.
  436. Given a univariate polynomial `f` in `Z[x]` computes its complete
  437. factorization `f_1, ..., f_n` into irreducibles over integers::
  438. f = content(f) f_1**k_1 ... f_n**k_n
  439. The factorization is computed by reducing the input polynomial
  440. into a primitive square-free polynomial and factoring it using
  441. Zassenhaus algorithm. Trial division is used to recover the
  442. multiplicities of factors.
  443. The result is returned as a tuple consisting of::
  444. (content(f), [(f_1, k_1), ..., (f_n, k_n))
  445. Examples
  446. ========
  447. Consider the polynomial `f = 2*x**4 - 2`::
  448. >>> from sympy.polys import ring, ZZ
  449. >>> R, x = ring("x", ZZ)
  450. >>> R.dup_zz_factor(2*x**4 - 2)
  451. (2, [(x - 1, 1), (x + 1, 1), (x**2 + 1, 1)])
  452. In result we got the following factorization::
  453. f = 2 (x - 1) (x + 1) (x**2 + 1)
  454. Note that this is a complete factorization over integers,
  455. however over Gaussian integers we can factor the last term.
  456. By default, polynomials `x**n - 1` and `x**n + 1` are factored
  457. using cyclotomic decomposition to speedup computations. To
  458. disable this behaviour set cyclotomic=False.
  459. References
  460. ==========
  461. .. [1] [Gathen99]_
  462. """
  463. cont, g = dup_primitive(f, K)
  464. n = dup_degree(g)
  465. if dup_LC(g, K) < 0:
  466. cont, g = -cont, dup_neg(g, K)
  467. if n <= 0:
  468. return cont, []
  469. elif n == 1:
  470. return cont, [(g, 1)]
  471. if query('USE_IRREDUCIBLE_IN_FACTOR'):
  472. if dup_zz_irreducible_p(g, K):
  473. return cont, [(g, 1)]
  474. g = dup_sqf_part(g, K)
  475. H = None
  476. if query('USE_CYCLOTOMIC_FACTOR'):
  477. H = dup_zz_cyclotomic_factor(g, K)
  478. if H is None:
  479. H = dup_zz_zassenhaus(g, K)
  480. factors = dup_trial_division(f, H, K)
  481. return cont, factors
  482. def dmp_zz_wang_non_divisors(E, cs, ct, K):
  483. """Wang/EEZ: Compute a set of valid divisors. """
  484. result = [ cs*ct ]
  485. for q in E:
  486. q = abs(q)
  487. for r in reversed(result):
  488. while r != 1:
  489. r = K.gcd(r, q)
  490. q = q // r
  491. if K.is_one(q):
  492. return None
  493. result.append(q)
  494. return result[1:]
  495. def dmp_zz_wang_test_points(f, T, ct, A, u, K):
  496. """Wang/EEZ: Test evaluation points for suitability. """
  497. if not dmp_eval_tail(dmp_LC(f, K), A, u - 1, K):
  498. raise EvaluationFailed('no luck')
  499. g = dmp_eval_tail(f, A, u, K)
  500. if not dup_sqf_p(g, K):
  501. raise EvaluationFailed('no luck')
  502. c, h = dup_primitive(g, K)
  503. if K.is_negative(dup_LC(h, K)):
  504. c, h = -c, dup_neg(h, K)
  505. v = u - 1
  506. E = [ dmp_eval_tail(t, A, v, K) for t, _ in T ]
  507. D = dmp_zz_wang_non_divisors(E, c, ct, K)
  508. if D is not None:
  509. return c, h, E
  510. else:
  511. raise EvaluationFailed('no luck')
  512. def dmp_zz_wang_lead_coeffs(f, T, cs, E, H, A, u, K):
  513. """Wang/EEZ: Compute correct leading coefficients. """
  514. C, J, v = [], [0]*len(E), u - 1
  515. for h in H:
  516. c = dmp_one(v, K)
  517. d = dup_LC(h, K)*cs
  518. for i in reversed(range(len(E))):
  519. k, e, (t, _) = 0, E[i], T[i]
  520. while not (d % e):
  521. d, k = d//e, k + 1
  522. if k != 0:
  523. c, J[i] = dmp_mul(c, dmp_pow(t, k, v, K), v, K), 1
  524. C.append(c)
  525. if not all(J):
  526. raise ExtraneousFactors # pragma: no cover
  527. CC, HH = [], []
  528. for c, h in zip(C, H):
  529. d = dmp_eval_tail(c, A, v, K)
  530. lc = dup_LC(h, K)
  531. if K.is_one(cs):
  532. cc = lc//d
  533. else:
  534. g = K.gcd(lc, d)
  535. d, cc = d//g, lc//g
  536. h, cs = dup_mul_ground(h, d, K), cs//d
  537. c = dmp_mul_ground(c, cc, v, K)
  538. CC.append(c)
  539. HH.append(h)
  540. if K.is_one(cs):
  541. return f, HH, CC
  542. CCC, HHH = [], []
  543. for c, h in zip(CC, HH):
  544. CCC.append(dmp_mul_ground(c, cs, v, K))
  545. HHH.append(dmp_mul_ground(h, cs, 0, K))
  546. f = dmp_mul_ground(f, cs**(len(H) - 1), u, K)
  547. return f, HHH, CCC
  548. def dup_zz_diophantine(F, m, p, K):
  549. """Wang/EEZ: Solve univariate Diophantine equations. """
  550. if len(F) == 2:
  551. a, b = F
  552. f = gf_from_int_poly(a, p)
  553. g = gf_from_int_poly(b, p)
  554. s, t, G = gf_gcdex(g, f, p, K)
  555. s = gf_lshift(s, m, K)
  556. t = gf_lshift(t, m, K)
  557. q, s = gf_div(s, f, p, K)
  558. t = gf_add_mul(t, q, g, p, K)
  559. s = gf_to_int_poly(s, p)
  560. t = gf_to_int_poly(t, p)
  561. result = [s, t]
  562. else:
  563. G = [F[-1]]
  564. for f in reversed(F[1:-1]):
  565. G.insert(0, dup_mul(f, G[0], K))
  566. S, T = [], [[1]]
  567. for f, g in zip(F, G):
  568. t, s = dmp_zz_diophantine([g, f], T[-1], [], 0, p, 1, K)
  569. T.append(t)
  570. S.append(s)
  571. result, S = [], S + [T[-1]]
  572. for s, f in zip(S, F):
  573. s = gf_from_int_poly(s, p)
  574. f = gf_from_int_poly(f, p)
  575. r = gf_rem(gf_lshift(s, m, K), f, p, K)
  576. s = gf_to_int_poly(r, p)
  577. result.append(s)
  578. return result
  579. def dmp_zz_diophantine(F, c, A, d, p, u, K):
  580. """Wang/EEZ: Solve multivariate Diophantine equations. """
  581. if not A:
  582. S = [ [] for _ in F ]
  583. n = dup_degree(c)
  584. for i, coeff in enumerate(c):
  585. if not coeff:
  586. continue
  587. T = dup_zz_diophantine(F, n - i, p, K)
  588. for j, (s, t) in enumerate(zip(S, T)):
  589. t = dup_mul_ground(t, coeff, K)
  590. S[j] = dup_trunc(dup_add(s, t, K), p, K)
  591. else:
  592. n = len(A)
  593. e = dmp_expand(F, u, K)
  594. a, A = A[-1], A[:-1]
  595. B, G = [], []
  596. for f in F:
  597. B.append(dmp_quo(e, f, u, K))
  598. G.append(dmp_eval_in(f, a, n, u, K))
  599. C = dmp_eval_in(c, a, n, u, K)
  600. v = u - 1
  601. S = dmp_zz_diophantine(G, C, A, d, p, v, K)
  602. S = [ dmp_raise(s, 1, v, K) for s in S ]
  603. for s, b in zip(S, B):
  604. c = dmp_sub_mul(c, s, b, u, K)
  605. c = dmp_ground_trunc(c, p, u, K)
  606. m = dmp_nest([K.one, -a], n, K)
  607. M = dmp_one(n, K)
  608. for k in K.map(range(0, d)):
  609. if dmp_zero_p(c, u):
  610. break
  611. M = dmp_mul(M, m, u, K)
  612. C = dmp_diff_eval_in(c, k + 1, a, n, u, K)
  613. if not dmp_zero_p(C, v):
  614. C = dmp_quo_ground(C, K.factorial(k + 1), v, K)
  615. T = dmp_zz_diophantine(G, C, A, d, p, v, K)
  616. for i, t in enumerate(T):
  617. T[i] = dmp_mul(dmp_raise(t, 1, v, K), M, u, K)
  618. for i, (s, t) in enumerate(zip(S, T)):
  619. S[i] = dmp_add(s, t, u, K)
  620. for t, b in zip(T, B):
  621. c = dmp_sub_mul(c, t, b, u, K)
  622. c = dmp_ground_trunc(c, p, u, K)
  623. S = [ dmp_ground_trunc(s, p, u, K) for s in S ]
  624. return S
  625. def dmp_zz_wang_hensel_lifting(f, H, LC, A, p, u, K):
  626. """Wang/EEZ: Parallel Hensel lifting algorithm. """
  627. S, n, v = [f], len(A), u - 1
  628. H = list(H)
  629. for i, a in enumerate(reversed(A[1:])):
  630. s = dmp_eval_in(S[0], a, n - i, u - i, K)
  631. S.insert(0, dmp_ground_trunc(s, p, v - i, K))
  632. d = max(dmp_degree_list(f, u)[1:])
  633. for j, s, a in zip(range(2, n + 2), S, A):
  634. G, w = list(H), j - 1
  635. I, J = A[:j - 2], A[j - 1:]
  636. for i, (h, lc) in enumerate(zip(H, LC)):
  637. lc = dmp_ground_trunc(dmp_eval_tail(lc, J, v, K), p, w - 1, K)
  638. H[i] = [lc] + dmp_raise(h[1:], 1, w - 1, K)
  639. m = dmp_nest([K.one, -a], w, K)
  640. M = dmp_one(w, K)
  641. c = dmp_sub(s, dmp_expand(H, w, K), w, K)
  642. dj = dmp_degree_in(s, w, w)
  643. for k in K.map(range(0, dj)):
  644. if dmp_zero_p(c, w):
  645. break
  646. M = dmp_mul(M, m, w, K)
  647. C = dmp_diff_eval_in(c, k + 1, a, w, w, K)
  648. if not dmp_zero_p(C, w - 1):
  649. C = dmp_quo_ground(C, K.factorial(k + 1), w - 1, K)
  650. T = dmp_zz_diophantine(G, C, I, d, p, w - 1, K)
  651. for i, (h, t) in enumerate(zip(H, T)):
  652. h = dmp_add_mul(h, dmp_raise(t, 1, w - 1, K), M, w, K)
  653. H[i] = dmp_ground_trunc(h, p, w, K)
  654. h = dmp_sub(s, dmp_expand(H, w, K), w, K)
  655. c = dmp_ground_trunc(h, p, w, K)
  656. if dmp_expand(H, u, K) != f:
  657. raise ExtraneousFactors # pragma: no cover
  658. else:
  659. return H
  660. def dmp_zz_wang(f, u, K, mod=None, seed=None):
  661. r"""
  662. Factor primitive square-free polynomials in `Z[X]`.
  663. Given a multivariate polynomial `f` in `Z[x_1,...,x_n]`, which is
  664. primitive and square-free in `x_1`, computes factorization of `f` into
  665. irreducibles over integers.
  666. The procedure is based on Wang's Enhanced Extended Zassenhaus
  667. algorithm. The algorithm works by viewing `f` as a univariate polynomial
  668. in `Z[x_2,...,x_n][x_1]`, for which an evaluation mapping is computed::
  669. x_2 -> a_2, ..., x_n -> a_n
  670. where `a_i`, for `i = 2, \dots, n`, are carefully chosen integers. The
  671. mapping is used to transform `f` into a univariate polynomial in `Z[x_1]`,
  672. which can be factored efficiently using Zassenhaus algorithm. The last
  673. step is to lift univariate factors to obtain true multivariate
  674. factors. For this purpose a parallel Hensel lifting procedure is used.
  675. The parameter ``seed`` is passed to _randint and can be used to seed randint
  676. (when an integer) or (for testing purposes) can be a sequence of numbers.
  677. References
  678. ==========
  679. .. [1] [Wang78]_
  680. .. [2] [Geddes92]_
  681. """
  682. from sympy.core.random import _randint
  683. randint = _randint(seed)
  684. ct, T = dmp_zz_factor(dmp_LC(f, K), u - 1, K)
  685. b = dmp_zz_mignotte_bound(f, u, K)
  686. p = K(nextprime(b))
  687. if mod is None:
  688. if u == 1:
  689. mod = 2
  690. else:
  691. mod = 1
  692. history, configs, A, r = set(), [], [K.zero]*u, None
  693. try:
  694. cs, s, E = dmp_zz_wang_test_points(f, T, ct, A, u, K)
  695. _, H = dup_zz_factor_sqf(s, K)
  696. r = len(H)
  697. if r == 1:
  698. return [f]
  699. configs = [(s, cs, E, H, A)]
  700. except EvaluationFailed:
  701. pass
  702. eez_num_configs = query('EEZ_NUMBER_OF_CONFIGS')
  703. eez_num_tries = query('EEZ_NUMBER_OF_TRIES')
  704. eez_mod_step = query('EEZ_MODULUS_STEP')
  705. while len(configs) < eez_num_configs:
  706. for _ in range(eez_num_tries):
  707. A = [ K(randint(-mod, mod)) for _ in range(u) ]
  708. if tuple(A) not in history:
  709. history.add(tuple(A))
  710. else:
  711. continue
  712. try:
  713. cs, s, E = dmp_zz_wang_test_points(f, T, ct, A, u, K)
  714. except EvaluationFailed:
  715. continue
  716. _, H = dup_zz_factor_sqf(s, K)
  717. rr = len(H)
  718. if r is not None:
  719. if rr != r: # pragma: no cover
  720. if rr < r:
  721. configs, r = [], rr
  722. else:
  723. continue
  724. else:
  725. r = rr
  726. if r == 1:
  727. return [f]
  728. configs.append((s, cs, E, H, A))
  729. if len(configs) == eez_num_configs:
  730. break
  731. else:
  732. mod += eez_mod_step
  733. s_norm, s_arg, i = None, 0, 0
  734. for s, _, _, _, _ in configs:
  735. _s_norm = dup_max_norm(s, K)
  736. if s_norm is not None:
  737. if _s_norm < s_norm:
  738. s_norm = _s_norm
  739. s_arg = i
  740. else:
  741. s_norm = _s_norm
  742. i += 1
  743. _, cs, E, H, A = configs[s_arg]
  744. orig_f = f
  745. try:
  746. f, H, LC = dmp_zz_wang_lead_coeffs(f, T, cs, E, H, A, u, K)
  747. factors = dmp_zz_wang_hensel_lifting(f, H, LC, A, p, u, K)
  748. except ExtraneousFactors: # pragma: no cover
  749. if query('EEZ_RESTART_IF_NEEDED'):
  750. return dmp_zz_wang(orig_f, u, K, mod + 1)
  751. else:
  752. raise ExtraneousFactors(
  753. "we need to restart algorithm with better parameters")
  754. result = []
  755. for f in factors:
  756. _, f = dmp_ground_primitive(f, u, K)
  757. if K.is_negative(dmp_ground_LC(f, u, K)):
  758. f = dmp_neg(f, u, K)
  759. result.append(f)
  760. return result
  761. def dmp_zz_factor(f, u, K):
  762. r"""
  763. Factor (non square-free) polynomials in `Z[X]`.
  764. Given a multivariate polynomial `f` in `Z[x]` computes its complete
  765. factorization `f_1, \dots, f_n` into irreducibles over integers::
  766. f = content(f) f_1**k_1 ... f_n**k_n
  767. The factorization is computed by reducing the input polynomial
  768. into a primitive square-free polynomial and factoring it using
  769. Enhanced Extended Zassenhaus (EEZ) algorithm. Trial division
  770. is used to recover the multiplicities of factors.
  771. The result is returned as a tuple consisting of::
  772. (content(f), [(f_1, k_1), ..., (f_n, k_n))
  773. Consider polynomial `f = 2*(x**2 - y**2)`::
  774. >>> from sympy.polys import ring, ZZ
  775. >>> R, x,y = ring("x,y", ZZ)
  776. >>> R.dmp_zz_factor(2*x**2 - 2*y**2)
  777. (2, [(x - y, 1), (x + y, 1)])
  778. In result we got the following factorization::
  779. f = 2 (x - y) (x + y)
  780. References
  781. ==========
  782. .. [1] [Gathen99]_
  783. """
  784. if not u:
  785. return dup_zz_factor(f, K)
  786. if dmp_zero_p(f, u):
  787. return K.zero, []
  788. cont, g = dmp_ground_primitive(f, u, K)
  789. if dmp_ground_LC(g, u, K) < 0:
  790. cont, g = -cont, dmp_neg(g, u, K)
  791. if all(d <= 0 for d in dmp_degree_list(g, u)):
  792. return cont, []
  793. G, g = dmp_primitive(g, u, K)
  794. factors = []
  795. if dmp_degree(g, u) > 0:
  796. g = dmp_sqf_part(g, u, K)
  797. H = dmp_zz_wang(g, u, K)
  798. factors = dmp_trial_division(f, H, u, K)
  799. for g, k in dmp_zz_factor(G, u - 1, K)[1]:
  800. factors.insert(0, ([g], k))
  801. return cont, _sort_factors(factors)
  802. def dup_qq_i_factor(f, K0):
  803. """Factor univariate polynomials into irreducibles in `QQ_I[x]`. """
  804. # Factor in QQ<I>
  805. K1 = K0.as_AlgebraicField()
  806. f = dup_convert(f, K0, K1)
  807. coeff, factors = dup_factor_list(f, K1)
  808. factors = [(dup_convert(fac, K1, K0), i) for fac, i in factors]
  809. coeff = K0.convert(coeff, K1)
  810. return coeff, factors
  811. def dup_zz_i_factor(f, K0):
  812. """Factor univariate polynomials into irreducibles in `ZZ_I[x]`. """
  813. # First factor in QQ_I
  814. K1 = K0.get_field()
  815. f = dup_convert(f, K0, K1)
  816. coeff, factors = dup_qq_i_factor(f, K1)
  817. new_factors = []
  818. for fac, i in factors:
  819. # Extract content
  820. fac_denom, fac_num = dup_clear_denoms(fac, K1)
  821. fac_num_ZZ_I = dup_convert(fac_num, K1, K0)
  822. content, fac_prim = dmp_ground_primitive(fac_num_ZZ_I, 0, K1)
  823. coeff = (coeff * content ** i) // fac_denom ** i
  824. new_factors.append((fac_prim, i))
  825. factors = new_factors
  826. coeff = K0.convert(coeff, K1)
  827. return coeff, factors
  828. def dmp_qq_i_factor(f, u, K0):
  829. """Factor multivariate polynomials into irreducibles in `QQ_I[X]`. """
  830. # Factor in QQ<I>
  831. K1 = K0.as_AlgebraicField()
  832. f = dmp_convert(f, u, K0, K1)
  833. coeff, factors = dmp_factor_list(f, u, K1)
  834. factors = [(dmp_convert(fac, u, K1, K0), i) for fac, i in factors]
  835. coeff = K0.convert(coeff, K1)
  836. return coeff, factors
  837. def dmp_zz_i_factor(f, u, K0):
  838. """Factor multivariate polynomials into irreducibles in `ZZ_I[X]`. """
  839. # First factor in QQ_I
  840. K1 = K0.get_field()
  841. f = dmp_convert(f, u, K0, K1)
  842. coeff, factors = dmp_qq_i_factor(f, u, K1)
  843. new_factors = []
  844. for fac, i in factors:
  845. # Extract content
  846. fac_denom, fac_num = dmp_clear_denoms(fac, u, K1)
  847. fac_num_ZZ_I = dmp_convert(fac_num, u, K1, K0)
  848. content, fac_prim = dmp_ground_primitive(fac_num_ZZ_I, u, K1)
  849. coeff = (coeff * content ** i) // fac_denom ** i
  850. new_factors.append((fac_prim, i))
  851. factors = new_factors
  852. coeff = K0.convert(coeff, K1)
  853. return coeff, factors
  854. def dup_ext_factor(f, K):
  855. """Factor univariate polynomials over algebraic number fields. """
  856. n, lc = dup_degree(f), dup_LC(f, K)
  857. f = dup_monic(f, K)
  858. if n <= 0:
  859. return lc, []
  860. if n == 1:
  861. return lc, [(f, 1)]
  862. f, F = dup_sqf_part(f, K), f
  863. s, g, r = dup_sqf_norm(f, K)
  864. factors = dup_factor_list_include(r, K.dom)
  865. if len(factors) == 1:
  866. return lc, [(f, n//dup_degree(f))]
  867. H = s*K.unit
  868. for i, (factor, _) in enumerate(factors):
  869. h = dup_convert(factor, K.dom, K)
  870. h, _, g = dup_inner_gcd(h, g, K)
  871. h = dup_shift(h, H, K)
  872. factors[i] = h
  873. factors = dup_trial_division(F, factors, K)
  874. return lc, factors
  875. def dmp_ext_factor(f, u, K):
  876. """Factor multivariate polynomials over algebraic number fields. """
  877. if not u:
  878. return dup_ext_factor(f, K)
  879. lc = dmp_ground_LC(f, u, K)
  880. f = dmp_ground_monic(f, u, K)
  881. if all(d <= 0 for d in dmp_degree_list(f, u)):
  882. return lc, []
  883. f, F = dmp_sqf_part(f, u, K), f
  884. s, g, r = dmp_sqf_norm(f, u, K)
  885. factors = dmp_factor_list_include(r, u, K.dom)
  886. if len(factors) == 1:
  887. factors = [f]
  888. else:
  889. H = dmp_raise([K.one, s*K.unit], u, 0, K)
  890. for i, (factor, _) in enumerate(factors):
  891. h = dmp_convert(factor, u, K.dom, K)
  892. h, _, g = dmp_inner_gcd(h, g, u, K)
  893. h = dmp_compose(h, H, u, K)
  894. factors[i] = h
  895. return lc, dmp_trial_division(F, factors, u, K)
  896. def dup_gf_factor(f, K):
  897. """Factor univariate polynomials over finite fields. """
  898. f = dup_convert(f, K, K.dom)
  899. coeff, factors = gf_factor(f, K.mod, K.dom)
  900. for i, (f, k) in enumerate(factors):
  901. factors[i] = (dup_convert(f, K.dom, K), k)
  902. return K.convert(coeff, K.dom), factors
  903. def dmp_gf_factor(f, u, K):
  904. """Factor multivariate polynomials over finite fields. """
  905. raise NotImplementedError('multivariate polynomials over finite fields')
  906. def dup_factor_list(f, K0):
  907. """Factor univariate polynomials into irreducibles in `K[x]`. """
  908. j, f = dup_terms_gcd(f, K0)
  909. cont, f = dup_primitive(f, K0)
  910. if K0.is_FiniteField:
  911. coeff, factors = dup_gf_factor(f, K0)
  912. elif K0.is_Algebraic:
  913. coeff, factors = dup_ext_factor(f, K0)
  914. elif K0.is_GaussianRing:
  915. coeff, factors = dup_zz_i_factor(f, K0)
  916. elif K0.is_GaussianField:
  917. coeff, factors = dup_qq_i_factor(f, K0)
  918. else:
  919. if not K0.is_Exact:
  920. K0_inexact, K0 = K0, K0.get_exact()
  921. f = dup_convert(f, K0_inexact, K0)
  922. else:
  923. K0_inexact = None
  924. if K0.is_Field:
  925. K = K0.get_ring()
  926. denom, f = dup_clear_denoms(f, K0, K)
  927. f = dup_convert(f, K0, K)
  928. else:
  929. K = K0
  930. if K.is_ZZ:
  931. coeff, factors = dup_zz_factor(f, K)
  932. elif K.is_Poly:
  933. f, u = dmp_inject(f, 0, K)
  934. coeff, factors = dmp_factor_list(f, u, K.dom)
  935. for i, (f, k) in enumerate(factors):
  936. factors[i] = (dmp_eject(f, u, K), k)
  937. coeff = K.convert(coeff, K.dom)
  938. else: # pragma: no cover
  939. raise DomainError('factorization not supported over %s' % K0)
  940. if K0.is_Field:
  941. for i, (f, k) in enumerate(factors):
  942. factors[i] = (dup_convert(f, K, K0), k)
  943. coeff = K0.convert(coeff, K)
  944. coeff = K0.quo(coeff, denom)
  945. if K0_inexact:
  946. for i, (f, k) in enumerate(factors):
  947. max_norm = dup_max_norm(f, K0)
  948. f = dup_quo_ground(f, max_norm, K0)
  949. f = dup_convert(f, K0, K0_inexact)
  950. factors[i] = (f, k)
  951. coeff = K0.mul(coeff, K0.pow(max_norm, k))
  952. coeff = K0_inexact.convert(coeff, K0)
  953. K0 = K0_inexact
  954. if j:
  955. factors.insert(0, ([K0.one, K0.zero], j))
  956. return coeff*cont, _sort_factors(factors)
  957. def dup_factor_list_include(f, K):
  958. """Factor univariate polynomials into irreducibles in `K[x]`. """
  959. coeff, factors = dup_factor_list(f, K)
  960. if not factors:
  961. return [(dup_strip([coeff]), 1)]
  962. else:
  963. g = dup_mul_ground(factors[0][0], coeff, K)
  964. return [(g, factors[0][1])] + factors[1:]
  965. def dmp_factor_list(f, u, K0):
  966. """Factor multivariate polynomials into irreducibles in `K[X]`. """
  967. if not u:
  968. return dup_factor_list(f, K0)
  969. J, f = dmp_terms_gcd(f, u, K0)
  970. cont, f = dmp_ground_primitive(f, u, K0)
  971. if K0.is_FiniteField: # pragma: no cover
  972. coeff, factors = dmp_gf_factor(f, u, K0)
  973. elif K0.is_Algebraic:
  974. coeff, factors = dmp_ext_factor(f, u, K0)
  975. elif K0.is_GaussianRing:
  976. coeff, factors = dmp_zz_i_factor(f, u, K0)
  977. elif K0.is_GaussianField:
  978. coeff, factors = dmp_qq_i_factor(f, u, K0)
  979. else:
  980. if not K0.is_Exact:
  981. K0_inexact, K0 = K0, K0.get_exact()
  982. f = dmp_convert(f, u, K0_inexact, K0)
  983. else:
  984. K0_inexact = None
  985. if K0.is_Field:
  986. K = K0.get_ring()
  987. denom, f = dmp_clear_denoms(f, u, K0, K)
  988. f = dmp_convert(f, u, K0, K)
  989. else:
  990. K = K0
  991. if K.is_ZZ:
  992. levels, f, v = dmp_exclude(f, u, K)
  993. coeff, factors = dmp_zz_factor(f, v, K)
  994. for i, (f, k) in enumerate(factors):
  995. factors[i] = (dmp_include(f, levels, v, K), k)
  996. elif K.is_Poly:
  997. f, v = dmp_inject(f, u, K)
  998. coeff, factors = dmp_factor_list(f, v, K.dom)
  999. for i, (f, k) in enumerate(factors):
  1000. factors[i] = (dmp_eject(f, v, K), k)
  1001. coeff = K.convert(coeff, K.dom)
  1002. else: # pragma: no cover
  1003. raise DomainError('factorization not supported over %s' % K0)
  1004. if K0.is_Field:
  1005. for i, (f, k) in enumerate(factors):
  1006. factors[i] = (dmp_convert(f, u, K, K0), k)
  1007. coeff = K0.convert(coeff, K)
  1008. coeff = K0.quo(coeff, denom)
  1009. if K0_inexact:
  1010. for i, (f, k) in enumerate(factors):
  1011. max_norm = dmp_max_norm(f, u, K0)
  1012. f = dmp_quo_ground(f, max_norm, u, K0)
  1013. f = dmp_convert(f, u, K0, K0_inexact)
  1014. factors[i] = (f, k)
  1015. coeff = K0.mul(coeff, K0.pow(max_norm, k))
  1016. coeff = K0_inexact.convert(coeff, K0)
  1017. K0 = K0_inexact
  1018. for i, j in enumerate(reversed(J)):
  1019. if not j:
  1020. continue
  1021. term = {(0,)*(u - i) + (1,) + (0,)*i: K0.one}
  1022. factors.insert(0, (dmp_from_dict(term, u, K0), j))
  1023. return coeff*cont, _sort_factors(factors)
  1024. def dmp_factor_list_include(f, u, K):
  1025. """Factor multivariate polynomials into irreducibles in `K[X]`. """
  1026. if not u:
  1027. return dup_factor_list_include(f, K)
  1028. coeff, factors = dmp_factor_list(f, u, K)
  1029. if not factors:
  1030. return [(dmp_ground(coeff, u), 1)]
  1031. else:
  1032. g = dmp_mul_ground(factors[0][0], coeff, u, K)
  1033. return [(g, factors[0][1])] + factors[1:]
  1034. def dup_irreducible_p(f, K):
  1035. """
  1036. Returns ``True`` if a univariate polynomial ``f`` has no factors
  1037. over its domain.
  1038. """
  1039. return dmp_irreducible_p(f, 0, K)
  1040. def dmp_irreducible_p(f, u, K):
  1041. """
  1042. Returns ``True`` if a multivariate polynomial ``f`` has no factors
  1043. over its domain.
  1044. """
  1045. _, factors = dmp_factor_list(f, u, K)
  1046. if not factors:
  1047. return True
  1048. elif len(factors) > 1:
  1049. return False
  1050. else:
  1051. _, k = factors[0]
  1052. return k == 1