001/* 002 * $Id$ 003 */ 004 005package edu.jas.ufd; 006 007 008import java.util.Map; 009import java.util.SortedMap; 010import java.util.TreeMap; 011 012import org.apache.logging.log4j.LogManager; 013import org.apache.logging.log4j.Logger; 014 015import edu.jas.poly.AlgebraicNumber; 016import edu.jas.poly.AlgebraicNumberRing; 017import edu.jas.poly.ExpVector; 018import edu.jas.poly.GenPolynomial; 019import edu.jas.poly.GenPolynomialRing; 020import edu.jas.poly.PolyUtil; 021import edu.jas.structure.GcdRingElem; 022import edu.jas.structure.RingFactory; 023 024 025/** 026 * Squarefree decomposition for coefficient fields of characteristic p. 027 * @author Heinz Kredel 028 */ 029 030public abstract class SquarefreeFieldCharP<C extends GcdRingElem<C>> extends SquarefreeAbstract<C> { 031 032 033 private static final Logger logger = LogManager.getLogger(SquarefreeFieldCharP.class); 034 035 036 private static final boolean debug = logger.isDebugEnabled(); 037 038 039 /* 040 * Squarefree engine for characteristic p base coefficients. 041 */ 042 //protected final SquarefreeAbstract<C> rengine; 043 044 045 /** 046 * Factory for finite field of characteristic p coefficients. 047 */ 048 protected final RingFactory<C> coFac; 049 050 051 /** 052 * Factory for a algebraic extension of a finite field of characteristic p 053 * coefficients. If <code>coFac</code> is an algebraic extension, then 054 * <code>aCoFac</code> is equal to <code>coFac</code>, else 055 * <code>aCoFac</code> is <code>null</code>. 056 */ 057 protected final AlgebraicNumberRing<C> aCoFac; 058 059 060 /** 061 * Factory for a transcendental extension of a finite field of 062 * characteristic p coefficients. If <code>coFac</code> is an transcendental 063 * extension, then <code>qCoFac</code> is equal to <code>coFac</code>, else 064 * <code>qCoFac</code> is <code>null</code>. 065 */ 066 protected final QuotientRing<C> qCoFac; 067 068 069 /** 070 * Constructor. 071 */ 072 @SuppressWarnings("unchecked") 073 public SquarefreeFieldCharP(RingFactory<C> fac) { 074 super(GCDFactory.<C> getProxy(fac)); 075 if (!fac.isField()) { 076 //throw new IllegalArgumentException("fac must be a field: " + fac.toScript()); 077 logger.warn("fac should be a field: {}", fac.toScript()); 078 } 079 if (fac.characteristic().signum() == 0) { 080 throw new IllegalArgumentException("characterisic(fac) must be non-zero"); 081 } 082 coFac = fac; 083 Object oFac = coFac; 084 if (oFac instanceof AlgebraicNumberRing) { 085 aCoFac = (AlgebraicNumberRing<C>) oFac; // <C> is not correct 086 //rengine = (SquarefreeAbstract) SquarefreeFactory.getImplementation(aCoFac.ring); 087 qCoFac = null; 088 } else { 089 aCoFac = null; 090 if (oFac instanceof QuotientRing) { 091 qCoFac = (QuotientRing<C>) oFac; // <C> is not correct 092 //rengine = (SquarefreeAbstract) SquarefreeFactory.getImplementation(qCoFac.ring); 093 } else { 094 qCoFac = null; 095 } 096 } 097 } 098 099 100 /** 101 * Get the String representation. 102 * @see java.lang.Object#toString() 103 */ 104 @Override 105 public String toString() { 106 return getClass().getName() + " with " + engine + " over " + coFac; 107 } 108 109 110 /** 111 * GenPolynomial polynomial greatest squarefree divisor. 112 * @param P GenPolynomial. 113 * @return squarefree(pp(P)). 114 */ 115 @Override 116 public GenPolynomial<C> baseSquarefreePart(GenPolynomial<C> P) { 117 if (P == null || P.isZERO()) { 118 return P; 119 } 120 GenPolynomialRing<C> pfac = P.ring; 121 if (pfac.nvar > 1) { 122 throw new IllegalArgumentException( 123 this.getClass().getName() + " only for univariate polynomials"); 124 } 125 GenPolynomial<C> s = pfac.getONE(); 126 SortedMap<GenPolynomial<C>, Long> factors = baseSquarefreeFactors(P); 127 //if (logger.isWarnEnabled()) { 128 // logger.warn("sqfPart, better use sqfFactors, factors = {}", factors); 129 //} 130 for (GenPolynomial<C> sp : factors.keySet()) { 131 s = s.multiply(sp); 132 } 133 s = s.monic(); 134 return s; 135 } 136 137 138 /** 139 * GenPolynomial polynomial squarefree factorization. 140 * @param A GenPolynomial. 141 * @return [p_1 -> e_1, ..., p_k -> e_k] with A = prod_{i=1,...,k} 142 * p_i^{e_i} and p_i squarefree and gcd(p_i, p_j) = 1, for i != j. 143 */ 144 @Override 145 public SortedMap<GenPolynomial<C>, Long> baseSquarefreeFactors(GenPolynomial<C> A) { 146 SortedMap<GenPolynomial<C>, Long> sfactors = new TreeMap<GenPolynomial<C>, Long>(); 147 if (A == null || A.isZERO()) { 148 return sfactors; 149 } 150 GenPolynomialRing<C> pfac = A.ring; 151 if (A.isConstant()) { 152 C coeff = A.leadingBaseCoefficient(); 153 //System.out.println("coeff = " + coeff + " @ " + coeff.factory()); 154 SortedMap<C, Long> rfactors = squarefreeFactors(coeff); 155 //System.out.println("rfactors,const = " + rfactors); 156 if (rfactors != null && rfactors.size() > 0) { 157 for (Map.Entry<C, Long> me : rfactors.entrySet()) { 158 C c = me.getKey(); 159 if (!c.isONE()) { 160 GenPolynomial<C> cr = pfac.getONE().multiply(c); 161 Long rk = me.getValue(); // rfactors.get(c); 162 sfactors.put(cr, rk); 163 } 164 } 165 } else { 166 sfactors.put(A, 1L); 167 } 168 return sfactors; 169 } 170 if (pfac.nvar > 1) { 171 throw new IllegalArgumentException( 172 this.getClass().getName() + " only for univariate polynomials"); 173 } 174 C ldbcf = A.leadingBaseCoefficient(); 175 if (!ldbcf.isONE()) { 176 A = A.divide(ldbcf); 177 SortedMap<C, Long> rfactors = squarefreeFactors(ldbcf); 178 //System.out.println("rfactors,ldbcf = " + rfactors); 179 if (rfactors != null && rfactors.size() > 0) { 180 for (Map.Entry<C, Long> me : rfactors.entrySet()) { 181 C c = me.getKey(); 182 if (!c.isONE()) { 183 GenPolynomial<C> cr = pfac.getONE().multiply(c); 184 Long rk = me.getValue(); //rfactors.get(c); 185 sfactors.put(cr, rk); 186 } 187 } 188 } else { 189 GenPolynomial<C> f1 = pfac.getONE().multiply(ldbcf); 190 //System.out.println("gcda sqf f1 = " + f1); 191 sfactors.put(f1, 1L); 192 } 193 ldbcf = pfac.coFac.getONE(); 194 } 195 // divide by trailing term 196 ExpVector et = A.trailingExpVector(); 197 if (!et.isZERO()) { 198 GenPolynomial<C> tr = pfac.valueOf(et); 199 logger.info("trailing term = {}", tr); 200 A = PolyUtil.<C> basePseudoDivide(A, tr); 201 long ep = et.getVal(0); // univariate 202 et = et.subst(0, 1); 203 tr = pfac.valueOf(et); 204 logger.info("tr, ep = {}, {}", tr, ep); 205 sfactors.put(tr, ep); 206 if (A.length() == 1) { 207 return sfactors; 208 } 209 } 210 GenPolynomial<C> T0 = A; 211 long e = 1L; 212 GenPolynomial<C> Tp; 213 GenPolynomial<C> T = null; 214 GenPolynomial<C> V = null; 215 long k = 0L; 216 long mp = 0L; 217 boolean init = true; 218 while (true) { 219 //System.out.println("T0 = " + T0); 220 if (init) { 221 if (T0.isConstant() || T0.isZERO()) { 222 break; 223 } 224 Tp = PolyUtil.<C> baseDeriviative(T0); 225 T = engine.baseGcd(T0, Tp); 226 T = T.monic(); 227 V = PolyUtil.<C> basePseudoDivide(T0, T); 228 //System.out.println("iT0 = " + T0); 229 //System.out.println("iTp = " + Tp); 230 //System.out.println("iT = " + T); 231 //System.out.println("iV = " + V); 232 //System.out.println("const(iV) = " + V.isConstant()); 233 k = 0L; 234 mp = 0L; 235 init = false; 236 } 237 if (V.isConstant()) { 238 mp = pfac.characteristic().longValueExact(); // assert != 0 239 //T0 = PolyUtil.<C> baseModRoot(T,mp); 240 T0 = baseRootCharacteristic(T); 241 logger.info("char root: T0 = {}, T = {}", T0, T); 242 if (T0 == null) { 243 //break; 244 T0 = pfac.getZERO(); 245 } 246 e = e * mp; 247 init = true; 248 continue; 249 } 250 k++; 251 if (mp != 0L && k % mp == 0L) { 252 T = PolyUtil.<C> basePseudoDivide(T, V); 253 System.out.println("k = " + k); 254 //System.out.println("T = " + T); 255 k++; 256 } 257 GenPolynomial<C> W = engine.baseGcd(T, V); 258 W = W.monic(); 259 GenPolynomial<C> z = PolyUtil.<C> basePseudoDivide(V, W); 260 //System.out.println("W = " + W); 261 //System.out.println("z = " + z); 262 V = W; 263 T = PolyUtil.<C> basePseudoDivide(T, V); 264 //System.out.println("V = " + V); 265 //System.out.println("T = " + T); 266 if (z.degree(0) > 0) { 267 if (ldbcf.isONE() && !z.leadingBaseCoefficient().isONE()) { 268 z = z.monic(); 269 //logger.info("z,monic = {}", z); 270 } 271 logger.info("z, k = {}, {}", z, k); 272 sfactors.put(z, (e * k)); 273 } 274 } 275 logger.info("exit char root: T0 = {}, T = {}", T0, T); 276 return sfactors; 277 } 278 279 280 /** 281 * GenPolynomial recursive univariate polynomial greatest squarefree 282 * divisor. 283 * @param P recursive univariate GenPolynomial. 284 * @return squarefree(pp(P)). 285 */ 286 @Override 287 public GenPolynomial<GenPolynomial<C>> recursiveUnivariateSquarefreePart( 288 GenPolynomial<GenPolynomial<C>> P) { 289 if (P == null || P.isZERO()) { 290 return P; 291 } 292 GenPolynomialRing<GenPolynomial<C>> pfac = P.ring; 293 if (pfac.nvar > 1) { 294 throw new IllegalArgumentException( 295 this.getClass().getName() + " only for univariate polynomials"); 296 } 297 GenPolynomial<GenPolynomial<C>> s = pfac.getONE(); 298 SortedMap<GenPolynomial<GenPolynomial<C>>, Long> factors = recursiveUnivariateSquarefreeFactors(P); 299 if (logger.isWarnEnabled()) { 300 logger.info("sqfPart, better use sqfFactors, factors = {}", factors); 301 } 302 for (GenPolynomial<GenPolynomial<C>> sp : factors.keySet()) { 303 s = s.multiply(sp); 304 } 305 s = PolyUtil.<C> monic(s); 306 return s; 307 } 308 309 310 /** 311 * GenPolynomial recursive univariate polynomial squarefree factorization. 312 * @param P recursive univariate GenPolynomial. 313 * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} 314 * p_i^{e_i} and p_i squarefree and gcd(p_i, p_j) = 1, for i != j. 315 */ 316 @Override 317 public SortedMap<GenPolynomial<GenPolynomial<C>>, Long> recursiveUnivariateSquarefreeFactors( 318 GenPolynomial<GenPolynomial<C>> P) { 319 SortedMap<GenPolynomial<GenPolynomial<C>>, Long> sfactors = new TreeMap<GenPolynomial<GenPolynomial<C>>, Long>(); 320 if (P == null || P.isZERO()) { 321 return sfactors; 322 } 323 GenPolynomialRing<GenPolynomial<C>> pfac = P.ring; 324 if (pfac.nvar > 1) { 325 // recursiveContent not possible by return type 326 throw new IllegalArgumentException( 327 this.getClass().getName() + " only for univariate polynomials"); 328 } 329 // if base coefficient ring is a field, make monic 330 GenPolynomialRing<C> cfac = (GenPolynomialRing<C>) pfac.coFac; 331 C ldbcf = P.leadingBaseCoefficient().leadingBaseCoefficient(); 332 if (!ldbcf.isONE()) { 333 GenPolynomial<C> lc = cfac.getONE().multiply(ldbcf); 334 GenPolynomial<GenPolynomial<C>> pl = pfac.getONE().multiply(lc); 335 sfactors.put(pl, 1L); 336 C li = ldbcf.inverse(); 337 //System.out.println("li = " + li); 338 P = P.multiply(cfac.getONE().multiply(li)); 339 //System.out.println("P,monic = " + P); 340 ldbcf = P.leadingBaseCoefficient().leadingBaseCoefficient(); 341 logger.debug("new ldbcf: {}", ldbcf); 342 } 343 // factors of content 344 GenPolynomial<C> Pc = engine.recursiveContent(P); 345 logger.info("Pc = {}", Pc); 346 Pc = Pc.monic(); 347 if (!Pc.isONE()) { 348 P = PolyUtil.<C> coefficientPseudoDivide(P, Pc); 349 } 350 SortedMap<GenPolynomial<C>, Long> rsf = squarefreeFactors(Pc); 351 logger.info("rsf = {}", rsf); 352 // add factors of content 353 for (Map.Entry<GenPolynomial<C>, Long> me : rsf.entrySet()) { 354 GenPolynomial<C> c = me.getKey(); 355 if (!c.isONE()) { 356 GenPolynomial<GenPolynomial<C>> cr = pfac.getONE().multiply(c); 357 Long rk = me.getValue(); //rsf.get(c); 358 sfactors.put(cr, rk); 359 } 360 } 361 // divide by trailing term 362 ExpVector et = P.trailingExpVector(); 363 if (!et.isZERO()) { 364 GenPolynomial<GenPolynomial<C>> tr = pfac.valueOf(et); 365 logger.info("trailing term = {}", tr); 366 P = PolyUtil.<C> recursivePseudoDivide(P, tr); 367 long ep = et.getVal(0); // univariate 368 et = et.subst(0, 1); 369 tr = pfac.valueOf(et); 370 sfactors.put(tr, ep); 371 } 372 373 // factors of recursive polynomial 374 GenPolynomial<GenPolynomial<C>> T0 = P; 375 long e = 1L; 376 GenPolynomial<GenPolynomial<C>> Tp; 377 GenPolynomial<GenPolynomial<C>> T = null; 378 GenPolynomial<GenPolynomial<C>> V = null; 379 long k = 0L; 380 long mp = 0L; 381 boolean init = true; 382 while (true) { 383 if (init) { 384 if (T0.isConstant() || T0.isZERO()) { 385 break; 386 } 387 Tp = PolyUtil.<C> recursiveDeriviative(T0); 388 //System.out.println("iT0 = " + T0); 389 //System.out.println("iTp = " + Tp); 390 T = engine.recursiveUnivariateGcd(T0, Tp); 391 T = PolyUtil.<C> monic(T); 392 V = PolyUtil.<C> recursivePseudoDivide(T0, T); 393 //System.out.println("iT = " + T); 394 //System.out.println("iV = " + V); 395 k = 0L; 396 mp = 0L; 397 init = false; 398 } 399 if (V.isConstant()) { 400 mp = pfac.characteristic().longValueExact(); // assert != 0 401 //T0 = PolyUtil.<C> recursiveModRoot(T,mp); 402 T0 = recursiveUnivariateRootCharacteristic(T); 403 logger.info("char root: T0r = {}, Tr = {}", T0, T); 404 if (T0 == null) { 405 //break; 406 T0 = pfac.getZERO(); 407 } 408 e = e * mp; 409 init = true; 410 //continue; 411 } 412 k++; 413 if (mp != 0L && k % mp == 0L) { 414 T = PolyUtil.<C> recursivePseudoDivide(T, V); 415 System.out.println("k = " + k); 416 //System.out.println("T = " + T); 417 k++; 418 } 419 GenPolynomial<GenPolynomial<C>> W = engine.recursiveUnivariateGcd(T, V); 420 W = PolyUtil.<C> monic(W); 421 GenPolynomial<GenPolynomial<C>> z = PolyUtil.<C> recursivePseudoDivide(V, W); 422 //System.out.println("W = " + W); 423 //System.out.println("z = " + z); 424 V = W; 425 T = PolyUtil.<C> recursivePseudoDivide(T, V); 426 //System.out.println("V = " + V); 427 //System.out.println("T = " + T); 428 //was: if ( z.degree(0) > 0 ) { 429 if (!z.isONE() && !z.isZERO()) { 430 z = PolyUtil.<C> monic(z); 431 logger.info("z,put = {}", z); 432 sfactors.put(z, (e * k)); 433 } 434 } 435 logger.info("exit char root: T0 = {}, T = {}", T0, T); 436 if (sfactors.size() == 0) { 437 sfactors.put(pfac.getONE(), 1L); 438 } 439 return sfactors; 440 } 441 442 443 /** 444 * GenPolynomial greatest squarefree divisor. 445 * @param P GenPolynomial. 446 * @return squarefree(pp(P)). 447 */ 448 @Override 449 public GenPolynomial<C> squarefreePart(GenPolynomial<C> P) { 450 if (P == null) { 451 throw new IllegalArgumentException(this.getClass().getName() + " P != null"); 452 } 453 if (P.isZERO()) { 454 return P; 455 } 456 GenPolynomialRing<C> pfac = P.ring; 457 if (pfac.nvar <= 1) { 458 return baseSquarefreePart(P); 459 } 460 GenPolynomial<C> s = pfac.getONE(); 461 SortedMap<GenPolynomial<C>, Long> factors = squarefreeFactors(P); 462 if (logger.isWarnEnabled()) { 463 logger.info("sqfPart, better use sqfFactors, factors = {}", factors); 464 } 465 for (GenPolynomial<C> sp : factors.keySet()) { 466 if (sp.isConstant()) { 467 continue; 468 } 469 s = s.multiply(sp); 470 } 471 return s.monic(); 472 } 473 474 475 /** 476 * GenPolynomial squarefree factorization. 477 * @param P GenPolynomial. 478 * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} 479 * p_i^{e_i} and p_i squarefree and gcd(p_i, p_j) = 1, for i != j. 480 */ 481 @Override 482 public SortedMap<GenPolynomial<C>, Long> squarefreeFactors(GenPolynomial<C> P) { 483 if (P == null) { 484 throw new IllegalArgumentException(this.getClass().getName() + " P != null"); 485 } 486 GenPolynomialRing<C> pfac = P.ring; 487 if (pfac.nvar <= 1) { 488 return baseSquarefreeFactors(P); 489 } 490 SortedMap<GenPolynomial<C>, Long> sfactors = new TreeMap<GenPolynomial<C>, Long>(); 491 if (P.isZERO()) { 492 return sfactors; 493 } 494 if (P.isONE()) { 495 sfactors.put(P, 1L); 496 return sfactors; 497 } 498 GenPolynomialRing<GenPolynomial<C>> rfac = pfac.recursive(1); 499 GenPolynomial<GenPolynomial<C>> Pr = PolyUtil.<C> recursive(rfac, P); 500 SortedMap<GenPolynomial<GenPolynomial<C>>, Long> PP = recursiveUnivariateSquarefreeFactors(Pr); 501 for (Map.Entry<GenPolynomial<GenPolynomial<C>>, Long> m : PP.entrySet()) { 502 Long i = m.getValue(); 503 GenPolynomial<GenPolynomial<C>> Dr = m.getKey(); 504 GenPolynomial<C> D = PolyUtil.<C> distribute(pfac, Dr); 505 sfactors.put(D, i); 506 } 507 return sfactors; 508 } 509 510 511 /** 512 * Coefficient squarefree factorization. 513 * @param coeff coefficient. 514 * @return [p_1 -> e_1, ..., p_k -> e_k] with coeff = prod_{i=1,...,k} 515 * p_i^{e_i} and p_i squarefree and gcd(p_i, p_j) = 1, for i != j. 516 */ 517 @SuppressWarnings("unchecked") 518 @Override 519 public SortedMap<C, Long> squarefreeFactors(C coeff) { 520 if (coeff == null) { 521 return null; 522 } 523 SortedMap<C, Long> factors = new TreeMap<C, Long>(); 524 RingFactory<C> cfac = (RingFactory<C>) coeff.factory(); 525 if (aCoFac != null) { 526 AlgebraicNumber<C> an = (AlgebraicNumber<C>) (Object) coeff; 527 if (cfac.isFinite()) { 528 SquarefreeFiniteFieldCharP<C> reng = (SquarefreeFiniteFieldCharP) SquarefreeFactory 529 .getImplementation(cfac); 530 SortedMap<C, Long> rfactors = reng.rootCharacteristic(coeff); // ?? 531 logger.info("rfactors,finite = {}", rfactors); 532 factors.putAll(rfactors); 533 //return factors; 534 } else { 535 SquarefreeInfiniteAlgebraicFieldCharP<C> reng = (SquarefreeInfiniteAlgebraicFieldCharP) SquarefreeFactory 536 .getImplementation(cfac); 537 SortedMap<AlgebraicNumber<C>, Long> rfactors = reng.squarefreeFactors(an); 538 logger.info("rfactors,infinite,algeb = {}", rfactors); 539 for (Map.Entry<AlgebraicNumber<C>, Long> me : rfactors.entrySet()) { 540 AlgebraicNumber<C> c = me.getKey(); 541 if (!c.isONE()) { 542 C cr = (C) (Object) c; 543 Long rk = me.getValue(); 544 factors.put(cr, rk); 545 } 546 } 547 } 548 } else if (qCoFac != null) { 549 Quotient<C> q = (Quotient<C>) (Object) coeff; 550 SquarefreeInfiniteFieldCharP<C> reng = (SquarefreeInfiniteFieldCharP) SquarefreeFactory 551 .getImplementation(cfac); 552 SortedMap<Quotient<C>, Long> rfactors = reng.squarefreeFactors(q); 553 logger.info("rfactors,infinite = {}", rfactors); 554 for (Map.Entry<Quotient<C>, Long> me : rfactors.entrySet()) { 555 Quotient<C> c = me.getKey(); 556 if (!c.isONE()) { 557 C cr = (C) (Object) c; 558 Long rk = me.getValue(); 559 factors.put(cr, rk); 560 } 561 } 562 } else if (cfac.isFinite()) { 563 SquarefreeFiniteFieldCharP<C> reng = (SquarefreeFiniteFieldCharP) SquarefreeFactory 564 .getImplementation(cfac); 565 SortedMap<C, Long> rfactors = reng.rootCharacteristic(coeff); // ?? 566 logger.info("rfactors,finite = {}", rfactors); 567 factors.putAll(rfactors); 568 //return factors; 569 } else { 570 logger.warn("case {} not implemented", cfac); 571 } 572 return factors; 573 } 574 575 576 /* --------- char-th roots --------------------- */ 577 578 579 /** 580 * GenPolynomial char-th root univariate polynomial. 581 * @param P GenPolynomial. 582 * @return char-th_rootOf(P), or null if no char-th root. 583 */ 584 public abstract GenPolynomial<C> baseRootCharacteristic(GenPolynomial<C> P); 585 586 587 /** 588 * GenPolynomial char-th root univariate polynomial with polynomial 589 * coefficients. 590 * @param P recursive univariate GenPolynomial. 591 * @return char-th_rootOf(P), or null if P is no char-th root. 592 */ 593 public abstract GenPolynomial<GenPolynomial<C>> recursiveUnivariateRootCharacteristic( 594 GenPolynomial<GenPolynomial<C>> P); 595 596 597 /** 598 * Polynomial is char-th root. 599 * @param P polynomial. 600 * @param F = [p_1 -> e_1, ..., p_k -> e_k]. 601 * @return true if P = prod_{i=1,...,k} p_i**(e_i*p), else false. 602 */ 603 public boolean isCharRoot(GenPolynomial<C> P, SortedMap<GenPolynomial<C>, Long> F) { 604 if (P == null || F == null) { 605 throw new IllegalArgumentException("P and F may not be null"); 606 } 607 if (P.isZERO() && F.size() == 0) { 608 return true; 609 } 610 GenPolynomial<C> t = P.ring.getONE(); 611 long p = P.ring.characteristic().longValueExact(); 612 for (Map.Entry<GenPolynomial<C>, Long> me : F.entrySet()) { 613 GenPolynomial<C> f = me.getKey(); 614 Long E = me.getValue(); 615 long e = E.longValue(); 616 GenPolynomial<C> g = f.power(e); 617 if (!f.isConstant()) { 618 g = g.power(p); 619 } 620 t = t.multiply(g); 621 } 622 boolean f = P.equals(t) || P.equals(t.negate()); 623 if (!f) { 624 System.out.println("\nfactorization(map): " + f); 625 System.out.println("P = " + P); 626 System.out.println("t = " + t); 627 P = P.monic(); 628 t = t.monic(); 629 f = P.equals(t) || P.equals(t.negate()); 630 if (f) { 631 return f; 632 } 633 System.out.println("\nfactorization(map): " + f); 634 System.out.println("P = " + P); 635 System.out.println("t = " + t); 636 } 637 return f; 638 } 639 640 641 /** 642 * Recursive polynomial is char-th root. 643 * @param P recursive polynomial. 644 * @param F = [p_1 -> e_1, ..., p_k -> e_k]. 645 * @return true if P = prod_{i=1,...,k} p_i**(e_i*p), else false. 646 */ 647 public boolean isRecursiveCharRoot(GenPolynomial<GenPolynomial<C>> P, 648 SortedMap<GenPolynomial<GenPolynomial<C>>, Long> F) { 649 if (P == null || F == null) { 650 throw new IllegalArgumentException("P and F may not be null"); 651 } 652 if (P.isZERO() && F.size() == 0) { 653 return true; 654 } 655 GenPolynomial<GenPolynomial<C>> t = P.ring.getONE(); 656 long p = P.ring.characteristic().longValueExact(); 657 for (Map.Entry<GenPolynomial<GenPolynomial<C>>, Long> me : F.entrySet()) { 658 GenPolynomial<GenPolynomial<C>> f = me.getKey(); 659 Long E = me.getValue(); 660 long e = E.longValue(); 661 GenPolynomial<GenPolynomial<C>> g = f.power(e); 662 if (!f.isConstant()) { 663 g = g.power(p); 664 } 665 t = t.multiply(g); 666 } 667 boolean f = P.equals(t) || P.equals(t.negate()); 668 if (!f) { 669 System.out.println("\nfactorization(map): " + f); 670 System.out.println("P = " + P); 671 System.out.println("t = " + t); 672 P = P.monic(); 673 t = t.monic(); 674 f = P.equals(t) || P.equals(t.negate()); 675 if (f) { 676 return f; 677 } 678 System.out.println("\nfactorization(map): " + f); 679 System.out.println("P = " + P); 680 System.out.println("t = " + t); 681 } 682 return f; 683 } 684 685 686 /** 687 * Recursive polynomial is char-th root. 688 * @param P recursive polynomial. 689 * @param r = recursive polynomial. 690 * @return true if P = r**p, else false. 691 */ 692 public boolean isRecursiveCharRoot(GenPolynomial<GenPolynomial<C>> P, GenPolynomial<GenPolynomial<C>> r) { 693 if (P == null || r == null) { 694 throw new IllegalArgumentException("P and r may not be null"); 695 } 696 if (P.isZERO() && r.isZERO()) { 697 return true; 698 } 699 long p = P.ring.characteristic().longValueExact(); 700 GenPolynomial<GenPolynomial<C>> t = r.power(p); 701 702 boolean f = P.equals(t) || P.equals(t.negate()); 703 if (!f) { 704 System.out.println("\nisCharRoot: " + f); 705 System.out.println("P = " + P); 706 System.out.println("t = " + t); 707 P = P.monic(); 708 t = t.monic(); 709 f = P.equals(t) || P.equals(t.negate()); 710 if (f) { 711 return f; 712 } 713 System.out.println("\nisCharRoot: " + f); 714 System.out.println("P = " + P); 715 System.out.println("t = " + t); 716 } 717 return f; 718 } 719 720}