001/* 002 * $Id: RealAlgebraicRing.java 5868 2018-07-20 15:44:13Z kredel $ 003 */ 004 005package edu.jas.application; 006 007 008import java.io.Reader; 009import java.util.ArrayList; 010import java.util.List; 011import java.util.Random; 012 013import org.apache.logging.log4j.Logger; 014import org.apache.logging.log4j.LogManager; 015 016import edu.jas.arith.BigRational; 017import edu.jas.arith.Rational; 018import edu.jas.poly.GenPolynomial; 019import edu.jas.poly.GenPolynomialRing; 020import edu.jas.poly.PolyUtil; 021import edu.jas.root.Interval; 022import edu.jas.root.PolyUtilRoot; 023import edu.jas.root.RealRootTuple; 024import edu.jas.structure.GcdRingElem; 025import edu.jas.structure.RingFactory; 026 027 028/** 029 * Real algebraic number factory class based on bi-variate real algebraic 030 * numbers. Objects of this class are immutable with the exception of the 031 * isolating intervals. Bi-variate ideal implementation is in version 3614 032 * 2011-04-28 09:20:34Z. 033 * @author Heinz Kredel 034 */ 035 036public class RealAlgebraicRing<C extends GcdRingElem<C> & Rational> 037 implements RingFactory<RealAlgebraicNumber<C>> { 038 039 040 /** 041 * Representing ideal with univariate polynomials IdealWithUniv. 042 */ 043 /*package*/final IdealWithUniv<C> univs; 044 045 046 /** 047 * Representing ResidueRing. 048 */ 049 /*package*/final ResidueRing<C> algebraic; 050 051 052 /** 053 * Isolating intervals for the real algebraic roots of the real and 054 * imaginary part. <b>Note: </b> intervals may shrink eventually. 055 */ 056 /*package*/RealRootTuple<C> root; 057 058 059 /** 060 * Recursive real root ring. 061 */ 062 public final edu.jas.root.RealAlgebraicRing<edu.jas.root.RealAlgebraicNumber<C>> realRing; 063 064 065 /** 066 * Epsilon of the isolating rectangle for a complex root. 067 */ 068 protected BigRational eps; 069 070 071 /** 072 * Precision of the isolating rectangle for a complex root. 073 */ 074 public final int PRECISION = 9; //BigDecimal.DEFAULT_PRECISION; 075 076 077 private static final Logger logger = LogManager.getLogger(RealAlgebraicRing.class); 078 079 080 /** 081 * The constructor creates a RealAlgebraicNumber factory object from a 082 * IdealWithUniv, ResidueRing and a root tuple. 083 * @param m module IdealWithUniv<C>. 084 * @param a module ResidueRing<C>. 085 * @param r isolating rectangle for a complex root. 086 */ 087 public RealAlgebraicRing(IdealWithUniv<C> m, ResidueRing<C> a, RealRootTuple<C> r) { 088 univs = m; 089 algebraic = a; 090 root = r; 091 if (algebraic.characteristic().signum() > 0) { 092 throw new IllegalArgumentException("characteristic not zero"); 093 } 094 if (root.tuple.size() != 2) { 095 throw new IllegalArgumentException("wrong tuple size: " + root.tuple.size()); 096 } 097 eps = BigRational.ONE; 098 edu.jas.root.RealAlgebraicRing<C> rfac1 = root.tuple.get(0).factory(); 099 edu.jas.root.RealAlgebraicRing<C> rfac2 = root.tuple.get(1).factory(); 100 GenPolynomial<C> p0 = PolyUtil.<C> selectWithVariable(univs.ideal.list.list, 0); 101 if (p0 == null) { 102 throw new RuntimeException("no polynomial found in " + (0) + " of " + univs.ideal); 103 } 104 //System.out.println("realRing, pol = " + p0.toScript()); 105 GenPolynomialRing<C> pfac = p0.ring; 106 GenPolynomialRing<GenPolynomial<C>> prfac = pfac.recursive(1); 107 //System.out.println("prfac = " + prfac); 108 GenPolynomial<GenPolynomial<C>> p0r = PolyUtil.<C> recursive(prfac, p0); 109 GenPolynomialRing<edu.jas.root.RealAlgebraicNumber<C>> parfac = new GenPolynomialRing<edu.jas.root.RealAlgebraicNumber<C>>( 110 rfac1, prfac); 111 GenPolynomial<edu.jas.root.RealAlgebraicNumber<C>> p0ar = PolyUtilRoot 112 .<C> convertRecursiveToAlgebraicCoefficients(parfac, p0r); 113 Interval<C> r2 = rfac2.getRoot(); 114 edu.jas.root.RealAlgebraicNumber<C> rleft = rfac1.getZERO().sum(r2.left); 115 edu.jas.root.RealAlgebraicNumber<C> rright = rfac1.getZERO().sum(r2.right); 116 Interval<edu.jas.root.RealAlgebraicNumber<C>> r2r = new Interval<edu.jas.root.RealAlgebraicNumber<C>>( 117 rleft, rright); 118 edu.jas.root.RealAlgebraicRing<edu.jas.root.RealAlgebraicNumber<C>> rr = new edu.jas.root.RealAlgebraicRing<edu.jas.root.RealAlgebraicNumber<C>>( 119 p0ar, r2r); 120 logger.info("realRing = " + rr); 121 realRing = rr; 122 } 123 124 125 /** 126 * The constructor creates a RealAlgebraicNumber factory object from a 127 * IdealWithUniv and a root tuple. 128 * @param m module IdealWithUniv<C>. 129 * @param root isolating rectangle for a complex root. 130 */ 131 public RealAlgebraicRing(IdealWithUniv<C> m, RealRootTuple<C> root) { 132 this(m, new ResidueRing<C>(m.ideal), root); 133 } 134 135 136 /** 137 * The constructor creates a RealAlgebraicNumber factory object from a 138 * IdealWithUniv and a root tuple. 139 * @param m module IdealWithUniv<C>. 140 * @param root isolating rectangle for a complex root. 141 * @param isField indicator if m is maximal. 142 */ 143 public RealAlgebraicRing(IdealWithUniv<C> m, RealRootTuple<C> root, boolean isField) { 144 this(m, new ResidueRing<C>(m.ideal, isField), root); 145 } 146 147 148 /** 149 * Set a refined rectangle for the complex root. <b>Note: </b> rectangle may 150 * shrink eventually. 151 * @param v rectangle. 152 */ 153 public synchronized void setRoot(RealRootTuple<C> v) { 154 assert root.contains(v) : "root contains v"; 155 this.root = v; 156 } 157 158 159 /** 160 * Get rectangle for the complex root. 161 * @return v rectangle. 162 */ 163 public synchronized RealRootTuple<C> getRoot() { 164 return this.root; 165 } 166 167 168 /** 169 * Get epsilon. 170 * @return epsilon. 171 */ 172 public synchronized BigRational getEps() { 173 return this.eps; 174 } 175 176 177 /** 178 * Set a new epsilon. 179 * @param e epsilon. 180 */ 181 public synchronized void setEps(C e) { 182 setEps(e.getRational()); 183 } 184 185 186 /** 187 * Set a new epsilon. 188 * @param e epsilon. 189 */ 190 public synchronized void setEps(BigRational e) { 191 this.eps = e; 192 } 193 194 195 /** 196 * Refine root. 197 * @param e epsilon. 198 */ 199 public synchronized void refineRoot(BigRational e) { 200 setEps(e); 201 root.refineRoot(this.eps); 202 } 203 204 205 /** 206 * Is this structure finite or infinite. 207 * @return true if this structure is finite, else false. 208 * @see edu.jas.structure.ElemFactory#isFinite() 209 */ 210 public boolean isFinite() { 211 return realRing.isFinite(); 212 } 213 214 215 /** 216 * Copy RealAlgebraicNumber element c. 217 * @param c 218 * @return a copy of c. 219 */ 220 public RealAlgebraicNumber<C> copy(RealAlgebraicNumber<C> c) { 221 return new RealAlgebraicNumber<C>(this, c.number); 222 } 223 224 225 /** 226 * Get the zero element. 227 * @return 0 as RealAlgebraicNumber. 228 */ 229 public RealAlgebraicNumber<C> getZERO() { 230 return new RealAlgebraicNumber<C>(this, realRing.getZERO()); 231 } 232 233 234 /** 235 * Get the one element. 236 * @return 1 as RealAlgebraicNumber. 237 */ 238 public RealAlgebraicNumber<C> getONE() { 239 return new RealAlgebraicNumber<C>(this, realRing.getONE()); 240 } 241 242 243 /** 244 * Get a list of the generating elements. 245 * @return list of generators for the algebraic structure. 246 * @see edu.jas.structure.ElemFactory#generators() 247 */ 248 public List<RealAlgebraicNumber<C>> generators() { 249 List<edu.jas.root.RealAlgebraicNumber<edu.jas.root.RealAlgebraicNumber<C>>> agens = realRing 250 .generators(); 251 List<RealAlgebraicNumber<C>> gens = new ArrayList<RealAlgebraicNumber<C>>(agens.size()); 252 for (edu.jas.root.RealAlgebraicNumber<edu.jas.root.RealAlgebraicNumber<C>> a : agens) { 253 gens.add(getZERO().sum(a)); 254 } 255 return gens; 256 } 257 258 259 /** 260 * Query if this ring is commutative. 261 * @return true if this ring is commutative, else false. 262 */ 263 public boolean isCommutative() { 264 return realRing.isCommutative(); 265 } 266 267 268 /** 269 * Query if this ring is associative. 270 * @return true if this ring is associative, else false. 271 */ 272 public boolean isAssociative() { 273 return realRing.isAssociative(); 274 } 275 276 277 /** 278 * Query if this ring is a field. 279 * @return true if algebraic is prime, else false. 280 */ 281 public boolean isField() { 282 return realRing.isField(); 283 } 284 285 286 /** 287 * Assert that this ring is a field. 288 * @param isField true if this ring is a field, else false. 289 */ 290 public void setField(boolean isField) { 291 realRing.setField(isField); 292 } 293 294 295 /** 296 * Characteristic of this ring. 297 * @return characteristic of this ring. 298 */ 299 public java.math.BigInteger characteristic() { 300 return realRing.characteristic(); 301 } 302 303 304 /** 305 * Get a RealAlgebraicNumber element from a BigInteger value. 306 * @param a BigInteger. 307 * @return a RealAlgebraicNumber. 308 */ 309 public RealAlgebraicNumber<C> fromInteger(java.math.BigInteger a) { 310 return new RealAlgebraicNumber<C>(this, realRing.fromInteger(a)); 311 } 312 313 314 /** 315 * Get a RealAlgebraicNumber element from a long value. 316 * @param a long. 317 * @return a RealAlgebraicNumber. 318 */ 319 public RealAlgebraicNumber<C> fromInteger(long a) { 320 return new RealAlgebraicNumber<C>(this, realRing.fromInteger(a)); 321 } 322 323 324 /** 325 * Get the String representation as RingFactory. 326 * @see java.lang.Object#toString() 327 */ 328 @Override 329 public synchronized String toString() { 330 return "RealAlgebraicRing[ " + realRing.toString() + " in " + root + " | isField=" 331 + realRing.isField() + ", algebraic.ideal=" + algebraic.ideal.toString() + " ]"; 332 } 333 334 335 /** 336 * Get a scripting compatible string representation. 337 * @return script compatible representation for this ElemFactory. 338 * @see edu.jas.structure.ElemFactory#toScript() 339 */ 340 @Override 341 public synchronized String toScript() { 342 // Python case 343 return "RealRecN( " + realRing.toScript() + ", " + root.toScript() 344 //+ ", " + realRing.isField() 345 //+ ", " + realRing.ring.toScript() 346 + " )"; 347 } 348 349 350 /** 351 * Comparison with any other object. 352 * @see java.lang.Object#equals(java.lang.Object) 353 */ 354 @Override 355 @SuppressWarnings("unchecked") 356 public synchronized boolean equals(Object b) { 357 if (!(b instanceof RealAlgebraicRing)) { 358 return false; 359 } 360 RealAlgebraicRing<C> a = null; 361 try { 362 a = (RealAlgebraicRing<C>) b; 363 } catch (ClassCastException e) { 364 } 365 if (a == null) { 366 return false; 367 } 368 return realRing.equals(a.realRing) && root.equals(a.getRoot()); 369 } 370 371 372 /** 373 * Hash code for this RealAlgebraicNumber. 374 * @see java.lang.Object#hashCode() 375 */ 376 @Override 377 public synchronized int hashCode() { 378 return 37 * realRing.hashCode() + root.hashCode(); 379 } 380 381 382 /** 383 * RealAlgebraicNumber random. 384 * @param n such that 0 ≤ v ≤ (2<sup>n</sup>-1). 385 * @return a random integer mod modul. 386 */ 387 public RealAlgebraicNumber<C> random(int n) { 388 return new RealAlgebraicNumber<C>(this, realRing.random(n)); 389 } 390 391 392 /** 393 * RealAlgebraicNumber random. 394 * @param n such that 0 ≤ v ≤ (2<sup>n</sup>-1). 395 * @param rnd is a source for random bits. 396 * @return a random integer mod modul. 397 */ 398 public RealAlgebraicNumber<C> random(int n, Random rnd) { 399 return new RealAlgebraicNumber<C>(this, realRing.random(n, rnd)); 400 } 401 402 403 /** 404 * Parse RealAlgebraicNumber from String. 405 * @param s String. 406 * @return RealAlgebraicNumber from s. 407 */ 408 public RealAlgebraicNumber<C> parse(String s) { 409 return new RealAlgebraicNumber<C>(this, realRing.parse(s)); 410 } 411 412 413 /** 414 * Parse RealAlgebraicNumber from Reader. 415 * @param r Reader. 416 * @return next RealAlgebraicNumber from r. 417 */ 418 public RealAlgebraicNumber<C> parse(Reader r) { 419 return new RealAlgebraicNumber<C>(this, realRing.parse(r)); 420 } 421 422}