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