a40742cbbab300c131eb5063d5959ebc9c4ba41f
[debian/openrocket] / src / net / sf / openrocket / util / MathUtil.java
1 package net.sf.openrocket.util;
2
3 public class MathUtil {
4         public static final double EPSILON = 0.00000001;  // 10mm^3 in m^3
5
6         /**
7          * The square of x (x^2).  On Sun's JRE using this method is as fast as typing x*x. 
8          * @param x  x
9          * @return   x^2
10          */
11         public static double pow2(double x) {
12                 return x*x;
13         }
14         
15         /**
16          * The cube of x (x^3).
17          * @param x  x
18          * @return   x^3
19          */
20         public static double pow3(double x) {
21                 return x*x*x;
22         }
23         
24         public static double pow4(double x) {
25                 return (x*x)*(x*x);
26         }
27         
28         /**
29          * Clamps the value x to the range min - max.  
30          * @param x    Original value.
31          * @param min  Minimum value to return.
32          * @param max  Maximum value to return.
33          * @return     The clamped value.
34          */
35         public static double clamp(double x, double min, double max) {
36                 if (x < min)
37                         return min;
38                 if (x > max)
39                         return max;
40                 return x;
41         }
42         
43         public static float clamp(float x, float min, float max) {
44                 if (x < min)
45                         return min;
46                 if (x > max)
47                         return max;
48                 return x;
49         }
50         
51         public static int clamp(int x, int min, int max) {
52                 if (x < min)
53                         return min;
54                 if (x > max)
55                         return max;
56                 return x;
57         }
58         
59         
60         /**
61          * Maps a value from one value range to another.
62          * 
63          * @param value         the value to map.
64          * @param fromMin       the minimum of the starting range.
65          * @param fromMax       the maximum of the starting range.
66          * @param toMin         the minimum of the destination range.
67          * @param toMax         the maximum of the destination range.
68          * @return                      the mapped value.
69          * @throws      IllegalArgumentException  if fromMin == fromMax, but toMin != toMax.
70          */
71         public static double map(double value, double fromMin, double fromMax,
72                         double toMin, double toMax) {
73                 if (equals(toMin, toMax))
74                         return toMin;
75                 if (equals(fromMin, fromMax)) {
76                         throw new IllegalArgumentException("from range is singular and to range is not.");
77                 }
78                 return (value - fromMin)/(fromMax-fromMin) * (toMax - toMin) + toMin;
79         }
80         
81         /**
82          * Compute the minimum of two values.  This is performed by direct comparison. 
83          * However, if one of the values is NaN and the other is not, the non-NaN value is
84          * returned.
85          */
86         public static double min(double x, double y) {
87                 if (Double.isNaN(y))
88                         return x;
89                 return (x < y) ? x : y;
90         }
91         
92         /**
93          * Compute the maximum of two values.  This is performed by direct comparison. 
94          * However, if one of the values is NaN and the other is not, the non-NaN value is
95          * returned.
96          */
97         public static double max(double x, double y) {
98                 if (Double.isNaN(x))
99                         return y;
100                 return (x < y) ? y : x;
101         }
102         
103         /**
104          * Compute the minimum of three values.  This is performed by direct comparison. 
105          * However, if one of the values is NaN and the other is not, the non-NaN value is
106          * returned.
107          */
108         public static double min(double x, double y, double z) {
109                 if (x < y || Double.isNaN(y)) {
110                         return min(x,z);
111                 } else {
112                         return min(y,z);
113                 }
114         }
115         
116         /**
117          * Compute the maximum of three values.  This is performed by direct comparison. 
118          * However, if one of the values is NaN and the other is not, the non-NaN value is
119          * returned.
120          */
121         public static double max(double x, double y, double z) {
122                 if (x > y || Double.isNaN(y)) {
123                         return max(x,z);
124                 } else {
125                         return max(y,z);
126                 }
127         }
128         
129         /**
130          * Calculates the hypotenuse <code>sqrt(x^2+y^2)</code>.  This method is SIGNIFICANTLY
131          * faster than <code>Math.hypot(x,y)</code>.
132          */
133         public static double hypot(double x, double y) {
134                 return Math.sqrt(x*x + y*y);
135         }
136
137         /**
138          * Reduce the angle x to the range 0 - 2*PI.
139          * @param x  Original angle.
140          * @return   The equivalent angle in the range 0 ... 2*PI.
141          */
142         public static double reduce360(double x) {
143                 double d = Math.floor(x / (2*Math.PI));
144                 return x - d*2*Math.PI;
145         }
146
147         /**
148          * Reduce the angle x to the range -PI - PI.
149          * 
150          * Either -PI and PI might be returned, depending on the rounding function. 
151          * 
152          * @param x  Original angle.
153          * @return   The equivalent angle in the range -PI ... PI.
154          */
155         public static double reduce180(double x) {
156                 double d = Math.rint(x / (2*Math.PI));
157                 return x - d*2*Math.PI;
158         }
159         
160         
161         public static boolean equals(double a, double b) {
162                 double absb = Math.abs(b);
163                 
164                 if (absb < EPSILON/2) {
165                         // Near zero
166                         return Math.abs(a) < EPSILON/2;
167                 }
168                 return Math.abs(a-b) < EPSILON*absb;
169         }
170         
171         
172         /**
173          * Return the sign of the number.  This corresponds to Math.signum, but ignores
174          * the special cases of zero and NaN.  The value returned for those is arbitrary.
175          * <p>
176          * This method is about 4 times faster than Math.signum().
177          * 
178          * @param x             the checked value.
179          * @return              -1.0 if x<0; 1.0 if x>0; otherwise either -1.0 or 1.0.
180          */
181         public static double sign(double x) {
182                 return (x<0) ? -1.0 : 1.0;
183         }
184
185         /* Math.abs() is about 3x as fast as this:
186         
187         public static double abs(double x) {
188                 return (x<0) ? -x : x;
189         }
190         */
191         
192         
193 }