Rational.java revision 2f1a2e423e0fbb64467d6fcfa4e82c6384f31210
1/* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16package android.hardware.camera2; 17 18/** 19 * The rational data type used by CameraMetadata keys. Contains a pair of ints representing the 20 * numerator and denominator of a Rational number. This type is immutable. 21 */ 22public final class Rational { 23 private final int mNumerator; 24 private final int mDenominator; 25 26 /** 27 * <p>Create a Rational with a given numerator and denominator.</p> 28 * 29 * <p> 30 * The signs of the numerator and the denominator may be flipped such that the denominator 31 * is always 0. 32 * </p> 33 * 34 * @param numerator the numerator of the rational 35 * @param denominator the denominator of the rational 36 * 37 * @throws IllegalArgumentException if the denominator is 0 38 */ 39 public Rational(int numerator, int denominator) { 40 41 if (denominator == 0) { 42 throw new IllegalArgumentException("Argument 'denominator' is 0"); 43 } 44 45 if (denominator < 0) { 46 numerator = -numerator; 47 denominator = -denominator; 48 } 49 50 mNumerator = numerator; 51 mDenominator = denominator; 52 } 53 54 /** 55 * Gets the numerator of the rational. 56 */ 57 public int getNumerator() { 58 return mNumerator; 59 } 60 61 /** 62 * Gets the denominator of the rational 63 */ 64 public int getDenominator() { 65 return mDenominator; 66 } 67 68 /** 69 * <p>Compare this Rational to another object and see if they are equal.</p> 70 * 71 * <p>A Rational object can only be equal to another Rational object (comparing against any other 72 * type will return false).</p> 73 * 74 * <p>A Rational object is considered equal to another Rational object if and only if their 75 * reduced forms have the same numerator and denominator.</p> 76 * 77 * <p>A reduced form of a Rational is calculated by dividing both the numerator and the 78 * denominator by their greatest common divisor.</p> 79 * 80 * <pre> 81 * (new Rational(1, 2)).equals(new Rational(1, 2)) == true // trivially true 82 * (new Rational(2, 3)).equals(new Rational(1, 2)) == false // trivially false 83 * (new Rational(1, 2)).equals(new Rational(2, 4)) == true // true after reduction 84 * </pre> 85 * 86 * @param obj a reference to another object 87 * 88 * @return boolean that determines whether or not the two Rational objects are equal. 89 */ 90 @Override 91 public boolean equals(Object obj) { 92 if (obj == null) { 93 return false; 94 } 95 if (this == obj) { 96 return true; 97 } 98 if (obj instanceof Rational) { 99 Rational other = (Rational) obj; 100 if(mNumerator == other.mNumerator && mDenominator == other.mDenominator) { 101 return true; 102 } else { 103 int thisGcd = gcd(); 104 int otherGcd = other.gcd(); 105 106 int thisNumerator = mNumerator / thisGcd; 107 int thisDenominator = mDenominator / thisGcd; 108 109 int otherNumerator = other.mNumerator / otherGcd; 110 int otherDenominator = other.mDenominator / otherGcd; 111 112 return (thisNumerator == otherNumerator && thisDenominator == otherDenominator); 113 } 114 } 115 return false; 116 } 117 118 @Override 119 public String toString() { 120 return mNumerator + "/" + mDenominator; 121 } 122 123 @Override 124 public int hashCode() { 125 final long INT_MASK = 0xffffffffL; 126 127 long asLong = INT_MASK & mNumerator; 128 asLong <<= 32; 129 130 asLong |= (INT_MASK & mDenominator); 131 132 return ((Long)asLong).hashCode(); 133 } 134 135 /** 136 * Calculates the greatest common divisor using Euclid's algorithm. 137 * 138 * @return int value representing the gcd. Always positive. 139 * @hide 140 */ 141 public int gcd() { 142 /** 143 * Non-recursive implementation of Euclid's algorithm: 144 * 145 * gcd(a, 0) := a 146 * gcd(a, b) := gcd(b, a mod b) 147 * 148 */ 149 150 int a = mNumerator; 151 int b = mDenominator; 152 153 while (b != 0) { 154 int oldB = b; 155 156 b = a % b; 157 a = oldB; 158 } 159 160 return Math.abs(a); 161 } 162} 163