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