001/*
002 * $Id: Interval.java 5568 2016-08-03 19:14:39Z 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        //return "[" + left.getRational().getDecimal() + ", " + right.getRational().getDecimal() + "]";
065    }
066
067
068    /**
069     * Get a scripting compatible string representation.
070     * @return script compatible representation for this Interval.
071     */
072    public String toScript() {
073        // Python case
074        return "[ " + left.toScript() + ", " + right.toScript() + " ]";
075    }
076
077
078    /**
079     * Copy this.
080     * @return a copy of this.
081     */
082    public Interval<C> copy() {
083        return new Interval<C>(left, right);
084    }
085
086
087    /**
088     * Comparison with any other object.
089     * @see java.lang.Object#equals(java.lang.Object)
090     */
091    @Override
092    @SuppressWarnings("unchecked")
093    public boolean equals(Object b) {
094        if (!(b instanceof Interval)) {
095            return false;
096        }
097        Interval<C> a = null;
098        try {
099            a = (Interval<C>) b;
100        } catch (ClassCastException e) {
101            return false;
102        }
103        return left.equals(a.left) && right.equals(a.right);
104    }
105
106
107    /**
108     * Hash code for this Interval.
109     * @see java.lang.Object#hashCode()
110     */
111    @Override
112    public int hashCode() {
113        return 37 * left.hashCode() + right.hashCode();
114    }
115
116
117    /**
118     * Test if an element is contained in this interval.
119     * @param c element to test.
120     * @return true, if left <= b <= right;
121     */
122    public boolean contains(C c) {
123        return left.compareTo(c) <= 0 && c.compareTo(right) <= 0;
124    }
125
126
127    /**
128     * Test if an interval is contained in this interval.
129     * @param vc interval to test.
130     * @return true, if left <= vc.left and vc.right <= right;
131     */
132    public boolean contains(Interval<C> vc) {
133        return contains(vc.left) && contains(vc.right);
134    }
135
136
137    /**
138     * Length.
139     * @return |left-right|;
140     */
141    public C length() {
142        C m = right.subtract(left);
143        return m.abs();
144    }
145
146
147    /**
148     * BigRational Length.
149     * @return |left-right|;
150     */
151    public BigRational rationalLength() {
152        return length().getRational();
153    }
154
155
156    /**
157     * BigDecimal representation of Interval.
158     */
159    public BigDecimal toDecimal() {
160        BigDecimal l = new BigDecimal(left.getRational());
161        BigDecimal r = new BigDecimal(right.getRational());
162        BigDecimal two = new BigDecimal(2);
163        BigDecimal v = l.sum(r).divide(two);
164        return v;
165    }
166
167
168    /**
169     * Rational middle point.
170     * @return (left+right)/2;
171     */
172    public BigRational rationalMiddle() {
173        BigRational m = left.getRational().sum(right.getRational());
174        BigRational t = new BigRational(1L, 2L);
175        m = m.multiply(t);
176        return m;
177    }
178
179
180    /**
181     * Middle point.
182     * @return (left+right)/2;
183     */
184    public C middle() {
185        C m = left.sum(right);
186        C h = left.factory().parse("1/2");
187        m = m.multiply(h);
188        return m;
189    }
190
191
192    /**
193     * Random point of interval.
194     * @return a random point contained in this interval.
195     */
196    public C randomPoint() {
197        C dr = right.subtract(left);
198        RingFactory<C> fac = (RingFactory<C>) dr.factory();
199        C r = fac.random(13);
200        r = r.abs();
201        if (!r.isZERO()) {
202            if (r.compareTo(fac.getONE()) > 0) {
203                r = r.inverse();
204            }
205        }
206        // 0 <= r <= 1
207        dr = dr.multiply(r);
208        C rv = left.sum(dr);
209        //System.out.println("rv   = " + new BigDecimal(rv.getRational()) );
210        return rv;
211    }
212
213}