001/* 002 * $Id: LocalRing.java 5872 2018-07-20 16:01:46Z kredel $ 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.Logger; 014import org.apache.logging.log4j.LogManager; 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 * The constructor creates a LocalRing object from a RingFactory and a 055 * RingElem. 056 * @param i localization ideal generator. 057 */ 058 public LocalRing(RingFactory<C> r, C i) { 059 ring = r; 060 if (i == null) { 061 throw new IllegalArgumentException("ideal may not be null"); 062 } 063 ideal = i; 064 if (ideal.isONE()) { 065 throw new IllegalArgumentException("ideal may not be 1"); 066 } 067 } 068 069 070 /** 071 * Factory for base elements. 072 */ 073 public RingFactory<C> pairFactory() { 074 return ring; 075 } 076 077 078 /** 079 * Create from numerator. 080 */ 081 public Local<C> create(C n) { 082 return new Local<C>(this, n); 083 } 084 085 086 /** 087 * Create from numerator, denominator pair. 088 */ 089 public Local<C> create(C n, C d) { 090 return new Local<C>(this, n, d); 091 } 092 093 094 /** 095 * Is this structure finite or infinite. 096 * @return true if this structure is finite, else false. 097 * @see edu.jas.structure.ElemFactory#isFinite() 098 */ 099 public boolean isFinite() { 100 return ring.isFinite(); 101 } 102 103 104 /** 105 * Copy Local element c. 106 * @param c 107 * @return a copy of c. 108 */ 109 public Local<C> copy(Local<C> c) { 110 return new Local<C>(c.ring, c.num, c.den, true); 111 } 112 113 114 /** 115 * Get the zero element. 116 * @return 0 as Local. 117 */ 118 public Local<C> getZERO() { 119 return new Local<C>(this, ring.getZERO()); 120 } 121 122 123 /** 124 * Get the one element. 125 * @return 1 as Local. 126 */ 127 public Local<C> getONE() { 128 return new Local<C>(this, ring.getONE()); 129 } 130 131 132 /** 133 * Get a list of the generating elements. 134 * @return list of generators for the algebraic structure. 135 * @see edu.jas.structure.ElemFactory#generators() 136 */ 137 public List<Local<C>> generators() { 138 List<? extends C> rgens = ring.generators(); 139 List<Local<C>> gens = new ArrayList<Local<C>>(rgens.size() - 1); 140 for (C c : rgens) { 141 if (!c.isONE()) { 142 gens.add(new Local<C>(this, c)); 143 } 144 } 145 return gens; 146 } 147 148 149 /** 150 * Query if this ring is commutative. 151 * @return true if this ring is commutative, else false. 152 */ 153 public boolean isCommutative() { 154 return ring.isCommutative(); 155 } 156 157 158 /** 159 * Query if this ring is associative. 160 * @return true if this ring is associative, else false. 161 */ 162 public boolean isAssociative() { 163 return ring.isAssociative(); 164 } 165 166 167 /** 168 * Query if this ring is a field. 169 * @return false. 170 */ 171 public boolean isField() { 172 if (isField > 0) { 173 return true; 174 } 175 if (isField == 0) { 176 return false; 177 } 178 // ?? 179 return false; 180 } 181 182 183 /** 184 * Characteristic of this ring. 185 * @return characteristic of this ring. 186 */ 187 public java.math.BigInteger characteristic() { 188 return ring.characteristic(); 189 } 190 191 192 /** 193 * Get a Local element from a BigInteger value. 194 * @param a BigInteger. 195 * @return a Local. 196 */ 197 public Local<C> fromInteger(java.math.BigInteger a) { 198 return new Local<C>(this, ring.fromInteger(a)); 199 } 200 201 202 /** 203 * Get a Local element from a long value. 204 * @param a long. 205 * @return a Local. 206 */ 207 public Local<C> fromInteger(long a) { 208 return new Local<C>(this, ring.fromInteger(a)); 209 } 210 211 212 /** 213 * Get the String representation as RingFactory. 214 * @see java.lang.Object#toString() 215 */ 216 @Override 217 public String toString() { 218 return "Local[ " + ideal.toString() + " ]"; 219 } 220 221 222 /** 223 * Get a scripting compatible string representation. 224 * @return script compatible representation for this ElemFactory. 225 * @see edu.jas.structure.ElemFactory#toScript() 226 */ 227 @Override 228 public String toScript() { 229 // Python case 230 return "LocalRing(" + ideal.toScript() + ")"; 231 } 232 233 234 /** 235 * Comparison with any other object. 236 * @see java.lang.Object#equals(java.lang.Object) 237 */ 238 @Override 239 @SuppressWarnings("unchecked") 240 // not jet working 241 public boolean equals(Object b) { 242 if (b == null) { 243 return false; 244 } 245 if (!(b instanceof LocalRing)) { 246 return false; 247 } 248 LocalRing<C> a = (LocalRing<C>) b; 249 if (!ring.equals(a.ring)) { 250 return false; 251 } 252 return ideal.equals(a.ideal); 253 } 254 255 256 /** 257 * Hash code for this local ring. 258 * @see java.lang.Object#hashCode() 259 */ 260 @Override 261 public int hashCode() { 262 int h; 263 h = ring.hashCode(); 264 h = 37 * h + ideal.hashCode(); 265 return h; 266 } 267 268 269 /** 270 * Local random. 271 * @param n such that 0 ≤ v ≤ (2<sup>n</sup>-1). 272 * @return a random residue element. 273 */ 274 public Local<C> random(int n) { 275 C r = ring.random(n); 276 C s = ring.random(n); 277 s = s.remainder(ideal); 278 while (s.isZERO()) { 279 logger.debug("zero was in ideal"); 280 s = ring.random(n); 281 s = s.remainder(ideal); 282 } 283 return new Local<C>(this, r, s, false); 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 C x = ring.parse(s); 313 return new Local<C>(this, x); 314 } 315 316 317 /** 318 * Parse Local from Reader. 319 * @param r Reader. 320 * @return next Local from r. 321 */ 322 public Local<C> parse(Reader r) { 323 C x = ring.parse(r); 324 return new Local<C>(this, x); 325 } 326 327}