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