blob: 66e533e53bc342721cb3d6803cf2f630566507e9 [file] [log] [blame]
Igor Murashkinb519cc52013-07-02 11:23:44 -07001/*
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.photography;
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}