001/* 002 * $Id: AlgebraicNumber.java 5916 2018-08-29 20:21:02Z 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 @SuppressWarnings("unchecked") 379 public AlgebraicNumber<C>[] quotientRemainder(AlgebraicNumber<C> S) { 380 return new AlgebraicNumber[] { divide(S), remainder(S) }; 381 } 382 383 384 /** 385 * AlgebraicNumber multiplication. 386 * @param S AlgebraicNumber. 387 * @return this*S. 388 */ 389 public AlgebraicNumber<C> multiply(AlgebraicNumber<C> S) { 390 GenPolynomial<C> x = val.multiply(S.val); 391 return new AlgebraicNumber<C>(ring, x); 392 } 393 394 395 /** 396 * AlgebraicNumber multiplication. 397 * @param c coefficient. 398 * @return this*c. 399 */ 400 public AlgebraicNumber<C> multiply(C c) { 401 GenPolynomial<C> x = val.multiply(c); 402 return new AlgebraicNumber<C>(ring, x); 403 } 404 405 406 /** 407 * AlgebraicNumber multiplication. 408 * @param c polynomial. 409 * @return this*c. 410 */ 411 public AlgebraicNumber<C> multiply(GenPolynomial<C> c) { 412 GenPolynomial<C> x = val.multiply(c); 413 return new AlgebraicNumber<C>(ring, x); 414 } 415 416 417 /** 418 * AlgebraicNumber monic. 419 * @return this with monic value part. 420 */ 421 public AlgebraicNumber<C> monic() { 422 return new AlgebraicNumber<C>(ring, val.monic()); 423 } 424 425 426 /** 427 * AlgebraicNumber greatest common divisor. 428 * @param S AlgebraicNumber. 429 * @return gcd(this,S). 430 */ 431 public AlgebraicNumber<C> gcd(AlgebraicNumber<C> S) { 432 if (S.isZERO()) { 433 return this; 434 } 435 if (isZERO()) { 436 return S; 437 } 438 if (isUnit() || S.isUnit()) { 439 return ring.getONE(); 440 } 441 return new AlgebraicNumber<C>(ring, val.gcd(S.val)); 442 } 443 444 445 /** 446 * AlgebraicNumber extended greatest common divisor. 447 * @param S AlgebraicNumber. 448 * @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S). 449 */ 450 @SuppressWarnings("unchecked") 451 public AlgebraicNumber<C>[] egcd(AlgebraicNumber<C> S) { 452 AlgebraicNumber<C>[] ret = new AlgebraicNumber[3]; 453 ret[0] = null; 454 ret[1] = null; 455 ret[2] = null; 456 if (S == null || S.isZERO()) { 457 ret[0] = this; 458 return ret; 459 } 460 if (isZERO()) { 461 ret[0] = S; 462 return ret; 463 } 464 if (this.isUnit() || S.isUnit()) { 465 ret[0] = ring.getONE(); 466 if (this.isUnit() && S.isUnit()) { 467 AlgebraicNumber<C> half = ring.fromInteger(2).inverse(); 468 ret[1] = this.inverse().multiply(half); 469 ret[2] = S.inverse().multiply(half); 470 return ret; 471 } 472 if (this.isUnit()) { 473 // oder inverse(S-1)? 474 ret[1] = this.inverse(); 475 ret[2] = ring.getZERO(); 476 return ret; 477 } 478 // if ( S.isUnit() ) { 479 // oder inverse(this-1)? 480 ret[1] = ring.getZERO(); 481 ret[2] = S.inverse(); 482 return ret; 483 //} 484 } 485 //System.out.println("this = " + this + ", S = " + S); 486 GenPolynomial<C>[] qr; 487 GenPolynomial<C> q = this.val; 488 GenPolynomial<C> r = S.val; 489 GenPolynomial<C> c1 = ring.ring.getONE(); 490 GenPolynomial<C> d1 = ring.ring.getZERO(); 491 GenPolynomial<C> c2 = ring.ring.getZERO(); 492 GenPolynomial<C> d2 = ring.ring.getONE(); 493 GenPolynomial<C> x1; 494 GenPolynomial<C> x2; 495 while (!r.isZERO()) { 496 qr = q.quotientRemainder(r); 497 q = qr[0]; 498 x1 = c1.subtract(q.multiply(d1)); 499 x2 = c2.subtract(q.multiply(d2)); 500 c1 = d1; 501 c2 = d2; 502 d1 = x1; 503 d2 = x2; 504 q = r; 505 r = qr[1]; 506 } 507 //System.out.println("q = " + q + "\n c1 = " + c1 + "\n c2 = " + c2); 508 ret[0] = new AlgebraicNumber<C>(ring, q); 509 ret[1] = new AlgebraicNumber<C>(ring, c1); 510 ret[2] = new AlgebraicNumber<C>(ring, c2); 511 return ret; 512 } 513 514}