1b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin/*
2b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin * Copyright (C) 2013 The Android Open Source Project
3b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin *
4b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin * Licensed under the Apache License, Version 2.0 (the "License");
5b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin * you may not use this file except in compliance with the License.
6b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin * You may obtain a copy of the License at
7b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin *
8b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin *      http://www.apache.org/licenses/LICENSE-2.0
9b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin *
10b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin * Unless required by applicable law or agreed to in writing, software
11b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin * distributed under the License is distributed on an "AS IS" BASIS,
12b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin * See the License for the specific language governing permissions and
14b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin * limitations under the License.
15b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin */
1672f9f0a96e4476ef231d5001cb30521ad4ce5b1eIgor Murashkinpackage android.util;
17b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
18007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkinimport static com.android.internal.util.Preconditions.*;
19007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin
20007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkinimport java.io.IOException;
21007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkinimport java.io.InvalidObjectException;
22007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin
23b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin/**
2472f9f0a96e4476ef231d5001cb30521ad4ce5b1eIgor Murashkin * <p>An immutable data type representation a rational number.</p>
2572f9f0a96e4476ef231d5001cb30521ad4ce5b1eIgor Murashkin *
2672f9f0a96e4476ef231d5001cb30521ad4ce5b1eIgor Murashkin * <p>Contains a pair of {@code int}s representing the numerator and denominator of a
2772f9f0a96e4476ef231d5001cb30521ad4ce5b1eIgor Murashkin * Rational number. </p>
28b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin */
29007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkinpublic final class Rational extends Number implements Comparable<Rational> {
30007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    /**
31007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * Constant for the <em>Not-a-Number (NaN)</em> value of the {@code Rational} type.
32007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
33007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <p>A {@code NaN} value is considered to be equal to itself (that is {@code NaN.equals(NaN)}
34007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * will return {@code true}; it is always greater than any non-{@code NaN} value (that is
35007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * {@code NaN.compareTo(notNaN)} will return a number greater than {@code 0}).</p>
36007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
37007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <p>Equivalent to constructing a new rational with both the numerator and denominator
38007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * equal to {@code 0}.</p>
39007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     */
40007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    public static final Rational NaN = new Rational(0, 0);
41007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin
42007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    /**
43007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * Constant for the positive infinity value of the {@code Rational} type.
44007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
45007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <p>Equivalent to constructing a new rational with a positive numerator and a denominator
46007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * equal to {@code 0}.</p>
47007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     */
48007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    public static final Rational POSITIVE_INFINITY = new Rational(1, 0);
49007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin
50007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    /**
51007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * Constant for the negative infinity value of the {@code Rational} type.
52007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
53007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <p>Equivalent to constructing a new rational with a negative numerator and a denominator
54007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * equal to {@code 0}.</p>
55007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     */
56007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    public static final Rational NEGATIVE_INFINITY = new Rational(-1, 0);
57007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin
58007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    /**
59007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * Constant for the zero value of the {@code Rational} type.
60007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
61007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <p>Equivalent to constructing a new rational with a numerator equal to {@code 0} and
62007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * any non-zero denominator.</p>
63007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     */
64007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    public static final Rational ZERO = new Rational(0, 1);
65007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin
66007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    /**
67007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * Unique version number per class to be compliant with {@link java.io.Serializable}.
68007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
69007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <p>Increment each time the fields change in any way.</p>
70007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     */
71007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    private static final long serialVersionUID = 1L;
72007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin
73007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    /*
74007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * Do not change the order of these fields or add new instance fields to maintain the
75007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * Serializable compatibility across API revisions.
76007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     */
77b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    private final int mNumerator;
78b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    private final int mDenominator;
79b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
80b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    /**
81007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <p>Create a {@code Rational} with a given numerator and denominator.</p>
82b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     *
8323c8809568b68430f875df759108c58016c44c16Timothy Knight     * <p>The signs of the numerator and the denominator may be flipped such that the denominator
84007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * is always positive. Both the numerator and denominator will be converted to their reduced
85007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * forms (see {@link #equals} for more details).</p>
8623c8809568b68430f875df759108c58016c44c16Timothy Knight     *
87007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <p>For example,
88007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <ul>
89007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <li>a rational of {@code 2/4} will be reduced to {@code 1/2}.
90007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <li>a rational of {@code 1/-1} will be flipped to {@code -1/1}
91007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <li>a rational of {@code 5/0} will be reduced to {@code 1/0}
92007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <li>a rational of {@code 0/5} will be reduced to {@code 0/1}
93007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * </ul>
94007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * </p>
95b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     *
96b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     * @param numerator the numerator of the rational
97b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     * @param denominator the denominator of the rational
98007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
99007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * @see #equals
100b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     */
101b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    public Rational(int numerator, int denominator) {
102b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
103b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        if (denominator < 0) {
104b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            numerator = -numerator;
105b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            denominator = -denominator;
106b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        }
107b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
108007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        // Convert to reduced form
109007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        if (denominator == 0 && numerator > 0) {
110007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin            mNumerator = 1; // +Inf
111007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin            mDenominator = 0;
112007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        } else if (denominator == 0 && numerator < 0) {
113007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin            mNumerator = -1; // -Inf
114007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin            mDenominator = 0;
115007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        } else if (denominator == 0 && numerator == 0) {
116007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin            mNumerator = 0; // NaN
117007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin            mDenominator = 0;
118007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        } else if (numerator == 0) {
119007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin            mNumerator = 0;
120007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin            mDenominator = 1;
121007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        } else {
122007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin            int gcd = gcd(numerator, denominator);
123007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin
124007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin            mNumerator = numerator / gcd;
125007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin            mDenominator = denominator / gcd;
126007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        }
127b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
128b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
129b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    /**
130b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     * Gets the numerator of the rational.
131007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
132007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <p>The numerator will always return {@code 1} if this rational represents
133007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * infinity (that is, the denominator is {@code 0}).</p>
134b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     */
135b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    public int getNumerator() {
136b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        return mNumerator;
137b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
138b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
139b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    /**
140b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     * Gets the denominator of the rational
141007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
142007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <p>The denominator may return {@code 0}, in which case the rational may represent
143007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * positive infinity (if the numerator was positive), negative infinity (if the numerator
144007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * was negative), or {@code NaN} (if the numerator was {@code 0}).</p>
145007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
146007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <p>The denominator will always return {@code 1} if the numerator is {@code 0}.
147b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     */
148b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    public int getDenominator() {
149b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        return mDenominator;
150b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
151b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
152007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    /**
153007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * Indicates whether this rational is a <em>Not-a-Number (NaN)</em> value.
154007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
155007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <p>A {@code NaN} value occurs when both the numerator and the denominator are {@code 0}.</p>
156007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
157007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * @return {@code true} if this rational is a <em>Not-a-Number (NaN)</em> value;
158007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *         {@code false} if this is a (potentially infinite) number value
159007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     */
160007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    public boolean isNaN() {
16123c8809568b68430f875df759108c58016c44c16Timothy Knight        return mDenominator == 0 && mNumerator == 0;
16223c8809568b68430f875df759108c58016c44c16Timothy Knight    }
16323c8809568b68430f875df759108c58016c44c16Timothy Knight
164007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    /**
165007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * Indicates whether this rational represents an infinite value.
166007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
167007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <p>An infinite value occurs when the denominator is {@code 0} (but the numerator is not).</p>
168007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
169007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * @return {@code true} if this rational is a (positive or negative) infinite value;
170007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *         {@code false} if this is a finite number value (or {@code NaN})
171007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     */
172007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    public boolean isInfinite() {
173007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        return mNumerator != 0 && mDenominator == 0;
174007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    }
175007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin
176007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    /**
177007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * Indicates whether this rational represents a finite value.
178007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
179007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <p>A finite value occurs when the denominator is not {@code 0}; in other words
180007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * the rational is neither infinity or {@code NaN}.</p>
181007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
182007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * @return {@code true} if this rational is a (positive or negative) infinite value;
183007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *         {@code false} if this is a finite number value (or {@code NaN})
184007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     */
185007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    public boolean isFinite() {
186007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        return mDenominator != 0;
187007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    }
188007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin
189007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    /**
190007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * Indicates whether this rational represents a zero value.
191007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
192007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <p>A zero value is a {@link #isFinite finite} rational with a numerator of {@code 0}.</p>
193007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
194007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * @return {@code true} if this rational is finite zero value;
195007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *         {@code false} otherwise
196007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     */
197007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    public boolean isZero() {
198007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        return isFinite() && mNumerator == 0;
199007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    }
200007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin
201007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    private boolean isPosInf() {
20223c8809568b68430f875df759108c58016c44c16Timothy Knight        return mDenominator == 0 && mNumerator > 0;
20323c8809568b68430f875df759108c58016c44c16Timothy Knight    }
20423c8809568b68430f875df759108c58016c44c16Timothy Knight
20523c8809568b68430f875df759108c58016c44c16Timothy Knight    private boolean isNegInf() {
20623c8809568b68430f875df759108c58016c44c16Timothy Knight        return mDenominator == 0 && mNumerator < 0;
20723c8809568b68430f875df759108c58016c44c16Timothy Knight    }
20823c8809568b68430f875df759108c58016c44c16Timothy Knight
209b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    /**
210b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     * <p>Compare this Rational to another object and see if they are equal.</p>
211b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     *
212007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <p>A Rational object can only be equal to another Rational object (comparing against any
213007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * other type will return {@code false}).</p>
214b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     *
21523c8809568b68430f875df759108c58016c44c16Timothy Knight     * <p>A Rational object is considered equal to another Rational object if and only if one of
216007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * the following holds:</p>
217007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <ul><li>Both are {@code NaN}</li>
21823c8809568b68430f875df759108c58016c44c16Timothy Knight     *     <li>Both are infinities of the same sign</li>
21923c8809568b68430f875df759108c58016c44c16Timothy Knight     *     <li>Both have the same numerator and denominator in their reduced form</li>
22023c8809568b68430f875df759108c58016c44c16Timothy Knight     * </ul>
221b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     *
222b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     * <p>A reduced form of a Rational is calculated by dividing both the numerator and the
223b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     * denominator by their greatest common divisor.</p>
224b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     *
2253c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * <pre>{@code
226007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * (new Rational(1, 2)).equals(new Rational(1, 2)) == true   // trivially true
227007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * (new Rational(2, 3)).equals(new Rational(1, 2)) == false  // trivially false
228007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * (new Rational(1, 2)).equals(new Rational(2, 4)) == true   // true after reduction
229007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * (new Rational(0, 0)).equals(new Rational(0, 0)) == true   // NaN.equals(NaN)
230007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * (new Rational(1, 0)).equals(new Rational(5, 0)) == true   // both are +infinity
231007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * (new Rational(1, 0)).equals(new Rational(-1, 0)) == false // +infinity != -infinity
2323c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * }</pre>
233b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     *
234b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     * @param obj a reference to another object
235b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     *
23624eb8a313f1a80a35566b8dc456ec2684a05a22eBenjamin Hendricks     * @return A boolean that determines whether or not the two Rational objects are equal.
237b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     */
238b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    @Override
239b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    public boolean equals(Object obj) {
240007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        return obj instanceof Rational && equals((Rational) obj);
241007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    }
242007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin
243007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    private boolean equals(Rational other) {
244007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        return (mNumerator == other.mNumerator && mDenominator == other.mDenominator);
245b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
246b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
247007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    /**
248007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * Return a string representation of this rational, e.g. {@code "1/2"}.
249007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
250007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <p>The following rules of conversion apply:
251007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <ul>
252007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <li>{@code NaN} values will return {@code "NaN"}
253007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <li>Positive infinity values will return {@code "Infinity"}
254007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <li>Negative infinity values will return {@code "-Infinity"}
255007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <li>All other values will return {@code "numerator/denominator"} where {@code numerator}
256007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * and {@code denominator} are substituted with the appropriate numerator and denominator
257007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * values.
258007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * </ul></p>
259007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     */
260b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    @Override
261b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    public String toString() {
26223c8809568b68430f875df759108c58016c44c16Timothy Knight        if (isNaN()) {
26323c8809568b68430f875df759108c58016c44c16Timothy Knight            return "NaN";
264007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        } else if (isPosInf()) {
26523c8809568b68430f875df759108c58016c44c16Timothy Knight            return "Infinity";
26623c8809568b68430f875df759108c58016c44c16Timothy Knight        } else if (isNegInf()) {
26723c8809568b68430f875df759108c58016c44c16Timothy Knight            return "-Infinity";
26823c8809568b68430f875df759108c58016c44c16Timothy Knight        } else {
26923c8809568b68430f875df759108c58016c44c16Timothy Knight            return mNumerator + "/" + mDenominator;
27023c8809568b68430f875df759108c58016c44c16Timothy Knight        }
27123c8809568b68430f875df759108c58016c44c16Timothy Knight    }
27223c8809568b68430f875df759108c58016c44c16Timothy Knight
27323c8809568b68430f875df759108c58016c44c16Timothy Knight    /**
27423c8809568b68430f875df759108c58016c44c16Timothy Knight     * <p>Convert to a floating point representation.</p>
27523c8809568b68430f875df759108c58016c44c16Timothy Knight     *
27623c8809568b68430f875df759108c58016c44c16Timothy Knight     * @return The floating point representation of this rational number.
27723c8809568b68430f875df759108c58016c44c16Timothy Knight     * @hide
27823c8809568b68430f875df759108c58016c44c16Timothy Knight     */
27923c8809568b68430f875df759108c58016c44c16Timothy Knight    public float toFloat() {
280007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        // TODO: remove this duplicate function (used in CTS and the shim)
281007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        return floatValue();
282b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
283b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
2843c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    /**
2853c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     * {@inheritDoc}
2863c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin     */
287b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    @Override
288b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    public int hashCode() {
2893c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        // Bias the hash code for the first (2^16) values for both numerator and denominator
2903c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        int numeratorFlipped = mNumerator << 16 | mNumerator >>> 16;
291b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
2923c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        return mDenominator ^ numeratorFlipped;
293b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
294b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
295b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    /**
296b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     * Calculates the greatest common divisor using Euclid's algorithm.
297b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     *
298007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <p><em>Visible for testing only.</em></p>
299007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
300007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * @param numerator the numerator in a fraction
301007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * @param denominator the denominator in a fraction
302007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
30324eb8a313f1a80a35566b8dc456ec2684a05a22eBenjamin Hendricks     * @return An int value representing the gcd. Always positive.
304b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     * @hide
305b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     */
306007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    public static int gcd(int numerator, int denominator) {
307007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        /*
308b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin         * Non-recursive implementation of Euclid's algorithm:
309b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin         *
310b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin         *  gcd(a, 0) := a
311b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin         *  gcd(a, b) := gcd(b, a mod b)
312b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin         *
313b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin         */
314007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        int a = numerator;
315007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        int b = denominator;
316b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
317b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        while (b != 0) {
318b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            int oldB = b;
319b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
320b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            b = a % b;
321b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            a = oldB;
322b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        }
323b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
324b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        return Math.abs(a);
325b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
326007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin
327007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    /**
328007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * Returns the value of the specified number as a {@code double}.
329007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
330007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <p>The {@code double} is calculated by converting both the numerator and denominator
331007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * to a {@code double}; then returning the result of dividing the numerator by the
332007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * denominator.</p>
333007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
334007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * @return the divided value of the numerator and denominator as a {@code double}.
335007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     */
336007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    @Override
337007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    public double doubleValue() {
338007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        double num = mNumerator;
339007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        double den = mDenominator;
340007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin
341007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        return num / den;
342007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    }
343007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin
344007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    /**
345007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * Returns the value of the specified number as a {@code float}.
346007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
347007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <p>The {@code float} is calculated by converting both the numerator and denominator
348007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * to a {@code float}; then returning the result of dividing the numerator by the
349007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * denominator.</p>
350007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
351007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * @return the divided value of the numerator and denominator as a {@code float}.
352007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     */
353007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    @Override
354007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    public float floatValue() {
355007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        float num = mNumerator;
356007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        float den = mDenominator;
357007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin
358007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        return num / den;
359007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    }
360007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin
361007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    /**
362007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * Returns the value of the specified number as a {@code int}.
363007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
364007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <p>{@link #isInfinite Finite} rationals are converted to an {@code int} value
365007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * by dividing the numerator by the denominator; conversion for non-finite values happens
366007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * identically to casting a floating point value to an {@code int}, in particular:
367007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
368007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <p>
369007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <ul>
370007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <li>Positive infinity saturates to the largest maximum integer
371007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * {@link Integer#MAX_VALUE}</li>
372007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <li>Negative infinity saturates to the smallest maximum integer
373007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * {@link Integer#MIN_VALUE}</li>
374007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <li><em>Not-A-Number (NaN)</em> returns {@code 0}.</li>
375007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * </ul>
376007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * </p>
377007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
378007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * @return the divided value of the numerator and denominator as a {@code int}.
379007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     */
380007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    @Override
381007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    public int intValue() {
382007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        // Mimic float to int conversion rules from JLS 5.1.3
383007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin
384007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        if (isPosInf()) {
385007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin            return Integer.MAX_VALUE;
386007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        } else if (isNegInf()) {
387007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin            return Integer.MIN_VALUE;
388007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        } else if (isNaN()) {
389007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin            return 0;
390007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        } else { // finite
391007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin            return mNumerator / mDenominator;
392007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        }
393007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    }
394007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin
395007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    /**
396007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * Returns the value of the specified number as a {@code long}.
397007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
398007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <p>{@link #isInfinite Finite} rationals are converted to an {@code long} value
399007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * by dividing the numerator by the denominator; conversion for non-finite values happens
400007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * identically to casting a floating point value to a {@code long}, in particular:
401007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
402007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <p>
403007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <ul>
404007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <li>Positive infinity saturates to the largest maximum long
405007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * {@link Long#MAX_VALUE}</li>
406007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <li>Negative infinity saturates to the smallest maximum long
407007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * {@link Long#MIN_VALUE}</li>
408007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <li><em>Not-A-Number (NaN)</em> returns {@code 0}.</li>
409007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * </ul>
410007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * </p>
411007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
412007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * @return the divided value of the numerator and denominator as a {@code long}.
413007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     */
414007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    @Override
415007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    public long longValue() {
416007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        // Mimic float to long conversion rules from JLS 5.1.3
417007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin
418007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        if (isPosInf()) {
419007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin            return Long.MAX_VALUE;
420007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        } else if (isNegInf()) {
421007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin            return Long.MIN_VALUE;
422007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        } else if (isNaN()) {
423007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin            return 0;
424007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        } else { // finite
425007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin            return mNumerator / mDenominator;
426007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        }
427007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    }
428007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin
429007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    /**
430007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * Returns the value of the specified number as a {@code short}.
431007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
432007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <p>{@link #isInfinite Finite} rationals are converted to a {@code short} value
433007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * identically to {@link #intValue}; the {@code int} result is then truncated to a
434007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * {@code short} before returning the value.</p>
435007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
436007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * @return the divided value of the numerator and denominator as a {@code short}.
437007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     */
438007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    @Override
439007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    public short shortValue() {
440007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        return (short) intValue();
441007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    }
442007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin
443007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    /**
444007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * Compare this rational to the specified rational to determine their natural order.
445007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
446007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <p>{@link #NaN} is considered to be equal to itself and greater than all other
447007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * {@code Rational} values. Otherwise, if the objects are not {@link #equals equal}, then
448007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * the following rules apply:</p>
449007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
450007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <ul>
451007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <li>Positive infinity is greater than any other finite number (or negative infinity)
452007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <li>Negative infinity is less than any other finite number (or positive infinity)
453007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * <li>The finite number represented by this rational is checked numerically
454007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * against the other finite number by converting both rationals to a common denominator multiple
455007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * and comparing their numerators.
456007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * </ul>
457007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
458007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * @param another the rational to be compared
459007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
460007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * @return a negative integer, zero, or a positive integer as this object is less than,
461007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *         equal to, or greater than the specified rational.
462007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
463007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * @throws NullPointerException if {@code another} was {@code null}
464007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     */
465007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    @Override
466007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    public int compareTo(Rational another) {
467007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        checkNotNull(another, "another must not be null");
468007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin
469007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        if (equals(another)) {
470007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin            return 0;
471007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        } else if (isNaN()) { // NaN is greater than the other non-NaN value
472007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin            return 1;
473007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        } else if (another.isNaN()) { // the other NaN is greater than this non-NaN value
474007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin            return -1;
475007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        } else if (isPosInf() || another.isNegInf()) {
476007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin            return 1; // positive infinity is greater than any non-NaN/non-posInf value
477007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        } else if (isNegInf() || another.isPosInf()) {
478007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin            return -1; // negative infinity is less than any non-NaN/non-negInf value
479007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        }
480007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin
481007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        // else both this and another are finite numbers
482007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin
483007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        // make the denominators the same, then compare numerators
484007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        long thisNumerator = ((long)mNumerator) * another.mDenominator; // long to avoid overflow
485007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        long otherNumerator = ((long)another.mNumerator) * mDenominator; // long to avoid overflow
486007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin
487007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        // avoid underflow from subtraction by doing comparisons
488007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        if (thisNumerator < otherNumerator) {
489007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin            return -1;
490007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        } else if (thisNumerator > otherNumerator) {
491007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin            return 1;
492007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        } else {
493007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin            // This should be covered by #equals, but have this code path just in case
494007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin            return 0;
495007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        }
496007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    }
497007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin
498007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    /*
499007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * Serializable implementation.
500007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
501007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * The following methods are omitted:
502007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * >> writeObject - the default is sufficient (field by field serialization)
503007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * >> readObjectNoData - the default is sufficient (0s for both fields is a NaN)
504007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     */
505007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin
506007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    /**
507007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * writeObject with default serialized form - guards against
508007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * deserializing non-reduced forms of the rational.
509007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     *
510007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     * @throws InvalidObjectException if the invariants were violated
511007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin     */
512007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    private void readObject(java.io.ObjectInputStream in)
513007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin            throws IOException, ClassNotFoundException {
514007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        in.defaultReadObject();
515007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin
516007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        /*
517007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin         * Guard against trying to deserialize illegal values (in this case, ones
518007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin         * that don't have a standard reduced form).
519007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin         *
520007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin         * - Non-finite values must be one of [0, 1], [0, 0], [0, 1], [0, -1]
521007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin         * - Finite values must always have their greatest common divisor as 1
522007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin         */
523007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin
524007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        if (mNumerator == 0) { // either zero or NaN
525007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin            if (mDenominator == 1 || mDenominator == 0) {
526007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin                return;
527007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin            }
528007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin            throw new InvalidObjectException(
529007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin                    "Rational must be deserialized from a reduced form for zero values");
530007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        } else if (mDenominator == 0) { // either positive or negative infinity
531007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin            if (mNumerator == 1 || mNumerator == -1) {
532007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin                return;
533007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin            }
534007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin            throw new InvalidObjectException(
535007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin                    "Rational must be deserialized from a reduced form for infinity values");
536007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        } else { // finite value
537007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin            if (gcd(mNumerator, mDenominator) > 1) {
538007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin                throw new InvalidObjectException(
539b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar                        "Rational must be deserialized from a reduced form for finite values");
540007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin            }
541007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin        }
542007bfb14d2d720cdd699cfbb36ce206246901cefIgor Murashkin    }
543b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar
544b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar    private static NumberFormatException invalidRational(String s) {
545b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar        throw new NumberFormatException("Invalid Rational: \"" + s + "\"");
546b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar    }
547b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar
548b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar    /**
549b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar     * Parses the specified string as a rational value.
550b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar     * <p>The ASCII characters {@code \}{@code u003a} (':') and
551b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar     * {@code \}{@code u002f} ('/') are recognized as separators between
552b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar     * the numerator and denumerator.</p>
553b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar     * <p>
554b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar     * For any {@code Rational r}: {@code Rational.parseRational(r.toString()).equals(r)}.
555b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar     * However, the method also handles rational numbers expressed in the
556b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar     * following forms:</p>
557b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar     * <p>
558b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar     * "<i>num</i>{@code /}<i>den</i>" or
559b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar     * "<i>num</i>{@code :}<i>den</i>" {@code => new Rational(num, den);},
560b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar     * where <i>num</i> and <i>den</i> are string integers potentially
561b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar     * containing a sign, such as "-10", "+7" or "5".</p>
562b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar     *
563b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar     * <pre>{@code
564b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar     * Rational.parseRational("3:+6").equals(new Rational(1, 2)) == true
565b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar     * Rational.parseRational("-3/-6").equals(new Rational(1, 2)) == true
566b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar     * Rational.parseRational("4.56") => throws NumberFormatException
567b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar     * }</pre>
568b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar     *
569b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar     * @param string the string representation of a rational value.
570b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar     * @return the rational value represented by {@code string}.
571b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar     *
572b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar     * @throws NumberFormatException if {@code string} cannot be parsed
573b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar     * as a rational value.
574b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar     * @throws NullPointerException if {@code string} was {@code null}
575b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar     */
576b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar    public static Rational parseRational(String string)
577b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar            throws NumberFormatException {
578b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar        checkNotNull(string, "string must not be null");
579b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar
580b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar        if (string.equals("NaN")) {
581b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar            return NaN;
582b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar        } else if (string.equals("Infinity")) {
583b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar            return POSITIVE_INFINITY;
584b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar        } else if (string.equals("-Infinity")) {
585b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar            return NEGATIVE_INFINITY;
586b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar        }
587b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar
588b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar        int sep_ix = string.indexOf(':');
589b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar        if (sep_ix < 0) {
590b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar            sep_ix = string.indexOf('/');
591b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar        }
592b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar        if (sep_ix < 0) {
593b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar            throw invalidRational(string);
594b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar        }
595b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar        try {
596b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar            return new Rational(Integer.parseInt(string.substring(0, sep_ix)),
597b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar                    Integer.parseInt(string.substring(sep_ix + 1)));
598b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar        } catch (NumberFormatException e) {
599b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar            throw invalidRational(string);
600b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar        }
601b1a236b85fa8f3f46e3f6b76a7bf6f72faf9ee5dLajos Molnar    }
602b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin}
603