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