001/* 002 * $Id: SquarefreeInfiniteFieldCharP.java 4125 2012-08-19 19:05:22Z 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.Monomial; 018import edu.jas.poly.PolyUtil; 019import edu.jas.structure.GcdRingElem; 020import edu.jas.structure.Power; 021import edu.jas.structure.RingFactory; 022 023 024/** 025 * Squarefree decomposition for infinite coefficient fields of characteristic p. 026 * @author Heinz Kredel 027 */ 028 029public class SquarefreeInfiniteFieldCharP<C extends GcdRingElem<C>> extends SquarefreeFieldCharP<Quotient<C>> { 030 031 032 private static final Logger logger = Logger.getLogger(SquarefreeInfiniteFieldCharP.class); 033 034 035 //private final boolean debug = logger.isDebugEnabled(); 036 037 038 /** 039 * Squarefree engine for infinite ring of characteristic p base coefficients. 040 */ 041 protected final SquarefreeAbstract<C> qengine; 042 043 044 /** 045 * Constructor. 046 */ 047 public SquarefreeInfiniteFieldCharP(RingFactory<Quotient<C>> fac) { 048 super(fac); 049 // isFinite() predicate now present 050 if (fac.isFinite()) { 051 throw new IllegalArgumentException("fac must be in-finite"); 052 } 053 QuotientRing<C> qfac = (QuotientRing<C>) fac; 054 GenPolynomialRing<C> rfac = qfac.ring; 055 qengine = (SquarefreeAbstract) SquarefreeFactory.<C> getImplementation(rfac); 056 //qengine = new SquarefreeFiniteFieldCharP<C>(rfac.coFac); 057 //qengine = new SquarefreeInfiniteRingCharP<C>( rfac.coFac ); 058 } 059 060 061 /* --------- quotient char-th roots --------------------- */ 062 063 064 /** 065 * Squarefree factors of a Quotient. 066 * @param P Quotient. 067 * @return [p_1 -> e_1,...,p_k - > e_k] with P = prod_{i=1, ..., k} 068 * p_i**e_k. 069 */ 070 @Override 071 public SortedMap<Quotient<C>, Long> squarefreeFactors(Quotient<C> P) { 072 if (P == null) { 073 throw new IllegalArgumentException(this.getClass().getName() + " P == null"); 074 } 075 SortedMap<Quotient<C>, Long> factors = new TreeMap<Quotient<C>, Long>(); 076 if (P.isZERO()) { 077 return factors; 078 } 079 if (P.isONE()) { 080 factors.put(P, 1L); 081 return factors; 082 } 083 GenPolynomial<C> num = P.num; 084 GenPolynomial<C> den = P.den; 085 QuotientRing<C> pfac = P.ring; 086 GenPolynomial<C> one = pfac.ring.getONE(); 087 if (!num.isONE()) { 088 SortedMap<GenPolynomial<C>, Long> nfac = qengine.squarefreeFactors(num); 089 //System.out.println("nfac = " + nfac); 090 for (Map.Entry<GenPolynomial<C>, Long> me : nfac.entrySet()) { 091 GenPolynomial<C> nfp = me.getKey(); 092 Quotient<C> nf = new Quotient<C>(pfac, nfp); 093 factors.put(nf, me.getValue()); //nfac.get(nfp)); 094 } 095 } 096 if (den.isONE()) { 097 if (factors.size() == 0) { 098 factors.put(P, 1L); 099 } 100 return factors; 101 } 102 SortedMap<GenPolynomial<C>, Long> dfac = qengine.squarefreeFactors(den); 103 //System.out.println("dfac = " + dfac); 104 for (Map.Entry<GenPolynomial<C>, Long> me : dfac.entrySet()) { 105 GenPolynomial<C> dfp = me.getKey(); 106 Quotient<C> df = new Quotient<C>(pfac, one, dfp); 107 factors.put(df, me.getValue()); //dfac.get(dfp)); 108 } 109 if (factors.size() == 0) { 110 factors.put(P, 1L); 111 } 112 return factors; 113 } 114 115 116 /** 117 * Characteristics root of a Quotient. 118 * @param P Quotient. 119 * @return [p -> k] if exists k with e=charactristic(P)*k and P = p**e, 120 * else null. 121 */ 122 public SortedMap<Quotient<C>, Long> rootCharacteristic(Quotient<C> P) { 123 if (P == null) { 124 throw new IllegalArgumentException(this.getClass().getName() + " P == null"); 125 } 126 java.math.BigInteger c = P.ring.characteristic(); 127 if (c.signum() == 0) { 128 return null; 129 } 130 SortedMap<Quotient<C>, Long> root = new TreeMap<Quotient<C>, Long>(); 131 if (P.isZERO()) { 132 return root; 133 } 134 if (P.isONE()) { 135 root.put(P, 1L); 136 return root; 137 } 138 SortedMap<Quotient<C>, Long> sf = squarefreeFactors(P); 139 if (sf.size() == 0) { 140 return null; 141 } 142 if (logger.isInfoEnabled()) { 143 logger.info("sf,quot = " + sf); 144 } 145 // better: test if sf.size() == 2 // no, since num and den factors 146 Long k = null; 147 Long cl = c.longValue(); 148 for (Map.Entry<Quotient<C>, Long> me : sf.entrySet()) { 149 Quotient<C> p = me.getKey(); 150 //System.out.println("p = " + p); 151 if (p.isConstant()) { // todo: check for non-constants in coefficients 152 continue; 153 } 154 Long e = me.getValue(); //sf.get(p); 155 long E = e.longValue(); 156 long r = E % cl; 157 if (r != 0) { 158 //System.out.println("r = " + r); 159 return null; 160 } 161 if (k == null) { 162 k = e; 163 } else if (k >= e) { 164 k = e; 165 } 166 } 167 if (k == null) { 168 k = 1L; //return null; 169 } 170 // now c divides all exponents of non constant elements 171 for (Map.Entry<Quotient<C>, Long> me : sf.entrySet()) { 172 Quotient<C> q = me.getKey(); 173 Long e = me.getValue(); //sf.get(q); 174 //System.out.println("q = " + q + ", e = " + e); 175 if (e >= k) { 176 e = e / cl; 177 //q = Power.<Quotient<C>> positivePower(q, e); 178 root.put(q, e); 179 } else { // constant case 180 root.put(q, e); 181 } 182 } 183 //System.out.println("root = " + root); 184 return root; 185 } 186 187 188 /** 189 * GenPolynomial char-th root main variable. 190 * @param P univariate GenPolynomial with Quotient coefficients. 191 * @return char-th_rootOf(P), or null, if P is no char-th root. 192 */ 193 public GenPolynomial<Quotient<C>> rootCharacteristic(GenPolynomial<Quotient<C>> P) { 194 if (P == null || P.isZERO()) { 195 return P; 196 } 197 GenPolynomialRing<Quotient<C>> pfac = P.ring; 198 if (pfac.nvar > 1) { 199 // go to recursion 200 GenPolynomialRing<Quotient<C>> cfac = pfac.contract(1); 201 GenPolynomialRing<GenPolynomial<Quotient<C>>> rfac = new GenPolynomialRing<GenPolynomial<Quotient<C>>>( 202 cfac, 1); 203 GenPolynomial<GenPolynomial<Quotient<C>>> Pr = PolyUtil.<Quotient<C>> recursive(rfac, P); 204 GenPolynomial<GenPolynomial<Quotient<C>>> Prc = recursiveUnivariateRootCharacteristic(Pr); 205 if (Prc == null) { 206 return null; 207 } 208 GenPolynomial<Quotient<C>> D = PolyUtil.<Quotient<C>> distribute(pfac, Prc); 209 return D; 210 } 211 RingFactory<Quotient<C>> rf = pfac.coFac; 212 if (rf.characteristic().signum() != 1) { 213 // basePthRoot not possible 214 throw new IllegalArgumentException(P.getClass().getName() + " only for ModInteger polynomials " 215 + rf); 216 } 217 long mp = rf.characteristic().longValue(); 218 GenPolynomial<Quotient<C>> d = pfac.getZERO().copy(); 219 for (Monomial<Quotient<C>> m : P) { 220 ExpVector f = m.e; 221 long fl = f.getVal(0); 222 if (fl % mp != 0) { 223 return null; 224 } 225 fl = fl / mp; 226 SortedMap<Quotient<C>, Long> sm = rootCharacteristic(m.c); 227 if (sm == null) { 228 return null; 229 } 230 if (logger.isInfoEnabled()) { 231 logger.info("sm,root = " + sm); 232 } 233 Quotient<C> r = rf.getONE(); 234 for (Map.Entry<Quotient<C>, Long> me : sm.entrySet()) { 235 Quotient<C> rp = me.getKey(); 236 long gl = me.getValue(); // sm.get(rp); 237 if (gl > 1) { 238 rp = Power.<Quotient<C>> positivePower(rp, gl); 239 } 240 r = r.multiply(rp); 241 } 242 ExpVector e = ExpVector.create(1, 0, fl); 243 d.doPutToMap(e, r); 244 } 245 logger.info("sm,root,d = " + d); 246 return d; 247 } 248 249 250 /** 251 * GenPolynomial char-th root univariate polynomial. 252 * @param P GenPolynomial. 253 * @return char-th_rootOf(P). 254 */ 255 @Override 256 public GenPolynomial<Quotient<C>> baseRootCharacteristic(GenPolynomial<Quotient<C>> P) { 257 if (P == null || P.isZERO()) { 258 return P; 259 } 260 GenPolynomialRing<Quotient<C>> pfac = P.ring; 261 if (pfac.nvar > 1) { 262 // basePthRoot not possible by return type 263 throw new IllegalArgumentException(P.getClass().getName() + " only for univariate polynomials"); 264 } 265 RingFactory<Quotient<C>> rf = pfac.coFac; 266 if (rf.characteristic().signum() != 1) { 267 // basePthRoot not possible 268 throw new IllegalArgumentException(P.getClass().getName() + " only for char p > 0 " + rf); 269 } 270 long mp = rf.characteristic().longValue(); 271 GenPolynomial<Quotient<C>> d = pfac.getZERO().copy(); 272 for (Monomial<Quotient<C>> m : P) { 273 //System.out.println("m = " + m); 274 ExpVector f = m.e; 275 long fl = f.getVal(0); 276 if (fl % mp != 0) { 277 return null; 278 } 279 fl = fl / mp; 280 SortedMap<Quotient<C>, Long> sm = rootCharacteristic(m.c); 281 if (sm == null) { 282 return null; 283 } 284 if (logger.isInfoEnabled()) { 285 logger.info("sm,base,root = " + sm); 286 } 287 Quotient<C> r = rf.getONE(); 288 for (Map.Entry<Quotient<C>, Long> me : sm.entrySet()) { 289 Quotient<C> rp = me.getKey(); 290 //System.out.println("rp = " + rp); 291 long gl = me.getValue(); //sm.get(rp); 292 //System.out.println("gl = " + gl); 293 Quotient<C> re = rp; 294 if (gl > 1) { 295 re = Power.<Quotient<C>> positivePower(rp, gl); 296 } 297 //System.out.println("re = " + re); 298 r = r.multiply(re); 299 } 300 ExpVector e = ExpVector.create(1, 0, fl); 301 d.doPutToMap(e, r); 302 } 303 if (logger.isInfoEnabled()) { 304 logger.info("sm,base,d = " + d); 305 } 306 return d; 307 } 308 309 310 /** 311 * GenPolynomial char-th root univariate polynomial with polynomial 312 * coefficients. 313 * @param P recursive univariate GenPolynomial. 314 * @return char-th_rootOf(P), or null if P is no char-th root. 315 */ 316 @Override 317 public GenPolynomial<GenPolynomial<Quotient<C>>> recursiveUnivariateRootCharacteristic( 318 GenPolynomial<GenPolynomial<Quotient<C>>> P) { 319 if (P == null || P.isZERO()) { 320 return P; 321 } 322 GenPolynomialRing<GenPolynomial<Quotient<C>>> pfac = P.ring; 323 if (pfac.nvar > 1) { 324 // basePthRoot not possible by return type 325 throw new IllegalArgumentException(P.getClass().getName() 326 + " only for univariate recursive polynomials"); 327 } 328 RingFactory<GenPolynomial<Quotient<C>>> rf = pfac.coFac; 329 if (rf.characteristic().signum() != 1) { 330 // basePthRoot not possible 331 throw new IllegalArgumentException(P.getClass().getName() + " only for char p > 0 " + rf); 332 } 333 long mp = rf.characteristic().longValue(); 334 GenPolynomial<GenPolynomial<Quotient<C>>> d = pfac.getZERO().copy(); 335 for (Monomial<GenPolynomial<Quotient<C>>> m : P) { 336 ExpVector f = m.e; 337 long fl = f.getVal(0); 338 if (fl % mp != 0) { 339 return null; 340 } 341 fl = fl / mp; 342 GenPolynomial<Quotient<C>> r = rootCharacteristic(m.c); 343 if (r == null) { 344 return null; 345 } 346 ExpVector e = ExpVector.create(1, 0, fl); 347 d.doPutToMap(e, r); 348 } 349 return d; 350 } 351 352}