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