001/* 002 * $Id: QuotientRing.java 5916 2018-08-29 20:21:02Z kredel $ 003 */ 004 005package edu.jas.ufd; 006 007 008import java.io.Reader; 009import java.util.ArrayList; 010import java.util.List; 011import java.util.Random; 012 013import org.apache.logging.log4j.Logger; 014import org.apache.logging.log4j.LogManager; 015 016import edu.jas.kern.StringUtil; 017import edu.jas.poly.GenPolynomial; 018import edu.jas.poly.GenPolynomialRing; 019import edu.jas.poly.PolyUtil; 020// import edu.jas.gbufd.PolyGBUtil; 021import edu.jas.structure.GcdRingElem; 022import edu.jas.structure.QuotPairFactory; 023import edu.jas.structure.RingFactory; 024 025 026/** 027 * Quotient ring factory based on GenPolynomial with RingElem interface. Objects 028 * of this class are immutable. 029 * @author Heinz Kredel 030 */ 031public class QuotientRing<C extends GcdRingElem<C>> implements RingFactory<Quotient<C>>, 032 QuotPairFactory<GenPolynomial<C>, Quotient<C>> { 033 034 035 private static final Logger logger = LogManager.getLogger(QuotientRing.class); 036 037 038 //private static final boolean debug = logger.isDebugEnabled(); 039 040 041 /** 042 * Polynomial ring of the factory. 043 */ 044 public final GenPolynomialRing<C> ring; 045 046 047 /** 048 * GCD engine of the factory. 049 */ 050 public final GreatestCommonDivisor<C> engine; 051 052 053 /** 054 * Use GCD of package edu.jas.ufd. 055 */ 056 public final boolean ufdGCD; 057 058 059 /** 060 * The constructor creates a QuotientRing object from a GenPolynomialRing. 061 * @param r polynomial ring. 062 */ 063 public QuotientRing(GenPolynomialRing<C> r) { 064 this(r, true); 065 } 066 067 068 /** 069 * The constructor creates a QuotientRing object from a GenPolynomialRing. 070 * @param r polynomial ring. 071 * @param ufdGCD flag, if syzygy or gcd based algorithm used for engine. 072 */ 073 public QuotientRing(GenPolynomialRing<C> r, boolean ufdGCD) { 074 ring = r; 075 this.ufdGCD = ufdGCD; 076 // if (!ufdGCD) { 077 // engine = null; 078 // return; 079 // } 080 engine = GCDFactory.<C> getProxy(ring.coFac); 081 logger.debug("quotient ring constructed"); 082 } 083 084 085 /** 086 * Factory for base elements. 087 */ 088 public GenPolynomialRing<C> pairFactory() { 089 return ring; 090 } 091 092 093 /** 094 * Create from numerator. 095 */ 096 public Quotient<C> create(GenPolynomial<C> n) { 097 return new Quotient<C>(this, n); 098 } 099 100 101 /** 102 * Create from numerator, denominator pair. 103 */ 104 public Quotient<C> create(GenPolynomial<C> n, GenPolynomial<C> d) { 105 return new Quotient<C>(this, n, d); 106 } 107 108 109 /** 110 * Divide. 111 * @param n first polynomial. 112 * @param d second polynomial. 113 * @return divide(n,d) 114 */ 115 protected GenPolynomial<C> divide(GenPolynomial<C> n, GenPolynomial<C> d) { 116 return PolyUtil.<C> basePseudoDivide(n, d); 117 } 118 119 120 /** 121 * Greatest common divisor. 122 * @param n first polynomial. 123 * @param d second polynomial. 124 * @return gcd(n,d) 125 */ 126 protected GenPolynomial<C> gcd(GenPolynomial<C> n, GenPolynomial<C> d) { 127 if (ufdGCD) { 128 return engine.gcd(n, d); 129 } 130 return engine.gcd(n, d); 131 //return PolyGBUtil.<C> syzGcd(ring, n, d); 132 } 133 134 135 /** 136 * Is this structure finite or infinite. 137 * @return true if this structure is finite, else false. 138 * @see edu.jas.structure.ElemFactory#isFinite() 139 */ 140 public boolean isFinite() { 141 return false; 142 } 143 144 145 /** 146 * Copy Quotient element c. 147 * @param c 148 * @return a copy of c. 149 */ 150 public Quotient<C> copy(Quotient<C> c) { 151 return new Quotient<C>(c.ring, c.num, c.den, true); 152 } 153 154 155 /** 156 * Get the zero element. 157 * @return 0 as Quotient. 158 */ 159 public Quotient<C> getZERO() { 160 return new Quotient<C>(this, ring.getZERO()); 161 } 162 163 164 /** 165 * Get the one element. 166 * @return 1 as Quotient. 167 */ 168 public Quotient<C> getONE() { 169 return new Quotient<C>(this, ring.getONE()); 170 } 171 172 173 /** 174 * Get a list of the generating elements. 175 * @return list of generators for the algebraic structure. 176 * @see edu.jas.structure.ElemFactory#generators() 177 */ 178 public List<Quotient<C>> generators() { 179 List<GenPolynomial<C>> pgens = ring.generators(); 180 List<Quotient<C>> gens = new ArrayList<Quotient<C>>(pgens.size()); 181 for (GenPolynomial<C> p : pgens) { 182 Quotient<C> q = new Quotient<C>(this, p); 183 gens.add(q); 184 } 185 return gens; 186 } 187 188 189 /** 190 * Query if this ring is commutative. 191 * @return true if this ring is commutative, else false. 192 */ 193 public boolean isCommutative() { 194 return ring.isCommutative(); 195 } 196 197 198 /** 199 * Query if this ring is associative. 200 * @return true if this ring is associative, else false. 201 */ 202 public boolean isAssociative() { 203 return ring.isAssociative(); 204 } 205 206 207 /** 208 * Query if this ring is a field. 209 * @return true. 210 */ 211 public boolean isField() { 212 return true; 213 } 214 215 216 /** 217 * Characteristic of this ring. 218 * @return characteristic of this ring. 219 */ 220 public java.math.BigInteger characteristic() { 221 return ring.characteristic(); 222 } 223 224 225 /** 226 * Get a Quotient element from a BigInteger value. 227 * @param a BigInteger. 228 * @return a Quotient. 229 */ 230 public Quotient<C> fromInteger(java.math.BigInteger a) { 231 return new Quotient<C>(this, ring.fromInteger(a)); 232 } 233 234 235 /** 236 * Get a Quotient element from a long value. 237 * @param a long. 238 * @return a Quotient. 239 */ 240 public Quotient<C> fromInteger(long a) { 241 return new Quotient<C>(this, ring.fromInteger(a)); 242 } 243 244 245 /** 246 * Get the String representation as RingFactory. 247 * @see java.lang.Object#toString() 248 */ 249 @Override 250 public String toString() { 251 String s = null; 252 if (ring.coFac.characteristic().signum() == 0) { 253 s = "RatFunc"; 254 } else { 255 s = "ModFunc"; 256 } 257 return s + "( " + ring.toString() + " )"; 258 } 259 260 261 /** 262 * Get a scripting compatible string representation. 263 * @return script compatible representation for this ElemFactory. 264 * @see edu.jas.structure.ElemFactory#toScript() 265 */ 266 @Override 267 public String toScript() { 268 // Python case 269 return "RF(" + ring.toScript() + ")"; 270 } 271 272 273 /** 274 * Comparison with any other object. 275 * @see java.lang.Object#equals(java.lang.Object) 276 */ 277 @Override 278 @SuppressWarnings("unchecked") 279 public boolean equals(Object b) { 280 if (b == null) { 281 return false; 282 } 283 if (!(b instanceof QuotientRing)) { 284 return false; 285 } 286 QuotientRing<C> a = (QuotientRing<C>) b; 287 return ring.equals(a.ring); 288 } 289 290 291 /** 292 * Hash code for this quotient ring. 293 * @see java.lang.Object#hashCode() 294 */ 295 @Override 296 public int hashCode() { 297 int h; 298 h = ring.hashCode(); 299 return h; 300 } 301 302 303 /** 304 * Quotient random. 305 * @param n such that 0 ≤ v ≤ (2<sup>n</sup>-1). 306 * @return a random residue element. 307 */ 308 public Quotient<C> random(int n) { 309 GenPolynomial<C> r = ring.random(n).monic(); 310 GenPolynomial<C> s = ring.random(n).monic(); 311 while (s.isZERO()) { 312 s = ring.random(n).monic(); 313 } 314 return new Quotient<C>(this, r, s, false); 315 } 316 317 318 /** 319 * Generate a random quotient polynomial. 320 * @param k bitsize of random coefficients. 321 * @param l number of terms. 322 * @param d maximal degree in each variable. 323 * @param q density of nozero exponents. 324 * @return a random quotient polynomial. 325 */ 326 public Quotient<C> random(int k, int l, int d, float q) { 327 GenPolynomial<C> r = ring.random(k, l, d, q).monic(); 328 GenPolynomial<C> s = ring.random(k, l, d, q).monic(); 329 while (s.isZERO()) { 330 s = ring.random(k, l, d, q).monic(); 331 } 332 return new Quotient<C>(this, r, s, false); 333 } 334 335 336 /** 337 * Quotient random. 338 * @param n such that 0 ≤ v ≤ (2<sup>n</sup>-1). 339 * @param rnd is a source for random bits. 340 * @return a random quotient element. 341 */ 342 public Quotient<C> random(int n, Random rnd) { 343 GenPolynomial<C> r = ring.random(n, rnd).monic(); 344 GenPolynomial<C> s = ring.random(n, rnd).monic(); 345 while (s.isZERO()) { 346 s = ring.random(n, rnd).monic(); 347 } 348 return new Quotient<C>(this, r, s, false); 349 } 350 351 352 /** 353 * Parse Quotient from String. Syntax: "{ polynomial | polynomial }" or 354 * "{ polynomial }" or " polynomial | polynomial " or " polynomial " 355 * @param s String. 356 * @return Quotient from s. 357 */ 358 public Quotient<C> parse(String s) { 359 int i = s.indexOf("{"); 360 if (i >= 0) { 361 s = s.substring(i + 1); 362 } 363 i = s.lastIndexOf("}"); 364 if (i >= 0) { 365 s = s.substring(0, i); 366 } 367 i = s.indexOf("|"); 368 if (i < 0) { 369 GenPolynomial<C> n = ring.parse(s); 370 return new Quotient<C>(this, n); 371 } 372 String s1 = s.substring(0, i); 373 String s2 = s.substring(i + 1); 374 GenPolynomial<C> n = ring.parse(s1); 375 GenPolynomial<C> d = ring.parse(s2); 376 return new Quotient<C>(this, n, d); 377 } 378 379 380 /** 381 * Parse Quotient from Reader. 382 * @param r Reader. 383 * @return next Quotient from r. 384 */ 385 public Quotient<C> parse(Reader r) { 386 String s = StringUtil.nextPairedString(r, '{', '}'); 387 return parse(s); 388 } 389 390 391 /** 392 * Degree of extension field. 393 * @return degree of this extension field, -1 for transcendental extension. 394 */ 395 public long extensionDegree() { 396 long degree = -1L; 397 if (ring.nvar <= 0) { 398 degree = 0L; 399 } 400 return degree; 401 } 402 403}