001/* 002 * $Id$ 003 */ 004 005package edu.jas.root; 006 007 008import java.io.Serializable; 009import java.util.SortedSet; 010import java.util.TreeSet; 011 012import edu.jas.arith.BigDecimal; 013import edu.jas.arith.BigRational; 014import edu.jas.arith.Rational; 015import edu.jas.structure.RingElem; 016import edu.jas.structure.RingFactory; 017 018 019/** 020 * Interval. For example isolating interval for real roots. 021 * @param <C> coefficient type. 022 * @author Heinz Kredel 023 */ 024public class Interval<C extends RingElem<C> & Rational> implements Serializable { //findbugs 025 026 027 /** 028 * left interval border. 029 */ 030 public final C left; 031 032 033 /** 034 * right interval border. 035 */ 036 public final C right; 037 038 039 /** 040 * Constructor. 041 * @param left interval border. 042 * @param right interval border. 043 */ 044 public Interval(C left, C right) { 045 this.left = left; 046 this.right = right; 047 } 048 049 050 /** 051 * Constructor. 052 * @param mid left and right interval border. 053 */ 054 public Interval(C mid) { 055 this(mid, mid); 056 } 057 058 059 /** 060 * String representation of Interval. 061 * @see java.lang.Object#toString() 062 */ 063 @Override 064 public String toString() { 065 return "[" + left + ", " + right + "]"; 066 //return "[" + left.getRational().getDecimal() + ", " + right.getRational().getDecimal() + "]"; 067 } 068 069 070 /** 071 * Get a scripting compatible string representation. 072 * @return script compatible representation for this Interval. 073 */ 074 public String toScript() { 075 // Python case 076 return "[ " + left.toScript() + ", " + right.toScript() + " ]"; 077 } 078 079 080 /** 081 * Copy this. 082 * @return a copy of this. 083 */ 084 public Interval<C> copy() { 085 return new Interval<C>(left, right); 086 } 087 088 089 /** 090 * Comparison with any other object. 091 * @see java.lang.Object#equals(java.lang.Object) 092 */ 093 @Override 094 @SuppressWarnings("unchecked") 095 public boolean equals(Object b) { 096 if (!(b instanceof Interval)) { 097 return false; 098 } 099 Interval<C> a = null; 100 try { 101 a = (Interval<C>) b; 102 } catch (ClassCastException e) { 103 return false; 104 } 105 return left.equals(a.left) && right.equals(a.right); 106 } 107 108 109 /** 110 * Hash code for this Interval. 111 * @see java.lang.Object#hashCode() 112 */ 113 @Override 114 public int hashCode() { 115 return 37 * left.hashCode() + right.hashCode(); 116 } 117 118 119 /** 120 * Test if an element is contained in this interval. 121 * @param c element to test. 122 * @return true, if left ≤ b ≤ right; 123 */ 124 public boolean contains(C c) { 125 return left.compareTo(c) <= 0 && c.compareTo(right) <= 0; 126 } 127 128 129 /** 130 * Test if an interval is contained in this interval. 131 * @param vc interval to test. 132 * @return true, if left ≤ vc.left and vc.right ≤ right; 133 */ 134 public boolean contains(Interval<C> vc) { 135 return contains(vc.left) && contains(vc.right); 136 } 137 138 139 /** 140 * Length. 141 * @return |left-right|; 142 */ 143 public C length() { 144 C m = right.subtract(left); 145 return m.abs(); 146 } 147 148 149 /** 150 * BigRational Length. 151 * @return |left-right|; 152 */ 153 public BigRational rationalLength() { 154 return length().getRational(); 155 } 156 157 158 /** 159 * BigDecimal representation of Interval. 160 */ 161 public BigDecimal toDecimal() { 162 BigDecimal l = new BigDecimal(left.getRational()); 163 BigDecimal r = new BigDecimal(right.getRational()); 164 BigDecimal two = new BigDecimal(2); 165 BigDecimal v = l.sum(r).divide(two); 166 return v; 167 } 168 169 170 /** 171 * Rational middle point. 172 * @return (left+right)/2; 173 */ 174 public BigRational rationalMiddle() { 175 BigRational m = left.getRational().sum(right.getRational()); 176 BigRational t = new BigRational(1L, 2L); 177 m = m.multiply(t); 178 return m; 179 } 180 181 182 /** 183 * Middle point. 184 * @return (left+right)/2; 185 */ 186 public C middle() { 187 C m = left.sum(right); 188 C h = left.factory().parse("1/2"); 189 m = m.multiply(h); 190 return m; 191 } 192 193 194 /** 195 * Random point of interval. 196 * @return a random point contained in this interval. 197 */ 198 public C randomPoint() { 199 C dr = right.subtract(left); 200 RingFactory<C> fac = (RingFactory<C>) dr.factory(); 201 C r = fac.random(13); 202 r = r.abs(); 203 if (!r.isZERO()) { 204 if (r.compareTo(fac.getONE()) > 0) { 205 r = r.inverse(); 206 } 207 } 208 // 0 <= r <= 1 209 dr = dr.multiply(r); 210 C rv = left.sum(dr); 211 //System.out.println("rv = " + new BigDecimal(rv.getRational()) ); 212 return rv; 213 } 214 215 216 /** 217 * Sum of intervals. 218 * @param o other interval. 219 * @return this+other 220 */ 221 public Interval<C> sum(Interval<C> o) { 222 C l = left.sum(o.left); 223 C r = right.sum(o.right); 224 Interval<C> v = new Interval<C>(l, r); 225 return v; 226 } 227 228 229 /** 230 * Subtract intervals. 231 * @param o other interval. 232 * @return this-other 233 */ 234 public Interval<C> subtract(Interval<C> o) { 235 C l = left.subtract(o.right); 236 C r = right.subtract(o.left); 237 Interval<C> v = new Interval<C>(l, r); 238 return v; 239 } 240 241 242 /** 243 * Multiply intervals. 244 * @param o other interval. 245 * @return this*other 246 */ 247 public Interval<C> multiply(Interval<C> o) { 248 C v1 = left.multiply(o.left); 249 C v2 = left.multiply(o.right); 250 C v3 = right.multiply(o.left); 251 C v4 = right.multiply(o.right); 252 SortedSet<C> so = new TreeSet<C>(); 253 so.add(v1); so.add(v2); so.add(v3); so.add(v4); 254 //System.out.println("sorted set = " + so); 255 Interval<C> v = new Interval<C>(so.first(), so.last()); 256 return v; 257 } 258 259}