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