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