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