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