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