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