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 */
162f1a2e423e0fbb64467d6fcfa4e82c6384f31210Eino-Ville Talvalapackage android.hardware.camera2;
17b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
18b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin/**
19b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin * The rational data type used by CameraMetadata keys. Contains a pair of ints representing the
20b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin * numerator and denominator of a Rational number. This type is immutable.
21b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin */
22b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkinpublic final class Rational {
23b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    private final int mNumerator;
24b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    private final int mDenominator;
25b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
26b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    /**
27b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     * <p>Create a Rational with a given numerator and denominator.</p>
28b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     *
2923c8809568b68430f875df759108c58016c44c16Timothy Knight     * <p>The signs of the numerator and the denominator may be flipped such that the denominator
3023c8809568b68430f875df759108c58016c44c16Timothy Knight     * is always positive.</p>
3123c8809568b68430f875df759108c58016c44c16Timothy Knight     *
3223c8809568b68430f875df759108c58016c44c16Timothy Knight     * <p>A rational value with a 0-denominator may be constructed, but will have similar semantics
3323c8809568b68430f875df759108c58016c44c16Timothy Knight     * as float NaN and INF values. The int getter functions return 0 in this case.</p>
34b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     *
35b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     * @param numerator the numerator of the rational
36b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     * @param denominator the denominator of the rational
37b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     */
38b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    public Rational(int numerator, int denominator) {
39b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
40b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        if (denominator < 0) {
41b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            numerator = -numerator;
42b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            denominator = -denominator;
43b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        }
44b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
45b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        mNumerator = numerator;
46b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        mDenominator = denominator;
47b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
48b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
49b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    /**
50b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     * Gets the numerator of the rational.
51b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     */
52b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    public int getNumerator() {
5323c8809568b68430f875df759108c58016c44c16Timothy Knight        if (mDenominator == 0) {
5423c8809568b68430f875df759108c58016c44c16Timothy Knight            return 0;
5523c8809568b68430f875df759108c58016c44c16Timothy Knight        }
56b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        return mNumerator;
57b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
58b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
59b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    /**
60b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     * Gets the denominator of the rational
61b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     */
62b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    public int getDenominator() {
63b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        return mDenominator;
64b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
65b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
6623c8809568b68430f875df759108c58016c44c16Timothy Knight    private boolean isNaN() {
6723c8809568b68430f875df759108c58016c44c16Timothy Knight        return mDenominator == 0 && mNumerator == 0;
6823c8809568b68430f875df759108c58016c44c16Timothy Knight    }
6923c8809568b68430f875df759108c58016c44c16Timothy Knight
7023c8809568b68430f875df759108c58016c44c16Timothy Knight    private boolean isInf() {
7123c8809568b68430f875df759108c58016c44c16Timothy Knight        return mDenominator == 0 && mNumerator > 0;
7223c8809568b68430f875df759108c58016c44c16Timothy Knight    }
7323c8809568b68430f875df759108c58016c44c16Timothy Knight
7423c8809568b68430f875df759108c58016c44c16Timothy Knight    private boolean isNegInf() {
7523c8809568b68430f875df759108c58016c44c16Timothy Knight        return mDenominator == 0 && mNumerator < 0;
7623c8809568b68430f875df759108c58016c44c16Timothy Knight    }
7723c8809568b68430f875df759108c58016c44c16Timothy Knight
78b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    /**
79b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     * <p>Compare this Rational to another object and see if they are equal.</p>
80b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     *
81b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     * <p>A Rational object can only be equal to another Rational object (comparing against any other
82b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     * type will return false).</p>
83b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     *
8423c8809568b68430f875df759108c58016c44c16Timothy Knight     * <p>A Rational object is considered equal to another Rational object if and only if one of
8523c8809568b68430f875df759108c58016c44c16Timothy Knight     * the following holds</p>:
8623c8809568b68430f875df759108c58016c44c16Timothy Knight     * <ul><li>Both are NaN</li>
8723c8809568b68430f875df759108c58016c44c16Timothy Knight     *     <li>Both are infinities of the same sign</li>
8823c8809568b68430f875df759108c58016c44c16Timothy Knight     *     <li>Both have the same numerator and denominator in their reduced form</li>
8923c8809568b68430f875df759108c58016c44c16Timothy Knight     * </ul>
90b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     *
91b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     * <p>A reduced form of a Rational is calculated by dividing both the numerator and the
92b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     * denominator by their greatest common divisor.</p>
93b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     *
94b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     * <pre>
9523c8809568b68430f875df759108c58016c44c16Timothy Knight     *      (new Rational(1, 2)).equals(new Rational(1, 2)) == true   // trivially true
9623c8809568b68430f875df759108c58016c44c16Timothy Knight     *      (new Rational(2, 3)).equals(new Rational(1, 2)) == false  // trivially false
9723c8809568b68430f875df759108c58016c44c16Timothy Knight     *      (new Rational(1, 2)).equals(new Rational(2, 4)) == true   // true after reduction
9823c8809568b68430f875df759108c58016c44c16Timothy Knight     *      (new Rational(0, 0)).equals(new Rational(0, 0)) == true   // NaN.equals(NaN)
9923c8809568b68430f875df759108c58016c44c16Timothy Knight     *      (new Rational(1, 0)).equals(new Rational(5, 0)) == true   // both are +infinity
10023c8809568b68430f875df759108c58016c44c16Timothy Knight     *      (new Rational(1, 0)).equals(new Rational(-1, 0)) == false // +infinity != -infinity
101b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     * </pre>
102b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     *
103b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     * @param obj a reference to another object
104b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     *
10524eb8a313f1a80a35566b8dc456ec2684a05a22eBenjamin Hendricks     * @return A boolean that determines whether or not the two Rational objects are equal.
106b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     */
107b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    @Override
108b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    public boolean equals(Object obj) {
109b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        if (obj == null) {
110b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            return false;
11123c8809568b68430f875df759108c58016c44c16Timothy Knight        } else if (obj instanceof Rational) {
112b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            Rational other = (Rational) obj;
11323c8809568b68430f875df759108c58016c44c16Timothy Knight            if (mDenominator == 0 || other.mDenominator == 0) {
11423c8809568b68430f875df759108c58016c44c16Timothy Knight                if (isNaN() && other.isNaN()) {
11523c8809568b68430f875df759108c58016c44c16Timothy Knight                    return true;
11623c8809568b68430f875df759108c58016c44c16Timothy Knight                } else if (isInf() && other.isInf() || isNegInf() && other.isNegInf()) {
11723c8809568b68430f875df759108c58016c44c16Timothy Knight                    return true;
11823c8809568b68430f875df759108c58016c44c16Timothy Knight                } else {
11923c8809568b68430f875df759108c58016c44c16Timothy Knight                    return false;
12023c8809568b68430f875df759108c58016c44c16Timothy Knight                }
12123c8809568b68430f875df759108c58016c44c16Timothy Knight            } else if (mNumerator == other.mNumerator && mDenominator == other.mDenominator) {
122b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                return true;
123b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            } else {
124b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                int thisGcd = gcd();
125b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                int otherGcd = other.gcd();
126b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
127b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                int thisNumerator = mNumerator / thisGcd;
128b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                int thisDenominator = mDenominator / thisGcd;
129b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
130b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                int otherNumerator = other.mNumerator / otherGcd;
131b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                int otherDenominator = other.mDenominator / otherGcd;
132b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
133b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                return (thisNumerator == otherNumerator && thisDenominator == otherDenominator);
134b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            }
135b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        }
136b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        return false;
137b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
138b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
139b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    @Override
140b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    public String toString() {
14123c8809568b68430f875df759108c58016c44c16Timothy Knight        if (isNaN()) {
14223c8809568b68430f875df759108c58016c44c16Timothy Knight            return "NaN";
14323c8809568b68430f875df759108c58016c44c16Timothy Knight        } else if (isInf()) {
14423c8809568b68430f875df759108c58016c44c16Timothy Knight            return "Infinity";
14523c8809568b68430f875df759108c58016c44c16Timothy Knight        } else if (isNegInf()) {
14623c8809568b68430f875df759108c58016c44c16Timothy Knight            return "-Infinity";
14723c8809568b68430f875df759108c58016c44c16Timothy Knight        } else {
14823c8809568b68430f875df759108c58016c44c16Timothy Knight            return mNumerator + "/" + mDenominator;
14923c8809568b68430f875df759108c58016c44c16Timothy Knight        }
15023c8809568b68430f875df759108c58016c44c16Timothy Knight    }
15123c8809568b68430f875df759108c58016c44c16Timothy Knight
15223c8809568b68430f875df759108c58016c44c16Timothy Knight    /**
15323c8809568b68430f875df759108c58016c44c16Timothy Knight     * <p>Convert to a floating point representation.</p>
15423c8809568b68430f875df759108c58016c44c16Timothy Knight     *
15523c8809568b68430f875df759108c58016c44c16Timothy Knight     * @return The floating point representation of this rational number.
15623c8809568b68430f875df759108c58016c44c16Timothy Knight     * @hide
15723c8809568b68430f875df759108c58016c44c16Timothy Knight     */
15823c8809568b68430f875df759108c58016c44c16Timothy Knight    public float toFloat() {
15923c8809568b68430f875df759108c58016c44c16Timothy Knight        return (float) mNumerator / (float) mDenominator;
160b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
161b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
162b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    @Override
163b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    public int hashCode() {
164b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        final long INT_MASK = 0xffffffffL;
165b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
166b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        long asLong = INT_MASK & mNumerator;
167b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        asLong <<= 32;
168b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
169b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        asLong |= (INT_MASK & mDenominator);
170b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
171b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        return ((Long)asLong).hashCode();
172b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
173b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
174b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    /**
175b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     * Calculates the greatest common divisor using Euclid's algorithm.
176b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     *
17724eb8a313f1a80a35566b8dc456ec2684a05a22eBenjamin Hendricks     * @return An int value representing the gcd. Always positive.
178b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     * @hide
179b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin     */
180b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    public int gcd() {
181b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        /**
182b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin         * Non-recursive implementation of Euclid's algorithm:
183b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin         *
184b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin         *  gcd(a, 0) := a
185b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin         *  gcd(a, b) := gcd(b, a mod b)
186b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin         *
187b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin         */
188b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
189b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        int a = mNumerator;
190b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        int b = mDenominator;
191b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
192b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        while (b != 0) {
193b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            int oldB = b;
194b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
195b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            b = a % b;
196b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            a = oldB;
197b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        }
198b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
199b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        return Math.abs(a);
200b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
201b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin}
202