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 }