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 A = prod_{i=1,...,k} 130 * p_i^{e_i} and p_i squarefree and gcd(p_i, p_j) = 1, for i != j. 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 logger.info("trailing term = {}", tr); 160 A = PolyUtil.<C> basePseudoDivide(A, tr); 161 long ep = et.getVal(0); // univariate 162 et = et.subst(0, 1); 163 tr = pfac.valueOf(et); 164 logger.info("tr, ep = {}, {}", tr, ep); 165 sfactors.put(tr, ep); 166 if (A.length() == 1) { 167 return sfactors; 168 } 169 } 170 GenPolynomial<C> T0 = A; 171 GenPolynomial<C> Tp; 172 GenPolynomial<C> T = null; 173 GenPolynomial<C> V = null; 174 long k = 0L; 175 boolean init = true; 176 while (true) { 177 if (init) { 178 if (T0.isConstant() || T0.isZERO()) { 179 break; 180 } 181 Tp = PolyUtil.<C> baseDeriviative(T0); 182 T = engine.baseGcd(T0, Tp); 183 T = T.monic(); 184 V = PolyUtil.<C> basePseudoDivide(T0, T); 185 //System.out.println("iT0 = " + T0); 186 //System.out.println("iTp = " + Tp); 187 //System.out.println("iT = " + T); 188 //System.out.println("iV = " + V); 189 k = 0L; 190 init = false; 191 } 192 if (V.isConstant()) { 193 break; 194 } 195 k++; 196 GenPolynomial<C> W = engine.baseGcd(T, V); 197 W = W.monic(); 198 GenPolynomial<C> z = PolyUtil.<C> basePseudoDivide(V, W); 199 //System.out.println("W = " + W); 200 //System.out.println("z = " + z); 201 V = W; 202 T = PolyUtil.<C> basePseudoDivide(T, V); 203 //System.out.println("V = " + V); 204 //System.out.println("T = " + T); 205 if (z.degree(0) > 0) { 206 if (ldbcf.isONE() && !z.leadingBaseCoefficient().isONE()) { 207 z = z.monic(); 208 //logger.info("z,monic = {}", z); 209 } 210 logger.info("z, k = {}, {}", z, k); 211 sfactors.put(z, k); 212 } 213 } 214 return normalizeFactorization(sfactors); 215 } 216 217 218 /** 219 * GenPolynomial recursive univariate polynomial greatest squarefree 220 * divisor. 221 * @param P recursive univariate GenPolynomial. 222 * @return squarefree(pp(P)). 223 */ 224 @Override 225 public GenPolynomial<GenPolynomial<C>> recursiveUnivariateSquarefreePart( 226 GenPolynomial<GenPolynomial<C>> P) { 227 if (P == null || P.isZERO()) { 228 return P; 229 } 230 GenPolynomialRing<GenPolynomial<C>> pfac = P.ring; 231 if (pfac.nvar > 1) { 232 throw new IllegalArgumentException( 233 this.getClass().getName() + " only for univariate recursive polynomials"); 234 } 235 // squarefree content 236 GenPolynomial<GenPolynomial<C>> pp = P; 237 GenPolynomial<C> Pc = engine.recursiveContent(P); 238 //?? Pc = Pc.monic(); 239 if (!Pc.isONE()) { 240 pp = PolyUtil.<C> coefficientPseudoDivide(pp, Pc); 241 //System.out.println("pp,sqp = " + pp); 242 //GenPolynomial<C> Pr = squarefreePart(Pc); 243 //Pr = Pr.monic(); 244 //System.out.println("Pr,sqp = " + Pr); 245 } 246 if (pp.leadingExpVector().getVal(0) < 1) { 247 //System.out.println("pp = " + pp); 248 //System.out.println("Pc = " + Pc); 249 return pp.multiply(Pc); 250 } 251 GenPolynomial<GenPolynomial<C>> d = PolyUtil.<C> recursiveDeriviative(pp); 252 //System.out.println("d = " + d); 253 GenPolynomial<GenPolynomial<C>> g = engine.recursiveUnivariateGcd(pp, d); 254 //System.out.println("g,rec = " + g); 255 //??g = PolyUtil.<C> monic(g); 256 GenPolynomial<GenPolynomial<C>> q = PolyUtil.<C> recursivePseudoDivide(pp, g); 257 //?? q = PolyUtil.<C> monic(q); 258 return q.multiply(Pc); 259 } 260 261 262 /** 263 * GenPolynomial test if is squarefree. 264 * @param P GenPolynomial. 265 * @return true if P is squarefree, else false. 266 */ 267 public boolean isRecursiveUnivariateSquarefree(GenPolynomial<GenPolynomial<C>> P) { 268 if (P == null || P.isZERO()) { 269 return true; 270 } 271 GenPolynomialRing<GenPolynomial<C>> pfac = P.ring; 272 if (pfac.nvar > 1) { 273 throw new IllegalArgumentException( 274 this.getClass().getName() + " only for univariate recursive polynomials"); 275 } 276 GenPolynomial<GenPolynomial<C>> pp = P; 277 GenPolynomial<GenPolynomial<C>> d = PolyUtil.<C> recursiveDeriviative(pp); 278 //System.out.println("d = " + d); 279 GenPolynomial<GenPolynomial<C>> g = engine.recursiveUnivariateGcd(pp, d); 280 logger.info("gcd = {}", g); 281 //System.out.println("g,rec = " + g); 282 //g = PolyUtil.<C> monic(g); 283 //return g.isONE(); 284 return g.degree(0) == 0; 285 } 286 287 288 /** 289 * GenPolynomial recursive univariate polynomial squarefree factorization. 290 * @param P recursive univariate GenPolynomial. 291 * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} 292 * p_i^{e_i} and p_i squarefree and gcd(p_i, p_j) = 1, for i != j. 293 */ 294 @Override 295 public SortedMap<GenPolynomial<GenPolynomial<C>>, Long> recursiveUnivariateSquarefreeFactors( 296 GenPolynomial<GenPolynomial<C>> P) { 297 SortedMap<GenPolynomial<GenPolynomial<C>>, Long> sfactors = new TreeMap<GenPolynomial<GenPolynomial<C>>, Long>(); 298 if (P == null || P.isZERO()) { 299 return sfactors; 300 } 301 GenPolynomialRing<GenPolynomial<C>> pfac = P.ring; 302 if (pfac.nvar > 1) { 303 // recursiveContent not possible by return type 304 throw new IllegalArgumentException( 305 this.getClass().getName() + " only for univariate polynomials"); 306 } 307 // if base coefficient ring is a field, make monic 308 GenPolynomialRing<C> cfac = (GenPolynomialRing<C>) pfac.coFac; 309 C ldbcf = P.leadingBaseCoefficient().leadingBaseCoefficient(); 310 if (!ldbcf.isONE()) { 311 GenPolynomial<C> lc = cfac.getONE().multiply(ldbcf); 312 GenPolynomial<GenPolynomial<C>> pl = pfac.getONE().multiply(lc); 313 sfactors.put(pl, 1L); 314 C li = ldbcf.inverse(); 315 //System.out.println("li = " + li); 316 P = P.multiply(cfac.getONE().multiply(li)); 317 //System.out.println("P,monic = " + P); 318 ldbcf = P.leadingBaseCoefficient().leadingBaseCoefficient(); 319 } 320 // factors of content 321 GenPolynomial<C> Pc = engine.recursiveContent(P); 322 logger.info("recursiveContent = {}", Pc); 323 Pc = Pc.monic(); 324 if (!Pc.isONE()) { 325 P = PolyUtil.<C> coefficientPseudoDivide(P, Pc); 326 } 327 SortedMap<GenPolynomial<C>, Long> rsf = squarefreeFactors(Pc); 328 logger.info("squarefreeFactors = {}", rsf); 329 // add factors of content 330 for (Map.Entry<GenPolynomial<C>, Long> me : rsf.entrySet()) { 331 GenPolynomial<C> c = me.getKey(); 332 if (!c.isONE()) { 333 GenPolynomial<GenPolynomial<C>> cr = pfac.getONE().multiply(c); 334 Long rk = me.getValue(); // rsf.get(c); 335 sfactors.put(cr, rk); 336 } 337 } 338 // divide by trailing term 339 ExpVector et = P.trailingExpVector(); 340 if (!et.isZERO()) { 341 GenPolynomial<GenPolynomial<C>> tr = pfac.valueOf(et); 342 logger.info("trailing term = {}", tr); 343 P = PolyUtil.<C> recursivePseudoDivide(P, tr); 344 long ep = et.getVal(0); // univariate 345 et = et.subst(0, 1); 346 tr = pfac.valueOf(et); 347 sfactors.put(tr, ep); 348 } 349 350 // factors of recursive polynomial 351 GenPolynomial<GenPolynomial<C>> T0 = P; 352 GenPolynomial<GenPolynomial<C>> Tp; 353 GenPolynomial<GenPolynomial<C>> T = null; 354 GenPolynomial<GenPolynomial<C>> V = null; 355 long k = 0L; 356 boolean init = true; 357 while (true) { 358 if (init) { 359 if (T0.isConstant() || T0.isZERO()) { 360 break; 361 } 362 Tp = PolyUtil.<C> recursiveDeriviative(T0); 363 T = engine.recursiveUnivariateGcd(T0, Tp); 364 T = PolyUtil.<C> monic(T); 365 V = PolyUtil.<C> recursivePseudoDivide(T0, T); 366 //System.out.println("iT0 = " + T0); 367 //System.out.println("iTp = " + Tp); 368 //System.out.println("iT = " + T); 369 //System.out.println("iV = " + V); 370 k = 0L; 371 init = false; 372 } 373 if (V.isConstant()) { 374 break; 375 } 376 k++; 377 GenPolynomial<GenPolynomial<C>> W = engine.recursiveUnivariateGcd(T, V); 378 W = PolyUtil.<C> monic(W); 379 GenPolynomial<GenPolynomial<C>> z = PolyUtil.<C> recursivePseudoDivide(V, W); 380 //System.out.println("W = " + W); 381 //System.out.println("z = " + z); 382 V = W; 383 T = PolyUtil.<C> recursivePseudoDivide(T, V); 384 //System.out.println("V = " + V); 385 //System.out.println("T = " + T); 386 //was: if ( z.degree(0) > 0 ) { 387 if (!z.isONE() && !z.isZERO()) { 388 if (ldbcf.isONE()) { 389 z = PolyUtil.<C> monic(z); 390 logger.info("z,monic = {}", z); 391 } 392 sfactors.put(z, k); 393 } 394 } 395 return sfactors; 396 } 397 398 399 /** 400 * GenPolynomial greatest squarefree divisor. 401 * @param P GenPolynomial. 402 * @return squarefree(pp(P)). 403 */ 404 @Override 405 public GenPolynomial<C> squarefreePart(GenPolynomial<C> P) { 406 if (P == null) { 407 throw new IllegalArgumentException(this.getClass().getName() + " P != null"); 408 } 409 if (P.isZERO()) { 410 return P; 411 } 412 GenPolynomialRing<C> pfac = P.ring; 413 if (pfac.nvar <= 1) { 414 return baseSquarefreePart(P); 415 } 416 GenPolynomialRing<GenPolynomial<C>> rfac = pfac.recursive(1); 417 GenPolynomial<GenPolynomial<C>> Pr = PolyUtil.<C> recursive(rfac, P); 418 GenPolynomial<C> Pc = engine.recursiveContent(Pr); 419 Pr = PolyUtil.<C> coefficientPseudoDivide(Pr, Pc); 420 GenPolynomial<C> Ps = squarefreePart(Pc); 421 logger.info("content = {}, squarefreePart = {}", Pc, Ps); 422 GenPolynomial<GenPolynomial<C>> PP = recursiveUnivariateSquarefreePart(Pr); 423 GenPolynomial<GenPolynomial<C>> PS = PP.multiply(Ps); 424 GenPolynomial<C> D = PolyUtil.<C> distribute(pfac, PS); 425 logger.info("univRec = {}, squarefreePart = {}", Pr, PP); 426 return D; 427 } 428 429 430 /** 431 * GenPolynomial test if is squarefree. 432 * @param P GenPolynomial. 433 * @return true if P is squarefree, else false. 434 */ 435 @Override 436 public boolean isSquarefree(GenPolynomial<C> P) { 437 if (P == null) { 438 throw new IllegalArgumentException(this.getClass().getName() + " P != null"); 439 } 440 if (P.isZERO()) { 441 return true; 442 } 443 GenPolynomialRing<C> pfac = P.ring; 444 if (pfac.nvar <= 1) { 445 return isBaseSquarefree(P); 446 } 447 GenPolynomialRing<GenPolynomial<C>> rfac = pfac.recursive(1); 448 GenPolynomial<GenPolynomial<C>> Pr = PolyUtil.<C> recursive(rfac, P); 449 return isRecursiveUnivariateSquarefree(Pr); 450 } 451 452 453 /** 454 * GenPolynomial squarefree factorization. 455 * @param P GenPolynomial. 456 * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} 457 * p_i^{e_i} and p_i squarefree and gcd(p_i, p_j) = 1, for i != j. 458 */ 459 @Override 460 public SortedMap<GenPolynomial<C>, Long> squarefreeFactors(GenPolynomial<C> P) { 461 if (P == null) { 462 throw new IllegalArgumentException(this.getClass().getName() + " P != null"); 463 } 464 GenPolynomialRing<C> pfac = P.ring; 465 if (pfac.nvar <= 1) { 466 return normalizeFactorization(baseSquarefreeFactors(P)); 467 } 468 SortedMap<GenPolynomial<C>, Long> sfactors = new TreeMap<GenPolynomial<C>, Long>(); 469 if (P.isZERO()) { 470 return normalizeFactorization(sfactors); 471 } 472 if (P.isONE()) { 473 sfactors.put(P, 1L); 474 return normalizeFactorization(sfactors); 475 } 476 GenPolynomialRing<GenPolynomial<C>> rfac = pfac.recursive(1); 477 GenPolynomial<GenPolynomial<C>> Pr = PolyUtil.<C> recursive(rfac, P); 478 SortedMap<GenPolynomial<GenPolynomial<C>>, Long> PP = recursiveUnivariateSquarefreeFactors(Pr); 479 480 for (Map.Entry<GenPolynomial<GenPolynomial<C>>, Long> m : PP.entrySet()) { 481 Long i = m.getValue(); 482 GenPolynomial<GenPolynomial<C>> Dr = m.getKey(); 483 GenPolynomial<C> D = PolyUtil.<C> distribute(pfac, Dr); 484 sfactors.put(D, i); 485 } 486 logger.info("squarefreeFactors({}) = {}", P, sfactors); 487 return normalizeFactorization(sfactors); 488 } 489 490 491 /** 492 * Coefficients squarefree factorization. 493 * @param P coefficient. 494 * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} 495 * p_i^{e_i} and p_i squarefree and gcd(p_i, p_j) = 1, for i != j. 496 */ 497 @Override 498 public SortedMap<C, Long> squarefreeFactors(C P) { 499 throw new UnsupportedOperationException("method not implemented"); 500 } 501 502}