001/* 002 * $Id: AlgebraicNumber.java 5562 2016-08-01 19:52:55Z 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 * Is AlgebraicNumber a root of unity. 152 * @return true if |this**i| == 1, for some 0 < i ≤ deg(modul), else false. 153 */ 154 public boolean isRootOfUnity() { 155 long d = ring.modul.degree(); 156 AlgebraicNumber<C> t = ring.getONE(); 157 for (long i = 1; i <= d; i++) { 158 t = t.multiply(this); 159 if (t.abs().isONE()) { 160 //System.out.println("isRootOfUnity for i = " + i); 161 return true; 162 } 163 } 164 return false; 165 } 166 167 168 /** 169 * Get the String representation as RingElem. 170 * @see java.lang.Object#toString() 171 */ 172 @Override 173 public String toString() { 174 if (PrettyPrint.isTrue()) { 175 return val.toString(ring.ring.vars); 176 } 177 return "AlgebraicNumber[ " + val.toString() + " ]"; 178 } 179 180 181 /** 182 * Get a scripting compatible string representation. 183 * @return script compatible representation for this Element. 184 * @see edu.jas.structure.Element#toScript() 185 */ 186 @Override 187 public String toScript() { 188 // Python case 189 return val.toScript(); 190 } 191 192 193 /** 194 * Get a scripting compatible string representation of the factory. 195 * @return script compatible representation for this ElemFactory. 196 * @see edu.jas.structure.Element#toScriptFactory() 197 */ 198 @Override 199 public String toScriptFactory() { 200 // Python case 201 return factory().toScript(); 202 } 203 204 205 /** 206 * AlgebraicNumber comparison. 207 * @param b AlgebraicNumber. 208 * @return sign(this-b). 209 */ 210 @Override 211 public int compareTo(AlgebraicNumber<C> b) { 212 int s = 0; 213 if (ring.modul != b.ring.modul) { // avoid compareTo if possible 214 s = ring.modul.compareTo(b.ring.modul); 215 } 216 if (s != 0) { 217 return s; 218 } 219 return val.compareTo(b.val); 220 } 221 222 223 /** 224 * Comparison with any other object. 225 * @see java.lang.Object#equals(java.lang.Object) 226 */ 227 @Override 228 @SuppressWarnings("unchecked") 229 public boolean equals(Object b) { 230 if (b == null) { 231 return false; 232 } 233 if (!(b instanceof AlgebraicNumber)) { 234 return false; 235 } 236 AlgebraicNumber<C> a = (AlgebraicNumber<C>) b; 237 if (!ring.equals(a.ring)) { 238 return false; 239 } 240 return (0 == compareTo(a)); 241 } 242 243 244 /** 245 * Hash code for this AlgebraicNumber. 246 * @see java.lang.Object#hashCode() 247 */ 248 @Override 249 public int hashCode() { 250 return 37 * val.hashCode() + ring.hashCode(); 251 } 252 253 254 /** 255 * AlgebraicNumber absolute value. 256 * @return the absolute value of this. 257 * @see edu.jas.structure.RingElem#abs() 258 */ 259 public AlgebraicNumber<C> abs() { 260 return new AlgebraicNumber<C>(ring, val.abs()); 261 } 262 263 264 /** 265 * AlgebraicNumber summation. 266 * @param S AlgebraicNumber. 267 * @return this+S. 268 */ 269 public AlgebraicNumber<C> sum(AlgebraicNumber<C> S) { 270 return new AlgebraicNumber<C>(ring, val.sum(S.val)); 271 } 272 273 274 /** 275 * AlgebraicNumber summation. 276 * @param c coefficient. 277 * @return this+c. 278 */ 279 public AlgebraicNumber<C> sum(GenPolynomial<C> c) { 280 return new AlgebraicNumber<C>(ring, val.sum(c)); 281 } 282 283 284 /** 285 * AlgebraicNumber summation. 286 * @param c polynomial. 287 * @return this+c. 288 */ 289 public AlgebraicNumber<C> sum(C c) { 290 return new AlgebraicNumber<C>(ring, val.sum(c)); 291 } 292 293 294 /** 295 * AlgebraicNumber negate. 296 * @return -this. 297 * @see edu.jas.structure.RingElem#negate() 298 */ 299 public AlgebraicNumber<C> negate() { 300 return new AlgebraicNumber<C>(ring, val.negate()); 301 } 302 303 304 /** 305 * AlgebraicNumber signum. 306 * @see edu.jas.structure.RingElem#signum() 307 * @return signum(this). 308 */ 309 public int signum() { 310 return val.signum(); 311 } 312 313 314 /** 315 * AlgebraicNumber subtraction. 316 * @param S AlgebraicNumber. 317 * @return this-S. 318 */ 319 public AlgebraicNumber<C> subtract(AlgebraicNumber<C> S) { 320 return new AlgebraicNumber<C>(ring, val.subtract(S.val)); 321 } 322 323 324 /** 325 * AlgebraicNumber division. 326 * @param S AlgebraicNumber. 327 * @return this/S. 328 */ 329 public AlgebraicNumber<C> divide(AlgebraicNumber<C> S) { 330 return multiply(S.inverse()); 331 } 332 333 334 /** 335 * AlgebraicNumber inverse. 336 * @see edu.jas.structure.RingElem#inverse() 337 * @throws NotInvertibleException if the element is not invertible. 338 * @return S with S = 1/this if defined. 339 */ 340 public AlgebraicNumber<C> inverse() { 341 try { 342 return new AlgebraicNumber<C>(ring, val.modInverse(ring.modul)); 343 } catch (AlgebraicNotInvertibleException e) { 344 //System.out.println(e); 345 throw e; 346 } catch (NotInvertibleException e) { 347 throw new AlgebraicNotInvertibleException(e + ", val = " + val + ", modul = " + ring.modul 348 + ", gcd = " + val.gcd(ring.modul), e); 349 } 350 } 351 352 353 /** 354 * AlgebraicNumber remainder. 355 * @param S AlgebraicNumber. 356 * @return this - (this/S)*S. 357 */ 358 public AlgebraicNumber<C> remainder(AlgebraicNumber<C> S) { 359 if (S == null || S.isZERO()) { 360 throw new ArithmeticException("division by zero"); 361 } 362 if (S.isONE()) { 363 return ring.getZERO(); 364 } 365 if (S.isUnit()) { 366 return ring.getZERO(); 367 } 368 GenPolynomial<C> x = val.remainder(S.val); 369 return new AlgebraicNumber<C>(ring, x); 370 } 371 372 373 /** 374 * Quotient and remainder by division of this by S. 375 * @param S a AlgebraicNumber 376 * @return [this/S, this - (this/S)*S]. 377 */ 378 public AlgebraicNumber<C>[] quotientRemainder(AlgebraicNumber<C> S) { 379 return new AlgebraicNumber[] { divide(S), remainder(S) }; 380 } 381 382 383 /** 384 * AlgebraicNumber multiplication. 385 * @param S AlgebraicNumber. 386 * @return this*S. 387 */ 388 public AlgebraicNumber<C> multiply(AlgebraicNumber<C> S) { 389 GenPolynomial<C> x = val.multiply(S.val); 390 return new AlgebraicNumber<C>(ring, x); 391 } 392 393 394 /** 395 * AlgebraicNumber multiplication. 396 * @param c coefficient. 397 * @return this*c. 398 */ 399 public AlgebraicNumber<C> multiply(C c) { 400 GenPolynomial<C> x = val.multiply(c); 401 return new AlgebraicNumber<C>(ring, x); 402 } 403 404 405 /** 406 * AlgebraicNumber multiplication. 407 * @param c polynomial. 408 * @return this*c. 409 */ 410 public AlgebraicNumber<C> multiply(GenPolynomial<C> c) { 411 GenPolynomial<C> x = val.multiply(c); 412 return new AlgebraicNumber<C>(ring, x); 413 } 414 415 416 /** 417 * AlgebraicNumber monic. 418 * @return this with monic value part. 419 */ 420 public AlgebraicNumber<C> monic() { 421 return new AlgebraicNumber<C>(ring, val.monic()); 422 } 423 424 425 /** 426 * AlgebraicNumber greatest common divisor. 427 * @param S AlgebraicNumber. 428 * @return gcd(this,S). 429 */ 430 public AlgebraicNumber<C> gcd(AlgebraicNumber<C> S) { 431 if (S.isZERO()) { 432 return this; 433 } 434 if (isZERO()) { 435 return S; 436 } 437 if (isUnit() || S.isUnit()) { 438 return ring.getONE(); 439 } 440 return new AlgebraicNumber<C>(ring, val.gcd(S.val)); 441 } 442 443 444 /** 445 * AlgebraicNumber extended greatest common divisor. 446 * @param S AlgebraicNumber. 447 * @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S). 448 */ 449 @SuppressWarnings("unchecked") 450 public AlgebraicNumber<C>[] egcd(AlgebraicNumber<C> S) { 451 AlgebraicNumber<C>[] ret = new AlgebraicNumber[3]; 452 ret[0] = null; 453 ret[1] = null; 454 ret[2] = null; 455 if (S == null || S.isZERO()) { 456 ret[0] = this; 457 return ret; 458 } 459 if (isZERO()) { 460 ret[0] = S; 461 return ret; 462 } 463 if (this.isUnit() || S.isUnit()) { 464 ret[0] = ring.getONE(); 465 if (this.isUnit() && S.isUnit()) { 466 AlgebraicNumber<C> half = ring.fromInteger(2).inverse(); 467 ret[1] = this.inverse().multiply(half); 468 ret[2] = S.inverse().multiply(half); 469 return ret; 470 } 471 if (this.isUnit()) { 472 // oder inverse(S-1)? 473 ret[1] = this.inverse(); 474 ret[2] = ring.getZERO(); 475 return ret; 476 } 477 // if ( S.isUnit() ) { 478 // oder inverse(this-1)? 479 ret[1] = ring.getZERO(); 480 ret[2] = S.inverse(); 481 return ret; 482 //} 483 } 484 //System.out.println("this = " + this + ", S = " + S); 485 GenPolynomial<C>[] qr; 486 GenPolynomial<C> q = this.val; 487 GenPolynomial<C> r = S.val; 488 GenPolynomial<C> c1 = ring.ring.getONE(); 489 GenPolynomial<C> d1 = ring.ring.getZERO(); 490 GenPolynomial<C> c2 = ring.ring.getZERO(); 491 GenPolynomial<C> d2 = ring.ring.getONE(); 492 GenPolynomial<C> x1; 493 GenPolynomial<C> x2; 494 while (!r.isZERO()) { 495 qr = q.quotientRemainder(r); 496 q = qr[0]; 497 x1 = c1.subtract(q.multiply(d1)); 498 x2 = c2.subtract(q.multiply(d2)); 499 c1 = d1; 500 c2 = d2; 501 d1 = x1; 502 d2 = x2; 503 q = r; 504 r = qr[1]; 505 } 506 //System.out.println("q = " + q + "\n c1 = " + c1 + "\n c2 = " + c2); 507 ret[0] = new AlgebraicNumber<C>(ring, q); 508 ret[1] = new AlgebraicNumber<C>(ring, c1); 509 ret[2] = new AlgebraicNumber<C>(ring, c2); 510 return ret; 511 } 512 513}