1 /*
2  * Copyright (C) 2009 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  */
16 
17 package android.util;
18 
19 import java.util.Random;
20 
21 /**
22  * A class that contains utility methods related to numbers.
23  *
24  * @hide Pending API council approval
25  */
26 public final class MathUtils {
27     private static final float DEG_TO_RAD = 3.1415926f / 180.0f;
28     private static final float RAD_TO_DEG = 180.0f / 3.1415926f;
29 
MathUtils()30     private MathUtils() {
31     }
32 
abs(float v)33     public static float abs(float v) {
34         return v > 0 ? v : -v;
35     }
36 
constrain(int amount, int low, int high)37     public static int constrain(int amount, int low, int high) {
38         return amount < low ? low : (amount > high ? high : amount);
39     }
40 
constrain(long amount, long low, long high)41     public static long constrain(long amount, long low, long high) {
42         return amount < low ? low : (amount > high ? high : amount);
43     }
44 
constrain(float amount, float low, float high)45     public static float constrain(float amount, float low, float high) {
46         return amount < low ? low : (amount > high ? high : amount);
47     }
48 
log(float a)49     public static float log(float a) {
50         return (float) Math.log(a);
51     }
52 
exp(float a)53     public static float exp(float a) {
54         return (float) Math.exp(a);
55     }
56 
pow(float a, float b)57     public static float pow(float a, float b) {
58         return (float) Math.pow(a, b);
59     }
60 
max(float a, float b)61     public static float max(float a, float b) {
62         return a > b ? a : b;
63     }
64 
max(int a, int b)65     public static float max(int a, int b) {
66         return a > b ? a : b;
67     }
68 
max(float a, float b, float c)69     public static float max(float a, float b, float c) {
70         return a > b ? (a > c ? a : c) : (b > c ? b : c);
71     }
72 
max(int a, int b, int c)73     public static float max(int a, int b, int c) {
74         return a > b ? (a > c ? a : c) : (b > c ? b : c);
75     }
76 
min(float a, float b)77     public static float min(float a, float b) {
78         return a < b ? a : b;
79     }
80 
min(int a, int b)81     public static float min(int a, int b) {
82         return a < b ? a : b;
83     }
84 
min(float a, float b, float c)85     public static float min(float a, float b, float c) {
86         return a < b ? (a < c ? a : c) : (b < c ? b : c);
87     }
88 
min(int a, int b, int c)89     public static float min(int a, int b, int c) {
90         return a < b ? (a < c ? a : c) : (b < c ? b : c);
91     }
92 
dist(float x1, float y1, float x2, float y2)93     public static float dist(float x1, float y1, float x2, float y2) {
94         final float x = (x2 - x1);
95         final float y = (y2 - y1);
96         return (float) Math.hypot(x, y);
97     }
98 
dist(float x1, float y1, float z1, float x2, float y2, float z2)99     public static float dist(float x1, float y1, float z1, float x2, float y2, float z2) {
100         final float x = (x2 - x1);
101         final float y = (y2 - y1);
102         final float z = (z2 - z1);
103         return (float) Math.sqrt(x * x + y * y + z * z);
104     }
105 
mag(float a, float b)106     public static float mag(float a, float b) {
107         return (float) Math.hypot(a, b);
108     }
109 
mag(float a, float b, float c)110     public static float mag(float a, float b, float c) {
111         return (float) Math.sqrt(a * a + b * b + c * c);
112     }
113 
sq(float v)114     public static float sq(float v) {
115         return v * v;
116     }
117 
dot(float v1x, float v1y, float v2x, float v2y)118     public static float dot(float v1x, float v1y, float v2x, float v2y) {
119         return v1x * v2x + v1y * v2y;
120     }
121 
cross(float v1x, float v1y, float v2x, float v2y)122     public static float cross(float v1x, float v1y, float v2x, float v2y) {
123         return v1x * v2y - v1y * v2x;
124     }
125 
radians(float degrees)126     public static float radians(float degrees) {
127         return degrees * DEG_TO_RAD;
128     }
129 
degrees(float radians)130     public static float degrees(float radians) {
131         return radians * RAD_TO_DEG;
132     }
133 
acos(float value)134     public static float acos(float value) {
135         return (float) Math.acos(value);
136     }
137 
asin(float value)138     public static float asin(float value) {
139         return (float) Math.asin(value);
140     }
141 
atan(float value)142     public static float atan(float value) {
143         return (float) Math.atan(value);
144     }
145 
atan2(float a, float b)146     public static float atan2(float a, float b) {
147         return (float) Math.atan2(a, b);
148     }
149 
tan(float angle)150     public static float tan(float angle) {
151         return (float) Math.tan(angle);
152     }
153 
lerp(float start, float stop, float amount)154     public static float lerp(float start, float stop, float amount) {
155         return start + (stop - start) * amount;
156     }
157 
158     /**
159      * Returns an interpolated angle in degrees between a set of start and end
160      * angles.
161      * <p>
162      * Unlike {@link #lerp(float, float, float)}, the direction and distance of
163      * travel is determined by the shortest angle between the start and end
164      * angles. For example, if the starting angle is 0 and the ending angle is
165      * 350, then the interpolated angle will be in the range [0,-10] rather
166      * than [0,350].
167      *
168      * @param start the starting angle in degrees
169      * @param end the ending angle in degrees
170      * @param amount the position between start and end in the range [0,1]
171      *               where 0 is the starting angle and 1 is the ending angle
172      * @return the interpolated angle in degrees
173      */
lerpDeg(float start, float end, float amount)174     public static float lerpDeg(float start, float end, float amount) {
175         final float minAngle = (((end - start) + 180) % 360) - 180;
176         return minAngle * amount + start;
177     }
178 
norm(float start, float stop, float value)179     public static float norm(float start, float stop, float value) {
180         return (value - start) / (stop - start);
181     }
182 
map(float minStart, float minStop, float maxStart, float maxStop, float value)183     public static float map(float minStart, float minStop, float maxStart, float maxStop, float value) {
184         return maxStart + (maxStart - maxStop) * ((value - minStart) / (minStop - minStart));
185     }
186 
187     /**
188      * Returns the sum of the two parameters, or throws an exception if the resulting sum would
189      * cause an overflow or underflow.
190      * @throws IllegalArgumentException when overflow or underflow would occur.
191      */
addOrThrow(int a, int b)192     public static int addOrThrow(int a, int b) throws IllegalArgumentException {
193         if (b == 0) {
194             return a;
195         }
196 
197         if (b > 0 && a <= (Integer.MAX_VALUE - b)) {
198             return a + b;
199         }
200 
201         if (b < 0 && a >= (Integer.MIN_VALUE - b)) {
202             return a + b;
203         }
204         throw new IllegalArgumentException("Addition overflow: " + a + " + " + b);
205     }
206 }
207