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.ExpVector; 016import edu.jas.poly.GenPolynomial; 017import edu.jas.poly.GenPolynomialRing; 018import edu.jas.poly.PolyUtil; 019import edu.jas.structure.GcdRingElem; 020import edu.jas.structure.RingFactory; 021 022 023/** 024 * Squarefree decomposition for coefficient fields of characteristic 0. 025 * @author Heinz Kredel 026 */ 027 028public class SquarefreeFieldChar0<C extends GcdRingElem<C>> extends SquarefreeAbstract<C> { 029 030 031 private static final Logger logger = LogManager.getLogger(SquarefreeFieldChar0.class); 032 033 034 //private static final boolean debug = logger.isDebugEnabled(); 035 036 037 /** 038 * Factory for field of characteristic 0 coefficients. 039 */ 040 protected final RingFactory<C> coFac; 041 042 043 /** 044 * Constructor. 045 */ 046 public SquarefreeFieldChar0(RingFactory<C> fac) { 047 super(GCDFactory.<C> getProxy(fac)); 048 if (!fac.isField()) { 049 throw new IllegalArgumentException("fac must be a field"); 050 } 051 if (fac.characteristic().signum() != 0) { 052 throw new IllegalArgumentException("characterisic(fac) must be zero"); 053 } 054 coFac = fac; 055 } 056 057 058 /** 059 * Get the String representation. 060 * @see java.lang.Object#toString() 061 */ 062 @Override 063 public String toString() { 064 return getClass().getName() + " with " + engine + " over " + coFac; 065 } 066 067 068 /** 069 * GenPolynomial polynomial greatest squarefree divisor. 070 * @param P GenPolynomial. 071 * @return squarefree(pp(P)). 072 */ 073 @Override 074 public GenPolynomial<C> baseSquarefreePart(GenPolynomial<C> P) { 075 if (P == null || P.isZERO()) { 076 return P; 077 } 078 GenPolynomialRing<C> pfac = P.ring; 079 if (pfac.nvar > 1) { 080 throw new IllegalArgumentException( 081 this.getClass().getName() + " only for univariate polynomials"); 082 } 083 GenPolynomial<C> pp = P.monic(); 084 if (pp.isConstant()) { 085 return pp; 086 } 087 GenPolynomial<C> d = PolyUtil.<C> baseDeriviative(pp); 088 d = d.monic(); 089 //System.out.println("d = " + d); 090 GenPolynomial<C> g = engine.baseGcd(pp, d); 091 g = g.monic(); 092 GenPolynomial<C> q = PolyUtil.<C> basePseudoDivide(pp, g); 093 q = q.monic(); 094 return q; 095 } 096 097 098 /** 099 * GenPolynomial test if is squarefree. 100 * @param P GenPolynomial. 101 * @return true if P is squarefree, else false. 102 */ 103 public boolean isBaseSquarefree(GenPolynomial<C> P) { 104 if (P == null || P.isZERO()) { 105 return true; 106 } 107 GenPolynomialRing<C> pfac = P.ring; 108 if (pfac.nvar > 1) { 109 throw new IllegalArgumentException( 110 this.getClass().getName() + " only for univariate polynomials"); 111 } 112 GenPolynomial<C> pp = P.monic(); 113 if (pp.isConstant()) { 114 return true; 115 } 116 GenPolynomial<C> d = PolyUtil.<C> baseDeriviative(pp); 117 d = d.monic(); 118 //System.out.println("d = " + d); 119 GenPolynomial<C> g = engine.baseGcd(pp, d); 120 //g = g.monic(); 121 //return g.isONE(); 122 return g.degree(0) == 0; 123 } 124 125 126 /** 127 * GenPolynomial polynomial squarefree factorization. 128 * @param A GenPolynomial. 129 * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} 130 * p_i^{e_i} and p_i squarefree. 131 */ 132 @Override 133 public SortedMap<GenPolynomial<C>, Long> baseSquarefreeFactors(GenPolynomial<C> A) { 134 SortedMap<GenPolynomial<C>, Long> sfactors = new TreeMap<GenPolynomial<C>, Long>(); 135 if (A == null || A.isZERO()) { 136 return sfactors; 137 } 138 if (A.isConstant()) { 139 sfactors.put(A, 1L); 140 return sfactors; 141 } 142 GenPolynomialRing<C> pfac = A.ring; 143 if (pfac.nvar > 1) { 144 throw new IllegalArgumentException( 145 this.getClass().getName() + " only for univariate polynomials"); 146 } 147 C ldbcf = A.leadingBaseCoefficient(); 148 if (!ldbcf.isONE()) { 149 A = A.divide(ldbcf); 150 GenPolynomial<C> f1 = pfac.getONE().multiply(ldbcf); 151 //System.out.println("gcda sqf f1 = " + f1); 152 sfactors.put(f1, 1L); 153 ldbcf = pfac.coFac.getONE(); 154 } 155 // divide by trailing term 156 ExpVector et = A.trailingExpVector(); 157 if (!et.isZERO()) { 158 GenPolynomial<C> tr = pfac.valueOf(et); 159 if (logger.isInfoEnabled()) { 160 logger.info("trailing term = " + tr); 161 } 162 A = PolyUtil.<C> basePseudoDivide(A, tr); 163 long ep = et.getVal(0); // univariate 164 et = et.subst(0, 1); 165 tr = pfac.valueOf(et); 166 if (logger.isInfoEnabled()) { 167 logger.info("tr, ep = " + tr + ", " + ep); 168 } 169 sfactors.put(tr, ep); 170 if (A.length() == 1) { 171 return sfactors; 172 } 173 } 174 GenPolynomial<C> T0 = A; 175 GenPolynomial<C> Tp; 176 GenPolynomial<C> T = null; 177 GenPolynomial<C> V = null; 178 long k = 0L; 179 boolean init = true; 180 while (true) { 181 if (init) { 182 if (T0.isConstant() || T0.isZERO()) { 183 break; 184 } 185 Tp = PolyUtil.<C> baseDeriviative(T0); 186 T = engine.baseGcd(T0, Tp); 187 T = T.monic(); 188 V = PolyUtil.<C> basePseudoDivide(T0, T); 189 //System.out.println("iT0 = " + T0); 190 //System.out.println("iTp = " + Tp); 191 //System.out.println("iT = " + T); 192 //System.out.println("iV = " + V); 193 k = 0L; 194 init = false; 195 } 196 if (V.isConstant()) { 197 break; 198 } 199 k++; 200 GenPolynomial<C> W = engine.baseGcd(T, V); 201 W = W.monic(); 202 GenPolynomial<C> z = PolyUtil.<C> basePseudoDivide(V, W); 203 //System.out.println("W = " + W); 204 //System.out.println("z = " + z); 205 V = W; 206 T = PolyUtil.<C> basePseudoDivide(T, V); 207 //System.out.println("V = " + V); 208 //System.out.println("T = " + T); 209 if (z.degree(0) > 0) { 210 if (ldbcf.isONE() && !z.leadingBaseCoefficient().isONE()) { 211 z = z.monic(); 212 //logger.info("z,monic = " + z); 213 } 214 logger.info("z, k = " + z + ", " + k); 215 sfactors.put(z, k); 216 } 217 } 218 return normalizeFactorization(sfactors); 219 } 220 221 222 /** 223 * GenPolynomial recursive univariate polynomial greatest squarefree 224 * divisor. 225 * @param P recursive univariate GenPolynomial. 226 * @return squarefree(pp(P)). 227 */ 228 @Override 229 public GenPolynomial<GenPolynomial<C>> recursiveUnivariateSquarefreePart( 230 GenPolynomial<GenPolynomial<C>> P) { 231 if (P == null || P.isZERO()) { 232 return P; 233 } 234 GenPolynomialRing<GenPolynomial<C>> pfac = P.ring; 235 if (pfac.nvar > 1) { 236 throw new IllegalArgumentException( 237 this.getClass().getName() + " only for univariate recursive polynomials"); 238 } 239 // squarefree content 240 GenPolynomial<GenPolynomial<C>> pp = P; 241 GenPolynomial<C> Pc = engine.recursiveContent(P); 242 //?? Pc = Pc.monic(); 243 if (!Pc.isONE()) { 244 pp = PolyUtil.<C> coefficientPseudoDivide(pp, Pc); 245 //System.out.println("pp,sqp = " + pp); 246 //GenPolynomial<C> Pr = squarefreePart(Pc); 247 //Pr = Pr.monic(); 248 //System.out.println("Pr,sqp = " + Pr); 249 } 250 if (pp.leadingExpVector().getVal(0) < 1) { 251 //System.out.println("pp = " + pp); 252 //System.out.println("Pc = " + Pc); 253 return pp.multiply(Pc); 254 } 255 GenPolynomial<GenPolynomial<C>> d = PolyUtil.<C> recursiveDeriviative(pp); 256 //System.out.println("d = " + d); 257 GenPolynomial<GenPolynomial<C>> g = engine.recursiveUnivariateGcd(pp, d); 258 //System.out.println("g,rec = " + g); 259 //??g = PolyUtil.<C> monic(g); 260 GenPolynomial<GenPolynomial<C>> q = PolyUtil.<C> recursivePseudoDivide(pp, g); 261 //?? q = PolyUtil.<C> monic(q); 262 return q.multiply(Pc); 263 } 264 265 266 /** 267 * GenPolynomial test if is squarefree. 268 * @param P GenPolynomial. 269 * @return true if P is squarefree, else false. 270 */ 271 public boolean isRecursiveUnivariateSquarefree(GenPolynomial<GenPolynomial<C>> P) { 272 if (P == null || P.isZERO()) { 273 return true; 274 } 275 GenPolynomialRing<GenPolynomial<C>> pfac = P.ring; 276 if (pfac.nvar > 1) { 277 throw new IllegalArgumentException( 278 this.getClass().getName() + " only for univariate recursive polynomials"); 279 } 280 GenPolynomial<GenPolynomial<C>> pp = P; 281 GenPolynomial<GenPolynomial<C>> d = PolyUtil.<C> recursiveDeriviative(pp); 282 //System.out.println("d = " + d); 283 GenPolynomial<GenPolynomial<C>> g = engine.recursiveUnivariateGcd(pp, d); 284 if (logger.isInfoEnabled()) { 285 logger.info("gcd = " + g); 286 } 287 //System.out.println("g,rec = " + g); 288 //g = PolyUtil.<C> monic(g); 289 //return g.isONE(); 290 return g.degree(0) == 0; 291 } 292 293 294 /** 295 * GenPolynomial recursive univariate polynomial squarefree factorization. 296 * @param P recursive univariate GenPolynomial. 297 * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} 298 * p_i^{e_i} and p_i squarefree. 299 */ 300 @Override 301 public SortedMap<GenPolynomial<GenPolynomial<C>>, Long> recursiveUnivariateSquarefreeFactors( 302 GenPolynomial<GenPolynomial<C>> P) { 303 SortedMap<GenPolynomial<GenPolynomial<C>>, Long> sfactors = new TreeMap<GenPolynomial<GenPolynomial<C>>, Long>(); 304 if (P == null || P.isZERO()) { 305 return sfactors; 306 } 307 GenPolynomialRing<GenPolynomial<C>> pfac = P.ring; 308 if (pfac.nvar > 1) { 309 // recursiveContent not possible by return type 310 throw new IllegalArgumentException( 311 this.getClass().getName() + " only for univariate polynomials"); 312 } 313 // if base coefficient ring is a field, make monic 314 GenPolynomialRing<C> cfac = (GenPolynomialRing<C>) pfac.coFac; 315 C ldbcf = P.leadingBaseCoefficient().leadingBaseCoefficient(); 316 if (!ldbcf.isONE()) { 317 GenPolynomial<C> lc = cfac.getONE().multiply(ldbcf); 318 GenPolynomial<GenPolynomial<C>> pl = pfac.getONE().multiply(lc); 319 sfactors.put(pl, 1L); 320 C li = ldbcf.inverse(); 321 //System.out.println("li = " + li); 322 P = P.multiply(cfac.getONE().multiply(li)); 323 //System.out.println("P,monic = " + P); 324 ldbcf = P.leadingBaseCoefficient().leadingBaseCoefficient(); 325 } 326 // factors of content 327 GenPolynomial<C> Pc = engine.recursiveContent(P); 328 if (logger.isInfoEnabled()) { 329 logger.info("recursiveContent = " + Pc); 330 } 331 Pc = Pc.monic(); 332 if (!Pc.isONE()) { 333 P = PolyUtil.<C> coefficientPseudoDivide(P, Pc); 334 } 335 SortedMap<GenPolynomial<C>, Long> rsf = squarefreeFactors(Pc); 336 if (logger.isInfoEnabled()) { 337 logger.info("squarefreeFactors = " + rsf); 338 } 339 // add factors of content 340 for (Map.Entry<GenPolynomial<C>, Long> me : rsf.entrySet()) { 341 GenPolynomial<C> c = me.getKey(); 342 if (!c.isONE()) { 343 GenPolynomial<GenPolynomial<C>> cr = pfac.getONE().multiply(c); 344 Long rk = me.getValue(); // rsf.get(c); 345 sfactors.put(cr, rk); 346 } 347 } 348 // divide by trailing term 349 ExpVector et = P.trailingExpVector(); 350 if (!et.isZERO()) { 351 GenPolynomial<GenPolynomial<C>> tr = pfac.valueOf(et); 352 if (logger.isInfoEnabled()) { 353 logger.info("trailing term = " + tr); 354 } 355 P = PolyUtil.<C> recursivePseudoDivide(P, tr); 356 long ep = et.getVal(0); // univariate 357 et = et.subst(0, 1); 358 tr = pfac.valueOf(et); 359 sfactors.put(tr, ep); 360 } 361 362 // factors of recursive polynomial 363 GenPolynomial<GenPolynomial<C>> T0 = P; 364 GenPolynomial<GenPolynomial<C>> Tp; 365 GenPolynomial<GenPolynomial<C>> T = null; 366 GenPolynomial<GenPolynomial<C>> V = null; 367 long k = 0L; 368 boolean init = true; 369 while (true) { 370 if (init) { 371 if (T0.isConstant() || T0.isZERO()) { 372 break; 373 } 374 Tp = PolyUtil.<C> recursiveDeriviative(T0); 375 T = engine.recursiveUnivariateGcd(T0, Tp); 376 T = PolyUtil.<C> monic(T); 377 V = PolyUtil.<C> recursivePseudoDivide(T0, T); 378 //System.out.println("iT0 = " + T0); 379 //System.out.println("iTp = " + Tp); 380 //System.out.println("iT = " + T); 381 //System.out.println("iV = " + V); 382 k = 0L; 383 init = false; 384 } 385 if (V.isConstant()) { 386 break; 387 } 388 k++; 389 GenPolynomial<GenPolynomial<C>> W = engine.recursiveUnivariateGcd(T, V); 390 W = PolyUtil.<C> monic(W); 391 GenPolynomial<GenPolynomial<C>> z = PolyUtil.<C> recursivePseudoDivide(V, W); 392 //System.out.println("W = " + W); 393 //System.out.println("z = " + z); 394 V = W; 395 T = PolyUtil.<C> recursivePseudoDivide(T, V); 396 //System.out.println("V = " + V); 397 //System.out.println("T = " + T); 398 //was: if ( z.degree(0) > 0 ) { 399 if (!z.isONE() && !z.isZERO()) { 400 if (ldbcf.isONE()) { 401 z = PolyUtil.<C> monic(z); 402 logger.info("z,monic = " + z); 403 } 404 sfactors.put(z, k); 405 } 406 } 407 return sfactors; 408 } 409 410 411 /** 412 * GenPolynomial greatest squarefree divisor. 413 * @param P GenPolynomial. 414 * @return squarefree(pp(P)). 415 */ 416 @Override 417 public GenPolynomial<C> squarefreePart(GenPolynomial<C> P) { 418 if (P == null) { 419 throw new IllegalArgumentException(this.getClass().getName() + " P != null"); 420 } 421 if (P.isZERO()) { 422 return P; 423 } 424 GenPolynomialRing<C> pfac = P.ring; 425 if (pfac.nvar <= 1) { 426 return baseSquarefreePart(P); 427 } 428 GenPolynomialRing<GenPolynomial<C>> rfac = pfac.recursive(1); 429 GenPolynomial<GenPolynomial<C>> Pr = PolyUtil.<C> recursive(rfac, P); 430 GenPolynomial<C> Pc = engine.recursiveContent(Pr); 431 Pr = PolyUtil.<C> coefficientPseudoDivide(Pr, Pc); 432 GenPolynomial<C> Ps = squarefreePart(Pc); 433 if (logger.isInfoEnabled()) { 434 logger.info("content = " + Pc + ", squarefreePart = " + Ps); 435 } 436 GenPolynomial<GenPolynomial<C>> PP = recursiveUnivariateSquarefreePart(Pr); 437 GenPolynomial<GenPolynomial<C>> PS = PP.multiply(Ps); 438 GenPolynomial<C> D = PolyUtil.<C> distribute(pfac, PS); 439 if (logger.isInfoEnabled()) { 440 logger.info("univRec = " + Pr + ", squarefreePart = " + PP); 441 } 442 return D; 443 } 444 445 446 /** 447 * GenPolynomial test if is squarefree. 448 * @param P GenPolynomial. 449 * @return true if P is squarefree, else false. 450 */ 451 @Override 452 public boolean isSquarefree(GenPolynomial<C> P) { 453 if (P == null) { 454 throw new IllegalArgumentException(this.getClass().getName() + " P != null"); 455 } 456 if (P.isZERO()) { 457 return true; 458 } 459 GenPolynomialRing<C> pfac = P.ring; 460 if (pfac.nvar <= 1) { 461 return isBaseSquarefree(P); 462 } 463 GenPolynomialRing<GenPolynomial<C>> rfac = pfac.recursive(1); 464 GenPolynomial<GenPolynomial<C>> Pr = PolyUtil.<C> recursive(rfac, P); 465 return isRecursiveUnivariateSquarefree(Pr); 466 } 467 468 469 /** 470 * GenPolynomial squarefree factorization. 471 * @param P GenPolynomial. 472 * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} 473 * p_i^{e_i} and p_i squarefree. 474 */ 475 @Override 476 public SortedMap<GenPolynomial<C>, Long> squarefreeFactors(GenPolynomial<C> P) { 477 if (P == null) { 478 throw new IllegalArgumentException(this.getClass().getName() + " P != null"); 479 } 480 GenPolynomialRing<C> pfac = P.ring; 481 if (pfac.nvar <= 1) { 482 return normalizeFactorization(baseSquarefreeFactors(P)); 483 } 484 SortedMap<GenPolynomial<C>, Long> sfactors = new TreeMap<GenPolynomial<C>, Long>(); 485 if (P.isZERO()) { 486 return normalizeFactorization(sfactors); 487 } 488 if (P.isONE()) { 489 sfactors.put(P, 1L); 490 return normalizeFactorization(sfactors); 491 } 492 GenPolynomialRing<GenPolynomial<C>> rfac = pfac.recursive(1); 493 GenPolynomial<GenPolynomial<C>> Pr = PolyUtil.<C> recursive(rfac, P); 494 SortedMap<GenPolynomial<GenPolynomial<C>>, Long> PP = recursiveUnivariateSquarefreeFactors(Pr); 495 496 for (Map.Entry<GenPolynomial<GenPolynomial<C>>, Long> m : PP.entrySet()) { 497 Long i = m.getValue(); 498 GenPolynomial<GenPolynomial<C>> Dr = m.getKey(); 499 GenPolynomial<C> D = PolyUtil.<C> distribute(pfac, Dr); 500 sfactors.put(D, i); 501 } 502 if (logger.isInfoEnabled()) { 503 logger.info("squarefreeFactors(" + P + ") = " + sfactors); 504 } 505 return normalizeFactorization(sfactors); 506 } 507 508 509 /** 510 * Coefficients squarefree factorization. 511 * @param P coefficient. 512 * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} 513 * p_i^{e_i} and p_i squarefree. 514 */ 515 @Override 516 public SortedMap<C, Long> squarefreeFactors(C P) { 517 throw new UnsupportedOperationException("method not implemented"); 518 } 519 520}