001/* 002 * $Id: GreatestCommonDivisorSubres.java 5847 2018-06-24 13:46:53Z elbarbary $ 003 */ 004 005package edu.jas.ufd; 006 007 008import java.util.ArrayList; 009import java.util.List; 010 011import org.apache.log4j.Logger; 012 013import edu.jas.poly.GenPolynomial; 014import edu.jas.poly.GenPolynomialRing; 015import edu.jas.poly.PolyUtil; 016import edu.jas.structure.GcdRingElem; 017import edu.jas.structure.RingFactory; 018 019 020/** 021 * Greatest common divisor algorithms with subresultant polynomial remainder 022 * sequence. 023 * @author Heinz Kredel 024 * @author Youssef Elbarbary 025 */ 026 027public class GreatestCommonDivisorSubres<C extends GcdRingElem<C>> extends GreatestCommonDivisorAbstract<C> { 028 029 030 private static final Logger logger = Logger.getLogger(GreatestCommonDivisorSubres.class); 031 032 033 private static final boolean debug = logger.isDebugEnabled(); 034 035 036 /** 037 * GenPolynomial pseudo remainder. For univariate polynomials. 038 * @param P GenPolynomial. 039 * @param S nonzero GenPolynomial. 040 * @return remainder with ldcf(S)<sup>m</sup> P = quotient * S + remainder. 041 * @see edu.jas.poly.GenPolynomial#remainder(edu.jas.poly.GenPolynomial). 042 * @deprecated Use 043 * {@link edu.jas.poly.PolyUtil#baseDensePseudoRemainder(edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial)} 044 * instead 045 */ 046 @Deprecated 047 public GenPolynomial<C> basePseudoRemainder(GenPolynomial<C> P, GenPolynomial<C> S) { 048 return PolyUtil.<C> baseDensePseudoRemainder(P, S); 049 } 050 051 052 /** 053 * GenPolynomial pseudo remainder. For recursive polynomials. 054 * @param P recursive GenPolynomial. 055 * @param S nonzero recursive GenPolynomial. 056 * @return remainder with ldcf(S)<sup>m</sup> P = quotient * S + remainder. 057 * @see edu.jas.poly.GenPolynomial#remainder(edu.jas.poly.GenPolynomial). 058 * @deprecated Use 059 * {@link edu.jas.poly.PolyUtil#recursiveDensePseudoRemainder(edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial)} 060 * instead 061 */ 062 @Deprecated 063 public GenPolynomial<GenPolynomial<C>> recursivePseudoRemainder(GenPolynomial<GenPolynomial<C>> P, 064 GenPolynomial<GenPolynomial<C>> S) { 065 return PolyUtil.<C> recursiveDensePseudoRemainder(P, S); 066 } 067 068 069 /** 070 * Univariate GenPolynomial greatest comon divisor. Uses pseudoRemainder for 071 * remainder. 072 * @param P univariate GenPolynomial. 073 * @param S univariate GenPolynomial. 074 * @return gcd(P,S). 075 */ 076 @Override 077 public GenPolynomial<C> baseGcd(GenPolynomial<C> P, GenPolynomial<C> S) { 078 if (S == null || S.isZERO()) { 079 return P; 080 } 081 if (P == null || P.isZERO()) { 082 return S; 083 } 084 if (P.ring.nvar > 1) { 085 throw new IllegalArgumentException(this.getClass().getName() + " no univariate polynomial"); 086 } 087 long e = P.degree(0); 088 long f = S.degree(0); 089 GenPolynomial<C> q; 090 GenPolynomial<C> r; 091 if (f > e) { 092 r = P; 093 q = S; 094 long g = f; 095 f = e; 096 e = g; 097 } else { 098 q = P; 099 r = S; 100 } 101 if (debug) { 102 logger.debug("degrees: e = " + e + ", f = " + f); 103 } 104 r = r.abs(); 105 q = q.abs(); 106 C a = baseContent(r); 107 C b = baseContent(q); 108 C c = gcd(a, b); // indirection 109 r = divide(r, a); // indirection 110 q = divide(q, b); // indirection 111 if (r.isONE()) { 112 return r.multiply(c); 113 } 114 if (q.isONE()) { 115 return q.multiply(c); 116 } 117 C g = r.ring.getONECoefficient(); 118 C h = r.ring.getONECoefficient(); 119 GenPolynomial<C> x; 120 C z; 121 while (!r.isZERO()) { 122 long delta = q.degree(0) - r.degree(0); 123 //System.out.println("delta = " + delta); 124 x = PolyUtil.<C> baseDensePseudoRemainder(q, r); 125 q = r; 126 if (!x.isZERO()) { 127 z = g.multiply(h.power(delta)); //power(P.ring.coFac, h, delta)); 128 //System.out.println("z = " + z); 129 r = x.divide(z); 130 g = q.leadingBaseCoefficient(); 131 z = g.power(delta); //power(P.ring.coFac, g, delta); 132 h = z.divide(h.power(delta - 1)); //power(P.ring.coFac, h, delta - 1)); 133 //System.out.println("g = " + g); 134 //System.out.println("h = " + h); 135 } else { 136 r = x; 137 } 138 } 139 q = basePrimitivePart(q); 140 return (q.multiply(c)).abs(); 141 } 142 143 144 /** 145 * Univariate GenPolynomial recursive greatest comon divisor. Uses 146 * pseudoRemainder for remainder. 147 * @param P univariate recursive GenPolynomial. 148 * @param S univariate recursive GenPolynomial. 149 * @return gcd(P,S). 150 */ 151 @Override 152 public GenPolynomial<GenPolynomial<C>> recursiveUnivariateGcd(GenPolynomial<GenPolynomial<C>> P, 153 GenPolynomial<GenPolynomial<C>> S) { 154 if (S == null || S.isZERO()) { 155 return P; 156 } 157 if (P == null || P.isZERO()) { 158 return S; 159 } 160 if (P.ring.nvar > 1) { 161 throw new IllegalArgumentException(this.getClass().getName() + " no univariate polynomial"); 162 } 163 long e = P.degree(0); 164 long f = S.degree(0); 165 GenPolynomial<GenPolynomial<C>> q; 166 GenPolynomial<GenPolynomial<C>> r; 167 if (f > e) { 168 r = P; 169 q = S; 170 long g = f; 171 f = e; 172 e = g; 173 } else { 174 q = P; 175 r = S; 176 } 177 if (debug) { 178 logger.debug("degrees: e = " + e + ", f = " + f); 179 } 180 r = r.abs(); 181 q = q.abs(); 182 GenPolynomial<C> a = recursiveContent(r); 183 GenPolynomial<C> b = recursiveContent(q); 184 185 GenPolynomial<C> c = gcd(a, b); // go to recursion 186 //System.out.println("rgcd c = " + c); 187 r = PolyUtil.<C> recursiveDivide(r, a); 188 q = PolyUtil.<C> recursiveDivide(q, b); 189 if (r.isONE()) { 190 return r.multiply(c); 191 } 192 if (q.isONE()) { 193 return q.multiply(c); 194 } 195 GenPolynomial<C> g = r.ring.getONECoefficient(); 196 GenPolynomial<C> h = r.ring.getONECoefficient(); 197 GenPolynomial<GenPolynomial<C>> x; 198 GenPolynomial<C> z = null; 199 while (!r.isZERO()) { 200 long delta = q.degree(0) - r.degree(0); 201 //System.out.println("rgcd delta = " + delta); 202 x = PolyUtil.<C> recursiveDensePseudoRemainder(q, r); 203 if (logger.isDebugEnabled()) { 204 logger.info("recursiveDensePseudoRemainder.bits = " + x.bitLength()); 205 } 206 q = r; 207 if (!x.isZERO()) { 208 z = g.multiply(h.power(delta)); //power(P.ring.coFac, h, delta)); 209 r = PolyUtil.<C> recursiveDivide(x, z); 210 g = q.leadingBaseCoefficient(); 211 z = g.power(delta); //power(P.ring.coFac, g, delta); 212 h = PolyUtil.<C> basePseudoDivide(z, h.power(delta - 1)); // power(P.ring.coFac, h, delta - 1) 213 } else { 214 r = x; 215 } 216 } 217 q = recursivePrimitivePart(q); 218 return q.abs().multiply(c); //.abs(); 219 } 220 221 222 /** 223 * Univariate GenPolynomial resultant. Uses pseudoRemainder for remainder. 224 * @param P univariate GenPolynomial. 225 * @param S univariate GenPolynomial. 226 * @return res(P,S). 227 */ 228 @Override 229 public GenPolynomial<C> baseResultant(GenPolynomial<C> P, GenPolynomial<C> S) { 230 if (S == null || S.isZERO()) { 231 return S; 232 } 233 if (P == null || P.isZERO()) { 234 return P; 235 } 236 if (P.ring.nvar > 1) { 237 throw new IllegalArgumentException(this.getClass().getName() + " no univariate polynomial"); 238 } 239 long e = P.degree(0); 240 long f = S.degree(0); 241 GenPolynomial<C> q; 242 GenPolynomial<C> r; 243 if (f > e) { 244 r = P; 245 q = S; 246 long g = f; 247 f = e; 248 e = g; 249 } else { 250 q = P; 251 r = S; 252 } 253 //r = r.abs(); 254 //q = q.abs(); 255 C a = baseContent(r); 256 C b = baseContent(q); 257 r = divide(r, a); // indirection 258 q = divide(q, b); // indirection 259 RingFactory<C> cofac = P.ring.coFac; 260 C g = cofac.getONE(); 261 C h = cofac.getONE(); 262 C t = a.power(e); //power(cofac, a, e); 263 t = t.multiply(b.power(f)); //power(cofac, b, f)); 264 long s = 1; 265 GenPolynomial<C> x; 266 C z; 267 while (r.degree(0) > 0) { 268 long delta = q.degree(0) - r.degree(0); 269 //System.out.println("delta = " + delta); 270 if ((q.degree(0) % 2 != 0) && (r.degree(0) % 2 != 0)) { 271 s = -s; 272 } 273 x = PolyUtil.<C> baseDensePseudoRemainder(q, r); 274 //System.out.println("x = " + x); 275 q = r; 276 if (x.degree(0) > 0) { 277 z = g.multiply(h.power(delta)); //power(cofac, h, delta)); 278 //System.out.println("z = " + z); 279 r = x.divide(z); 280 g = q.leadingBaseCoefficient(); 281 z = g.power(delta); //power(cofac, g, delta); 282 h = z.divide(h.power(delta - 1)); 283 } else { 284 r = x; 285 } 286 } 287 z = r.leadingBaseCoefficient().power(q.degree(0)); //power(cofac, r.leadingBaseCoefficient(), q.degree(0)); 288 h = z.divide(h.power(q.degree() - 1)); //power(cofac, h, q.degree(0) - 1)); 289 z = h.multiply(t); 290 if (s < 0) { 291 z = z.negate(); 292 } 293 x = P.ring.getONE().multiply(z); 294 return x; 295 } 296 297 298 /** 299 * Univariate GenPolynomial recursive resultant. Uses pseudoRemainder for 300 * remainder. 301 * @param P univariate recursive GenPolynomial. 302 * @param S univariate recursive GenPolynomial. 303 * @return res(P,S). 304 */ 305 @Override 306 public GenPolynomial<GenPolynomial<C>> recursiveUnivariateResultant(GenPolynomial<GenPolynomial<C>> P, 307 GenPolynomial<GenPolynomial<C>> S) { 308 if (S == null || S.isZERO()) { 309 return S; 310 } 311 if (P == null || P.isZERO()) { 312 return P; 313 } 314 if (P.ring.nvar > 1) { 315 throw new IllegalArgumentException(this.getClass().getName() + " no univariate polynomial"); 316 } 317 long e = P.degree(0); 318 long f = S.degree(0); 319 GenPolynomial<GenPolynomial<C>> q; 320 GenPolynomial<GenPolynomial<C>> r; 321 if (f > e) { 322 r = P; 323 q = S; 324 long g = f; 325 f = e; 326 e = g; 327 } else { 328 q = P; 329 r = S; 330 } 331 r = r.abs(); 332 q = q.abs(); 333 GenPolynomial<C> a = recursiveContent(r); 334 GenPolynomial<C> b = recursiveContent(q); 335 r = PolyUtil.<C> recursiveDivide(r, a); 336 q = PolyUtil.<C> recursiveDivide(q, b); 337 RingFactory<GenPolynomial<C>> cofac = P.ring.coFac; 338 GenPolynomial<C> g = cofac.getONE(); 339 GenPolynomial<C> h = cofac.getONE(); 340 GenPolynomial<GenPolynomial<C>> x; 341 GenPolynomial<C> t; 342 if (f == 0 && e == 0 && g.ring.nvar > 0) { 343 // if coeffs are multivariate (and non constant) 344 // otherwise it would be 1 345 t = resultant(a, b); 346 x = P.ring.getONE().multiply(t); 347 return x; 348 } 349 t = a.power(e); //power(cofac, a, e); 350 t = t.multiply(b.power(f)); //power(cofac, b, f)); 351 long s = 1; 352 GenPolynomial<C> z; 353 while (r.degree(0) > 0) { 354 long delta = q.degree(0) - r.degree(0); 355 //System.out.println("delta = " + delta); 356 if ((q.degree(0) % 2 != 0) && (r.degree(0) % 2 != 0)) { 357 s = -s; 358 } 359 x = PolyUtil.<C> recursiveDensePseudoRemainder(q, r); 360 //System.out.println("x = " + x); 361 q = r; 362 if (x.degree(0) > 0) { 363 z = g.multiply(h.power(delta)); //power(P.ring.coFac, h, delta)); 364 r = PolyUtil.<C> recursiveDivide(x, z); 365 g = q.leadingBaseCoefficient(); 366 z = g.power(delta); //power(cofac, g, delta); 367 h = PolyUtil.<C> basePseudoDivide(z, h.power(delta - 1)); //power(cofac, h, delta - 1)); 368 } else { 369 r = x; 370 } 371 } 372 z = r.leadingBaseCoefficient().power(q.degree(0)); //power(cofac, r.leadingBaseCoefficient(), q.degree(0)); 373 h = PolyUtil.<C> basePseudoDivide(z, h.power(q.degree() - 1)); //power(cofac, h, q.degree(0) - 1)); 374 z = h.multiply(t); 375 if (s < 0) { 376 z = z.negate(); 377 } 378 x = P.ring.getONE().multiply(z); 379 return x; 380 } 381 382 383 /** 384 * Univariate GenPolynomial recursive Subresultant list. Uses 385 * pseudoRemainder for remainder. 386 * @param P univariate recursive GenPolynomial. 387 * @param S univariate recursive GenPolynomial. 388 * @return subResList(P,S). 389 * @author Youssef Elbarbary 390 */ 391 public List<GenPolynomial<GenPolynomial<C>>> recursiveUnivariateSubResultantList( 392 GenPolynomial<GenPolynomial<C>> P, GenPolynomial<GenPolynomial<C>> S) { 393 List<GenPolynomial<GenPolynomial<C>>> myList = new ArrayList<GenPolynomial<GenPolynomial<C>>>(); 394 if (S == null || S.isZERO()) { 395 myList.add(S); 396 return myList; 397 } 398 if (P == null || P.isZERO()) { 399 myList.add(P); 400 return myList; 401 } 402 if (P.ring.nvar > 1) { 403 throw new IllegalArgumentException(this.getClass().getName() + " no univariate polynomial"); 404 } 405 long e = P.degree(0); 406 long f = S.degree(0); 407 GenPolynomial<GenPolynomial<C>> q; 408 GenPolynomial<GenPolynomial<C>> r; 409 if (f > e) { 410 r = P; 411 q = S; 412 long g = f; 413 f = e; 414 e = g; 415 } else { 416 q = P; 417 r = S; 418 } 419 r = r.abs(); 420 q = q.abs(); 421 GenPolynomial<C> a = recursiveContent(r); 422 GenPolynomial<C> b = recursiveContent(q); 423 r = PolyUtil.<C> recursiveDivide(r, a); 424 q = PolyUtil.<C> recursiveDivide(q, b); 425 RingFactory<GenPolynomial<C>> cofac = P.ring.coFac; 426 GenPolynomial<C> g = cofac.getONE(); 427 GenPolynomial<C> h = cofac.getONE(); 428 GenPolynomial<GenPolynomial<C>> x; 429 GenPolynomial<C> t; 430 if (f == 0 && e == 0 && g.ring.nvar > 0) { 431 // if coeffs are multivariate (and non constant) 432 // otherwise it would be 1 433 t = resultant(a, b); 434 x = P.ring.getONE().multiply(t); 435 myList.add(x); 436 return myList; 437 } 438 t = a.power(e); // power(cofac, a, e); 439 t = t.multiply(b.power(f)); // power(cofac, b, f)); 440 long s = 1; 441 GenPolynomial<C> z; 442 myList.add(P); // adding R0 443 myList.add(S); // adding R1 444 while (r.degree(0) > 0) { 445 long delta = q.degree(0) - r.degree(0); 446 if ((q.degree(0) % 2 != 0) && (r.degree(0) % 2 != 0)) { 447 s = -s; 448 } 449 x = PolyUtil.<C> recursiveDensePseudoRemainder(q, r); 450 q = r; 451 if (x.degree(0) >= 0) { // fixed: this was changed from > to >= 452 z = g.multiply(h.power(delta)); // power(P.ring.coFac, h, delta)); 453 r = PolyUtil.<C> recursiveDivide(x, z); 454 myList.add(r); 455 g = q.leadingBaseCoefficient(); 456 z = g.power(delta); // power(cofac, g, delta); 457 h = PolyUtil.<C> basePseudoDivide(z, h.power(delta - 1)); // power(cofac, h, delta - 1)); 458 } else { 459 r = x; 460 myList.add(r); 461 } 462 } 463 z = r.leadingBaseCoefficient().power(q.degree(0)); // power(cofac, r.leadingBaseCoefficient(), q.degree(0)); 464 h = PolyUtil.<C> basePseudoDivide(z, h.power(q.degree() - 1)); // power(cofac, h, q.degree(0) - 1)); 465 z = h.multiply(t); 466 if (s < 0) { 467 z = z.negate(); 468 } 469 x = P.ring.getONE().multiply(z); 470 myList.add(x); 471 // Printing the Subresultant List 472 //System.out.println("Liste von den SubResultanten(A - tD'):"); 473 //for (int i = 0; i < myList.size(); i++) { // just for printing the list 474 // System.out.println(myList.get(i)); 475 //} 476 if (logger.isInfoEnabled()) { 477 System.out.println("subResCoeffs: " + myList); 478 //logger.info("subResCoeffs: " + myList); 479 } 480 return myList; 481 } 482 483 484 /** 485 * GenPolynomial base coefficient discriminant. 486 * @param P GenPolynomial. 487 * @return discriminant(P). 488 */ 489 public GenPolynomial<C> baseDiscriminant(GenPolynomial<C> P) { 490 if (P == null) { 491 throw new IllegalArgumentException(this.getClass().getName() + " P != null"); 492 } 493 if (P.isZERO()) { 494 return P; 495 } 496 GenPolynomialRing<C> pfac = P.ring; 497 if (pfac.nvar > 1) { 498 throw new IllegalArgumentException(this.getClass().getName() + " P not univariate"); 499 } 500 C a = P.leadingBaseCoefficient(); 501 a = a.inverse(); 502 GenPolynomial<C> Pp = PolyUtil.<C> baseDeriviative(P); 503 GenPolynomial<C> res = baseResultant(P, Pp); 504 GenPolynomial<C> disc = res.multiply(a); 505 long n = P.degree(0); 506 n = n * (n - 1); 507 n = n / 2; 508 if (n % 2L != 0L) { 509 disc = disc.negate(); 510 } 511 return disc; 512 } 513 514}