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