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