release 0.9.6
[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                                         "value=" + value + " fromMin=" + fromMin + " fromMax=" + fromMax +
78                                         "toMin=" + toMin + " toMax=" + toMax);
79                 }
80                 return (value - fromMin)/(fromMax-fromMin) * (toMax - toMin) + toMin;
81         }
82         
83         /**
84          * Compute the minimum of two values.  This is performed by direct comparison. 
85          * However, if one of the values is NaN and the other is not, the non-NaN value is
86          * returned.
87          */
88         public static double min(double x, double y) {
89                 if (Double.isNaN(y))
90                         return x;
91                 return (x < y) ? x : y;
92         }
93         
94         /**
95          * Compute the maximum of two values.  This is performed by direct comparison. 
96          * However, if one of the values is NaN and the other is not, the non-NaN value is
97          * returned.
98          */
99         public static double max(double x, double y) {
100                 if (Double.isNaN(x))
101                         return y;
102                 return (x < y) ? y : x;
103         }
104         
105         /**
106          * Compute the minimum of three values.  This is performed by direct comparison. 
107          * However, if one of the values is NaN and the other is not, the non-NaN value is
108          * returned.
109          */
110         public static double min(double x, double y, double z) {
111                 if (x < y || Double.isNaN(y)) {
112                         return min(x,z);
113                 } else {
114                         return min(y,z);
115                 }
116         }
117         
118         /**
119          * Compute the maximum of three values.  This is performed by direct comparison. 
120          * However, if one of the values is NaN and the other is not, the non-NaN value is
121          * returned.
122          */
123         public static double max(double x, double y, double z) {
124                 if (x > y || Double.isNaN(y)) {
125                         return max(x,z);
126                 } else {
127                         return max(y,z);
128                 }
129         }
130         
131         /**
132          * Calculates the hypotenuse <code>sqrt(x^2+y^2)</code>.  This method is SIGNIFICANTLY
133          * faster than <code>Math.hypot(x,y)</code>.
134          */
135         public static double hypot(double x, double y) {
136                 return Math.sqrt(x*x + y*y);
137         }
138
139         /**
140          * Reduce the angle x to the range 0 - 2*PI.
141          * @param x  Original angle.
142          * @return   The equivalent angle in the range 0 ... 2*PI.
143          */
144         public static double reduce360(double x) {
145                 double d = Math.floor(x / (2*Math.PI));
146                 return x - d*2*Math.PI;
147         }
148
149         /**
150          * Reduce the angle x to the range -PI - PI.
151          * 
152          * Either -PI and PI might be returned, depending on the rounding function. 
153          * 
154          * @param x  Original angle.
155          * @return   The equivalent angle in the range -PI ... PI.
156          */
157         public static double reduce180(double x) {
158                 double d = Math.rint(x / (2*Math.PI));
159                 return x - d*2*Math.PI;
160         }
161         
162         
163         public static boolean equals(double a, double b) {
164                 double absb = Math.abs(b);
165                 
166                 if (absb < EPSILON/2) {
167                         // Near zero
168                         return Math.abs(a) < EPSILON/2;
169                 }
170                 return Math.abs(a-b) < EPSILON*absb;
171         }
172         
173         
174         /**
175          * Return the sign of the number.  This corresponds to Math.signum, but ignores
176          * the special cases of zero and NaN.  The value returned for those is arbitrary.
177          * <p>
178          * This method is about 4 times faster than Math.signum().
179          * 
180          * @param x             the checked value.
181          * @return              -1.0 if x<0; 1.0 if x>0; otherwise either -1.0 or 1.0.
182          */
183         public static double sign(double x) {
184                 return (x<0) ? -1.0 : 1.0;
185         }
186
187         /* Math.abs() is about 3x as fast as this:
188         
189         public static double abs(double x) {
190                 return (x<0) ? -x : x;
191         }
192         */
193         
194         
195 }