Initial commit
[debian/openrocket] / src / net / sf / openrocket / util / MathUtil.java
diff --git a/src/net/sf/openrocket/util/MathUtil.java b/src/net/sf/openrocket/util/MathUtil.java
new file mode 100644 (file)
index 0000000..a714f81
--- /dev/null
@@ -0,0 +1,217 @@
+package net.sf.openrocket.util;
+
+public class MathUtil {
+       public static final double EPSILON = 0.00000001;  // 10mm^3 in m^3
+
+       /**
+        * The square of x (x^2).  On Sun's JRE using this method is as fast as typing x*x. 
+        * @param x  x
+        * @return   x^2
+        */
+       public static double pow2(double x) {
+               return x*x;
+       }
+       
+       /**
+        * The cube of x (x^3).
+        * @param x  x
+        * @return   x^3
+        */
+       public static double pow3(double x) {
+               return x*x*x;
+       }
+       
+       public static double pow4(double x) {
+               return (x*x)*(x*x);
+       }
+       
+       /**
+        * Clamps the value x to the range min - max.  
+        * @param x    Original value.
+        * @param min  Minimum value to return.
+        * @param max  Maximum value to return.
+        * @return     The clamped value.
+        */
+       public static double clamp(double x, double min, double max) {
+               if (x < min)
+                       return min;
+               if (x > max)
+                       return max;
+               return x;
+       }
+       
+       public static float clamp(float x, float min, float max) {
+               if (x < min)
+                       return min;
+               if (x > max)
+                       return max;
+               return x;
+       }
+       
+       public static int clamp(int x, int min, int max) {
+               if (x < min)
+                       return min;
+               if (x > max)
+                       return max;
+               return x;
+       }
+       
+       
+       /**
+        * Maps a value from one value range to another.
+        * 
+        * @param value         the value to map.
+        * @param fromMin       the minimum of the starting range.
+        * @param fromMax       the maximum of the starting range.
+        * @param toMin         the minimum of the destination range.
+        * @param toMax         the maximum of the destination range.
+        * @return                      the mapped value.
+        * @throws      IllegalArgumentException  if fromMin == fromMax, but toMin != toMax.
+        */
+       public static double map(double value, double fromMin, double fromMax,
+                       double toMin, double toMax) {
+               if (equals(toMin, toMax))
+                       return toMin;
+               if (equals(fromMin, fromMax)) {
+                       throw new IllegalArgumentException("from range is singular an to range is not.");
+               }
+               return (value - fromMin)/(fromMax-fromMin) * (toMax - toMin) + toMin;
+       }
+       
+       /**
+        * Compute the minimum of two values.  This is performed by direct comparison. 
+        * However, if one of the values is NaN and the other is not, the non-NaN value is
+        * returned.
+        */
+       public static double min(double x, double y) {
+               if (Double.isNaN(y))
+                       return x;
+               return (x < y) ? x : y;
+       }
+       
+       /**
+        * Compute the maximum of two values.  This is performed by direct comparison. 
+        * However, if one of the values is NaN and the other is not, the non-NaN value is
+        * returned.
+        */
+       public static double max(double x, double y) {
+               if (Double.isNaN(x))
+                       return y;
+               return (x < y) ? y : x;
+       }
+       
+       /**
+        * Compute the minimum of three values.  This is performed by direct comparison. 
+        * However, if one of the values is NaN and the other is not, the non-NaN value is
+        * returned.
+        */
+       public static double min(double x, double y, double z) {
+               if (x < y || Double.isNaN(y)) {
+                       return min(x,z);
+               } else {
+                       return min(y,z);
+               }
+       }
+       
+       /**
+        * Compute the maximum of three values.  This is performed by direct comparison. 
+        * However, if one of the values is NaN and the other is not, the non-NaN value is
+        * returned.
+        */
+       public static double max(double x, double y, double z) {
+               if (x > y || Double.isNaN(y)) {
+                       return max(x,z);
+               } else {
+                       return max(y,z);
+               }
+       }
+       
+       /**
+        * Calculates the hypotenuse <code>sqrt(x^2+y^2)</code>.  This method is SIGNIFICANTLY
+        * faster than <code>Math.hypot(x,y)</code>.
+        */
+       public static double hypot(double x, double y) {
+               return Math.sqrt(x*x + y*y);
+       }
+
+       /**
+        * Reduce the angle x to the range 0 - 2*PI.
+        * @param x  Original angle.
+        * @return   The equivalent angle in the range 0 ... 2*PI.
+        */
+       public static double reduce360(double x) {
+               double d = Math.floor(x / (2*Math.PI));
+               return x - d*2*Math.PI;
+       }
+
+       /**
+        * Reduce the angle x to the range -PI - PI.
+        * 
+        * Either -PI and PI might be returned, depending on the rounding function. 
+        * 
+        * @param x  Original angle.
+        * @return   The equivalent angle in the range -PI ... PI.
+        */
+       public static double reduce180(double x) {
+               double d = Math.rint(x / (2*Math.PI));
+               return x - d*2*Math.PI;
+       }
+       
+       
+       public static boolean equals(double a, double b) {
+               double absb = Math.abs(b);
+               
+               if (absb < EPSILON/2) {
+                       // Near zero
+                       return Math.abs(a) < EPSILON/2;
+               }
+               return Math.abs(a-b) < EPSILON*absb;
+       }
+       
+       public static double sign(double x) {
+               return (x<0) ? -1.0 : 1.0;
+       }
+
+       /* Math.abs() is about 3x as fast as this:
+       
+       public static double abs(double x) {
+               return (x<0) ? -x : x;
+       }
+       */
+       
+       
+       public static void main(String[] arg) {
+               double nan = Double.NaN;
+               System.out.println("min(5,6)     = " + min(5, 6));
+               System.out.println("min(5,nan)   = " + min(5, nan));
+               System.out.println("min(nan,6)   = " + min(nan, 6));
+               System.out.println("min(nan,nan) = " + min(nan, nan));
+               System.out.println();
+               System.out.println("max(5,6)     = " + max(5, 6));
+               System.out.println("max(5,nan)   = " + max(5, nan));
+               System.out.println("max(nan,6)   = " + max(nan, 6));
+               System.out.println("max(nan,nan) = " + max(nan, nan));
+               System.out.println();
+               System.out.println("min(5,6,7)       = " + min(5, 6, 7));
+               System.out.println("min(5,6,nan)     = " + min(5, 6, nan));
+               System.out.println("min(5,nan,7)     = " + min(5, nan, 7));
+               System.out.println("min(5,nan,nan)   = " + min(5, nan, nan));
+               System.out.println("min(nan,6,7)     = " + min(nan, 6, 7));
+               System.out.println("min(nan,6,nan)   = " + min(nan, 6, nan));
+               System.out.println("min(nan,nan,7)   = " + min(nan, nan, 7));
+               System.out.println("min(nan,nan,nan) = " + min(nan, nan, nan));
+               System.out.println();
+               System.out.println("max(5,6,7)       = " + max(5, 6, 7));
+               System.out.println("max(5,6,nan)     = " + max(5, 6, nan));
+               System.out.println("max(5,nan,7)     = " + max(5, nan, 7));
+               System.out.println("max(5,nan,nan)   = " + max(5, nan, nan));
+               System.out.println("max(nan,6,7)     = " + max(nan, 6, 7));
+               System.out.println("max(nan,6,nan)   = " + max(nan, 6, nan));
+               System.out.println("max(nan,nan,7)   = " + max(nan, nan, 7));
+               System.out.println("max(nan,nan,nan) = " + max(nan, nan, nan));
+               System.out.println();
+               
+               
+       }
+       
+}