001 /*
002 * $Id: Residue.java 3287 2010-08-23 21:29:53Z kredel $
003 */
004
005 package edu.jas.application;
006
007 import edu.jas.poly.GenPolynomial;
008 import edu.jas.poly.PolyUtil;
009
010 import edu.jas.kern.PrettyPrint;
011
012 import edu.jas.structure.GcdRingElem;
013 import edu.jas.structure.RingFactory;
014
015
016 /**
017 * Residue ring element based on GenPolynomial with RingElem interface.
018 * Objects of this class are (nearly) immutable.
019 * @author Heinz Kredel
020 */
021 public class Residue<C extends GcdRingElem<C> >
022 implements GcdRingElem< Residue<C> > {
023
024
025 /** Residue class factory data structure.
026 */
027 public final ResidueRing<C> ring;
028
029
030 /** Value part of the element data structure.
031 */
032 public final GenPolynomial<C> val;
033
034
035 /** Flag to remember if this residue element is a unit.
036 * -1 is unknown, 1 is unit, 0 not a unit.
037 */
038 protected int isunit = -1; // initially unknown
039
040
041 /** The constructor creates a Residue object
042 * from a ring factory.
043 * @param r ring factory.
044 */
045 public Residue(ResidueRing<C> r) {
046 this( r, r.ring.getZERO(), 0 );
047 }
048
049
050 /** The constructor creates a Residue object
051 * from a ring factory and a polynomial.
052 * @param r ring factory.
053 * @param a polynomial list.
054 */
055 public Residue(ResidueRing<C> r, GenPolynomial<C> a) {
056 this( r, a, -1 );
057 }
058
059
060 /** The constructor creates a Residue object
061 * from a ring factory, a polynomial and an indicator if a is a unit.
062 * @param r ring factory.
063 * @param a polynomial list.
064 * @param u isunit indicator, -1, 0, 1.
065 */
066 public Residue(ResidueRing<C> r, GenPolynomial<C> a, int u) {
067 ring = r;
068 val = ring.ideal.normalform( a ); //.monic() no go
069 switch ( u ) {
070 case 0: isunit = u;
071 break;
072 case 1: isunit = u;
073 break;
074 default: isunit = -1;
075 }
076 if ( val.isONE() ) {
077 isunit = 1;
078 }
079 if ( val.isZERO() ) {
080 isunit = 0;
081 }
082 }
083
084 /**
085 * Get the corresponding element factory.
086 * @return factory for this Element.
087 * @see edu.jas.structure.Element#factory()
088 */
089 public ResidueRing<C> factory() {
090 return ring;
091 }
092
093
094 /** Clone this.
095 * @see java.lang.Object#clone()
096 */
097 @Override
098 public Residue<C> clone() {
099 return new Residue<C>( ring, val, isunit );
100 }
101
102
103 /** Is Residue zero.
104 * @return If this is 0 then true is returned, else false.
105 * @see edu.jas.structure.RingElem#isZERO()
106 */
107 public boolean isZERO() {
108 // ??return val.equals( ring.ring.getZERO() );
109 return val.isZERO();
110 }
111
112
113 /** Is Residue one.
114 * @return If this is 1 then true is returned, else false.
115 * @see edu.jas.structure.RingElem#isONE()
116 */
117 public boolean isONE() {
118 // ?? return val.equals( ring.ring.getONE() );
119 return val.isONE();
120 }
121
122
123 /** Is Residue unit.
124 * @return If this is a unit then true is returned, else false.
125 * @see edu.jas.structure.RingElem#isUnit()
126 */
127 public boolean isUnit() {
128 if ( isunit > 0 ) {
129 return true;
130 }
131 if ( isunit == 0 ) {
132 return false;
133 }
134 // not jet known
135 boolean u = ring.ideal.isUnit( val );
136 if ( u ) {
137 isunit = 1;
138 } else {
139 isunit = 0;
140 }
141 return ( u );
142 }
143
144
145 /** Is Residue a constant.
146 * @return true if this.val is a constant polynomial, else false.
147 */
148 public boolean isConstant() {
149 return val.isConstant();
150 }
151
152
153 /** Get the String representation as RingElem.
154 * @see java.lang.Object#toString()
155 */
156 @Override
157 public String toString() {
158 if ( PrettyPrint.isTrue() ) {
159 return val.toString( ring.ring.getVars() );
160 } else {
161 return "Residue[ " + val.toString()
162 + " mod " + ring.toString() + " ]";
163 }
164 }
165
166
167 /** Get a scripting compatible string representation.
168 * @return script compatible representation for this Element.
169 * @see edu.jas.structure.Element#toScript()
170 */
171 //JAVA6only: @Override
172 public String toScript() {
173 // Python case
174 return val.toScript();
175 // return "PolyResidue( " + val.toScript()
176 // + ", " + ring.toScript() + " )";
177 }
178
179
180 /** Get a scripting compatible string representation of the factory.
181 * @return script compatible representation for this ElemFactory.
182 * @see edu.jas.structure.Element#toScriptFactory()
183 */
184 //JAVA6only: @Override
185 public String toScriptFactory() {
186 // Python case
187 return factory().toScript();
188 }
189
190
191 /** Residue comparison.
192 * @param b Residue.
193 * @return sign(this-b), 0 means that this and b are equivalent in this residue class ring.
194 */
195 //JAVA6only: @Override
196 public int compareTo(Residue<C> b) {
197 GenPolynomial<C> v = b.val;
198 if ( ! ring.equals( b.ring ) ) {
199 v = ring.ideal.normalform( v );
200 }
201 return val.compareTo( v );
202 }
203
204
205 /** Comparison with any other object.
206 * @see java.lang.Object#equals(java.lang.Object)
207 * @return true means that this and b are equivalent in this residue class ring.
208 */
209 @Override
210 @SuppressWarnings("unchecked")
211 public boolean equals(Object b) {
212 if ( ! ( b instanceof Residue ) ) {
213 return false;
214 }
215 Residue<C> a = null;
216 try {
217 a = (Residue<C>) b;
218 } catch (ClassCastException e) {
219 }
220 if ( a == null ) {
221 return false;
222 }
223 return ( 0 == compareTo( a ) );
224 }
225
226
227 /** Hash code for this local.
228 * @see java.lang.Object#hashCode()
229 */
230 @Override
231 public int hashCode() {
232 int h;
233 h = ring.hashCode();
234 h = 37 * h + val.hashCode();
235 return h;
236 }
237
238
239 /** Residue absolute value.
240 * @return the absolute value of this.
241 * @see edu.jas.structure.RingElem#abs()
242 */
243 public Residue<C> abs() {
244 return new Residue<C>( ring, val.abs(), isunit );
245 }
246
247
248 /** Residue summation.
249 * @param S Residue.
250 * @return this+S.
251 */
252 public Residue<C> sum(Residue<C> S) {
253 return new Residue<C>( ring, val.sum( S.val ) );
254 }
255
256
257 /** Residue negate.
258 * @return -this.
259 * @see edu.jas.structure.RingElem#negate()
260 */
261 public Residue<C> negate() {
262 return new Residue<C>( ring, val.negate(), isunit );
263 }
264
265
266 /** Residue signum.
267 * @see edu.jas.structure.RingElem#signum()
268 * @return signum(this).
269 */
270 public int signum() {
271 return val.signum();
272 }
273
274
275 /** Residue subtraction.
276 * @param S Residue.
277 * @return this-S.
278 */
279 public Residue<C> subtract(Residue<C> S) {
280 return new Residue<C>( ring, val.subtract( S.val ) );
281 }
282
283
284 /** Residue division.
285 * @param S Residue.
286 * @return this/S.
287 */
288 public Residue<C> divide(Residue<C> S) {
289 if ( ring.isField() ) {
290 return multiply( S.inverse() );
291 }
292 GenPolynomial<C> x = PolyUtil.<C>basePseudoDivide( val, S.val );
293 return new Residue<C>( ring, x );
294 }
295
296
297 /** Residue inverse.
298 * @see edu.jas.structure.RingElem#inverse()
299 * @return S with S = 1/this if defined.
300 */
301 public Residue<C> inverse() {
302 GenPolynomial<C> x = ring.ideal.inverse( val );
303 return new Residue<C>( ring, x, 1 );
304 }
305
306
307 /** Residue remainder.
308 * @param S Residue.
309 * @return this - (this/S)*S.
310 */
311 public Residue<C> remainder(Residue<C> S) {
312 //GenPolynomial<C> x = val.remainder( S.val );
313 GenPolynomial<C> x = PolyUtil.<C>basePseudoRemainder( val, S.val );
314 return new Residue<C>( ring, x );
315 }
316
317
318 /** Residue multiplication.
319 * @param S Residue.
320 * @return this*S.
321 */
322 public Residue<C> multiply(Residue<C> S) {
323 GenPolynomial<C> x = val.multiply( S.val );
324 int i = -1;
325 if ( isunit == 1 && S.isunit == 1 ) {
326 i = 1;
327 } else if ( isunit == 0 || S.isunit == 0 ) {
328 i = 0;
329 }
330 return new Residue<C>( ring, x, i );
331 }
332
333
334 /** Residue monic.
335 * @return this with monic value part.
336 */
337 public Residue<C> monic() {
338 return new Residue<C>( ring, val.monic(), isunit );
339 }
340
341
342 /**
343 * Greatest common divisor.
344 * @param b other element.
345 * @return gcd(this,b).
346 */
347 public Residue<C> gcd(Residue<C> b) {
348 GenPolynomial<C> x = ring.engine.gcd( val, b.val );
349 int i = -1; // gcd might become a unit
350 if ( x.isONE() ) {
351 i = 1;
352 } else {
353 System.out.println("Residue gcd = " + x);
354 }
355 if ( isunit == 1 && b.isunit == 1 ) {
356 i = 1;
357 }
358 return new Residue<C>( ring, x, i );
359 }
360
361
362 /**
363 * Extended greatest common divisor.
364 * <b>Note: </b>Not implemented, throws UnsupportedOperationException.
365 * @param b other element.
366 * @return [ gcd(this,b), c1, c2 ] with c1*this + c2*b = gcd(this,b).
367 */
368 public Residue<C>[] egcd(Residue<C> b) {
369 throw new UnsupportedOperationException("egcd not implemented " + this.getClass().getName());
370 }
371 }