001/* 002 * $Id: ResidueRing.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.RingElem; 017import edu.jas.structure.RingFactory; 018 019 020/** 021 * Residue ring factory based on RingElem and RingFactory module. Objects of 022 * this class are immutable. 023 * @author Heinz Kredel 024 */ 025public class ResidueRing<C extends RingElem<C>> implements RingFactory<Residue<C>> { 026 027 028 private static final Logger logger = LogManager.getLogger(ResidueRing.class); 029 030 031 //private static final boolean debug = logger.isDebugEnabled(); 032 033 034 /** 035 * Ring element for reduction. 036 */ 037 protected final C modul; 038 039 040 /** 041 * Ring factory. 042 */ 043 protected final RingFactory<C> ring; 044 045 046 /** 047 * Indicator if this ring is a field. 048 */ 049 protected int isField = -1; // initially unknown 050 051 052 /** 053 * The constructor creates a ResidueRing object from an ring factory and a 054 * modul. 055 * @param r ring factory. 056 * @param m modul. 057 */ 058 public ResidueRing(RingFactory<C> r, C m) { 059 ring = r; 060 if (m.isZERO()) { 061 throw new IllegalArgumentException("modul may not be null"); 062 } 063 if (m.isONE()) { 064 logger.warn("modul is one"); 065 } 066 if (m.signum() < 0) { 067 m = m.negate(); 068 } 069 modul = m; 070 } 071 072 073 /** 074 * Is this structure finite or infinite. 075 * @return true if this structure is finite, else false. 076 * @see edu.jas.structure.ElemFactory#isFinite() 077 */ 078 public boolean isFinite() { 079 throw new UnsupportedOperationException("not implemented"); 080 //return ring.isFinite(); 081 } 082 083 084 /** 085 * Copy Residue element c. 086 * @param c 087 * @return a copy of c. 088 */ 089 public Residue<C> copy(Residue<C> c) { 090 return new Residue<C>(c.ring, c.val); 091 } 092 093 094 /** 095 * Get the zero element. 096 * @return 0 as Residue. 097 */ 098 public Residue<C> getZERO() { 099 return new Residue<C>(this, ring.getZERO()); 100 } 101 102 103 /** 104 * Get the one element. 105 * @return 1 as Residue. 106 */ 107 public Residue<C> getONE() { 108 Residue<C> one = new Residue<C>(this, ring.getONE()); 109 if (one.isZERO()) { 110 logger.warn("one is zero, so all residues are 0"); 111 } 112 return one; 113 } 114 115 116 /** 117 * Get a list of the generating elements. 118 * @return list of generators for the algebraic structure. 119 * @see edu.jas.structure.ElemFactory#generators() 120 */ 121 public List<Residue<C>> generators() { 122 List<? extends C> rgens = ring.generators(); 123 List<Residue<C>> gens = new ArrayList<Residue<C>>(rgens.size()); 124 for (C c : rgens) { 125 gens.add(new Residue<C>(this, c)); 126 } 127 return gens; 128 } 129 130 131 /** 132 * Query if this ring is commutative. 133 * @return true if this ring is commutative, else false. 134 */ 135 public boolean isCommutative() { 136 return ring.isCommutative(); 137 } 138 139 140 /** 141 * Query if this ring is associative. 142 * @return true if this ring is associative, else false. 143 */ 144 public boolean isAssociative() { 145 return ring.isAssociative(); 146 } 147 148 149 /** 150 * Query if this ring is a field. 151 * @return false. 152 */ 153 public boolean isField() { 154 if (isField > 0) { 155 return true; 156 } 157 if (isField == 0) { 158 return false; 159 } 160 // ideal is prime ? 161 return false; 162 } 163 164 165 /** 166 * Characteristic of this ring. 167 * @return characteristic of this ring. 168 */ 169 public java.math.BigInteger characteristic() { 170 return ring.characteristic(); 171 } 172 173 174 /** 175 * Get a Residue element from a BigInteger value. 176 * @param a BigInteger. 177 * @return a Residue. 178 */ 179 public Residue<C> fromInteger(java.math.BigInteger a) { 180 return new Residue<C>(this, ring.fromInteger(a)); 181 } 182 183 184 /** 185 * Get a Residue element from a long value. 186 * @param a long. 187 * @return a Residue. 188 */ 189 public Residue<C> fromInteger(long a) { 190 return new Residue<C>(this, ring.fromInteger(a)); 191 } 192 193 194 /** 195 * Get the String representation as RingFactory. 196 * @see java.lang.Object#toString() 197 */ 198 @Override 199 public String toString() { 200 return "Residue[ " + modul.toString() + " ]"; 201 } 202 203 204 /** 205 * Get a scripting compatible string representation. 206 * @return script compatible representation for this ElemFactory. 207 * @see edu.jas.structure.ElemFactory#toScript() 208 */ 209 @Override 210 public String toScript() { 211 // Python case 212 return "ResidueRing(" + modul.toScript() + ")"; 213 } 214 215 216 /** 217 * Comparison with any other object. 218 * @see java.lang.Object#equals(java.lang.Object) 219 */ 220 @Override 221 @SuppressWarnings("unchecked") 222 public boolean equals(Object b) { 223 if (b == null) { 224 return false; 225 } 226 if (!(b instanceof ResidueRing)) { 227 return false; 228 } 229 ResidueRing<C> a = (ResidueRing<C>) b; 230 if (!ring.equals(a.ring)) { 231 return false; 232 } 233 return modul.equals(a.modul); 234 } 235 236 237 /** 238 * Hash code for this residue ring. 239 * @see java.lang.Object#hashCode() 240 */ 241 @Override 242 public int hashCode() { 243 int h; 244 h = ring.hashCode(); 245 h = 37 * h + modul.hashCode(); 246 return h; 247 } 248 249 250 /** 251 * Residue random. 252 * @param n such that 0 ≤ v ≤ (2<sup>n</sup>-1). 253 * @return a random residue element. 254 */ 255 public Residue<C> random(int n) { 256 C x = ring.random(n); 257 // x = x.sum( ring.getONE() ); 258 return new Residue<C>(this, x); 259 } 260 261 262 /** 263 * Residue random. 264 * @param n such that 0 ≤ v ≤ (2<sup>n</sup>-1). 265 * @param rnd is a source for random bits. 266 * @return a random residue element. 267 */ 268 public Residue<C> random(int n, Random rnd) { 269 C x = ring.random(n, rnd); 270 // x = x.sum( ring.getONE() ); 271 return new Residue<C>(this, x); 272 } 273 274 275 /** 276 * Parse Residue from String. 277 * @param s String. 278 * @return Residue from s. 279 */ 280 public Residue<C> parse(String s) { 281 C x = ring.parse(s); 282 return new Residue<C>(this, x); 283 } 284 285 286 /** 287 * Parse Residue from Reader. 288 * @param r Reader. 289 * @return next Residue from r. 290 */ 291 public Residue<C> parse(Reader r) { 292 C x = ring.parse(r); 293 return new Residue<C>(this, x); 294 } 295 296}