/jas/src/main/java/edu/jas/ufd/GreatestCommonDivisorAbstract.java

http://symja.googlecode.com/ · Java · 1036 lines · 670 code · 95 blank · 271 comment · 227 complexity · ca22dd9499a0d42047f2a2579e9d7911 MD5 · raw file

  1. /*
  2. * $Id: GreatestCommonDivisorAbstract.java 3853 2012-01-01 19:32:34Z kredel $
  3. */
  4. package edu.jas.ufd;
  5. import java.util.ArrayList;
  6. import java.util.List;
  7. import org.apache.log4j.Logger;
  8. import edu.jas.poly.GenPolynomial;
  9. import edu.jas.poly.GenPolynomialRing;
  10. import edu.jas.poly.PolyUtil;
  11. import edu.jas.structure.GcdRingElem;
  12. import edu.jas.structure.RingFactory;
  13. /**
  14. * Greatest common divisor algorithms.
  15. * @author Heinz Kredel
  16. */
  17. public abstract class GreatestCommonDivisorAbstract<C extends GcdRingElem<C>> implements
  18. GreatestCommonDivisor<C> {
  19. private static final Logger logger = Logger.getLogger(GreatestCommonDivisorAbstract.class);
  20. private final boolean debug = logger.isDebugEnabled();
  21. /**
  22. * Get the String representation.
  23. * @see java.lang.Object#toString()
  24. */
  25. @Override
  26. public String toString() {
  27. return getClass().getName();
  28. }
  29. /**
  30. * GenPolynomial base coefficient content.
  31. * @param P GenPolynomial.
  32. * @return cont(P).
  33. */
  34. public C baseContent(GenPolynomial<C> P) {
  35. if (P == null) {
  36. throw new IllegalArgumentException(this.getClass().getName() + " P != null");
  37. }
  38. if (P.isZERO()) {
  39. return P.ring.getZEROCoefficient();
  40. }
  41. C d = null;
  42. for (C c : P.getMap().values()) {
  43. if (d == null) {
  44. d = c;
  45. } else {
  46. d = d.gcd(c);
  47. }
  48. if (d.isONE()) {
  49. return d;
  50. }
  51. }
  52. if ( d.signum() < 0 ) {
  53. d = d.negate();
  54. }
  55. return d;
  56. }
  57. /**
  58. * GenPolynomial base coefficient primitive part.
  59. * @param P GenPolynomial.
  60. * @return pp(P).
  61. */
  62. public GenPolynomial<C> basePrimitivePart(GenPolynomial<C> P) {
  63. if (P == null) {
  64. throw new IllegalArgumentException(this.getClass().getName() + " P != null");
  65. }
  66. if (P.isZERO()) {
  67. return P;
  68. }
  69. C d = baseContent(P);
  70. if (d.isONE()) {
  71. return P;
  72. }
  73. GenPolynomial<C> pp = P.divide(d);
  74. if (debug) {
  75. GenPolynomial<C> p = pp.multiply(d);
  76. if (!p.equals(P)) {
  77. throw new ArithmeticException("pp(p)*cont(p) != p: ");
  78. }
  79. }
  80. return pp;
  81. }
  82. /**
  83. * Univariate GenPolynomial greatest common divisor. Uses sparse
  84. * pseudoRemainder for remainder.
  85. * @param P univariate GenPolynomial.
  86. * @param S univariate GenPolynomial.
  87. * @return gcd(P,S).
  88. */
  89. public abstract GenPolynomial<C> baseGcd(GenPolynomial<C> P, GenPolynomial<C> S);
  90. /**
  91. * GenPolynomial recursive content.
  92. * @param P recursive GenPolynomial.
  93. * @return cont(P).
  94. */
  95. public GenPolynomial<C> recursiveContent(GenPolynomial<GenPolynomial<C>> P) {
  96. if (P == null) {
  97. throw new IllegalArgumentException(this.getClass().getName() + " P != null");
  98. }
  99. if (P.isZERO()) {
  100. return P.ring.getZEROCoefficient();
  101. }
  102. GenPolynomial<C> d = null;
  103. for (GenPolynomial<C> c : P.getMap().values()) {
  104. if (d == null) {
  105. d = c;
  106. } else {
  107. d = gcd(d, c); // go to recursion
  108. }
  109. if (d.isONE()) {
  110. return d;
  111. }
  112. }
  113. return d.abs();
  114. }
  115. /**
  116. * GenPolynomial recursive primitive part.
  117. * @param P recursive GenPolynomial.
  118. * @return pp(P).
  119. */
  120. public GenPolynomial<GenPolynomial<C>> recursivePrimitivePart(GenPolynomial<GenPolynomial<C>> P) {
  121. if (P == null) {
  122. throw new IllegalArgumentException(this.getClass().getName() + " P != null");
  123. }
  124. if (P.isZERO()) {
  125. return P;
  126. }
  127. GenPolynomial<C> d = recursiveContent(P);
  128. if (d.isONE()) {
  129. return P;
  130. }
  131. GenPolynomial<GenPolynomial<C>> pp = PolyUtil.<C> recursiveDivide(P, d);
  132. return pp;
  133. }
  134. /**
  135. * GenPolynomial base recursive content.
  136. * @param P recursive GenPolynomial.
  137. * @return baseCont(P).
  138. */
  139. public C baseRecursiveContent(GenPolynomial<GenPolynomial<C>> P) {
  140. if (P == null) {
  141. throw new IllegalArgumentException(this.getClass().getName() + " P != null");
  142. }
  143. if (P.isZERO()) {
  144. GenPolynomialRing<C> cf = (GenPolynomialRing<C>) P.ring.coFac;
  145. return cf.coFac.getZERO();
  146. }
  147. C d = null;
  148. for (GenPolynomial<C> c : P.getMap().values()) {
  149. C cc = baseContent(c);
  150. if (d == null) {
  151. d = cc;
  152. } else {
  153. d = gcd(d, cc);
  154. }
  155. if (d.isONE()) {
  156. return d;
  157. }
  158. }
  159. if ( d.signum() < 0 ) {
  160. d = d.negate();
  161. }
  162. return d;
  163. }
  164. /**
  165. * GenPolynomial base recursive primitive part.
  166. * @param P recursive GenPolynomial.
  167. * @return basePP(P).
  168. */
  169. public GenPolynomial<GenPolynomial<C>> baseRecursivePrimitivePart(GenPolynomial<GenPolynomial<C>> P) {
  170. if (P == null) {
  171. throw new IllegalArgumentException(this.getClass().getName() + " P != null");
  172. }
  173. if (P.isZERO()) {
  174. return P;
  175. }
  176. C d = baseRecursiveContent(P);
  177. if (d.isONE()) {
  178. return P;
  179. }
  180. GenPolynomial<GenPolynomial<C>> pp = PolyUtil.<C> baseRecursiveDivide(P, d);
  181. return pp;
  182. }
  183. /**
  184. * GenPolynomial recursive greatest common divisor. Uses pseudoRemainder for
  185. * remainder.
  186. * @param P recursive GenPolynomial.
  187. * @param S recursive GenPolynomial.
  188. * @return gcd(P,S).
  189. */
  190. public GenPolynomial<GenPolynomial<C>> recursiveGcd(GenPolynomial<GenPolynomial<C>> P,
  191. GenPolynomial<GenPolynomial<C>> S) {
  192. if (S == null || S.isZERO()) {
  193. return P;
  194. }
  195. if (P == null || P.isZERO()) {
  196. return S;
  197. }
  198. if (P.ring.nvar <= 1) {
  199. return recursiveUnivariateGcd(P, S);
  200. }
  201. // distributed polynomials gcd
  202. GenPolynomialRing<GenPolynomial<C>> rfac = P.ring;
  203. RingFactory<GenPolynomial<C>> rrfac = rfac.coFac;
  204. GenPolynomialRing<C> cfac = (GenPolynomialRing<C>) rrfac;
  205. GenPolynomialRing<C> dfac = cfac.extend(rfac.nvar);
  206. GenPolynomial<C> Pd = PolyUtil.<C> distribute(dfac, P);
  207. GenPolynomial<C> Sd = PolyUtil.<C> distribute(dfac, S);
  208. GenPolynomial<C> Dd = gcd(Pd, Sd);
  209. // convert to recursive
  210. GenPolynomial<GenPolynomial<C>> C = PolyUtil.<C> recursive(rfac, Dd);
  211. return C;
  212. }
  213. /**
  214. * Univariate GenPolynomial recursive greatest common divisor. Uses
  215. * pseudoRemainder for remainder.
  216. * @param P univariate recursive GenPolynomial.
  217. * @param S univariate recursive GenPolynomial.
  218. * @return gcd(P,S).
  219. */
  220. public abstract GenPolynomial<GenPolynomial<C>> recursiveUnivariateGcd(GenPolynomial<GenPolynomial<C>> P,
  221. GenPolynomial<GenPolynomial<C>> S);
  222. /**
  223. * GenPolynomial content.
  224. * @param P GenPolynomial.
  225. * @return cont(P).
  226. */
  227. public GenPolynomial<C> content(GenPolynomial<C> P) {
  228. if (P == null) {
  229. throw new IllegalArgumentException(this.getClass().getName() + " P != null");
  230. }
  231. GenPolynomialRing<C> pfac = P.ring;
  232. if (pfac.nvar <= 1) {
  233. // baseContent not possible by return type
  234. throw new IllegalArgumentException(this.getClass().getName()
  235. + " use baseContent for univariate polynomials");
  236. }
  237. GenPolynomialRing<C> cfac = pfac.contract(1);
  238. GenPolynomialRing<GenPolynomial<C>> rfac = new GenPolynomialRing<GenPolynomial<C>>(cfac, 1);
  239. GenPolynomial<GenPolynomial<C>> Pr = PolyUtil.<C> recursive(rfac, P);
  240. GenPolynomial<C> D = recursiveContent(Pr);
  241. return D;
  242. }
  243. /**
  244. * GenPolynomial primitive part.
  245. * @param P GenPolynomial.
  246. * @return pp(P).
  247. */
  248. public GenPolynomial<C> primitivePart(GenPolynomial<C> P) {
  249. if (P == null) {
  250. throw new IllegalArgumentException(this.getClass().getName() + " P != null");
  251. }
  252. if (P.isZERO()) {
  253. return P;
  254. }
  255. GenPolynomialRing<C> pfac = P.ring;
  256. if (pfac.nvar <= 1) {
  257. return basePrimitivePart(P);
  258. }
  259. GenPolynomialRing<C> cfac = pfac.contract(1);
  260. GenPolynomialRing<GenPolynomial<C>> rfac = new GenPolynomialRing<GenPolynomial<C>>(cfac, 1);
  261. GenPolynomial<GenPolynomial<C>> Pr = PolyUtil.<C> recursive(rfac, P);
  262. GenPolynomial<GenPolynomial<C>> PP = recursivePrimitivePart(Pr);
  263. GenPolynomial<C> D = PolyUtil.<C> distribute(pfac, PP);
  264. return D;
  265. }
  266. /**
  267. * GenPolynomial division. Indirection to GenPolynomial method.
  268. * @param a GenPolynomial.
  269. * @param b coefficient.
  270. * @return a/b.
  271. */
  272. public GenPolynomial<C> divide(GenPolynomial<C> a, C b) {
  273. if (b == null || b.isZERO()) {
  274. throw new IllegalArgumentException(this.getClass().getName() + " division by zero");
  275. }
  276. if (a == null || a.isZERO()) {
  277. return a;
  278. }
  279. return a.divide(b);
  280. }
  281. /**
  282. * Coefficient greatest common divisor. Indirection to coefficient method.
  283. * @param a coefficient.
  284. * @param b coefficient.
  285. * @return gcd(a,b).
  286. */
  287. public C gcd(C a, C b) {
  288. if (b == null || b.isZERO()) {
  289. return a;
  290. }
  291. if (a == null || a.isZERO()) {
  292. return b;
  293. }
  294. return a.gcd(b);
  295. }
  296. /**
  297. * GenPolynomial greatest common divisor.
  298. * @param P GenPolynomial.
  299. * @param S GenPolynomial.
  300. * @return gcd(P,S).
  301. */
  302. public GenPolynomial<C> gcd(GenPolynomial<C> P, GenPolynomial<C> S) {
  303. if (S == null || S.isZERO()) {
  304. return P;
  305. }
  306. if (P == null || P.isZERO()) {
  307. return S;
  308. }
  309. GenPolynomialRing<C> pfac = P.ring;
  310. if (pfac.nvar <= 1) {
  311. GenPolynomial<C> T = baseGcd(P, S);
  312. return T;
  313. }
  314. GenPolynomialRing<C> cfac = pfac.contract(1);
  315. GenPolynomialRing<GenPolynomial<C>> rfac;
  316. if ( pfac.getVars() != null && pfac.getVars().length > 0 ) {
  317. String[] v = new String[] { pfac.getVars()[pfac.nvar-1] };
  318. rfac = new GenPolynomialRing<GenPolynomial<C>>(cfac, 1, v);
  319. } else {
  320. rfac = new GenPolynomialRing<GenPolynomial<C>>(cfac, 1);
  321. }
  322. GenPolynomial<GenPolynomial<C>> Pr = PolyUtil.<C> recursive(rfac, P);
  323. GenPolynomial<GenPolynomial<C>> Sr = PolyUtil.<C> recursive(rfac, S);
  324. GenPolynomial<GenPolynomial<C>> Dr = recursiveUnivariateGcd(Pr, Sr);
  325. GenPolynomial<C> D = PolyUtil.<C> distribute(pfac, Dr);
  326. return D;
  327. }
  328. /**
  329. * GenPolynomial least common multiple.
  330. * @param P GenPolynomial.
  331. * @param S GenPolynomial.
  332. * @return lcm(P,S).
  333. */
  334. public GenPolynomial<C> lcm(GenPolynomial<C> P, GenPolynomial<C> S) {
  335. if (S == null || S.isZERO()) {
  336. return S;
  337. }
  338. if (P == null || P.isZERO()) {
  339. return P;
  340. }
  341. GenPolynomial<C> C = gcd(P, S);
  342. GenPolynomial<C> A = P.multiply(S);
  343. return PolyUtil.<C> basePseudoDivide(A, C);
  344. }
  345. /**
  346. * List of GenPolynomials greatest common divisor.
  347. * @param A non empty list of GenPolynomials.
  348. * @return gcd(A_i).
  349. */
  350. public GenPolynomial<C> gcd(List<GenPolynomial<C>> A) {
  351. if (A == null || A.isEmpty()) {
  352. throw new IllegalArgumentException("A may not be empty");
  353. }
  354. GenPolynomial<C> g = A.get(0);
  355. for ( int i = 1; i < A.size(); i++ ) {
  356. GenPolynomial<C> f = A.get(i);
  357. g = gcd(g,f);
  358. }
  359. return g;
  360. }
  361. /**
  362. * Univariate GenPolynomial resultant.
  363. * @param P univariate GenPolynomial.
  364. * @param S univariate GenPolynomial.
  365. * @return res(P,S).
  366. * @throws UnsupportedOperationException if there is no implementation in the sub-class.
  367. */
  368. public GenPolynomial<C> baseResultant(GenPolynomial<C> P, GenPolynomial<C> S) {
  369. // can not be abstract
  370. throw new UnsupportedOperationException("not implmented");
  371. }
  372. /**
  373. * Univariate GenPolynomial recursive resultant.
  374. * @param P univariate recursive GenPolynomial.
  375. * @param S univariate recursive GenPolynomial.
  376. * @return res(P,S).
  377. * @throws UnsupportedOperationException if there is no implementation in the sub-class.
  378. */
  379. public GenPolynomial<GenPolynomial<C>> recursiveUnivariateResultant(GenPolynomial<GenPolynomial<C>> P,
  380. GenPolynomial<GenPolynomial<C>> S) {
  381. // can not be abstract
  382. throw new UnsupportedOperationException("not implmented");
  383. }
  384. /**
  385. * GenPolynomial recursive resultant.
  386. * @param P univariate recursive GenPolynomial.
  387. * @param S univariate recursive GenPolynomial.
  388. * @return res(P,S).
  389. * @throws UnsupportedOperationException if there is no implementation in the sub-class.
  390. */
  391. public GenPolynomial<GenPolynomial<C>> recursiveResultant(GenPolynomial<GenPolynomial<C>> P,
  392. GenPolynomial<GenPolynomial<C>> S) {
  393. if (S == null || S.isZERO()) {
  394. return S;
  395. }
  396. if (P == null || P.isZERO()) {
  397. return P;
  398. }
  399. GenPolynomialRing<GenPolynomial<C>> rfac = P.ring;
  400. GenPolynomialRing<C> cfac = (GenPolynomialRing<C>) rfac.coFac;
  401. GenPolynomialRing<C> dfac = cfac.extend(rfac.getVars());
  402. GenPolynomial<C> Pp = PolyUtil.<C> distribute(dfac, P);
  403. GenPolynomial<C> Sp = PolyUtil.<C> distribute(dfac, S);
  404. GenPolynomial<C> res = resultant(Pp,Sp);
  405. GenPolynomial<GenPolynomial<C>> Rr = PolyUtil.<C> recursive(rfac, res);
  406. return Rr;
  407. }
  408. /**
  409. * GenPolynomial resultant.
  410. * The input polynomials are considered as univariate polynomials in the main variable.
  411. * @param P GenPolynomial.
  412. * @param S GenPolynomial.
  413. * @return res(P,S).
  414. * @see edu.jas.ufd.GreatestCommonDivisorSubres#recursiveResultant
  415. * @throws UnsupportedOperationException if there is no implementation in the sub-class.
  416. */
  417. public GenPolynomial<C> resultant(GenPolynomial<C> P, GenPolynomial<C> S) {
  418. if (S == null || S.isZERO()) {
  419. return S;
  420. }
  421. if (P == null || P.isZERO()) {
  422. return P;
  423. }
  424. // no more hacked: GreatestCommonDivisorSubres<C> ufd_sr = new GreatestCommonDivisorSubres<C>();
  425. GenPolynomialRing<C> pfac = P.ring;
  426. if (pfac.nvar <= 1) {
  427. return baseResultant(P, S);
  428. }
  429. GenPolynomialRing<C> cfac = pfac.contract(1);
  430. GenPolynomialRing<GenPolynomial<C>> rfac = new GenPolynomialRing<GenPolynomial<C>>(cfac, 1);
  431. GenPolynomial<GenPolynomial<C>> Pr = PolyUtil.<C> recursive(rfac, P);
  432. GenPolynomial<GenPolynomial<C>> Sr = PolyUtil.<C> recursive(rfac, S);
  433. GenPolynomial<GenPolynomial<C>> Dr = recursiveUnivariateResultant(Pr, Sr);
  434. GenPolynomial<C> D = PolyUtil.<C> distribute(pfac, Dr);
  435. return D;
  436. }
  437. /**
  438. * GenPolynomial co-prime list.
  439. * @param A list of GenPolynomials.
  440. * @return B with gcd(b,c) = 1 for all b != c in B and for all non-constant
  441. * a in A there exists b in B with b|a. B does not contain zero or
  442. * constant polynomials.
  443. */
  444. public List<GenPolynomial<C>> coPrime(List<GenPolynomial<C>> A) {
  445. if (A == null || A.isEmpty()) {
  446. return A;
  447. }
  448. List<GenPolynomial<C>> B = new ArrayList<GenPolynomial<C>>(A.size());
  449. // make a coprime to rest of list
  450. GenPolynomial<C> a = A.get(0);
  451. //System.out.println("a = " + a);
  452. if (!a.isZERO() && !a.isConstant()) {
  453. for (int i = 1; i < A.size(); i++) {
  454. GenPolynomial<C> b = A.get(i);
  455. GenPolynomial<C> g = gcd(a, b).abs();
  456. if (!g.isONE()) {
  457. a = PolyUtil.<C> basePseudoDivide(a, g);
  458. b = PolyUtil.<C> basePseudoDivide(b, g);
  459. GenPolynomial<C> gp = gcd(a, g).abs();
  460. while (!gp.isONE()) {
  461. a = PolyUtil.<C> basePseudoDivide(a, gp);
  462. g = PolyUtil.<C> basePseudoDivide(g, gp);
  463. B.add(g); // gcd(a,g) == 1
  464. g = gp;
  465. gp = gcd(a, gp).abs();
  466. }
  467. if (!g.isZERO() && !g.isConstant() /*&& !B.contains(g)*/) {
  468. B.add(g); // gcd(a,g) == 1
  469. }
  470. }
  471. if (!b.isZERO() && !b.isConstant()) {
  472. B.add(b); // gcd(a,b) == 1
  473. }
  474. }
  475. } else {
  476. B.addAll(A.subList(1, A.size()));
  477. }
  478. // make rest coprime
  479. B = coPrime(B);
  480. //System.out.println("B = " + B);
  481. if (!a.isZERO() && !a.isConstant() /*&& !B.contains(a)*/) {
  482. a = a.abs();
  483. B.add(a);
  484. }
  485. return B;
  486. }
  487. /**
  488. * GenPolynomial co-prime list.
  489. * @param A list of GenPolynomials.
  490. * @return B with gcd(b,c) = 1 for all b != c in B and for all non-constant
  491. * a in A there exists b in B with b|a. B does not contain zero or
  492. * constant polynomials.
  493. */
  494. public List<GenPolynomial<C>> coPrimeRec(List<GenPolynomial<C>> A) {
  495. if (A == null || A.isEmpty()) {
  496. return A;
  497. }
  498. List<GenPolynomial<C>> B = new ArrayList<GenPolynomial<C>>();
  499. // make a co-prime to rest of list
  500. for (GenPolynomial<C> a : A) {
  501. //System.out.println("a = " + a);
  502. B = coPrime(a, B);
  503. //System.out.println("B = " + B);
  504. }
  505. return B;
  506. }
  507. /**
  508. * GenPolynomial co-prime list.
  509. * @param a GenPolynomial.
  510. * @param P co-prime list of GenPolynomials.
  511. * @return B with gcd(b,c) = 1 for all b != c in B and for non-constant a
  512. * there exists b in P with b|a. B does not contain zero or constant
  513. * polynomials.
  514. */
  515. public List<GenPolynomial<C>> coPrime(GenPolynomial<C> a, List<GenPolynomial<C>> P) {
  516. if (a == null || a.isZERO() || a.isConstant()) {
  517. return P;
  518. }
  519. List<GenPolynomial<C>> B = new ArrayList<GenPolynomial<C>>(P.size() + 1);
  520. // make a coprime to elements of the list P
  521. for (int i = 0; i < P.size(); i++) {
  522. GenPolynomial<C> b = P.get(i);
  523. GenPolynomial<C> g = gcd(a, b).abs();
  524. if (!g.isONE()) {
  525. a = PolyUtil.<C> basePseudoDivide(a, g);
  526. b = PolyUtil.<C> basePseudoDivide(b, g);
  527. // make g co-prime to new a, g is co-prime to c != b in P, B
  528. GenPolynomial<C> gp = gcd(a, g).abs();
  529. while (!gp.isONE()) {
  530. a = PolyUtil.<C> basePseudoDivide(a, gp);
  531. g = PolyUtil.<C> basePseudoDivide(g, gp);
  532. if (!g.isZERO() && !g.isConstant() /*&& !B.contains(g)*/) {
  533. B.add(g); // gcd(a,g) == 1 and gcd(g,c) == 1 for c != b in P, B
  534. }
  535. g = gp;
  536. gp = gcd(a, gp).abs();
  537. }
  538. // make new g co-prime to new b
  539. gp = gcd(b, g).abs();
  540. while (!gp.isONE()) {
  541. b = PolyUtil.<C> basePseudoDivide(b, gp);
  542. g = PolyUtil.<C> basePseudoDivide(g, gp);
  543. if (!g.isZERO() && !g.isConstant() /*&& !B.contains(g)*/) {
  544. B.add(g); // gcd(a,g) == 1 and gcd(g,c) == 1 for c != b in P, B
  545. }
  546. g = gp;
  547. gp = gcd(b, gp).abs();
  548. }
  549. if (!g.isZERO() && !g.isConstant() /*&& !B.contains(g)*/) {
  550. B.add(g); // gcd(a,g) == 1 and gcd(g,c) == 1 for c != b in P, B
  551. }
  552. }
  553. if (!b.isZERO() && !b.isConstant() /*&& !B.contains(b)*/) {
  554. B.add(b); // gcd(a,b) == 1 and gcd(b,c) == 1 for c != b in P, B
  555. }
  556. }
  557. if (!a.isZERO() && !a.isConstant() /*&& !B.contains(a)*/) {
  558. B.add(a);
  559. }
  560. return B;
  561. }
  562. /**
  563. * GenPolynomial test for co-prime list.
  564. * @param A list of GenPolynomials.
  565. * @return true if gcd(b,c) = 1 for all b != c in B, else false.
  566. */
  567. public boolean isCoPrime(List<GenPolynomial<C>> A) {
  568. if (A == null || A.isEmpty()) {
  569. return true;
  570. }
  571. if (A.size() == 1) {
  572. return true;
  573. }
  574. for (int i = 0; i < A.size(); i++) {
  575. GenPolynomial<C> a = A.get(i);
  576. for (int j = i + 1; j < A.size(); j++) {
  577. GenPolynomial<C> b = A.get(j);
  578. GenPolynomial<C> g = gcd(a, b);
  579. if (!g.isONE()) {
  580. System.out.println("not co-prime, a: " + a);
  581. System.out.println("not co-prime, b: " + b);
  582. System.out.println("not co-prime, g: " + g);
  583. return false;
  584. }
  585. }
  586. }
  587. return true;
  588. }
  589. /**
  590. * GenPolynomial test for co-prime list of given list.
  591. * @param A list of GenPolynomials.
  592. * @param P list of co-prime GenPolynomials.
  593. * @return true if isCoPrime(P) and for all a in A exists p in P with p | a,
  594. * else false.
  595. */
  596. public boolean isCoPrime(List<GenPolynomial<C>> P, List<GenPolynomial<C>> A) {
  597. if (!isCoPrime(P)) {
  598. return false;
  599. }
  600. if (A == null || A.isEmpty()) {
  601. return true;
  602. }
  603. for (GenPolynomial<C> q : A) {
  604. if (q.isZERO() || q.isConstant()) {
  605. continue;
  606. }
  607. boolean divides = false;
  608. for (GenPolynomial<C> p : P) {
  609. GenPolynomial<C> a = PolyUtil.<C> baseSparsePseudoRemainder(q, p);
  610. if (a.isZERO()) { // p divides q
  611. divides = true;
  612. break;
  613. }
  614. }
  615. if (!divides) {
  616. System.out.println("no divisor for: " + q);
  617. return false;
  618. }
  619. }
  620. return true;
  621. }
  622. /**
  623. * Univariate GenPolynomial extended greatest common divisor. Uses sparse
  624. * pseudoRemainder for remainder.
  625. * @param P univariate GenPolynomial.
  626. * @param S univariate GenPolynomial.
  627. * @return [ gcd(P,S), a, b ] with a*P + b*S = gcd(P,S).
  628. */
  629. public GenPolynomial<C>[] baseExtendedGcd(GenPolynomial<C> P, GenPolynomial<C> S) {
  630. //return P.egcd(S);
  631. GenPolynomial<C>[] hegcd = baseHalfExtendedGcd(P,S);
  632. GenPolynomial<C>[] ret = (GenPolynomial<C>[]) new GenPolynomial[3];
  633. ret[0] = hegcd[0];
  634. ret[1] = hegcd[1];
  635. GenPolynomial<C> x = hegcd[0].subtract( hegcd[1].multiply(P) );
  636. GenPolynomial<C>[] qr = PolyUtil.<C> basePseudoQuotientRemainder(x, S);
  637. // assert qr[1].isZERO()
  638. ret[2] = qr[0];
  639. return ret;
  640. }
  641. /**
  642. * Univariate GenPolynomial half extended greatest comon divisor.
  643. * Uses sparse pseudoRemainder for remainder.
  644. * @param S GenPolynomial.
  645. * @return [ gcd(P,S), a ] with a*P + b*S = gcd(P,S).
  646. */
  647. public GenPolynomial<C>[] baseHalfExtendedGcd(GenPolynomial<C> P, GenPolynomial<C> S) {
  648. //if ( P == null ) {
  649. // throw new IllegalArgumentException("null P not allowed");
  650. //}
  651. GenPolynomial<C>[] ret = (GenPolynomial<C>[]) new GenPolynomial[2];
  652. ret[0] = null;
  653. ret[1] = null;
  654. if ( S == null || S.isZERO() ) {
  655. ret[0] = P;
  656. ret[1] = P.ring.getONE();
  657. return ret;
  658. }
  659. if ( P == null || P.isZERO() ) {
  660. ret[0] = S;
  661. ret[1] = S.ring.getZERO();
  662. return ret;
  663. }
  664. if ( P.ring.nvar != 1 ) {
  665. throw new IllegalArgumentException(this.getClass().getName()
  666. + " not univariate polynomials " + P.ring);
  667. }
  668. GenPolynomial<C> q = P;
  669. GenPolynomial<C> r = S;
  670. GenPolynomial<C> c1 = P.ring.getONE().clone();
  671. GenPolynomial<C> d1 = P.ring.getZERO().clone();
  672. while ( !r.isZERO() ) {
  673. GenPolynomial<C>[] qr = PolyUtil.<C> basePseudoQuotientRemainder(q, r);
  674. //q.divideAndRemainder(r);
  675. q = qr[0];
  676. GenPolynomial<C> x = c1.subtract( q.multiply(d1) );
  677. c1 = d1;
  678. d1 = x;
  679. q = r;
  680. r = qr[1];
  681. }
  682. // normalize ldcf(q) to 1, i.e. make monic
  683. C g = q.leadingBaseCoefficient();
  684. if ( g.isUnit() ) {
  685. C h = g.inverse();
  686. q = q.multiply( h );
  687. c1 = c1.multiply( h );
  688. }
  689. //assert ( ((c1.multiply(P)).remainder(S).equals(q) ));
  690. ret[0] = q;
  691. ret[1] = c1;
  692. return ret;
  693. }
  694. /**
  695. * Univariate GenPolynomial greatest common divisor diophantine version.
  696. * @param P univariate GenPolynomial.
  697. * @param S univariate GenPolynomial.
  698. * @param c univariate GenPolynomial.
  699. * @return [ a, b ] with a*P + b*S = c and deg(a) < deg(S).
  700. */
  701. public GenPolynomial<C>[] baseGcdDiophant(GenPolynomial<C> P, GenPolynomial<C> S, GenPolynomial<C> c) {
  702. GenPolynomial<C>[] egcd = baseExtendedGcd(P,S);
  703. GenPolynomial<C> g = egcd[0];
  704. GenPolynomial<C>[] qr = PolyUtil.<C> basePseudoQuotientRemainder(c, g);
  705. if ( !qr[1].isZERO() ) {
  706. throw new ArithmeticException("not solvable, r = " + qr[1] + ", c = " + c + ", g = " + g);
  707. }
  708. GenPolynomial<C> q = qr[0];
  709. GenPolynomial<C> a = egcd[1].multiply(q);
  710. GenPolynomial<C> b = egcd[2].multiply(q);
  711. if ( !a.isZERO() && a.degree(0) >= S.degree(0) ) {
  712. qr = PolyUtil.<C> basePseudoQuotientRemainder(a, S);
  713. a = qr[1];
  714. b = b.sum( P.multiply( qr[0] ) );
  715. }
  716. GenPolynomial<C>[] ret = (GenPolynomial<C>[]) new GenPolynomial[2];
  717. ret[0] = a;
  718. ret[1] = b;
  719. if ( true ) {
  720. return ret;
  721. }
  722. GenPolynomial<C> y = ret[0].multiply(P).sum( ret[1].multiply(S) );
  723. if ( !y.equals(c) ) {
  724. System.out.println("P = " + P);
  725. System.out.println("S = " + S);
  726. System.out.println("c = " + c);
  727. System.out.println("a = " + a);
  728. System.out.println("b = " + b);
  729. System.out.println("y = " + y);
  730. throw new ArithmeticException("not diophant, x = " + y.subtract(c));
  731. }
  732. return ret;
  733. }
  734. /**
  735. * Univariate GenPolynomial partial fraction decomposition.
  736. * @param A univariate GenPolynomial.
  737. * @param P univariate GenPolynomial.
  738. * @param S univariate GenPolynomial.
  739. * @return [ A0, Ap, As ] with A/(P*S) = A0 + Ap/P + As/S with deg(Ap) < deg(P) and deg(As) < deg(S).
  740. */
  741. public GenPolynomial<C>[] basePartialFraction(GenPolynomial<C> A, GenPolynomial<C> P, GenPolynomial<C> S) {
  742. GenPolynomial<C>[] ret = (GenPolynomial<C>[]) new GenPolynomial[3];
  743. ret[0] = null;
  744. ret[1] = null;
  745. ret[2] = null;
  746. GenPolynomial<C> ps = P.multiply(S);
  747. GenPolynomial<C>[] qr = PolyUtil.<C> basePseudoQuotientRemainder(A, ps);
  748. ret[0] = qr[0];
  749. GenPolynomial<C> r = qr[1];
  750. GenPolynomial<C>[] diop = baseGcdDiophant(S,P,r); // switch arguments
  751. // GenPolynomial<C> x = diop[0].multiply(S).sum( diop[1].multiply(P) );
  752. // if ( !x.equals(r) ) {
  753. // System.out.println("r = " + r);
  754. // System.out.println("x = " + x);
  755. // throw new RuntimeException("not partial fraction, x = " + x);
  756. // }
  757. ret[1] = diop[0];
  758. ret[2] = diop[1];
  759. if ( ret[1].degree(0) >= P.degree(0) ) {
  760. qr = PolyUtil.<C> basePseudoQuotientRemainder(ret[1], P);
  761. ret[0] = ret[0].sum( qr[0] );
  762. ret[1] = qr[1];
  763. }
  764. if ( ret[2].degree(0) >= S.degree(0) ) {
  765. qr = PolyUtil.<C> basePseudoQuotientRemainder(ret[2], S);
  766. ret[0] = ret[0].sum( qr[0] );
  767. ret[2] = qr[1];
  768. }
  769. return ret;
  770. }
  771. /**
  772. * Univariate GenPolynomial partial fraction decomposition.
  773. * @param A univariate GenPolynomial.
  774. * @param P univariate GenPolynomial.
  775. * @param e exponent for P.
  776. * @return [ F0, F1, ..., Fe ] with A/(P^e) = sum( Fi / P^i ) with deg(Fi) < deg(P).
  777. */
  778. public List<GenPolynomial<C>> basePartialFraction(GenPolynomial<C> A, GenPolynomial<C> P, int e) {
  779. if ( A == null || P == null || e == 0 ) {
  780. throw new IllegalArgumentException("null A, P or e = 0 not allowed");
  781. }
  782. List<GenPolynomial<C>> pf = new ArrayList<GenPolynomial<C>>( e );
  783. if ( A.isZERO() ) {
  784. for ( int i = 0; i < e; i++ ) {
  785. pf.add(A);
  786. }
  787. return pf;
  788. }
  789. if ( e == 1 ) {
  790. GenPolynomial<C>[] qr = PolyUtil.<C> basePseudoQuotientRemainder(A, P);
  791. pf.add(qr[0]);
  792. pf.add(qr[1]);
  793. return pf;
  794. }
  795. GenPolynomial<C> a = A;
  796. for ( int j = e; j > 0; j-- ) {
  797. GenPolynomial<C>[] qr = PolyUtil.<C> basePseudoQuotientRemainder(a, P);
  798. a = qr[0];
  799. pf.add(0,qr[1]);
  800. }
  801. pf.add(0,a);
  802. return pf;
  803. }
  804. /**
  805. * Univariate GenPolynomial partial fraction decomposition.
  806. * @param A univariate GenPolynomial.
  807. * @param D list of co-prime univariate GenPolynomials.
  808. * @return [ A0, A1,..., An ] with A/prod(D) = A0 + sum( Ai/Di ) with deg(Ai) < deg(Di).
  809. */
  810. public List<GenPolynomial<C>> basePartialFraction(GenPolynomial<C> A, List<GenPolynomial<C>> D) {
  811. if ( D == null || A == null ) {
  812. throw new IllegalArgumentException("null A or D not allowed");
  813. }
  814. List<GenPolynomial<C>> pf = new ArrayList<GenPolynomial<C>>( D.size()+1 );
  815. if ( A.isZERO() || D.size() == 0 ) {
  816. pf.add(A);
  817. for ( int i = 0; i < D.size(); i++ ) {
  818. pf.add(A);
  819. }
  820. return pf;
  821. }
  822. List<GenPolynomial<C>> Dp = new ArrayList<GenPolynomial<C>>( D.size()-1 );
  823. GenPolynomial<C> P = A.ring.getONE();
  824. GenPolynomial<C> d1 = null;
  825. for ( GenPolynomial<C> d : D ) {
  826. if ( d1 == null ) {
  827. d1 = d;
  828. } else {
  829. P = P.multiply(d);
  830. Dp.add(d);
  831. }
  832. }
  833. GenPolynomial<C>[] qr = PolyUtil.<C> basePseudoQuotientRemainder(A, P.multiply(d1));
  834. GenPolynomial<C> A0 = qr[0];
  835. GenPolynomial<C> r = qr[1];
  836. if ( D.size() == 1 ) {
  837. pf.add(A0);
  838. pf.add(r);
  839. return pf;
  840. }
  841. GenPolynomial<C>[] diop = baseGcdDiophant(P,d1,r); // switch arguments
  842. GenPolynomial<C> A1 = diop[0];
  843. GenPolynomial<C> S = diop[1];
  844. List<GenPolynomial<C>> Fr = basePartialFraction(S,Dp);
  845. A0 = A0.sum( Fr.remove(0) );
  846. pf.add(A0);
  847. pf.add(A1);
  848. pf.addAll(Fr);
  849. return pf;
  850. }
  851. /**
  852. * Test for Univariate GenPolynomial partial fraction decomposition.
  853. * @param A univariate GenPolynomial.
  854. * @param D list of (co-prime) univariate GenPolynomials.
  855. * @param F list of univariate GenPolynomials from a partial fraction computation.
  856. * @return true if A/prod(D) = F0 + sum( Fi/Di ) with deg(Fi) < deg(Di), Fi in F,
  857. else false.
  858. */
  859. public boolean isBasePartialFraction(GenPolynomial<C> A, List<GenPolynomial<C>> D, List<GenPolynomial<C>> F) {
  860. if ( D == null || A == null || F == null ) {
  861. throw new IllegalArgumentException("null A, F or D not allowed");
  862. }
  863. if ( D.size() != F.size()-1 ) {
  864. return false;
  865. }
  866. // A0*prod(D) + sum( Ai * Dip ), Dip = prod(D,j!=i)
  867. GenPolynomial<C> P = A.ring.getONE();
  868. for ( GenPolynomial<C> d : D ) {
  869. P = P.multiply(d);
  870. }
  871. List<GenPolynomial<C>> Fp = new ArrayList<GenPolynomial<C>>( F );
  872. GenPolynomial<C> A0 = Fp.remove(0).multiply(P);
  873. //System.out.println("A0 = " + A0);
  874. int j = 0;
  875. for ( GenPolynomial<C> Fi : Fp ) {
  876. P = A.ring.getONE();
  877. int i = 0;
  878. for ( GenPolynomial<C> d : D ) {
  879. if ( i != j ) {
  880. P = P.multiply(d);
  881. }
  882. i++;
  883. }
  884. //System.out.println("Fi = " + Fi);
  885. //System.out.println("P = " + P);
  886. A0 = A0.sum( Fi.multiply(P) );
  887. //System.out.println("A0 = " + A0);
  888. j++;
  889. }
  890. boolean t = A.equals(A0);
  891. if ( ! t ) {
  892. System.out.println("not isPartFrac = " + A0);
  893. }
  894. return t;
  895. }
  896. /**
  897. * Test for Univariate GenPolynomial partial fraction decomposition.
  898. * @param A univariate GenPolynomial.
  899. * @param P univariate GenPolynomial.
  900. * @param e exponent for P.
  901. * @param F list of univariate GenPolynomials from a partial fraction computation.
  902. * @return true if A/(P^e) = F0 + sum( Fi / P^i ) with deg(Fi) < deg(P), Fi in F,
  903. else false.
  904. */
  905. public boolean isBasePartialFraction(GenPolynomial<C> A, GenPolynomial<C> P, int e, List<GenPolynomial<C>> F) {
  906. if ( A == null || P == null || F == null || e == 0 ) {
  907. throw new IllegalArgumentException("null A, P, F or e = 0 not allowed");
  908. }
  909. GenPolynomial<C> A0 = basePartialFractionValue(P,e,F);
  910. // A.ring.getZERO();
  911. // for ( GenPolynomial<C> Fi : F ) {
  912. // A0 = A0.multiply(P);
  913. // A0 = A0.sum(Fi);
  914. // //System.out.println("A0 = " + A0);
  915. // }
  916. boolean t = A.equals(A0);
  917. if ( ! t ) {
  918. System.out.println("not isPartFrac = " + A0);
  919. }
  920. return t;
  921. }
  922. /**
  923. * Test for Univariate GenPolynomial partial fraction decomposition.
  924. * @param P univariate GenPolynomial.
  925. * @param e exponent for P.
  926. * @param F list of univariate GenPolynomials from a partial fraction computation.
  927. * @return (F0 + sum( Fi / P^i )) * P^e.
  928. */
  929. public GenPolynomial<C> basePartialFractionValue(GenPolynomial<C> P, int e, List<GenPolynomial<C>> F) {
  930. if ( P == null || F == null || e == 0 ) {
  931. throw new IllegalArgumentException("null P, F or e = 0 not allowed");
  932. }
  933. GenPolynomial<C> A0 = P.ring.getZERO();
  934. for ( GenPolynomial<C> Fi : F ) {
  935. A0 = A0.multiply(P);
  936. A0 = A0.sum(Fi);
  937. //System.out.println("A0 = " + A0);
  938. }
  939. return A0;
  940. }
  941. }