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