test_factortools.py 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  1. """Tools for polynomial factorization routines in characteristic zero. """
  2. from sympy.polys.rings import ring, xring
  3. from sympy.polys.domains import FF, ZZ, QQ, ZZ_I, QQ_I, RR, EX
  4. from sympy.polys import polyconfig as config
  5. from sympy.polys.polyerrors import DomainError
  6. from sympy.polys.polyclasses import ANP
  7. from sympy.polys.specialpolys import f_polys, w_polys
  8. from sympy.core.numbers import I
  9. from sympy.functions.elementary.miscellaneous import sqrt
  10. from sympy.functions.elementary.trigonometric import sin
  11. from sympy.ntheory.generate import nextprime
  12. from sympy.testing.pytest import raises, XFAIL
  13. f_0, f_1, f_2, f_3, f_4, f_5, f_6 = f_polys()
  14. w_1, w_2 = w_polys()
  15. def test_dup_trial_division():
  16. R, x = ring("x", ZZ)
  17. assert R.dup_trial_division(x**5 + 8*x**4 + 25*x**3 + 38*x**2 + 28*x + 8, (x + 1, x + 2)) == [(x + 1, 2), (x + 2, 3)]
  18. def test_dmp_trial_division():
  19. R, x, y = ring("x,y", ZZ)
  20. assert R.dmp_trial_division(x**5 + 8*x**4 + 25*x**3 + 38*x**2 + 28*x + 8, (x + 1, x + 2)) == [(x + 1, 2), (x + 2, 3)]
  21. def test_dup_zz_mignotte_bound():
  22. R, x = ring("x", ZZ)
  23. assert R.dup_zz_mignotte_bound(2*x**2 + 3*x + 4) == 6
  24. assert R.dup_zz_mignotte_bound(x**3 + 14*x**2 + 56*x + 64) == 152
  25. def test_dmp_zz_mignotte_bound():
  26. R, x, y = ring("x,y", ZZ)
  27. assert R.dmp_zz_mignotte_bound(2*x**2 + 3*x + 4) == 32
  28. def test_dup_zz_hensel_step():
  29. R, x = ring("x", ZZ)
  30. f = x**4 - 1
  31. g = x**3 + 2*x**2 - x - 2
  32. h = x - 2
  33. s = -2
  34. t = 2*x**2 - 2*x - 1
  35. G, H, S, T = R.dup_zz_hensel_step(5, f, g, h, s, t)
  36. assert G == x**3 + 7*x**2 - x - 7
  37. assert H == x - 7
  38. assert S == 8
  39. assert T == -8*x**2 - 12*x - 1
  40. def test_dup_zz_hensel_lift():
  41. R, x = ring("x", ZZ)
  42. f = x**4 - 1
  43. F = [x - 1, x - 2, x + 2, x + 1]
  44. assert R.dup_zz_hensel_lift(ZZ(5), f, F, 4) == \
  45. [x - 1, x - 182, x + 182, x + 1]
  46. def test_dup_zz_irreducible_p():
  47. R, x = ring("x", ZZ)
  48. assert R.dup_zz_irreducible_p(3*x**4 + 2*x**3 + 6*x**2 + 8*x + 7) is None
  49. assert R.dup_zz_irreducible_p(3*x**4 + 2*x**3 + 6*x**2 + 8*x + 4) is None
  50. assert R.dup_zz_irreducible_p(3*x**4 + 2*x**3 + 6*x**2 + 8*x + 10) is True
  51. assert R.dup_zz_irreducible_p(3*x**4 + 2*x**3 + 6*x**2 + 8*x + 14) is True
  52. def test_dup_cyclotomic_p():
  53. R, x = ring("x", ZZ)
  54. assert R.dup_cyclotomic_p(x - 1) is True
  55. assert R.dup_cyclotomic_p(x + 1) is True
  56. assert R.dup_cyclotomic_p(x**2 + x + 1) is True
  57. assert R.dup_cyclotomic_p(x**2 + 1) is True
  58. assert R.dup_cyclotomic_p(x**4 + x**3 + x**2 + x + 1) is True
  59. assert R.dup_cyclotomic_p(x**2 - x + 1) is True
  60. assert R.dup_cyclotomic_p(x**6 + x**5 + x**4 + x**3 + x**2 + x + 1) is True
  61. assert R.dup_cyclotomic_p(x**4 + 1) is True
  62. assert R.dup_cyclotomic_p(x**6 + x**3 + 1) is True
  63. assert R.dup_cyclotomic_p(0) is False
  64. assert R.dup_cyclotomic_p(1) is False
  65. assert R.dup_cyclotomic_p(x) is False
  66. assert R.dup_cyclotomic_p(x + 2) is False
  67. assert R.dup_cyclotomic_p(3*x + 1) is False
  68. assert R.dup_cyclotomic_p(x**2 - 1) is False
  69. f = x**16 + x**14 - x**10 + x**8 - x**6 + x**2 + 1
  70. assert R.dup_cyclotomic_p(f) is False
  71. g = x**16 + x**14 - x**10 - x**8 - x**6 + x**2 + 1
  72. assert R.dup_cyclotomic_p(g) is True
  73. R, x = ring("x", QQ)
  74. assert R.dup_cyclotomic_p(x**2 + x + 1) is True
  75. assert R.dup_cyclotomic_p(QQ(1,2)*x**2 + x + 1) is False
  76. R, x = ring("x", ZZ["y"])
  77. assert R.dup_cyclotomic_p(x**2 + x + 1) is False
  78. def test_dup_zz_cyclotomic_poly():
  79. R, x = ring("x", ZZ)
  80. assert R.dup_zz_cyclotomic_poly(1) == x - 1
  81. assert R.dup_zz_cyclotomic_poly(2) == x + 1
  82. assert R.dup_zz_cyclotomic_poly(3) == x**2 + x + 1
  83. assert R.dup_zz_cyclotomic_poly(4) == x**2 + 1
  84. assert R.dup_zz_cyclotomic_poly(5) == x**4 + x**3 + x**2 + x + 1
  85. assert R.dup_zz_cyclotomic_poly(6) == x**2 - x + 1
  86. assert R.dup_zz_cyclotomic_poly(7) == x**6 + x**5 + x**4 + x**3 + x**2 + x + 1
  87. assert R.dup_zz_cyclotomic_poly(8) == x**4 + 1
  88. assert R.dup_zz_cyclotomic_poly(9) == x**6 + x**3 + 1
  89. def test_dup_zz_cyclotomic_factor():
  90. R, x = ring("x", ZZ)
  91. assert R.dup_zz_cyclotomic_factor(0) is None
  92. assert R.dup_zz_cyclotomic_factor(1) is None
  93. assert R.dup_zz_cyclotomic_factor(2*x**10 - 1) is None
  94. assert R.dup_zz_cyclotomic_factor(x**10 - 3) is None
  95. assert R.dup_zz_cyclotomic_factor(x**10 + x**5 - 1) is None
  96. assert R.dup_zz_cyclotomic_factor(x + 1) == [x + 1]
  97. assert R.dup_zz_cyclotomic_factor(x - 1) == [x - 1]
  98. assert R.dup_zz_cyclotomic_factor(x**2 + 1) == [x**2 + 1]
  99. assert R.dup_zz_cyclotomic_factor(x**2 - 1) == [x - 1, x + 1]
  100. assert R.dup_zz_cyclotomic_factor(x**27 + 1) == \
  101. [x + 1, x**2 - x + 1, x**6 - x**3 + 1, x**18 - x**9 + 1]
  102. assert R.dup_zz_cyclotomic_factor(x**27 - 1) == \
  103. [x - 1, x**2 + x + 1, x**6 + x**3 + 1, x**18 + x**9 + 1]
  104. def test_dup_zz_factor():
  105. R, x = ring("x", ZZ)
  106. assert R.dup_zz_factor(0) == (0, [])
  107. assert R.dup_zz_factor(7) == (7, [])
  108. assert R.dup_zz_factor(-7) == (-7, [])
  109. assert R.dup_zz_factor_sqf(0) == (0, [])
  110. assert R.dup_zz_factor_sqf(7) == (7, [])
  111. assert R.dup_zz_factor_sqf(-7) == (-7, [])
  112. assert R.dup_zz_factor(2*x + 4) == (2, [(x + 2, 1)])
  113. assert R.dup_zz_factor_sqf(2*x + 4) == (2, [x + 2])
  114. f = x**4 + x + 1
  115. for i in range(0, 20):
  116. assert R.dup_zz_factor(f) == (1, [(f, 1)])
  117. assert R.dup_zz_factor(x**2 + 2*x + 2) == \
  118. (1, [(x**2 + 2*x + 2, 1)])
  119. assert R.dup_zz_factor(18*x**2 + 12*x + 2) == \
  120. (2, [(3*x + 1, 2)])
  121. assert R.dup_zz_factor(-9*x**2 + 1) == \
  122. (-1, [(3*x - 1, 1),
  123. (3*x + 1, 1)])
  124. assert R.dup_zz_factor_sqf(-9*x**2 + 1) == \
  125. (-1, [3*x - 1,
  126. 3*x + 1])
  127. assert R.dup_zz_factor(x**3 - 6*x**2 + 11*x - 6) == \
  128. (1, [(x - 3, 1),
  129. (x - 2, 1),
  130. (x - 1, 1)])
  131. assert R.dup_zz_factor_sqf(x**3 - 6*x**2 + 11*x - 6) == \
  132. (1, [x - 3,
  133. x - 2,
  134. x - 1])
  135. assert R.dup_zz_factor(3*x**3 + 10*x**2 + 13*x + 10) == \
  136. (1, [(x + 2, 1),
  137. (3*x**2 + 4*x + 5, 1)])
  138. assert R.dup_zz_factor_sqf(3*x**3 + 10*x**2 + 13*x + 10) == \
  139. (1, [x + 2,
  140. 3*x**2 + 4*x + 5])
  141. assert R.dup_zz_factor(-x**6 + x**2) == \
  142. (-1, [(x - 1, 1),
  143. (x + 1, 1),
  144. (x, 2),
  145. (x**2 + 1, 1)])
  146. f = 1080*x**8 + 5184*x**7 + 2099*x**6 + 744*x**5 + 2736*x**4 - 648*x**3 + 129*x**2 - 324
  147. assert R.dup_zz_factor(f) == \
  148. (1, [(5*x**4 + 24*x**3 + 9*x**2 + 12, 1),
  149. (216*x**4 + 31*x**2 - 27, 1)])
  150. f = -29802322387695312500000000000000000000*x**25 \
  151. + 2980232238769531250000000000000000*x**20 \
  152. + 1743435859680175781250000000000*x**15 \
  153. + 114142894744873046875000000*x**10 \
  154. - 210106372833251953125*x**5 \
  155. + 95367431640625
  156. assert R.dup_zz_factor(f) == \
  157. (-95367431640625, [(5*x - 1, 1),
  158. (100*x**2 + 10*x - 1, 2),
  159. (625*x**4 + 125*x**3 + 25*x**2 + 5*x + 1, 1),
  160. (10000*x**4 - 3000*x**3 + 400*x**2 - 20*x + 1, 2),
  161. (10000*x**4 + 2000*x**3 + 400*x**2 + 30*x + 1, 2)])
  162. f = x**10 - 1
  163. config.setup('USE_CYCLOTOMIC_FACTOR', True)
  164. F_0 = R.dup_zz_factor(f)
  165. config.setup('USE_CYCLOTOMIC_FACTOR', False)
  166. F_1 = R.dup_zz_factor(f)
  167. assert F_0 == F_1 == \
  168. (1, [(x - 1, 1),
  169. (x + 1, 1),
  170. (x**4 - x**3 + x**2 - x + 1, 1),
  171. (x**4 + x**3 + x**2 + x + 1, 1)])
  172. config.setup('USE_CYCLOTOMIC_FACTOR')
  173. f = x**10 + 1
  174. config.setup('USE_CYCLOTOMIC_FACTOR', True)
  175. F_0 = R.dup_zz_factor(f)
  176. config.setup('USE_CYCLOTOMIC_FACTOR', False)
  177. F_1 = R.dup_zz_factor(f)
  178. assert F_0 == F_1 == \
  179. (1, [(x**2 + 1, 1),
  180. (x**8 - x**6 + x**4 - x**2 + 1, 1)])
  181. config.setup('USE_CYCLOTOMIC_FACTOR')
  182. def test_dmp_zz_wang():
  183. R, x,y,z = ring("x,y,z", ZZ)
  184. UV, _x = ring("x", ZZ)
  185. p = ZZ(nextprime(R.dmp_zz_mignotte_bound(w_1)))
  186. assert p == 6291469
  187. t_1, k_1, e_1 = y, 1, ZZ(-14)
  188. t_2, k_2, e_2 = z, 2, ZZ(3)
  189. t_3, k_3, e_3 = y + z, 2, ZZ(-11)
  190. t_4, k_4, e_4 = y - z, 1, ZZ(-17)
  191. T = [t_1, t_2, t_3, t_4]
  192. K = [k_1, k_2, k_3, k_4]
  193. E = [e_1, e_2, e_3, e_4]
  194. T = zip([ t.drop(x) for t in T ], K)
  195. A = [ZZ(-14), ZZ(3)]
  196. S = R.dmp_eval_tail(w_1, A)
  197. cs, s = UV.dup_primitive(S)
  198. assert cs == 1 and s == S == \
  199. 1036728*_x**6 + 915552*_x**5 + 55748*_x**4 + 105621*_x**3 - 17304*_x**2 - 26841*_x - 644
  200. assert R.dmp_zz_wang_non_divisors(E, cs, ZZ(4)) == [7, 3, 11, 17]
  201. assert UV.dup_sqf_p(s) and UV.dup_degree(s) == R.dmp_degree(w_1)
  202. _, H = UV.dup_zz_factor_sqf(s)
  203. h_1 = 44*_x**2 + 42*_x + 1
  204. h_2 = 126*_x**2 - 9*_x + 28
  205. h_3 = 187*_x**2 - 23
  206. assert H == [h_1, h_2, h_3]
  207. LC = [ lc.drop(x) for lc in [-4*y - 4*z, -y*z**2, y**2 - z**2] ]
  208. assert R.dmp_zz_wang_lead_coeffs(w_1, T, cs, E, H, A) == (w_1, H, LC)
  209. factors = R.dmp_zz_wang_hensel_lifting(w_1, H, LC, A, p)
  210. assert R.dmp_expand(factors) == w_1
  211. @XFAIL
  212. def test_dmp_zz_wang_fail():
  213. R, x,y,z = ring("x,y,z", ZZ)
  214. UV, _x = ring("x", ZZ)
  215. p = ZZ(nextprime(R.dmp_zz_mignotte_bound(w_1)))
  216. assert p == 6291469
  217. H_1 = [44*x**2 + 42*x + 1, 126*x**2 - 9*x + 28, 187*x**2 - 23]
  218. H_2 = [-4*x**2*y - 12*x**2 - 3*x*y + 1, -9*x**2*y - 9*x - 2*y, x**2*y**2 - 9*x**2 + y - 9]
  219. H_3 = [-4*x**2*y - 12*x**2 - 3*x*y + 1, -9*x**2*y - 9*x - 2*y, x**2*y**2 - 9*x**2 + y - 9]
  220. c_1 = -70686*x**5 - 5863*x**4 - 17826*x**3 + 2009*x**2 + 5031*x + 74
  221. c_2 = 9*x**5*y**4 + 12*x**5*y**3 - 45*x**5*y**2 - 108*x**5*y - 324*x**5 + 18*x**4*y**3 - 216*x**4*y**2 - 810*x**4*y + 2*x**3*y**4 + 9*x**3*y**3 - 252*x**3*y**2 - 288*x**3*y - 945*x**3 - 30*x**2*y**2 - 414*x**2*y + 2*x*y**3 - 54*x*y**2 - 3*x*y + 81*x + 12*y
  222. c_3 = -36*x**4*y**2 - 108*x**4*y - 27*x**3*y**2 - 36*x**3*y - 108*x**3 - 8*x**2*y**2 - 42*x**2*y - 6*x*y**2 + 9*x + 2*y
  223. assert R.dmp_zz_diophantine(H_1, c_1, [], 5, p) == [-3*x, -2, 1]
  224. assert R.dmp_zz_diophantine(H_2, c_2, [ZZ(-14)], 5, p) == [-x*y, -3*x, -6]
  225. assert R.dmp_zz_diophantine(H_3, c_3, [ZZ(-14)], 5, p) == [0, 0, -1]
  226. def test_issue_6355():
  227. # This tests a bug in the Wang algorithm that occurred only with a very
  228. # specific set of random numbers.
  229. random_sequence = [-1, -1, 0, 0, 0, 0, -1, -1, 0, -1, 3, -1, 3, 3, 3, 3, -1, 3]
  230. R, x, y, z = ring("x,y,z", ZZ)
  231. f = 2*x**2 + y*z - y - z**2 + z
  232. assert R.dmp_zz_wang(f, seed=random_sequence) == [f]
  233. def test_dmp_zz_factor():
  234. R, x = ring("x", ZZ)
  235. assert R.dmp_zz_factor(0) == (0, [])
  236. assert R.dmp_zz_factor(7) == (7, [])
  237. assert R.dmp_zz_factor(-7) == (-7, [])
  238. assert R.dmp_zz_factor(x**2 - 9) == (1, [(x - 3, 1), (x + 3, 1)])
  239. R, x, y = ring("x,y", ZZ)
  240. assert R.dmp_zz_factor(0) == (0, [])
  241. assert R.dmp_zz_factor(7) == (7, [])
  242. assert R.dmp_zz_factor(-7) == (-7, [])
  243. assert R.dmp_zz_factor(x) == (1, [(x, 1)])
  244. assert R.dmp_zz_factor(4*x) == (4, [(x, 1)])
  245. assert R.dmp_zz_factor(4*x + 2) == (2, [(2*x + 1, 1)])
  246. assert R.dmp_zz_factor(x*y + 1) == (1, [(x*y + 1, 1)])
  247. assert R.dmp_zz_factor(y**2 + 1) == (1, [(y**2 + 1, 1)])
  248. assert R.dmp_zz_factor(y**2 - 1) == (1, [(y - 1, 1), (y + 1, 1)])
  249. assert R.dmp_zz_factor(x**2*y**2 + 6*x**2*y + 9*x**2 - 1) == (1, [(x*y + 3*x - 1, 1), (x*y + 3*x + 1, 1)])
  250. assert R.dmp_zz_factor(x**2*y**2 - 9) == (1, [(x*y - 3, 1), (x*y + 3, 1)])
  251. R, x, y, z = ring("x,y,z", ZZ)
  252. assert R.dmp_zz_factor(x**2*y**2*z**2 - 9) == \
  253. (1, [(x*y*z - 3, 1),
  254. (x*y*z + 3, 1)])
  255. R, x, y, z, u = ring("x,y,z,u", ZZ)
  256. assert R.dmp_zz_factor(x**2*y**2*z**2*u**2 - 9) == \
  257. (1, [(x*y*z*u - 3, 1),
  258. (x*y*z*u + 3, 1)])
  259. R, x, y, z = ring("x,y,z", ZZ)
  260. assert R.dmp_zz_factor(f_1) == \
  261. (1, [(x + y*z + 20, 1),
  262. (x*y + z + 10, 1),
  263. (x*z + y + 30, 1)])
  264. assert R.dmp_zz_factor(f_2) == \
  265. (1, [(x**2*y**2 + x**2*z**2 + y + 90, 1),
  266. (x**3*y + x**3*z + z - 11, 1)])
  267. assert R.dmp_zz_factor(f_3) == \
  268. (1, [(x**2*y**2 + x*z**4 + x + z, 1),
  269. (x**3 + x*y*z + y**2 + y*z**3, 1)])
  270. assert R.dmp_zz_factor(f_4) == \
  271. (-1, [(x*y**3 + z**2, 1),
  272. (x**2*z + y**4*z**2 + 5, 1),
  273. (x**3*y - z**2 - 3, 1),
  274. (x**3*y**4 + z**2, 1)])
  275. assert R.dmp_zz_factor(f_5) == \
  276. (-1, [(x + y - z, 3)])
  277. R, x, y, z, t = ring("x,y,z,t", ZZ)
  278. assert R.dmp_zz_factor(f_6) == \
  279. (1, [(47*x*y + z**3*t**2 - t**2, 1),
  280. (45*x**3 - 9*y**3 - y**2 + 3*z**3 + 2*z*t, 1)])
  281. R, x, y, z = ring("x,y,z", ZZ)
  282. assert R.dmp_zz_factor(w_1) == \
  283. (1, [(x**2*y**2 - x**2*z**2 + y - z**2, 1),
  284. (x**2*y*z**2 + 3*x*z + 2*y, 1),
  285. (4*x**2*y + 4*x**2*z + x*y*z - 1, 1)])
  286. R, x, y = ring("x,y", ZZ)
  287. f = -12*x**16*y + 240*x**12*y**3 - 768*x**10*y**4 + 1080*x**8*y**5 - 768*x**6*y**6 + 240*x**4*y**7 - 12*y**9
  288. assert R.dmp_zz_factor(f) == \
  289. (-12, [(y, 1),
  290. (x**2 - y, 6),
  291. (x**4 + 6*x**2*y + y**2, 1)])
  292. def test_dup_qq_i_factor():
  293. R, x = ring("x", QQ_I)
  294. i = QQ_I(0, 1)
  295. assert R.dup_qq_i_factor(x**2 - 2) == (QQ_I(1, 0), [(x**2 - 2, 1)])
  296. assert R.dup_qq_i_factor(x**2 - 1) == (QQ_I(1, 0), [(x - 1, 1), (x + 1, 1)])
  297. assert R.dup_qq_i_factor(x**2 + 1) == (QQ_I(1, 0), [(x - i, 1), (x + i, 1)])
  298. assert R.dup_qq_i_factor(x**2/4 + 1) == \
  299. (QQ_I(QQ(1, 4), 0), [(x - 2*i, 1), (x + 2*i, 1)])
  300. assert R.dup_qq_i_factor(x**2 + 4) == \
  301. (QQ_I(1, 0), [(x - 2*i, 1), (x + 2*i, 1)])
  302. assert R.dup_qq_i_factor(x**2 + 2*x + 1) == \
  303. (QQ_I(1, 0), [(x + 1, 2)])
  304. assert R.dup_qq_i_factor(x**2 + 2*i*x - 1) == \
  305. (QQ_I(1, 0), [(x + i, 2)])
  306. f = 8192*x**2 + x*(22656 + 175232*i) - 921416 + 242313*i
  307. assert R.dup_qq_i_factor(f) == \
  308. (QQ_I(8192, 0), [(x + QQ_I(QQ(177, 128), QQ(1369, 128)), 2)])
  309. def test_dmp_qq_i_factor():
  310. R, x, y = ring("x, y", QQ_I)
  311. i = QQ_I(0, 1)
  312. assert R.dmp_qq_i_factor(x**2 + 2*y**2) == \
  313. (QQ_I(1, 0), [(x**2 + 2*y**2, 1)])
  314. assert R.dmp_qq_i_factor(x**2 + y**2) == \
  315. (QQ_I(1, 0), [(x - i*y, 1), (x + i*y, 1)])
  316. assert R.dmp_qq_i_factor(x**2 + y**2/4) == \
  317. (QQ_I(1, 0), [(x - i*y/2, 1), (x + i*y/2, 1)])
  318. assert R.dmp_qq_i_factor(4*x**2 + y**2) == \
  319. (QQ_I(4, 0), [(x - i*y/2, 1), (x + i*y/2, 1)])
  320. def test_dup_zz_i_factor():
  321. R, x = ring("x", ZZ_I)
  322. i = ZZ_I(0, 1)
  323. assert R.dup_zz_i_factor(x**2 - 2) == (ZZ_I(1, 0), [(x**2 - 2, 1)])
  324. assert R.dup_zz_i_factor(x**2 - 1) == (ZZ_I(1, 0), [(x - 1, 1), (x + 1, 1)])
  325. assert R.dup_zz_i_factor(x**2 + 1) == (ZZ_I(1, 0), [(x - i, 1), (x + i, 1)])
  326. assert R.dup_zz_i_factor(x**2 + 4) == \
  327. (ZZ_I(1, 0), [(x - 2*i, 1), (x + 2*i, 1)])
  328. assert R.dup_zz_i_factor(x**2 + 2*x + 1) == \
  329. (ZZ_I(1, 0), [(x + 1, 2)])
  330. assert R.dup_zz_i_factor(x**2 + 2*i*x - 1) == \
  331. (ZZ_I(1, 0), [(x + i, 2)])
  332. f = 8192*x**2 + x*(22656 + 175232*i) - 921416 + 242313*i
  333. assert R.dup_zz_i_factor(f) == \
  334. (ZZ_I(0, 1), [((64 - 64*i)*x + (773 + 596*i), 2)])
  335. def test_dmp_zz_i_factor():
  336. R, x, y = ring("x, y", ZZ_I)
  337. i = ZZ_I(0, 1)
  338. assert R.dmp_zz_i_factor(x**2 + 2*y**2) == \
  339. (ZZ_I(1, 0), [(x**2 + 2*y**2, 1)])
  340. assert R.dmp_zz_i_factor(x**2 + y**2) == \
  341. (ZZ_I(1, 0), [(x - i*y, 1), (x + i*y, 1)])
  342. assert R.dmp_zz_i_factor(4*x**2 + y**2) == \
  343. (ZZ_I(1, 0), [(2*x - i*y, 1), (2*x + i*y, 1)])
  344. def test_dup_ext_factor():
  345. R, x = ring("x", QQ.algebraic_field(I))
  346. def anp(element):
  347. return ANP(element, [QQ(1), QQ(0), QQ(1)], QQ)
  348. assert R.dup_ext_factor(0) == (anp([]), [])
  349. f = anp([QQ(1)])*x + anp([QQ(1)])
  350. assert R.dup_ext_factor(f) == (anp([QQ(1)]), [(f, 1)])
  351. g = anp([QQ(2)])*x + anp([QQ(2)])
  352. assert R.dup_ext_factor(g) == (anp([QQ(2)]), [(f, 1)])
  353. f = anp([QQ(7)])*x**4 + anp([QQ(1, 1)])
  354. g = anp([QQ(1)])*x**4 + anp([QQ(1, 7)])
  355. assert R.dup_ext_factor(f) == (anp([QQ(7)]), [(g, 1)])
  356. f = anp([QQ(1)])*x**4 + anp([QQ(1)])
  357. assert R.dup_ext_factor(f) == \
  358. (anp([QQ(1, 1)]), [(anp([QQ(1)])*x**2 + anp([QQ(-1), QQ(0)]), 1),
  359. (anp([QQ(1)])*x**2 + anp([QQ( 1), QQ(0)]), 1)])
  360. f = anp([QQ(4, 1)])*x**2 + anp([QQ(9, 1)])
  361. assert R.dup_ext_factor(f) == \
  362. (anp([QQ(4, 1)]), [(anp([QQ(1, 1)])*x + anp([-QQ(3, 2), QQ(0, 1)]), 1),
  363. (anp([QQ(1, 1)])*x + anp([ QQ(3, 2), QQ(0, 1)]), 1)])
  364. f = anp([QQ(4, 1)])*x**4 + anp([QQ(8, 1)])*x**3 + anp([QQ(77, 1)])*x**2 + anp([QQ(18, 1)])*x + anp([QQ(153, 1)])
  365. assert R.dup_ext_factor(f) == \
  366. (anp([QQ(4, 1)]), [(anp([QQ(1, 1)])*x + anp([-QQ(4, 1), QQ(1, 1)]), 1),
  367. (anp([QQ(1, 1)])*x + anp([-QQ(3, 2), QQ(0, 1)]), 1),
  368. (anp([QQ(1, 1)])*x + anp([ QQ(3, 2), QQ(0, 1)]), 1),
  369. (anp([QQ(1, 1)])*x + anp([ QQ(4, 1), QQ(1, 1)]), 1)])
  370. R, x = ring("x", QQ.algebraic_field(sqrt(2)))
  371. def anp(element):
  372. return ANP(element, [QQ(1), QQ(0), QQ(-2)], QQ)
  373. f = anp([QQ(1)])*x**4 + anp([QQ(1, 1)])
  374. assert R.dup_ext_factor(f) == \
  375. (anp([QQ(1)]), [(anp([QQ(1)])*x**2 + anp([QQ(-1), QQ(0)])*x + anp([QQ(1)]), 1),
  376. (anp([QQ(1)])*x**2 + anp([QQ( 1), QQ(0)])*x + anp([QQ(1)]), 1)])
  377. f = anp([QQ(1, 1)])*x**2 + anp([QQ(2), QQ(0)])*x + anp([QQ(2, 1)])
  378. assert R.dup_ext_factor(f) == \
  379. (anp([QQ(1, 1)]), [(anp([1])*x + anp([1, 0]), 2)])
  380. assert R.dup_ext_factor(f**3) == \
  381. (anp([QQ(1, 1)]), [(anp([1])*x + anp([1, 0]), 6)])
  382. f *= anp([QQ(2, 1)])
  383. assert R.dup_ext_factor(f) == \
  384. (anp([QQ(2, 1)]), [(anp([1])*x + anp([1, 0]), 2)])
  385. assert R.dup_ext_factor(f**3) == \
  386. (anp([QQ(8, 1)]), [(anp([1])*x + anp([1, 0]), 6)])
  387. def test_dmp_ext_factor():
  388. R, x,y = ring("x,y", QQ.algebraic_field(sqrt(2)))
  389. def anp(x):
  390. return ANP(x, [QQ(1), QQ(0), QQ(-2)], QQ)
  391. assert R.dmp_ext_factor(0) == (anp([]), [])
  392. f = anp([QQ(1)])*x + anp([QQ(1)])
  393. assert R.dmp_ext_factor(f) == (anp([QQ(1)]), [(f, 1)])
  394. g = anp([QQ(2)])*x + anp([QQ(2)])
  395. assert R.dmp_ext_factor(g) == (anp([QQ(2)]), [(f, 1)])
  396. f = anp([QQ(1)])*x**2 + anp([QQ(-2)])*y**2
  397. assert R.dmp_ext_factor(f) == \
  398. (anp([QQ(1)]), [(anp([QQ(1)])*x + anp([QQ(-1), QQ(0)])*y, 1),
  399. (anp([QQ(1)])*x + anp([QQ( 1), QQ(0)])*y, 1)])
  400. f = anp([QQ(2)])*x**2 + anp([QQ(-4)])*y**2
  401. assert R.dmp_ext_factor(f) == \
  402. (anp([QQ(2)]), [(anp([QQ(1)])*x + anp([QQ(-1), QQ(0)])*y, 1),
  403. (anp([QQ(1)])*x + anp([QQ( 1), QQ(0)])*y, 1)])
  404. def test_dup_factor_list():
  405. R, x = ring("x", ZZ)
  406. assert R.dup_factor_list(0) == (0, [])
  407. assert R.dup_factor_list(7) == (7, [])
  408. R, x = ring("x", QQ)
  409. assert R.dup_factor_list(0) == (0, [])
  410. assert R.dup_factor_list(QQ(1, 7)) == (QQ(1, 7), [])
  411. R, x = ring("x", ZZ['t'])
  412. assert R.dup_factor_list(0) == (0, [])
  413. assert R.dup_factor_list(7) == (7, [])
  414. R, x = ring("x", QQ['t'])
  415. assert R.dup_factor_list(0) == (0, [])
  416. assert R.dup_factor_list(QQ(1, 7)) == (QQ(1, 7), [])
  417. R, x = ring("x", ZZ)
  418. assert R.dup_factor_list_include(0) == [(0, 1)]
  419. assert R.dup_factor_list_include(7) == [(7, 1)]
  420. assert R.dup_factor_list(x**2 + 2*x + 1) == (1, [(x + 1, 2)])
  421. assert R.dup_factor_list_include(x**2 + 2*x + 1) == [(x + 1, 2)]
  422. # issue 8037
  423. assert R.dup_factor_list(6*x**2 - 5*x - 6) == (1, [(2*x - 3, 1), (3*x + 2, 1)])
  424. R, x = ring("x", QQ)
  425. assert R.dup_factor_list(QQ(1,2)*x**2 + x + QQ(1,2)) == (QQ(1, 2), [(x + 1, 2)])
  426. R, x = ring("x", FF(2))
  427. assert R.dup_factor_list(x**2 + 1) == (1, [(x + 1, 2)])
  428. R, x = ring("x", RR)
  429. assert R.dup_factor_list(1.0*x**2 + 2.0*x + 1.0) == (1.0, [(1.0*x + 1.0, 2)])
  430. assert R.dup_factor_list(2.0*x**2 + 4.0*x + 2.0) == (2.0, [(1.0*x + 1.0, 2)])
  431. f = 6.7225336055071*x**2 - 10.6463972754741*x - 0.33469524022264
  432. coeff, factors = R.dup_factor_list(f)
  433. assert coeff == RR(10.6463972754741)
  434. assert len(factors) == 1
  435. assert factors[0][0].max_norm() == RR(1.0)
  436. assert factors[0][1] == 1
  437. Rt, t = ring("t", ZZ)
  438. R, x = ring("x", Rt)
  439. f = 4*t*x**2 + 4*t**2*x
  440. assert R.dup_factor_list(f) == \
  441. (4*t, [(x, 1),
  442. (x + t, 1)])
  443. Rt, t = ring("t", QQ)
  444. R, x = ring("x", Rt)
  445. f = QQ(1, 2)*t*x**2 + QQ(1, 2)*t**2*x
  446. assert R.dup_factor_list(f) == \
  447. (QQ(1, 2)*t, [(x, 1),
  448. (x + t, 1)])
  449. R, x = ring("x", QQ.algebraic_field(I))
  450. def anp(element):
  451. return ANP(element, [QQ(1), QQ(0), QQ(1)], QQ)
  452. f = anp([QQ(1, 1)])*x**4 + anp([QQ(2, 1)])*x**2
  453. assert R.dup_factor_list(f) == \
  454. (anp([QQ(1, 1)]), [(anp([QQ(1, 1)])*x, 2),
  455. (anp([QQ(1, 1)])*x**2 + anp([])*x + anp([QQ(2, 1)]), 1)])
  456. R, x = ring("x", EX)
  457. raises(DomainError, lambda: R.dup_factor_list(EX(sin(1))))
  458. def test_dmp_factor_list():
  459. R, x, y = ring("x,y", ZZ)
  460. assert R.dmp_factor_list(0) == (ZZ(0), [])
  461. assert R.dmp_factor_list(7) == (7, [])
  462. R, x, y = ring("x,y", QQ)
  463. assert R.dmp_factor_list(0) == (QQ(0), [])
  464. assert R.dmp_factor_list(QQ(1, 7)) == (QQ(1, 7), [])
  465. Rt, t = ring("t", ZZ)
  466. R, x, y = ring("x,y", Rt)
  467. assert R.dmp_factor_list(0) == (0, [])
  468. assert R.dmp_factor_list(7) == (ZZ(7), [])
  469. Rt, t = ring("t", QQ)
  470. R, x, y = ring("x,y", Rt)
  471. assert R.dmp_factor_list(0) == (0, [])
  472. assert R.dmp_factor_list(QQ(1, 7)) == (QQ(1, 7), [])
  473. R, x, y = ring("x,y", ZZ)
  474. assert R.dmp_factor_list_include(0) == [(0, 1)]
  475. assert R.dmp_factor_list_include(7) == [(7, 1)]
  476. R, X = xring("x:200", ZZ)
  477. f, g = X[0]**2 + 2*X[0] + 1, X[0] + 1
  478. assert R.dmp_factor_list(f) == (1, [(g, 2)])
  479. f, g = X[-1]**2 + 2*X[-1] + 1, X[-1] + 1
  480. assert R.dmp_factor_list(f) == (1, [(g, 2)])
  481. R, x = ring("x", ZZ)
  482. assert R.dmp_factor_list(x**2 + 2*x + 1) == (1, [(x + 1, 2)])
  483. R, x = ring("x", QQ)
  484. assert R.dmp_factor_list(QQ(1,2)*x**2 + x + QQ(1,2)) == (QQ(1,2), [(x + 1, 2)])
  485. R, x, y = ring("x,y", ZZ)
  486. assert R.dmp_factor_list(x**2 + 2*x + 1) == (1, [(x + 1, 2)])
  487. R, x, y = ring("x,y", QQ)
  488. assert R.dmp_factor_list(QQ(1,2)*x**2 + x + QQ(1,2)) == (QQ(1,2), [(x + 1, 2)])
  489. R, x, y = ring("x,y", ZZ)
  490. f = 4*x**2*y + 4*x*y**2
  491. assert R.dmp_factor_list(f) == \
  492. (4, [(y, 1),
  493. (x, 1),
  494. (x + y, 1)])
  495. assert R.dmp_factor_list_include(f) == \
  496. [(4*y, 1),
  497. (x, 1),
  498. (x + y, 1)]
  499. R, x, y = ring("x,y", QQ)
  500. f = QQ(1,2)*x**2*y + QQ(1,2)*x*y**2
  501. assert R.dmp_factor_list(f) == \
  502. (QQ(1,2), [(y, 1),
  503. (x, 1),
  504. (x + y, 1)])
  505. R, x, y = ring("x,y", RR)
  506. f = 2.0*x**2 - 8.0*y**2
  507. assert R.dmp_factor_list(f) == \
  508. (RR(8.0), [(0.5*x - y, 1),
  509. (0.5*x + y, 1)])
  510. f = 6.7225336055071*x**2*y**2 - 10.6463972754741*x*y - 0.33469524022264
  511. coeff, factors = R.dmp_factor_list(f)
  512. assert coeff == RR(10.6463972754741)
  513. assert len(factors) == 1
  514. assert factors[0][0].max_norm() == RR(1.0)
  515. assert factors[0][1] == 1
  516. Rt, t = ring("t", ZZ)
  517. R, x, y = ring("x,y", Rt)
  518. f = 4*t*x**2 + 4*t**2*x
  519. assert R.dmp_factor_list(f) == \
  520. (4*t, [(x, 1),
  521. (x + t, 1)])
  522. Rt, t = ring("t", QQ)
  523. R, x, y = ring("x,y", Rt)
  524. f = QQ(1, 2)*t*x**2 + QQ(1, 2)*t**2*x
  525. assert R.dmp_factor_list(f) == \
  526. (QQ(1, 2)*t, [(x, 1),
  527. (x + t, 1)])
  528. R, x, y = ring("x,y", FF(2))
  529. raises(NotImplementedError, lambda: R.dmp_factor_list(x**2 + y**2))
  530. R, x, y = ring("x,y", EX)
  531. raises(DomainError, lambda: R.dmp_factor_list(EX(sin(1))))
  532. def test_dup_irreducible_p():
  533. R, x = ring("x", ZZ)
  534. assert R.dup_irreducible_p(x**2 + x + 1) is True
  535. assert R.dup_irreducible_p(x**2 + 2*x + 1) is False
  536. def test_dmp_irreducible_p():
  537. R, x, y = ring("x,y", ZZ)
  538. assert R.dmp_irreducible_p(x**2 + x + 1) is True
  539. assert R.dmp_irreducible_p(x**2 + 2*x + 1) is False