/*
 * Created on 29.12.2004
 */
package basics.utl;

import java.math.BigDecimal;
import basics.testing.Test;

/**
 * @author ks
 */
public class NumUtl
{
private NumUtl()
{
}

public static synchronized double round(double value, int precision)
{
   try
   {
      return (new BigDecimal(value).setScale(precision, BigDecimal.ROUND_HALF_UP)).doubleValue();
   }
   catch(Exception e)
   {
      return value;
   }
}

public static synchronized double roundUp(double value, int precision)
{
   try
   {
      return (new BigDecimal(value).setScale(precision, BigDecimal.ROUND_UP)).doubleValue();
   }
   catch(Exception e)
   {
      return value;
   }
}

public static synchronized float round(float value, int precision)
{
   return (new BigDecimal(value).setScale(precision, BigDecimal.ROUND_HALF_UP)).floatValue();
}

/**
 * returns lowest of 2 values
 */
public static synchronized double minimum(double v1, double v2)
{
   return v1 < v2 ? v1 : v2;
}

/**
 * returns highest of 2 values
 */
public static synchronized double maximum(double v1, double v2)
{
   return v1 > v2 ? v1 : v2;
}

/**
 * returns value except value is below minimum else return minimum
 */
public static synchronized double valueLimitedByMinimum(double value, double minimum)
{
   return value < minimum ? minimum : value;
}

/**
 * returns value except value is over maximum else return maximum
 */
public static synchronized double valueLimitedByMaximum(double value, double maximum)
{
   return value > maximum ? maximum : value;
}

/**
 * returns value except value is over maximum or below minimum else return maximum/minimum
 */
public static synchronized double valueLimitedByMinMax(double value, double minimum, double maximum)
{
   value = value < minimum ? minimum : value;
   return value > maximum ? maximum : value;
}

public static void main(String [] args)
{
   double v = Double.parseDouble(args[0]);
   int d = Integer.parseInt(args[1]);
   int p = Integer.parseInt(args[2]);
   System.out.println(args[0] + " --> " + FormatterUtl.format(v, d, p));
   System.out.println(args[0] + " x log" + args[2] + "(" + args[1] + ") = "
      + (SUtl.toDouble(args[0], 0) * logn(SUtl.toDouble(args[1], 0), SUtl.toDouble(args[2], 0))));
}

public static double logn(double d, double b)
{
   return Math.log(d) / Math.log(b);
}

public static double log2(double d)
{
   return Math.log(d) / Math.log(2.0);
}

public static final synchronized double [] copyThreadSafe(double [] src, double target[])
{
   target = new double [src.length];
   System.arraycopy(src, 0, target, 0, target.length);
   return target;
}

public static void unittest()
{
   Test.assertTrue(valueLimitedByMaximum(1.21, 1.22) == 1.21, "1.21 limits 1.22");
   Test.assertTrue(valueLimitedByMaximum(1.23, 1.22) == 1.22, "1.22 limits 1.23");
   Test.assertTrue(minimum(1.23, 1.22) == 1.22, "1.22 is below 1.23");
   Test.assertTrue(minimum(1.21, 1.22) == 1.21, "1.21 is below 1.22");
   Test.assertTrue(valueLimitedByMinMax(1.21, 1.20, 1.22) == 1.21, "1.21 is between 1.20 and 1.22");
   Test.assertTrue(valueLimitedByMinMax(1.21, 1.22, 1.22) == 1.22,
      "1.21 is not between 1.22 and 1.22");
   Test.assertTrue(valueLimitedByMinMax(1.21, 1.22, 1.20) == 1.20,
      "1.21 is not between 1.22 and 1.20");
   Test.assertTrue(valueLimitedByMinMax(1.24, 1.22, 1.23) == 1.23,
      "1.24 is not between 1.22 and 1.23");
   Test.assertTrue(round(1.24, 0) == 1, "1.24 should be rounded to 1");
   Test.assertTrue(round(1.24, 1) == 1.2, "1.24 should be rounded to 1,2");
   Test.assertTrue(copyThreadSafe(new double [] { 1.1, 2.2, 3.3 }, new double [] { }).length == 3,
      "Copied array must have length 3");
}
}
