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