001/* 002 * $Id: SquarefreeInfiniteFieldCharP.java 5774 2017-11-05 17:04:30Z 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.RingFactory; 021 022 023/** 024 * Squarefree decomposition for infinite coefficient fields of characteristic p. 025 * @author Heinz Kredel 026 */ 027 028public class SquarefreeInfiniteFieldCharP<C extends GcdRingElem<C>> 029 extends SquarefreeFieldCharP<Quotient<C>> { 030 031 032 private static final Logger logger = Logger.getLogger(SquarefreeInfiniteFieldCharP.class); 033 034 035 //private static final boolean debug = logger.isDebugEnabled(); 036 037 038 /** 039 * Squarefree engine for infinite ring of characteristic p base 040 * coefficients. 041 */ 042 protected final SquarefreeAbstract<C> qengine; 043 044 045 /** 046 * Constructor. 047 */ 048 @SuppressWarnings("cast") 049 public SquarefreeInfiniteFieldCharP(RingFactory<Quotient<C>> fac) { 050 super(fac); 051 // isFinite() predicate now present 052 if (fac.isFinite()) { 053 throw new IllegalArgumentException("fac must be in-finite"); 054 } 055 QuotientRing<C> qfac = (QuotientRing<C>) fac; 056 GenPolynomialRing<C> rfac = qfac.ring; 057 qengine = (SquarefreeAbstract) SquarefreeFactory.<C> getImplementation(rfac); 058 //qengine = new SquarefreeFiniteFieldCharP<C>(rfac.coFac); 059 //qengine = new SquarefreeInfiniteRingCharP<C>( rfac.coFac ); 060 } 061 062 063 /* --------- quotient char-th roots --------------------- */ 064 065 066 /** 067 * Squarefree factors of a Quotient. 068 * @param P Quotient. 069 * @return [p_1 -> e_1,...,p_k - > e_k] with P = prod_{i=1, ..., k} 070 * p_i**e_k. 071 */ 072 @Override 073 public SortedMap<Quotient<C>, Long> squarefreeFactors(Quotient<C> P) { 074 if (P == null) { 075 throw new IllegalArgumentException(this.getClass().getName() + " P == null"); 076 } 077 SortedMap<Quotient<C>, Long> factors = new TreeMap<Quotient<C>, Long>(); 078 if (P.isZERO()) { 079 return factors; 080 } 081 if (P.isONE()) { 082 factors.put(P, 1L); 083 return factors; 084 } 085 GenPolynomial<C> num = P.num; 086 GenPolynomial<C> den = P.den; 087 QuotientRing<C> pfac = P.ring; 088 GenPolynomial<C> one = pfac.ring.getONE(); 089 if (!num.isONE()) { 090 SortedMap<GenPolynomial<C>, Long> nfac = qengine.squarefreeFactors(num); 091 //System.out.println("nfac = " + nfac); 092 for (Map.Entry<GenPolynomial<C>, Long> me : nfac.entrySet()) { 093 GenPolynomial<C> nfp = me.getKey(); 094 Quotient<C> nf = new Quotient<C>(pfac, nfp); 095 factors.put(nf, me.getValue()); //nfac.get(nfp)); 096 } 097 } 098 if (den.isONE()) { 099 if (factors.size() == 0) { 100 factors.put(P, 1L); 101 } 102 return factors; 103 } 104 SortedMap<GenPolynomial<C>, Long> dfac = qengine.squarefreeFactors(den); 105 //System.out.println("dfac = " + dfac); 106 for (Map.Entry<GenPolynomial<C>, Long> me : dfac.entrySet()) { 107 GenPolynomial<C> dfp = me.getKey(); 108 Quotient<C> df = new Quotient<C>(pfac, one, dfp); 109 factors.put(df, me.getValue()); //dfac.get(dfp)); 110 } 111 if (factors.size() == 0) { 112 factors.put(P, 1L); 113 } 114 return factors; 115 } 116 117 118 /** 119 * Characteristics root of a Quotient. 120 * @param P Quotient. 121 * @return [p -> k] if exists k with e=charactristic(P)*k and P = p**e, 122 * else null. 123 */ 124 public SortedMap<Quotient<C>, Long> rootCharacteristic(Quotient<C> P) { 125 if (P == null) { 126 throw new IllegalArgumentException(this.getClass().getName() + " P == null"); 127 } 128 java.math.BigInteger c = P.ring.characteristic(); 129 if (c.signum() == 0) { 130 return null; 131 } 132 SortedMap<Quotient<C>, Long> root = new TreeMap<Quotient<C>, Long>(); 133 if (P.isZERO()) { 134 return root; 135 } 136 if (P.isONE()) { 137 root.put(P, 1L); 138 return root; 139 } 140 SortedMap<Quotient<C>, Long> sf = squarefreeFactors(P); 141 if (sf.size() == 0) { 142 return null; 143 } 144 if (logger.isInfoEnabled()) { 145 logger.info("sf,quot = " + sf); 146 } 147 // better: test if sf.size() == 2 // no, since num and den factors 148 Long k = null; 149 Long cl = c.longValue(); 150 for (Map.Entry<Quotient<C>, Long> me : sf.entrySet()) { 151 Quotient<C> p = me.getKey(); 152 //System.out.println("p = " + p); 153 if (p.isConstant()) { // todo: check for non-constants in coefficients 154 continue; 155 } 156 Long e = me.getValue(); //sf.get(p); 157 long E = e.longValue(); 158 long r = E % cl; 159 if (r != 0) { 160 //System.out.println("r = " + r); 161 return null; 162 } 163 if (k == null) { 164 k = e; 165 } else if (k >= e) { 166 k = e; 167 } 168 } 169 if (k == null) { 170 k = 1L; //return null; 171 } 172 // now c divides all exponents of non constant elements 173 for (Map.Entry<Quotient<C>, Long> me : sf.entrySet()) { 174 Quotient<C> q = me.getKey(); 175 Long e = me.getValue(); //sf.get(q); 176 //System.out.println("q = " + q + ", e = " + e); 177 if (e >= k) { 178 e = e / cl; 179 //q = q.power(e); 180 root.put(q, e); 181 } else { // constant case 182 root.put(q, e); 183 } 184 } 185 //System.out.println("root = " + root); 186 return root; 187 } 188 189 190 /** 191 * GenPolynomial char-th root main variable. 192 * @param P univariate GenPolynomial with Quotient coefficients. 193 * @return char-th_rootOf(P), or null, if P is no char-th root. 194 */ 195 public GenPolynomial<Quotient<C>> rootCharacteristic(GenPolynomial<Quotient<C>> P) { 196 if (P == null || P.isZERO()) { 197 return P; 198 } 199 GenPolynomialRing<Quotient<C>> pfac = P.ring; 200 if (pfac.nvar > 1) { 201 // go to recursion 202 GenPolynomialRing<GenPolynomial<Quotient<C>>> rfac = pfac.recursive(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( 215 P.getClass().getName() + " only for ModInteger polynomials " + 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 = rp.power(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 = rp.power(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( 326 P.getClass().getName() + " 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}