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