001 /* 002 * $Id: AlgebraicNumberRing.java 3487 2011-01-10 22:39:18Z kredel $ 003 */ 004 005 package edu.jas.poly; 006 007 008 import java.io.Reader; 009 import java.util.ArrayList; 010 import java.util.Iterator; 011 import java.util.List; 012 import java.util.Random; 013 014 import org.apache.log4j.Logger; 015 016 import edu.jas.kern.Scripting; 017 import edu.jas.structure.GcdRingElem; 018 import edu.jas.structure.RingFactory; 019 import edu.jas.util.CartesianProduct; 020 import edu.jas.util.CartesianProductInfinite; 021 022 023 /** 024 * Algebraic number factory class based on GenPolynomial with RingElem 025 * interface. Objects of this class are immutable. 026 * @author Heinz Kredel 027 */ 028 029 public class AlgebraicNumberRing<C extends GcdRingElem<C>> implements RingFactory<AlgebraicNumber<C>>, 030 Iterable<AlgebraicNumber<C>> { 031 032 033 /** 034 * Ring part of the factory data structure. 035 */ 036 public final GenPolynomialRing<C> ring; 037 038 039 /** 040 * Module part of the factory data structure. 041 */ 042 public final GenPolynomial<C> modul; 043 044 045 /** 046 * Indicator if this ring is a field 047 */ 048 protected int isField = -1; // initially unknown 049 050 051 private static final Logger logger = Logger.getLogger(AlgebraicNumberRing.class); 052 053 054 // private final boolean debug = logger.isDebugEnabled(); 055 056 057 /** 058 * The constructor creates a AlgebraicNumber factory object from a 059 * GenPolynomial objects module. 060 * @param m module GenPolynomial<C>. 061 */ 062 public AlgebraicNumberRing(GenPolynomial<C> m) { 063 ring = m.ring; 064 modul = m; // assert m != 0 065 if (ring.nvar > 1) { 066 throw new IllegalArgumentException("only univariate polynomials allowed"); 067 } 068 } 069 070 071 /** 072 * The constructor creates a AlgebraicNumber factory object from a 073 * GenPolynomial objects module. 074 * @param m module GenPolynomial<C>. 075 * @param isField indicator if m is prime. 076 */ 077 public AlgebraicNumberRing(GenPolynomial<C> m, boolean isField) { 078 ring = m.ring; 079 modul = m; // assert m != 0 080 this.isField = (isField ? 1 : 0); 081 if (ring.nvar > 1) { 082 throw new IllegalArgumentException("only univariate polynomials allowed"); 083 } 084 } 085 086 087 /** 088 * Get the module part. 089 * @return modul. 090 */ 091 public GenPolynomial<C> getModul() { 092 return modul; 093 } 094 095 096 /** 097 * Copy AlgebraicNumber element c. 098 * @param c algebraic number to copy. 099 * @return a copy of c. 100 */ 101 public AlgebraicNumber<C> copy(AlgebraicNumber<C> c) { 102 return new AlgebraicNumber<C>(this, c.val); 103 } 104 105 106 /** 107 * Get the zero element. 108 * @return 0 as AlgebraicNumber. 109 */ 110 public AlgebraicNumber<C> getZERO() { 111 return new AlgebraicNumber<C>(this, ring.getZERO()); 112 } 113 114 115 /** 116 * Get the one element. 117 * @return 1 as AlgebraicNumber. 118 */ 119 public AlgebraicNumber<C> getONE() { 120 return new AlgebraicNumber<C>(this, ring.getONE()); 121 } 122 123 124 /** 125 * Get the generating element. 126 * @return alpha as AlgebraicNumber. 127 */ 128 public AlgebraicNumber<C> getGenerator() { 129 return new AlgebraicNumber<C>(this, ring.univariate(0)); 130 } 131 132 133 /** 134 * Get a list of the generating elements. 135 * @return list of generators for the algebraic structure. 136 * @see edu.jas.structure.ElemFactory#generators() 137 */ 138 public List<AlgebraicNumber<C>> generators() { 139 List<GenPolynomial<C>> gc = ring.generators(); 140 List<AlgebraicNumber<C>> gens = new ArrayList<AlgebraicNumber<C>>(gc.size()); 141 for (GenPolynomial<C> g : gc) { 142 gens.add(new AlgebraicNumber<C>(this, g)); 143 } 144 return gens; 145 } 146 147 148 /** 149 * Is this structure finite or infinite. 150 * @return true if this structure is finite, else false. 151 * @see edu.jas.structure.ElemFactory#isFinite() 152 */ 153 public boolean isFinite() { 154 return ring.coFac.isFinite(); 155 } 156 157 158 /** 159 * Query if this ring is commutative. 160 * @return true if this ring is commutative, else false. 161 */ 162 public boolean isCommutative() { 163 return ring.isCommutative(); 164 } 165 166 167 /** 168 * Query if this ring is associative. 169 * @return true if this ring is associative, else false. 170 */ 171 public boolean isAssociative() { 172 return ring.isAssociative(); 173 } 174 175 176 /** 177 * Query if this ring is a field. 178 * @return true if modul is prime, else false. 179 */ 180 public boolean isField() { 181 if (isField > 0) { 182 return true; 183 } 184 if (isField == 0) { 185 return false; 186 } 187 if (!ring.coFac.isField()) { 188 isField = 0; 189 return false; 190 } 191 return false; 192 } 193 194 195 /** 196 * Set field property of this ring. 197 * @param field true, if this ring is determined to be a field, false, if it 198 * is determined that it is not a field. 199 */ 200 public void setField(boolean field) { 201 if (isField > 0 && field) { 202 return; 203 } 204 if (isField == 0 && !field) { 205 return; 206 } 207 if (field) { 208 isField = 1; 209 } else { 210 isField = 0; 211 } 212 return; 213 } 214 215 216 /** 217 * Get the internal field indicator. 218 * @return internal field indicator. 219 */ 220 public int getField() { 221 return isField; 222 } 223 224 225 /** 226 * Characteristic of this ring. 227 * @return characteristic of this ring. 228 */ 229 public java.math.BigInteger characteristic() { 230 return ring.characteristic(); 231 } 232 233 234 /** 235 * Get a AlgebraicNumber element from a BigInteger value. 236 * @param a BigInteger. 237 * @return a AlgebraicNumber. 238 */ 239 public AlgebraicNumber<C> fillFromInteger(java.math.BigInteger a) { 240 if (characteristic().signum() == 0) { 241 return new AlgebraicNumber<C>(this, ring.fromInteger(a)); 242 } 243 java.math.BigInteger p = characteristic(); 244 java.math.BigInteger b = a; 245 GenPolynomial<C> v = ring.getZERO(); 246 GenPolynomial<C> x = ring.univariate(0, 1L); 247 GenPolynomial<C> t = ring.getONE(); 248 do { 249 java.math.BigInteger[] qr = b.divideAndRemainder(p); 250 java.math.BigInteger q = qr[0]; 251 java.math.BigInteger r = qr[1]; 252 //System.out.println("q = " + q + ", r = " +r); 253 GenPolynomial<C> rp = ring.fromInteger(r); 254 v = v.sum(t.multiply(rp)); 255 t = t.multiply(x); 256 b = q; 257 } while (!b.equals(java.math.BigInteger.ZERO)); 258 AlgebraicNumber<C> an = new AlgebraicNumber<C>(this, v); 259 logger.info("fill(" + a + ") = " + v + ", mod: " + an); 260 //RuntimeException e = new RuntimeException("hihihi"); 261 //e.printStackTrace(); 262 return an; 263 } 264 265 266 /** 267 * Get a AlgebraicNumber element from a long value. 268 * @param a long. 269 * @return a AlgebraicNumber. 270 */ 271 public AlgebraicNumber<C> fillFromInteger(long a) { 272 return fillFromInteger(new java.math.BigInteger("" + a)); 273 } 274 275 276 /** 277 * Get a AlgebraicNumber element from a BigInteger value. 278 * @param a BigInteger. 279 * @return a AlgebraicNumber. 280 */ 281 public AlgebraicNumber<C> fromInteger(java.math.BigInteger a) { 282 return new AlgebraicNumber<C>(this, ring.fromInteger(a)); 283 } 284 285 286 /** 287 * Get a AlgebraicNumber element from a long value. 288 * @param a long. 289 * @return a AlgebraicNumber. 290 */ 291 public AlgebraicNumber<C> fromInteger(long a) { 292 return new AlgebraicNumber<C>(this, ring.fromInteger(a)); 293 // if ( characteristic().signum() == 0 ) { 294 // } 295 // return fromInteger( new java.math.BigInteger(""+a) ); 296 } 297 298 299 /** 300 * Get the String representation as RingFactory. 301 * @see java.lang.Object#toString() 302 */ 303 @Override 304 public String toString() { 305 return "AlgebraicNumberRing[ " + modul.toString() + " | isField=" + isField + " :: " 306 + ring.toString() + " ]"; 307 } 308 309 310 /** 311 * Get a scripting compatible string representation. 312 * @return script compatible representation for this ElemFactory. 313 * @see edu.jas.structure.ElemFactory#toScript() 314 */ 315 //JAVA6only: @Override 316 public String toScript() { 317 StringBuffer s = new StringBuffer(); 318 s.append("AN("); 319 s.append(modul.toScript()); 320 switch (Scripting.getLang() ) { 321 case Ruby: 322 s.append((isField() ? ",true" : ",false")); 323 break; 324 case Python: 325 default: 326 s.append((isField() ? ",True" : ",False")); 327 } 328 s.append(","); 329 s.append(ring.toScript()); 330 s.append(")"); 331 return s.toString(); 332 } 333 334 335 /** 336 * Comparison with any other object. 337 * @see java.lang.Object#equals(java.lang.Object) 338 */ 339 @Override 340 @SuppressWarnings("unchecked") 341 // not jet working 342 public boolean equals(Object b) { 343 if (!(b instanceof AlgebraicNumberRing)) { 344 return false; 345 } 346 AlgebraicNumberRing<C> a = null; 347 try { 348 a = (AlgebraicNumberRing<C>) b; 349 } catch (ClassCastException e) { 350 } 351 if (a == null) { 352 return false; 353 } 354 return modul.equals(a.modul); 355 } 356 357 358 /** 359 * Hash code for this AlgebraicNumber. 360 * @see java.lang.Object#hashCode() 361 */ 362 @Override 363 public int hashCode() { 364 return 37 * modul.hashCode() + ring.hashCode(); 365 } 366 367 368 /** 369 * AlgebraicNumber random. 370 * @param n such that 0 ≤ v ≤ (2<sup>n</sup>-1). 371 * @return a random integer mod modul. 372 */ 373 public AlgebraicNumber<C> random(int n) { 374 GenPolynomial<C> x = ring.random(n).monic(); 375 return new AlgebraicNumber<C>(this, x); 376 } 377 378 379 /** 380 * AlgebraicNumber random. 381 * @param n such that 0 ≤ v ≤ (2<sup>n</sup>-1). 382 * @param rnd is a source for random bits. 383 * @return a random integer mod modul. 384 */ 385 public AlgebraicNumber<C> random(int n, Random rnd) { 386 GenPolynomial<C> x = ring.random(n, rnd).monic(); 387 return new AlgebraicNumber<C>(this, x); 388 } 389 390 391 /** 392 * Parse AlgebraicNumber from String. 393 * @param s String. 394 * @return AlgebraicNumber from s. 395 */ 396 public AlgebraicNumber<C> parse(String s) { 397 GenPolynomial<C> x = ring.parse(s); 398 return new AlgebraicNumber<C>(this, x); 399 } 400 401 402 /** 403 * Parse AlgebraicNumber from Reader. 404 * @param r Reader. 405 * @return next AlgebraicNumber from r. 406 */ 407 public AlgebraicNumber<C> parse(Reader r) { 408 GenPolynomial<C> x = ring.parse(r); 409 return new AlgebraicNumber<C>(this, x); 410 } 411 412 413 /** 414 * AlgebraicNumber chinese remainder algorithm. Assert deg(c.modul) >= 415 * deg(a.modul) and c.modul * a.modul = this.modul. 416 * @param c AlgebraicNumber. 417 * @param ci inverse of c.modul in ring of a. 418 * @param a other AlgebraicNumber. 419 * @return S, with S mod c.modul == c and S mod a.modul == a. 420 */ 421 public AlgebraicNumber<C> chineseRemainder(AlgebraicNumber<C> c, AlgebraicNumber<C> ci, 422 AlgebraicNumber<C> a) { 423 if (true) { // debug 424 if (c.ring.modul.compareTo(a.ring.modul) < 1) { 425 System.out.println("AlgebraicNumber error " + c + ", " + a); 426 } 427 } 428 AlgebraicNumber<C> b = new AlgebraicNumber<C>(a.ring, c.val); 429 // c mod a.modul 430 // c( tbcf(a.modul) ) if deg(a.modul)==1 431 AlgebraicNumber<C> d = a.subtract(b); // a-c mod a.modul 432 if (d.isZERO()) { 433 return new AlgebraicNumber<C>(this, c.val); 434 } 435 b = d.multiply(ci); // b = (a-c)*ci mod a.modul 436 // (c.modul*b)+c mod this.modul = c mod c.modul = 437 // (c.modul*ci*(a-c)+c) mod a.modul = a mod a.modul 438 GenPolynomial<C> s = c.ring.modul.multiply(b.val); 439 s = s.sum(c.val); 440 return new AlgebraicNumber<C>(this, s); 441 } 442 443 444 /** 445 * AlgebraicNumber interpolation algorithm. Assert deg(c.modul) >= 446 * deg(A.modul) and c.modul * A.modul = this.modul. Special case with 447 * deg(A.modul) == 1. Similar algorithm as chinese remainder algortihm. 448 * @param c AlgebraicNumber. 449 * @param ci inverse of (c.modul)(a) in ring of A. 450 * @param am trailing base coefficient of modul of other AlgebraicNumber A. 451 * @param a value of other AlgebraicNumber A. 452 * @return S, with S(c) == c and S(A) == a. 453 */ 454 public AlgebraicNumber<C> interpolate(AlgebraicNumber<C> c, C ci, C am, C a) { 455 C b = PolyUtil.<C> evaluateMain(ring.coFac /*a*/, c.val, am); 456 // c mod a.modul 457 // c( tbcf(a.modul) ) if deg(a.modul)==1 458 C d = a.subtract(b); // a-c mod a.modul 459 if (d.isZERO()) { 460 return new AlgebraicNumber<C>(this, c.val); 461 } 462 b = d.multiply(ci); // b = (a-c)*ci mod a.modul 463 // (c.modul*b)+c mod this.modul = c mod c.modul = 464 // (c.modul*ci*(a-c)+c) mod a.modul = a mod a.modul 465 GenPolynomial<C> s = c.ring.modul.multiply(b); 466 s = s.sum(c.val); 467 return new AlgebraicNumber<C>(this, s); 468 } 469 470 471 /** 472 * Depth of extension field tower. 473 * @return number of nested algebraic extension fields 474 */ 475 @SuppressWarnings("unchecked") 476 public int depth() { 477 AlgebraicNumberRing<C> arr = this; 478 int depth = 1; 479 RingFactory<C> cf = arr.ring.coFac; 480 if (cf instanceof AlgebraicNumberRing) { 481 arr = (AlgebraicNumberRing<C>) (Object) cf; 482 depth += arr.depth(); 483 } 484 return depth; 485 } 486 487 488 /** 489 * Degree of extension field. 490 * @return degree of this algebraic extension field 491 */ 492 public long extensionDegree() { 493 long degree = modul.degree(0); 494 return degree; 495 } 496 497 498 /** 499 * Total degree of nested extension fields. 500 * @return degree of tower of algebraic extension fields 501 */ 502 @SuppressWarnings("unchecked") 503 public long totalExtensionDegree() { 504 long degree = modul.degree(0); 505 AlgebraicNumberRing<C> arr = this; 506 RingFactory<C> cf = arr.ring.coFac; 507 if (cf instanceof AlgebraicNumberRing) { 508 arr = (AlgebraicNumberRing<C>) (Object) cf; 509 if (degree == 0L) { 510 degree = arr.totalExtensionDegree(); 511 } else { 512 degree *= arr.totalExtensionDegree(); 513 } 514 } 515 return degree; 516 } 517 518 519 /** 520 * Get a AlgebraicNumber iterator. <b>Note: </b> Only for finite field 521 * coefficients or fields which are iterable. 522 * @return a iterator over all algebraic numbers in this ring. 523 */ 524 public Iterator<AlgebraicNumber<C>> iterator() { 525 return new AlgebraicNumberIterator<C>(this); 526 } 527 528 } 529 530 531 /** 532 * Algebraic number iterator. 533 * @author Heinz Kredel 534 */ 535 class AlgebraicNumberIterator<C extends GcdRingElem<C>> implements Iterator<AlgebraicNumber<C>> { 536 537 538 /** 539 * data structure. 540 */ 541 final Iterator<List<C>> iter; 542 543 544 final List<GenPolynomial<C>> powers; 545 546 547 final AlgebraicNumberRing<C> aring; 548 549 550 private static final Logger logger = Logger.getLogger(AlgebraicNumberIterator.class); 551 552 553 // private final boolean debug = logger.isDebugEnabled(); 554 555 556 /** 557 * CartesianProduct iterator constructor. 558 * @param comps components of the cartesian product. 559 */ 560 public AlgebraicNumberIterator(AlgebraicNumberRing<C> aring) { 561 RingFactory<C> cf = aring.ring.coFac; 562 this.aring = aring; 563 long d = aring.modul.degree(0); 564 //System.out.println("d = " + d); 565 powers = new ArrayList<GenPolynomial<C>>((int) d); 566 for (long j = d - 1; j >= 0L; j--) { 567 powers.add(aring.ring.univariate(0, j)); 568 } 569 //System.out.println("powers = " + powers); 570 if (!(cf instanceof Iterable)) { 571 throw new IllegalArgumentException("only for iterable coefficients implemented"); 572 } 573 List<Iterable<C>> comps = new ArrayList<Iterable<C>>((int) d); 574 Iterable<C> cfi = (Iterable<C>) cf; 575 for (long j = 0L; j < d; j++) { 576 comps.add(cfi); 577 } 578 if (cf.isFinite()) { 579 CartesianProduct<C> tuples = new CartesianProduct<C>(comps); 580 iter = tuples.iterator(); 581 } else { 582 CartesianProductInfinite<C> tuples = new CartesianProductInfinite<C>(comps); 583 iter = tuples.iterator(); 584 } 585 } 586 587 588 /** 589 * Test for availability of a next tuple. 590 * @return true if the iteration has more tuples, else false. 591 */ 592 public boolean hasNext() { 593 return iter.hasNext(); 594 } 595 596 597 /** 598 * Get next tuple. 599 * @return next tuple. 600 */ 601 public AlgebraicNumber<C> next() { 602 List<C> coeffs = iter.next(); 603 //System.out.println("coeffs = " + coeffs); 604 GenPolynomial<C> pol = aring.ring.getZERO(); 605 int i = 0; 606 for (GenPolynomial<C> f : powers) { 607 C c = coeffs.get(i++); 608 if (c.isZERO()) { 609 continue; 610 } 611 pol = pol.sum(f.multiply(c)); 612 } 613 return new AlgebraicNumber<C>(aring, pol); 614 } 615 616 617 /** 618 * Remove a tuple if allowed. 619 */ 620 public void remove() { 621 throw new UnsupportedOperationException("cannnot remove tuples"); 622 } 623 624 }