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