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