001/* 002 * $Id$ 003 */ 004 005package edu.jas.poly; 006 007 008import java.io.Reader; 009import java.util.ArrayList; 010import java.util.List; 011import java.util.Random; 012 013import org.apache.logging.log4j.LogManager; 014import org.apache.logging.log4j.Logger; 015 016import edu.jas.structure.QuotPairFactory; 017import edu.jas.structure.RingElem; 018import edu.jas.structure.RingFactory; 019 020 021/** 022 * Local ring factory based on RingElem principal ideal. Objects of this class 023 * are immutable. 024 * @author Heinz Kredel 025 */ 026public class LocalRing<C extends RingElem<C>> implements RingFactory<Local<C>>, QuotPairFactory<C, Local<C>> { 027 028 029 private static final Logger logger = LogManager.getLogger(LocalRing.class); 030 031 032 //private static final boolean debug = logger.isDebugEnabled(); 033 034 035 /** 036 * Ideal generator for localization. 037 */ 038 protected final C ideal; 039 040 041 /** 042 * Ring factory. 043 */ 044 protected final RingFactory<C> ring; 045 046 047 /** 048 * Indicator if this ring is a field. 049 */ 050 protected int isField = -1; // initially unknown 051 052 053 /** 054 * A default random sequence generator. 055 */ 056 protected final static Random random = new Random(); 057 058 059 /** 060 * The constructor creates a LocalRing object from a RingFactory and a 061 * RingElem. 062 * @param i localization ideal generator. 063 */ 064 public LocalRing(RingFactory<C> r, C i) { 065 ring = r; 066 if (i == null) { 067 throw new IllegalArgumentException("ideal may not be null"); 068 } 069 ideal = i; 070 if (ideal.isONE()) { 071 throw new IllegalArgumentException("ideal may not be 1"); 072 } 073 } 074 075 076 /** 077 * Factory for base elements. 078 */ 079 public RingFactory<C> pairFactory() { 080 return ring; 081 } 082 083 084 /** 085 * Create from numerator. 086 */ 087 public Local<C> create(C n) { 088 return new Local<C>(this, n); 089 } 090 091 092 /** 093 * Create from numerator, denominator pair. 094 */ 095 public Local<C> create(C n, C d) { 096 return new Local<C>(this, n, d); 097 } 098 099 100 /** 101 * Is this structure finite or infinite. 102 * @return true if this structure is finite, else false. 103 * @see edu.jas.structure.ElemFactory#isFinite() 104 */ 105 public boolean isFinite() { 106 return ring.isFinite(); 107 } 108 109 110 /** 111 * Copy Local element c. 112 * @param c 113 * @return a copy of c. 114 */ 115 public Local<C> copy(Local<C> c) { 116 return new Local<C>(c.ring, c.num, c.den, true); 117 } 118 119 120 /** 121 * Get the zero element. 122 * @return 0 as Local. 123 */ 124 public Local<C> getZERO() { 125 return new Local<C>(this, ring.getZERO()); 126 } 127 128 129 /** 130 * Get the one element. 131 * @return 1 as Local. 132 */ 133 public Local<C> getONE() { 134 return new Local<C>(this, ring.getONE()); 135 } 136 137 138 /** 139 * Get a list of the generating elements. 140 * @return list of generators for the algebraic structure. 141 * @see edu.jas.structure.ElemFactory#generators() 142 */ 143 public List<Local<C>> generators() { 144 List<? extends C> rgens = ring.generators(); 145 List<Local<C>> gens = new ArrayList<Local<C>>(rgens.size() - 1); 146 C one = ring.getONE(); 147 for (C c : rgens) { 148 gens.add(new Local<C>(this, c)); 149 if (!c.isONE()) { 150 gens.add(new Local<C>(this, one, c)); 151 } 152 } 153 return gens; 154 } 155 156 157 /** 158 * Query if this ring is commutative. 159 * @return true if this ring is commutative, else false. 160 */ 161 public boolean isCommutative() { 162 return ring.isCommutative(); 163 } 164 165 166 /** 167 * Query if this ring is associative. 168 * @return true if this ring is associative, else false. 169 */ 170 public boolean isAssociative() { 171 return ring.isAssociative(); 172 } 173 174 175 /** 176 * Query if this ring is a field. 177 * @return false. 178 */ 179 public boolean isField() { 180 if (isField > 0) { 181 return true; 182 } 183 if (isField == 0) { 184 return false; 185 } 186 // ?? 187 return false; 188 } 189 190 191 /** 192 * Characteristic of this ring. 193 * @return characteristic of this ring. 194 */ 195 public java.math.BigInteger characteristic() { 196 return ring.characteristic(); 197 } 198 199 200 /** 201 * Get a Local element from a BigInteger value. 202 * @param a BigInteger. 203 * @return a Local. 204 */ 205 public Local<C> fromInteger(java.math.BigInteger a) { 206 return new Local<C>(this, ring.fromInteger(a)); 207 } 208 209 210 /** 211 * Get a Local element from a long value. 212 * @param a long. 213 * @return a Local. 214 */ 215 public Local<C> fromInteger(long a) { 216 return new Local<C>(this, ring.fromInteger(a)); 217 } 218 219 220 /** 221 * Get the String representation as RingFactory. 222 * @see java.lang.Object#toString() 223 */ 224 @Override 225 public String toString() { 226 return "Local[ " + ideal.toString() + " ]"; 227 } 228 229 230 /** 231 * Get a scripting compatible string representation. 232 * @return script compatible representation for this ElemFactory. 233 * @see edu.jas.structure.ElemFactory#toScript() 234 */ 235 @Override 236 public String toScript() { 237 // Python case 238 return "LocalRing(" + ideal.toScript() + ")"; 239 } 240 241 242 /** 243 * Comparison with any other object. 244 * @see java.lang.Object#equals(java.lang.Object) 245 */ 246 @Override 247 // not jet working 248 @SuppressWarnings("unchecked") 249 public boolean equals(Object b) { 250 if (b == null) { 251 return false; 252 } 253 if (!(b instanceof LocalRing)) { 254 return false; 255 } 256 LocalRing<C> a = (LocalRing<C>) b; 257 if (!ring.equals(a.ring)) { 258 return false; 259 } 260 return ideal.equals(a.ideal); 261 } 262 263 264 /** 265 * Hash code for this local ring. 266 * @see java.lang.Object#hashCode() 267 */ 268 @Override 269 public int hashCode() { 270 int h; 271 h = ring.hashCode(); 272 h = 37 * h + ideal.hashCode(); 273 return h; 274 } 275 276 277 /** 278 * Local random. 279 * @param n such that 0 ≤ v ≤ (2<sup>n</sup>-1). 280 * @return a random residue element. 281 */ 282 public Local<C> random(int n) { 283 return random(n, random); 284 } 285 286 287 /** 288 * Local random. 289 * @param n such that 0 ≤ v ≤ (2<sup>n</sup>-1). 290 * @param rnd is a source for random bits. 291 * @return a random residue element. 292 */ 293 public Local<C> random(int n, Random rnd) { 294 C r = ring.random(n, rnd); 295 C s = ring.random(n, rnd); 296 s = s.remainder(ideal); 297 while (s.isZERO()) { 298 logger.debug("zero was in ideal"); 299 s = ring.random(n, rnd); 300 s = s.remainder(ideal); 301 } 302 return new Local<C>(this, r, s, false); 303 } 304 305 306 /** 307 * Parse Local from String. 308 * @param s String. 309 * @return Local from s. 310 */ 311 public Local<C> parse(String s) { 312 int i = s.indexOf("{"); 313 if (i >= 0) { 314 s = s.substring(i + 1); 315 } 316 i = s.lastIndexOf("}"); 317 if (i >= 0) { 318 s = s.substring(0, i); 319 } 320 i = s.indexOf("|"); 321 if (i < 0) { 322 C n = ring.parse(s); 323 return new Local<C>(this, n); 324 } 325 String s1 = s.substring(0, i); 326 String s2 = s.substring(i + 1); 327 C n = ring.parse(s1); 328 C d = ring.parse(s2); 329 return new Local<C>(this, n, d); 330 } 331 332 333 /** 334 * Parse Local from Reader. 335 * @param r Reader. 336 * @return next Local from r. 337 */ 338 public Local<C> parse(Reader r) { 339 C x = ring.parse(r); 340 return new Local<C>(this, x); 341 } 342 343}