You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@poi.apache.org by av...@apache.org on 2005/06/14 19:41:33 UTC

cvs commit: jakarta-poi/src/scratchpad/testcases/org/apache/poi/hssf/record/formula/functions AbstractNumericTestCase.java TestFinanceLib.java TestMathX.java TestStatsLib.java

avik        2005/06/14 10:41:33

  Added:       src/scratchpad/src/org/apache/poi/hssf/record/formula/functions
                        FinanceLib.java MathX.java
                        MultiOperandNumericFunction.java StatsLib.java
                        TextFunction.java XYNumericFunction.java
               src/scratchpad/testcases/org/apache/poi/hssf/record/formula/functions
                        AbstractNumericTestCase.java TestFinanceLib.java
                        TestMathX.java TestStatsLib.java
  Log:
  Amol's formula eval additions. Missed these files, sorry
  
  Revision  Changes    Path
  1.1                  jakarta-poi/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/FinanceLib.java
  
  Index: FinanceLib.java
  ===================================================================
  /*
   * Created on May 21, 2005
   *
   */
  package org.apache.poi.hssf.record.formula.functions;
  
  /**
   * @author Amol S. Deshmukh < amolweb at ya hoo dot com >
   * 
   * 
   * This class is a functon library for common fiscal functions.
   * <b>Glossary of terms/abbreviations:</b>
   * <br/>
   * <ul>
   * <li><em>FV:</em> Future Value</li>
   * <li><em>PV:</em> Present Value</li>
   * <li><em>NPV:</em> Net Present Value</li>
   * <li><em>PMT:</em> (Periodic) Payment</li>
   * 
   * </ul>
   * For more info on the terms/abbreviations please use the references below 
   * (hyperlinks are subject to change):
   * </br>Online References:
   * <ol>
   * <li>GNU Emacs Calc 2.02 Manual: http://theory.uwinnipeg.ca/gnu/calc/calc_203.html</li>
   * <li>Yahoo Financial Glossary: http://biz.yahoo.com/f/g/nn.html#y</li>
   * </ol>
   */
  public class FinanceLib {
      
      // constants for default values
      
      
      
      private FinanceLib() {}
      
      /**
       * Future value of an amount given the number of payments, rate, amount
       * of individual payment, present value and boolean value indicating whether
       * payments are due at the beginning of period 
       * (false => payments are due at end of period) 
       * @param r rate
       * @param n num of periods
       * @param y pmt per period
       * @param f future value
       * @param t type (true=pmt at end of period, false=pmt at begining of period)
       * @return
       */
      public static double fv(double r, int n, double y, double p, boolean t) {
          double r1 = r + 1;
          return ((1-Math.pow(r1, n)) * (t ? r1 : 1) * y ) / r  
                    - 
                 p*Math.pow(r1, n);
      }
      
      /**
       * Present value of an amount given the number of future payments, rate, amount
       * of individual payment, future value and boolean value indicating whether
       * payments are due at the beginning of period 
       * (false => payments are due at end of period) 
       * @param r
       * @param n
       * @param y
       * @param f
       * @param t
       * @return
       */
      public static double pv(double r, int n, double y, double f, boolean t) {
          double r1 = r + 1;
          return (( ( 1 - Math.pow(r1, n) ) / r ) * (t ? r1 : 1)  * y - f)
                    /
                 Math.pow(r1, n);
      }
      
      /**
       * calculates the Net Present Value of a principal amount
       * given the discount rate and a sequence of cash flows 
       * (supplied as an array). If the amounts are income the value should 
       * be positive, else if they are payments and not income, the 
       * value should be negative.
       * @param r
       * @param cfs cashflow amounts
       * @return
       */
      public static double npv(double r, double[] cfs) {
          double npv = 0;
          double r1 = r + 1;
          double trate = r1;
          for (int i=0, iSize=cfs.length; i<iSize; i++) {
              npv += cfs[i] / trate;
              trate *= r1;
          }
          return npv;
      }
      
      /**
       * 
       * @param r
       * @param n
       * @param p
       * @param f
       * @param t
       * @return
       */
      public static double pmt(double r, int n, double p, double f, boolean t) {
          double r1 = r + 1;
          return ( f + p * Math.pow(r1, n) ) * r 
                    / 
                 ((t ? r1 : 1) * (1 - Math.pow(r1, n)));
      }
      
      /**
       * 
       * @param r
       * @param n
       * @param p
       * @param f
       * @param t
       * @return
       */
      public static int nper(double r, double y, double p, double f, boolean t) {
          double r1 = r + 1;
          double ryr = (t ? r1 : 1) * y / r;
          double a1 = ((ryr-f) < 0) ? Math.log(f-ryr) : Math.log(ryr-f);
          double a2 = ((ryr-f) < 0) ? Math.log(-p-ryr) : Math.log(p+ryr);
          double a3 = Math.log(r1);
          double dval = ( a1 - a2 ) / a3;
          
          return (int) Math.round(dval);
      }
      
  
  }
  
  
  
  1.1                  jakarta-poi/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/MathX.java
  
  Index: MathX.java
  ===================================================================
  /*
   * Created on May 19, 2005
   *
   */
  package org.apache.poi.hssf.record.formula.functions;
  
  
  
  /**
   * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
   * This class is an extension to the standard math library
   * provided by java.lang.Math class. It follows the Math class
   * in that it has a private constructor and all static methods.
   */
  public final class MathX {
  
      
      private MathX() {}
      
      
      /**
       * Returns a value rounded to p digits after decimal.
       * If p is negative, then the number is rounded to
       * places to the left of the decimal point. eg. 
       * 10.23 rounded to -1 will give: 10. If p is zero,
       * the returned value is rounded to the nearest integral
       * value.
       * <p>If n is negative, the resulting value is obtained
       * as the round value of absolute value of n multiplied
       * by the sign value of n (@see MathX.sign(double d)). 
       * Thus, -0.6666666 rounded to p=0 will give -1 not 0.
       * <p>If n is NaN, returned value is NaN.
       * @param n
       * @param p
       * @return
       */
      public static double round(double n, int p) {
          double retval;
          
          if (Double.isNaN(n) || Double.isInfinite(n)) {
              retval = Double.NaN;
          }
          else {
              if (p != 0) {
                  double temp = Math.pow(10, p);
                  retval = Math.round(n*temp)/temp;
              }
              else {
                  retval = Math.round(n);
              }
          }
          
          return retval;
      }
  
      /**
       * Returns a value rounded-up to p digits after decimal.
       * If p is negative, then the number is rounded to
       * places to the left of the decimal point. eg. 
       * 10.23 rounded to -1 will give: 20. If p is zero,
       * the returned value is rounded to the nearest integral
       * value.
       * <p>If n is negative, the resulting value is obtained
       * as the round-up value of absolute value of n multiplied
       * by the sign value of n (@see MathX.sign(double d)). 
       * Thus, -0.2 rounded-up to p=0 will give -1 not 0.
       * <p>If n is NaN, returned value is NaN.
       * @param n
       * @param p
       * @return
       */
      public static double roundUp(double n, int p) {
          double retval;
          
          if (Double.isNaN(n) || Double.isInfinite(n)) {
              retval = Double.NaN;
          }
          else {
              if (p != 0) {
                  double temp = Math.pow(10, p);
                  double nat = Math.abs(n*temp);
                  
                  retval = sign(n) * 
                      ((nat == (long) nat)
                              ? nat / temp
                              : Math.round(nat + 0.5) / temp);
              }
              else {
                  double na = Math.abs(n);
                  retval = sign(n) * 
                      ((na == (long) na)
                          ? na
                          : (long) na + 1);
              }
          }
          
          return retval;
      }
  
      /**
       * Returns a value rounded to p digits after decimal.
       * If p is negative, then the number is rounded to
       * places to the left of the decimal point. eg. 
       * 10.23 rounded to -1 will give: 10. If p is zero,
       * the returned value is rounded to the nearest integral
       * value.
       * <p>If n is negative, the resulting value is obtained
       * as the round-up value of absolute value of n multiplied
       * by the sign value of n (@see MathX.sign(double d)). 
       * Thus, -0.8 rounded-down to p=0 will give 0 not -1.
       * <p>If n is NaN, returned value is NaN.
       * @param n
       * @param p
       * @return
       */
      public static double roundDown(double n, int p) {
          double retval;
          
          if (Double.isNaN(n) || Double.isInfinite(n)) {
              retval = Double.NaN;
          }
          else {
              if (p != 0) {
                  double temp = Math.pow(10, p);
                  retval = sign(n) * Math.round((Math.abs(n)*temp) - 0.5)/temp;
              }
              else {
                  retval = (long) n;
              }
          }
          
          return retval;
      }
      
      
      /**
       * If d < 0, returns short -1
       * <br/>
       * If d > 0, returns short 1
       * <br/>
       * If d == 0, returns short 0 
       * <p> If d is NaN, then 1 will be returned. It is the responsibility
       * of caller to check for d isNaN if some other value is desired.
       * @param d
       * @return
       */
      public static short sign(double d) {
          return (short) ((d == 0)
                  ? 0
                  : (d < 0)
                          ? -1
                          : 1);
      }
     
      /**
       * average of all values
       * @param values
       * @return
       */
      public static double average(double[] values) {
          double ave = 0;
          double sum = 0;
          for (int i=0, iSize=values.length; i<iSize; i++) {
              sum += values[i];
          }
          ave = sum / values.length;
          return ave;
      }
      
      
      /**
       * sum of all values
       * @param values
       * @return
       */
      public static double sum(double[] values) {
          double sum = 0;
          for (int i=0, iSize=values.length; i<iSize; i++) {
              sum += values[i];
          }
          return sum;
      }
      
      /**
       * sum of squares of all values
       * @param values
       * @return
       */
      public static double sumsq(double[] values) {
          double sumsq = 0;
          for (int i=0, iSize=values.length; i<iSize; i++) {
              sumsq += values[i]*values[i];
          }
          return sumsq;
      }
      
      
      /**
       * product of all values
       * @param values
       * @return
       */
      public static double product(double[] values) {
          double product = 0;
          if (values!=null && values.length > 0) {
              product = 1;
              for (int i=0, iSize=values.length; i<iSize; i++) {
                  product *= values[i];
              }
          }
          return product;
      }
      
      /**
       * min of all values. If supplied array is zero length,
       * Double.POSITIVE_INFINITY is returned.
       * @param values
       * @return
       */
      public static double min(double[] values) {
          double min = Double.POSITIVE_INFINITY;
          for (int i=0, iSize=values.length; i<iSize; i++) {
              min = Math.min(min, values[i]);
          }
          return min;
      }
  
      /**
       * min of all values. If supplied array is zero length,
       * Double.NEGATIVE_INFINITY is returned.
       * @param values
       * @return
       */
      public static double max(double[] values) {
          double max = Double.NEGATIVE_INFINITY;
          for (int i=0, iSize=values.length; i<iSize; i++) {
              max = Math.max(max, values[i]);
          }
          return max;
      }
  
      /**
       * Note: this function is different from java.lang.Math.floor(..).
       * <p>
       * When n and s are "valid" arguments, the returned value is: Math.floor(n/s) * s;
       * <br/>
       * n and s are invalid if any of following conditions are true:
       * <ul>
       * <li>s is zero</li>
       * <li>n is negative and s is positive</li>
       * <li>n is positive and s is negative</li>
       * </ul>
       * In all such cases, Double.NaN is returned.
       * @param n
       * @param s
       * @return
       */
      public static double floor(double n, double s) {
          double f;
          
          if ((n<0 && s>0) || (n>0 && s<0) || (s==0 && n!=0)) {
              f = Double.NaN;
          }
          else {
              f = (n==0 || s==0) ? 0 : Math.floor(n/s) * s;
          }
          
          return f;
      }
      
      /**
       * Note: this function is different from java.lang.Math.ceil(..).
       * <p>
       * When n and s are "valid" arguments, the returned value is: Math.ceiling(n/s) * s;
       * <br/>
       * n and s are invalid if any of following conditions are true:
       * <ul>
       * <li>s is zero</li>
       * <li>n is negative and s is positive</li>
       * <li>n is positive and s is negative</li>
       * </ul>
       * In all such cases, Double.NaN is returned.
       * @param n
       * @param s
       * @return
       */
      public static double ceiling(double n, double s) {
          double c;
          
          if ((n<0 && s>0) || (n>0 && s<0)) {
              c = Double.NaN;
          }
          else {
              c = (n == 0 || s == 0) ? 0 : Math.ceil(n/s) * s;
          }
          
          return c;
      }
      
      /**
       * <br/> for all n >= 1; factorial n = n * (n-1) * (n-2) * ... * 1 
       * <br/> else if n == 0; factorial n = 1
       * <br/> else if n < 0; factorial n = Double.NaN
       * <br/> Loss of precision can occur if n is large enough.
       * If n is large so that the resulting value would be greater 
       * than Double.MAX_VALUE; Double.POSITIVE_INFINITY is returned.
       * If n < 0, Double.NaN is returned. 
       * @param n
       * @return
       */
      public static double factorial(int n) {
          double d = 1;
          
          if (n >= 0) {
              if (n <= 170) {
                  for (int i=1; i<=n; i++) {
                      d *= i;
                  }
              }
              else {
                  d = Double.POSITIVE_INFINITY;
              }
          }
          else {
              d = Double.NaN;
          }
          return d;
      }
      
  
      /**
       * returns the remainder resulting from operation:
       * n / d. 
       * <br/> The result has the sign of the divisor.
       * <br/> Examples:
       * <ul>
       * <li>mod(3.4, 2) = 1.4</li>
       * <li>mod(-3.4, 2) = 0.6</li>
       * <li>mod(-3.4, -2) = -1.4</li>
       * <li>mod(3.4, -2) = -0.6</li>
       * </ul>
       * If d == 0, result is NaN
       * @param n
       * @param d
       * @return
       */
      public static double mod(double n, double d) {
          double result = 0;
          
          if (d == 0) {
              result = Double.NaN;
          }
          else if (sign(n) == sign(d)) {
              double t = Math.abs(n / d);
              t = t - (long) t;
              result = sign(d) * Math.abs(t * d);
          }
          else {
              double t = Math.abs(n / d);
              t = t - (long) t;
              t = Math.ceil(t) - t;
              result = sign(d) * Math.abs(t * d);
          }
          
          return result;
      }
      
      
      /**
       * inverse hyperbolic cosine
       * @param d
       * @return
       */
      public static double acosh(double d) {
          return Math.log(Math.sqrt(Math.pow(d, 2) - 1) + d);
      }
      
      /**
       * inverse hyperbolic sine
       * @param d
       * @return
       */
      public static double asinh(double d) {
          double d2 = d*d;
          return Math.log(Math.sqrt(d*d + 1) + d);
      }
      
      /**
       * inverse hyperbolic tangent
       * @param d
       * @return
       */
      public static double atanh(double d) {
          return Math.log((1 + d)/(1 - d)) / 2;
      }
      
      /**
       * hyperbolic cosine
       * @param d
       * @return
       */
      public static double cosh(double d) {
          double ePowX = Math.pow(Math.E, d);
          double ePowNegX = Math.pow(Math.E, -d);
          d = (ePowX + ePowNegX) / 2;
          return d;
      }
      
      /**
       * hyperbolic sine
       * @param d
       * @return
       */
      public static double sinh(double d) {
          double ePowX = Math.pow(Math.E, d);
          double ePowNegX = Math.pow(Math.E, -d);
          d = (ePowX - ePowNegX) / 2;
          return d;
      }
      
      /**
       * hyperbolic tangent
       * @param d
       * @return
       */
      public static double tanh(double d) {
          double ePowX = Math.pow(Math.E, d);
          double ePowNegX = Math.pow(Math.E, -d);
          d = (ePowX - ePowNegX) / (ePowX + ePowNegX);
          return d;
      }
      
      /**
       * returns the sum of product of corresponding double value in each
       * subarray. It is the responsibility of the caller to ensure that
       * all the subarrays are of equal length. If the subarrays are
       * not of equal length, the return value can be unpredictable.
       * @param arrays
       * @return
       */
      public static double sumproduct(double[][] arrays) {
          double d = 0;
          
          try {
              int narr = arrays.length;
              int arrlen = arrays[0].length; 
              
              for (int j=0; j<arrlen; j++) {
                  double t = 1;
                  for (int i=0; i<narr; i++) {
                      t *= arrays[i][j];
                  }
                  d += t;
              }            
          }
          catch (ArrayIndexOutOfBoundsException ae) {
              d = Double.NaN;
          }
          
          return d;
      }
      
      /**
       * returns the sum of difference of squares of corresponding double 
       * value in each subarray: ie. sigma (xarr[i]^2-yarr[i]^2) 
       * <br/>
       * It is the responsibility of the caller 
       * to ensure that the two subarrays are of equal length. If the 
       * subarrays are not of equal length, the return value can be 
       * unpredictable.
       * @param arrays
       * @return
       */
      public static double sumx2my2(double[] xarr, double[] yarr) {
          double d = 0;
          
          try {
              for (int i=0, iSize=xarr.length; i<iSize; i++) {
                  d += (xarr[i] + yarr[i]) * (xarr[i] - yarr[i]);
              }            
          }
          catch (ArrayIndexOutOfBoundsException ae) {
              d = Double.NaN;
          }
          
          return d;
      }
      
      /**
       * returns the sum of sum of squares of corresponding double 
       * value in each subarray: ie. sigma (xarr[i]^2 + yarr[i]^2) 
       * <br/>
       * It is the responsibility of the caller 
       * to ensure that the two subarrays are of equal length. If the 
       * subarrays are not of equal length, the return value can be 
       * unpredictable.
       * @param arrays
       * @return
       */
      public static double sumx2py2(double[] xarr, double[] yarr) {
          double d = 0;
          
          try {
              for (int i=0, iSize=xarr.length; i<iSize; i++) {
                  d += (xarr[i] * xarr[i]) + (yarr[i] * yarr[i]);
              }            
          }
          catch (ArrayIndexOutOfBoundsException ae) {
              d = Double.NaN;
          }
          
          return d;
      }
      
  
      /**
       * returns the sum of squares of difference of corresponding double 
       * value in each subarray: ie. sigma ( (xarr[i]-yarr[i])^2 ) 
       * <br/>
       * It is the responsibility of the caller 
       * to ensure that the two subarrays are of equal length. If the 
       * subarrays are not of equal length, the return value can be 
       * unpredictable.
       * @param arrays
       * @return
       */
      public static double sumxmy2(double[] xarr, double[] yarr) {
          double d = 0;
          
          try {
              for (int i=0, iSize=xarr.length; i<iSize; i++) {
                  double t = (xarr[i] - yarr[i]);
                  d += t * t;
              }            
          }
          catch (ArrayIndexOutOfBoundsException ae) {
              d = Double.NaN;
          }
          
          return d;
      }
      
      /**
       * returns the total number of combinations possible when
       * k items are chosen out of total of n items. If the number
       * is too large, loss of precision may occur (since returned
       * value is double). If the returned value is larger than
       * Double.MAX_VALUE, Double.POSITIVE_INFINITY is returned.
       * If either of the parameters is negative, Double.NaN is returned.
       * @param n
       * @param k
       * @return
       */
      public static double nChooseK(int n, int k) {
          double d = 1;
          if (n<0 || k<0 || n<k) {
              d= Double.NaN;
          }
          else {
              int minnk = Math.min(n-k, k);
              int maxnk = Math.max(n-k, k);
              for (int i=maxnk; i<n; i++) {
                  d *= i+1;
              }
              d /= factorial(minnk);
          }
          
          return d;
      }
      
  }
  
  
  
  1.1                  jakarta-poi/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/MultiOperandNumericFunction.java
  
  Index: MultiOperandNumericFunction.java
  ===================================================================
  /*
   * Created on May 22, 2005
   *
   */
  package org.apache.poi.hssf.record.formula.functions;
  
  import org.apache.poi.hssf.record.formula.eval.AreaEval;
  import org.apache.poi.hssf.record.formula.eval.BlankEval;
  import org.apache.poi.hssf.record.formula.eval.Eval;
  import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
  import org.apache.poi.hssf.record.formula.eval.Ref2DEval;
  import org.apache.poi.hssf.record.formula.eval.RefEval;
  import org.apache.poi.hssf.record.formula.eval.ValueEval;
  import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
  
  /**
   * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
   * This is the super class for all excel function evaluator
   * classes that take variable number of operands, and
   * where the order of operands does not matter
   */
  public abstract class MultiOperandNumericFunction extends NumericFunction {
  
      private static final ValueEvalToNumericXlator DEFAULT_NUM_XLATOR =
          new ValueEvalToNumericXlator((short) (
                    ValueEvalToNumericXlator.BOOL_IS_PARSED  
                  | ValueEvalToNumericXlator.REF_BOOL_IS_PARSED  
                  | ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED  
                //| ValueEvalToNumericXlator.STRING_IS_PARSED  
                  | ValueEvalToNumericXlator.REF_STRING_IS_PARSED  
                  | ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED  
                //| ValueEvalToNumericXlator.STRING_TO_BOOL_IS_PARSED  
                //| ValueEvalToNumericXlator.REF_STRING_TO_BOOL_IS_PARSED  
                //| ValueEvalToNumericXlator.STRING_IS_INVALID_VALUE  
                //| ValueEvalToNumericXlator.REF_STRING_IS_INVALID_VALUE  
                  ));
      
      private static final int DEFAULT_MAX_NUM_OPERANDS = 30;
  
      /**
       * this is the default impl for the factory method getXlator
       * of the super class NumericFunction. Subclasses can override this method
       * if they desire to return a different ValueEvalToNumericXlator instance
       * than the default.
       */
      protected ValueEvalToNumericXlator getXlator() {
          return DEFAULT_NUM_XLATOR;
      }
      
      /**
       * Maximum number of operands accepted by this function.
       * Subclasses may override to change default value.
       * @return
       */
      protected int getMaxNumOperands() {
          return DEFAULT_MAX_NUM_OPERANDS;
      }
      
      /**
       * Returns a double array that contains values for the numeric cells
       * from among the list of operands. Blanks and Blank equivalent cells
       * are ignored. Error operands or cells containing operands of type
       * that are considered invalid and would result in #VALUE! error in 
       * excel cause this function to return null.
       * 
       * @param operands
       * @param srcRow
       * @param srcCol
       * @return
       */
      protected double[] getNumberArray(Eval[] operands, int srcRow, short srcCol) {
          double[] retval = new double[30];
          int count = 0;
          
          outer: do { // goto simulator loop
              if (operands.length > getMaxNumOperands()) {
                  break outer;
              }
              else {
                  for (int i=0, iSize=operands.length; i<iSize; i++) {
                      double[] temp = getNumberArray(operands[i], srcRow, srcCol);
                      if (temp == null) {
                          retval = null; // error occurred.
                          break;
                      }
                      retval = putInArray(retval, count, temp);
                      count += temp.length;
                  }
              }
          } while (false); // end goto simulator loop
          
          if (retval != null) {
              double[] temp = retval;
              retval = new double[count];
              System.arraycopy(temp, 0, retval, 0, count);
          }
          
          return retval;
      }
      
      /**
       * Same as getNumberArray(Eval[], int, short) except that this
       * takes Eval instead of Eval[].
       * @param operand
       * @param srcRow
       * @param srcCol
       * @return
       */
      protected double[] getNumberArray(Eval operand, int srcRow, short srcCol) {
          double[] retval;
          int count = 0;
          
          if (operand instanceof AreaEval) {
              AreaEval ae = (AreaEval) operand;
              ValueEval[] values = ae.getValues();
              retval = new double[values.length];
              for (int j=0, jSize=values.length; j<jSize; j++) {
                  /*
                   * TODO: For an AreaEval, we are constructing a RefEval
                   * per element.
                   * For now this is a tempfix solution since this may
                   * require a more generic fix at the level of
                   * HSSFFormulaEvaluator where we store an array
                   * of RefEvals as the "values" array. 
                   */
                  RefEval re = (values[j] instanceof RefEval)
                          ? new Ref2DEval(null, ((RefEval) values[j]).getInnerValueEval(), true)
                          : new Ref2DEval(null, values[j], false);
                  ValueEval ve = singleOperandEvaluate(re, srcRow, srcCol);
                  
                  if (ve instanceof NumericValueEval) {
                      NumericValueEval nve = (NumericValueEval) ve;
                      retval = putInArray(retval, count++, nve.getNumberValue());
                  }
                  else if (ve instanceof BlankEval) {} // ignore operand
                  else {
                      retval = null; // null => indicate to calling subclass that error occurred
                      break;
                  }
              }
          }
          else { // for ValueEvals other than AreaEval
              retval = new double[1];
              ValueEval ve = singleOperandEvaluate(operand, srcRow, srcCol);
              
              if (ve instanceof NumericValueEval) {
                  NumericValueEval nve = (NumericValueEval) ve;
                  retval = putInArray(retval, count++, nve.getNumberValue());
              }
              else if (ve instanceof BlankEval) {} // ignore operand
              else {
                  retval = null; // null => indicate to calling subclass that error occurred
              }
          }
          
          if (retval != null && retval.length >= 1) {
              double[] temp = retval;
              retval = new double[count];
              System.arraycopy(temp, 0, retval, 0, count);
          }
          
          return retval;
      }
      
      /**
       * puts d at position pos in array arr. If pos is greater than arr, the 
       * array is dynamically resized (using a simple doubling rule).
       * @param arr
       * @param pos
       * @param d
       * @return
       */
      private static double[] putInArray(double[] arr, int pos, double d) {
          double[] tarr = arr;
          while (pos >= arr.length) {
              arr = new double[arr.length << 1];
          }
          if (tarr.length != arr.length) {
              System.arraycopy(tarr, 0, arr, 0, tarr.length);
          }
          arr[pos] = d;
          return arr;
      }
      
      private static double[] putInArray(double[] arr, int pos, double[] d) {
          double[] tarr = arr;
          while (pos+d.length >= arr.length) {
              arr = new double[arr.length << 1];
          }
          if (tarr.length != arr.length) {
              System.arraycopy(tarr, 0, arr, 0, tarr.length);
          }
          for (int i=0, iSize=d.length; i<iSize; i++) {
              arr[pos+i] = d[i];
          }
          return arr;
      }
      
      protected static boolean areSubArraysConsistent(double[][] values) {
          boolean retval = false;
          
          outer: do {
              if (values != null && values.length > 0) {
                  if (values[0] == null)
                      break outer;
                  int len = values[0].length;
                  for (int i=1, iSize=values.length; i<iSize; i++) {
                      if (values[i] == null)
                          break outer;
                      int tlen = values[i].length;
                      if (len != tlen) {
                          break outer;
                      }
                  }
              }
              retval = true;
          } while (false);
          return retval;
      }
      
  }
  
  
  
  1.1                  jakarta-poi/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/StatsLib.java
  
  Index: StatsLib.java
  ===================================================================
  /*
   * Created on May 30, 2005
   *
   */
  package org.apache.poi.hssf.record.formula.functions;
  
  import java.util.Arrays;
  
  /**
   * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
   *
   * Library for common statistics functions
   */
  public class StatsLib {
  
      private StatsLib() {}
  
  
      /**
       * returns the mean of deviations from mean.
       * @param v
       * @return
       */
      public static double avedev(double[] v) {
          double r = 0;
          double m = 0;
          double s = 0;
          for (int i=0, iSize=v.length; i<iSize; i++) {
              s += v[i];
          }
          m = s / v.length;
          s = 0;
          for (int i=0, iSize=v.length; i<iSize; i++) {
              s += Math.abs(v[i]-m);
          }
          r = s / v.length;
          return r;
      }
      
      public static double stdev(double[] v) {
          double r = Double.NaN;
          if (v!=null && v.length > 1) {
              r = Math.sqrt( devsq(v) / (v.length - 1) );
          }
          return r;
      }
      
      /**
       * if v is zero length or contains no duplicates, return value
       * is Double.NaN. Else returns the value that occurs most times
       * and if there is a tie, returns the first such value. 
       * @param v
       * @return
       */
      public static double mode(double[] v) {
          double r = Double.NaN;
          
          // very naive impl, may need to be optimized
          if (v!=null && v.length > 1) {
              int[] counts = new int[v.length]; 
              Arrays.fill(counts, 1);
              for (int i=0, iSize=v.length; i<iSize; i++) {
                  for (int j=i+1, jSize=v.length; j<jSize; j++) {
                      if (v[i] == v[j]) counts[i]++;
                  }
              }
              double maxv = 0;
              int maxc = 0;
              for (int i=0, iSize=counts.length; i<iSize; i++) {
                  if (counts[i] > maxc) {
                      maxv = v[i];
                      maxc = counts[i];
                  }
              }
              r = (maxc > 1) ? maxv : Double.NaN; // "no-dups" check
          }
          return r;
      }
      
      public static double median(double[] v) {
          double r = Double.NaN;
          
          if (v!=null && v.length >= 1) {
              int n = v.length;
              Arrays.sort(v);
              r = (n % 2 == 0)
                  ? (v[n / 2] + v[n / 2 - 1]) / 2
                  : v[n / 2];
          }
          
          return r;
      }
      
      
      public static double devsq(double[] v) {
          double r = Double.NaN;
          if (v!=null && v.length >= 1) {
              double m = 0;
              double s = 0;
              int n = v.length;
              for (int i=0; i<n; i++) {
                  s += v[i];
              }
              m = s / n;
              s = 0;
              for (int i=0; i<n; i++) {
                  s += (v[i]- m) * (v[i] - m);
              }
              
              r = (n == 1)
                      ? 0
                      : s;
          }
          return r;
      }
      
      /**
       * returns the kth largest element in the array. Duplicates
       * are considered as distinct values. Hence, eg.
       * for array {1,2,4,3,3} & k=2, returned value is 3.
       * <br/>
       * k <= 0 & k >= v.length and null or empty arrays
       * will result in return value Double.NaN
       * @param v
       * @param k
       * @return
       */
      public static double kthLargest(double[] v, int k) {
          double r = Double.NaN;
          k--; // since arrays are 0-based
          if (v!=null && v.length > k && k >= 0) {
              Arrays.sort(v);
              r = v[v.length-k-1];
          }
          return r;
      }
  
      /**
       * returns the kth smallest element in the array. Duplicates
       * are considered as distinct values. Hence, eg.
       * for array {1,1,2,4,3,3} & k=2, returned value is 1.
       * <br/>
       * k <= 0 & k >= v.length or null array or empty array
       * will result in return value Double.NaN
       * @param v
       * @param k
       * @return
       */
      public static double kthSmallest(double[] v, int k) {
          double r = Double.NaN;
          k--; // since arrays are 0-based
          if (v!=null && v.length > k && k >= 0) {
              Arrays.sort(v);
              r = v[k];
          }
          return r;
      }
  }
  
  
  
  1.1                  jakarta-poi/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/TextFunction.java
  
  Index: TextFunction.java
  ===================================================================
  /*
   * Created on May 22, 2005
   *
   */
  package org.apache.poi.hssf.record.formula.functions;
  
  import org.apache.poi.hssf.record.formula.eval.AreaEval;
  import org.apache.poi.hssf.record.formula.eval.BlankEval;
  import org.apache.poi.hssf.record.formula.eval.ErrorEval;
  import org.apache.poi.hssf.record.formula.eval.Eval;
  import org.apache.poi.hssf.record.formula.eval.RefEval;
  import org.apache.poi.hssf.record.formula.eval.StringValueEval;
  import org.apache.poi.hssf.record.formula.eval.ValueEval;
  
  /**
   * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
   *
   */
  public abstract class TextFunction implements Function {
      
      protected static final String EMPTY_STRING = "";
      
      protected ValueEval singleOperandEvaluate(Eval eval, int srcRow, short srcCol) {
          ValueEval retval;
          if (eval instanceof AreaEval) {
              AreaEval ae = (AreaEval) eval;
              if (ae.contains(srcRow, srcCol)) { // circular ref!
                  retval = ErrorEval.CIRCULAR_REF_ERROR;
              }
              else if (ae.isRow()) {
                  if (ae.containsColumn(srcCol)) {
                      ValueEval ve = ae.getValueAt(ae.getFirstRow(), srcCol);
                      retval = attemptXlateToText(ve);
                  }
                  else {
                      retval = ErrorEval.VALUE_INVALID;
                  }
              }
              else if (ae.isColumn()) {
                  if (ae.containsRow(srcRow)) {
                      ValueEval ve = ae.getValueAt(srcRow, ae.getFirstColumn());
                      retval = attemptXlateToText(ve);
                  }
                  else {
                      retval = ErrorEval.VALUE_INVALID;
                  }
              }
              else {
                  retval = ErrorEval.VALUE_INVALID;
              }
          }
          else {
              retval = attemptXlateToText((ValueEval) eval);
          }
          return retval;
      }
  
      
      /**
       * converts from Different ValueEval types to StringEval.
       * Note: AreaEvals are not handled, if arg is an AreaEval,
       * the returned value is ErrorEval.VALUE_INVALID
       * @param ve
       * @return
       */
      protected ValueEval attemptXlateToText(ValueEval ve) {
          ValueEval retval;
          if (ve instanceof StringValueEval) {
              retval = ve;
          }
          else if (ve instanceof RefEval) {
              RefEval re = (RefEval) ve;
              ValueEval ive = re.getInnerValueEval();
              if (ive instanceof StringValueEval) {
                  retval = ive;
              }
              else if (ive instanceof BlankEval) {
                  retval = ive;
              }
              else {
                  retval = ErrorEval.VALUE_INVALID;
              }
          }
          else if (ve instanceof BlankEval) {
              retval = ve;
          }
          else {
              retval = ErrorEval.VALUE_INVALID;
          }
          return retval;
      }
  }
  
  
  
  1.1                  jakarta-poi/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/XYNumericFunction.java
  
  Index: XYNumericFunction.java
  ===================================================================
  /*
   * Created on May 29, 2005
   *
   */
  package org.apache.poi.hssf.record.formula.functions;
  
  import org.apache.poi.hssf.record.formula.eval.AreaEval;
  import org.apache.poi.hssf.record.formula.eval.ErrorEval;
  import org.apache.poi.hssf.record.formula.eval.Eval;
  import org.apache.poi.hssf.record.formula.eval.NumberEval;
  import org.apache.poi.hssf.record.formula.eval.RefEval;
  import org.apache.poi.hssf.record.formula.eval.ValueEval;
  import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
  
  /**
   * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
   *
   */
  public abstract class XYNumericFunction extends NumericFunction {
      protected static final int X = 0;
      protected static final int Y = 1;
  
      private static final ValueEvalToNumericXlator DEFAULT_NUM_XLATOR =
          new ValueEvalToNumericXlator((short) (
                    ValueEvalToNumericXlator.BOOL_IS_PARSED  
                  | ValueEvalToNumericXlator.REF_BOOL_IS_PARSED  
                  | ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED  
                //| ValueEvalToNumericXlator.STRING_IS_PARSED  
                  | ValueEvalToNumericXlator.REF_STRING_IS_PARSED  
                  | ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED  
                //| ValueEvalToNumericXlator.STRING_TO_BOOL_IS_PARSED  
                //| ValueEvalToNumericXlator.REF_STRING_TO_BOOL_IS_PARSED  
                //| ValueEvalToNumericXlator.STRING_IS_INVALID_VALUE  
                //| ValueEvalToNumericXlator.REF_STRING_IS_INVALID_VALUE  
                  ));
  
      /**
       * this is the default impl for the factory method getXlator
       * of the super class NumericFunction. Subclasses can override this method
       * if they desire to return a different ValueEvalToNumericXlator instance
       * than the default.
       */
      protected ValueEvalToNumericXlator getXlator() {
          return DEFAULT_NUM_XLATOR;
      }
      
      protected int getMaxNumOperands() {
          return 30;
      }
  
      /**
       * Returns a double array that contains values for the numeric cells
       * from among the list of operands. Blanks and Blank equivalent cells
       * are ignored. Error operands or cells containing operands of type
       * that are considered invalid and would result in #VALUE! error in 
       * excel cause this function to return null.
       * 
       * @param operands
       * @param srcRow
       * @param srcCol
       * @return
       */
      protected double[][] getNumberArray(Eval[] xops, Eval[] yops, int srcRow, short srcCol) {
          double[][] retval = new double[2][30];
          int count = 0;
          
          if (xops.length > getMaxNumOperands() 
                  || yops.length > getMaxNumOperands()
                  || xops.length != yops.length) {
              retval = null;
          }
          else {
              
              for (int i=0, iSize=xops.length; i<iSize; i++) {
                  Eval xEval = xops[i];
                  Eval yEval = yops[i];
                  
                  if (isNumberEval(xEval) && isNumberEval(yEval)) {
                      retval[X] = ensureCapacity(retval[X], count);
                      retval[Y] = ensureCapacity(retval[Y], count);
                      retval[X][count] = getDoubleValue(xEval);
                      retval[Y][count] = getDoubleValue(yEval);
                      if (Double.isNaN(retval[X][count]) || Double.isNaN(retval[Y][count])) {
                          retval = null;
                          break;
                      }
                      count++;
                  }
              }
          }
          
          if (retval != null) {
              double[][] temp = retval;
              retval[X] = trimToSize(retval[X], count);
              retval[Y] = trimToSize(retval[Y], count);
          }
          
          return retval;
      }
      
      protected double[][] getValues(Eval[] operands, int srcCellRow, short srcCellCol) {
          double[][] retval = null;
          
          outer: do {
              if (operands.length == 2) {
                  Eval[] xEvals = new Eval[1];
                  Eval[] yEvals = new Eval[1];
                  if (operands[X] instanceof AreaEval) {
                      AreaEval ae = (AreaEval) operands[0];
                      xEvals = ae.getValues();
                  }
                  else if (operands[X] instanceof ErrorEval) {
                      break outer;
                  }
                  else {
                      xEvals[0] = operands[X];
                  }
                  
                  if (operands[Y] instanceof AreaEval) {
                      AreaEval ae = (AreaEval) operands[Y];
                      yEvals = ae.getValues();
                  }
                  else if (operands[Y] instanceof ErrorEval) {
                      break outer;
                  }
                  else {
                      yEvals[0] = operands[Y];
                  }
                  
                  retval = getNumberArray(xEvals, yEvals, srcCellRow, srcCellCol);
              }
          } while (false);
          
          return retval;
      }
      
  
      protected static double[] ensureCapacity(double[] arr, int pos) {
          double[] temp = arr;
          while (pos >= arr.length) {
              arr = new double[arr.length << 2];
          }
          if (temp.length != arr.length)
              System.arraycopy(temp, 0, arr, 0, temp.length);
          return arr;
      }
      
      protected static double[] trimToSize(double[] arr, int len) {
          double[] tarr = arr;
          if (arr.length > len) {
              tarr = new double[len];
              System.arraycopy(arr, 0, tarr, 0, len);
          }
          return tarr;
      }
      
      protected static boolean isNumberEval(Eval eval) {
          boolean retval = false;
          
          if (eval instanceof NumberEval) {
              retval = true;
          }
          else if (eval instanceof RefEval) {
              RefEval re = (RefEval) eval;
              ValueEval ve = re.getInnerValueEval();
              retval = (ve instanceof NumberEval);
          }
          
          return retval;
      }
      
      protected static double getDoubleValue(Eval eval) {
          double retval = 0;
          if (eval instanceof NumberEval) {
              NumberEval ne = (NumberEval) eval;
              retval = ne.getNumberValue();
          }
          else if (eval instanceof RefEval) {
              RefEval re = (RefEval) eval;
              ValueEval ve = re.getInnerValueEval();
                  retval = (ve instanceof NumberEval)
                      ? ((NumberEval) ve).getNumberValue()
                      : Double.NaN;
          }
          else if (eval instanceof ErrorEval) {
              retval = Double.NaN;
          }
          return retval;
      }
  }
  
  
  
  1.1                  jakarta-poi/src/scratchpad/testcases/org/apache/poi/hssf/record/formula/functions/AbstractNumericTestCase.java
  
  Index: AbstractNumericTestCase.java
  ===================================================================
  /*
   * Created on May 29, 2005
   *
   */
  package org.apache.poi.hssf.record.formula.functions;
  
  import junit.framework.TestCase;
  
  /**
   * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
   *
   */
  public abstract class AbstractNumericTestCase extends TestCase {
  
      public static final double POS_ZERO = 1E-4;
      public static final double DIFF_TOLERANCE_FACTOR = 1E-8;
  
      public void setUp() {
      }
  
      public void tearDown() {
      }
  
      /**
       * Why doesnt JUnit have a method like this for doubles? 
       * The current impl (3.8.1) of Junit has a retar*** method
       * for comparing doubles. DO NOT use that.
       * TODO: This class should really be in an abstract super class
       * to avoid code duplication across this project.
       * @param message
       * @param baseval
       * @param checkval
       */
      public static void assertEquals(String message, double baseval, double checkval, double almostZero, double diffToleranceFactor) {
          double posZero = Math.abs(almostZero);
          double negZero = -1 * posZero;
          if (Double.isNaN(baseval)) {
              assertTrue(message+": Expected " + baseval + " but was " + checkval
                      , Double.isNaN(baseval));
          }
          else if (Double.isInfinite(baseval)) {
              assertTrue(message+": Expected " + baseval + " but was " + checkval
                      , Double.isInfinite(baseval) && ((baseval<0) == (checkval<0)));
          }
          else {
              assertTrue(message+": Expected " + baseval + " but was " + checkval
                  ,baseval != 0
                      ? Math.abs(baseval - checkval) <= Math.abs(diffToleranceFactor * baseval)
                      : checkval < posZero && checkval > negZero);
          }
      }
  
      public static void assertEquals(String msg, double baseval, double checkval) {
          assertEquals(msg, baseval, checkval, POS_ZERO, DIFF_TOLERANCE_FACTOR);
      }
  
  }
  
  
  
  1.1                  jakarta-poi/src/scratchpad/testcases/org/apache/poi/hssf/record/formula/functions/TestFinanceLib.java
  
  Index: TestFinanceLib.java
  ===================================================================
  /*
   * Created on May 23, 2005
   *
   */
  package org.apache.poi.hssf.record.formula.functions;
  
  
  /**
   * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
   *
   */
  public class TestFinanceLib extends AbstractNumericTestCase {
  
      public void testFv() {
          double f, r, y, p, x;
          int n;
          boolean t = false;
          
          r = 1; n = 10; y = 100; p = 10000; t = false;
          f = FinanceLib.fv(r, n, y, p, t);
          x = -10342300;
          assertEquals("fv ", x, f);
          
          r = 1; n = 10; y = 100; p = 10000; t = true;
          f = FinanceLib.fv(r, n, y, p, t);
          x = -10444600;
          assertEquals("fv ", x, f);
          
          r = 2; n = 12; y = 120; p = 12000; t = false;
          f = FinanceLib.fv(r, n, y, p, t);
          x = -6409178400d;
          assertEquals("fv ", x, f);
          
          r = 2; n = 12; y = 120; p = 12000; t = true;
          f = FinanceLib.fv(r, n, y, p, t);
          x = -6472951200d;
          assertEquals("fv ", x, f);
          
          // cross tests with pv
          r = 2.95; n = 13; y = 13000; p = -4406.78544294496; t = false;
          f = FinanceLib.fv(r, n, y, p, t);
          x = 333891.230010986; // as returned by excel
          assertEquals("fv ", x, f);
          
          r = 2.95; n = 13; y = 13000; p = -17406.7852148156; t = true;
          f = FinanceLib.fv(r, n, y, p, t);
          x = 333891.230102539; // as returned by excel
          assertEquals("fv ", x, f);
          
      }
      public void testNpv() {
          double r, v[], npv, x;
          
          r = 1; v = new double[]{100, 200, 300, 400};
          npv = FinanceLib.npv(r, v);
          x = 162.5;
          assertEquals("npv ", x, npv);
          
          r = 2.5; v = new double[]{1000, 666.66666, 333.33, 12.2768416};
          npv = FinanceLib.npv(r, v);
          x = 347.99232604144827;
          assertEquals("npv ", x, npv);
          
          r = 12.33333; v = new double[]{1000, 0, -900, -7777.5765};
          npv = FinanceLib.npv(r, v);
          x = 74.3742433377061;
          assertEquals("npv ", x, npv);
          
          r = 0.05; v = new double[]{200000, 300000.55, 400000, 1000000, 6000000, 7000000, -300000};
          npv = FinanceLib.npv(r, v);
          x = 11342283.4233124;
          assertEquals("npv ", x, npv);
      }
      public void testPmt() {
          double f, r, y, p, x;
          int n;
          boolean t = false;
          
          // cross check with pv
          r = 1; n = 10; p = -109.66796875; f = 10000; t = false;
          y = FinanceLib.pmt(r, n, p, f, t);
          x = 100;
          assertEquals("pmt ", x, y);    
          
          r = 1; n = 10; p = -209.5703125; f = 10000; t = true;
          y = FinanceLib.pmt(r, n, p, f, t);
          x = 100;
          assertEquals("pmt ", x, y);
          
          // cross check with fv
          r = 2; n = 12; f = -6409178400d; p = 12000; t = false;
          y = FinanceLib.pmt(r, n, p, f, t);
          x = 120;
          assertEquals("pmt ", x, y);    
          
          r = 2; n = 12; f = -6472951200d; p = 12000; t = true;
          y = FinanceLib.pmt(r, n, p, f, t);
          x = 120;
          assertEquals("pmt ", x, y);
      }
      
      public void testPv() {
          double f, r, y, p, x;
          int n;
          boolean t = false;
          
          r = 1; n = 10; y = 100; f = 10000; t = false;
          p = FinanceLib.pv(r, n, y, f, t);
          x = -109.66796875;
          assertEquals("pv ", x, p);    
          
          r = 1; n = 10; y = 100; f = 10000; t = true;
          p = FinanceLib.pv(r, n, y, f, t);
          x = -209.5703125;
          assertEquals("pv ", x, p);    
          
          r = 2.95; n = 13; y = 13000; f = 333891.23; t = false;
          p = FinanceLib.pv(r, n, y, f, t);
          x = -4406.78544294496;
          assertEquals("pv ", x, p);
          
          r = 2.95; n = 13; y = 13000; f = 333891.23; t = true;
          p = FinanceLib.pv(r, n, y, f, t);
          x = -17406.7852148156;
          assertEquals("pv ", x, p);
          
          // cross tests with fv
          r = 2; n = 12; y = 120; f = -6409178400d; t = false;
          p = FinanceLib.pv(r, n, y, f, t);
          x = 12000;
          assertEquals("pv ", x, p);
          
          r = 2; n = 12; y = 120; f = -6472951200d; t = true;
          p = FinanceLib.pv(r, n, y, f, t);
          x = 12000; 
          assertEquals("pv ", x, p);
          
      }
      
      public void testNper() {
          double f, r, y, p, x;
          int n;
          boolean t = false;
          
          // cross check with pv
          r = 1; y = 100; p = -109.66796875; f = 10000; t = false;
          n = FinanceLib.nper(r, y, p, f, t);
          x = 10;
          assertEquals("nper ", x, n);    
          
          r = 1; y = 100; p = -209.5703125; f = 10000; t = true;
          n = FinanceLib.nper(r, y, p, f, t);
          x = 10;
          assertEquals("nper ", x, n);
          
          // cross check with fv
          r = 2; y = 120; f = -6409178400d; p = 12000; t = false;
          n = FinanceLib.nper(r, y, p, f, t);
          x = 12;
          assertEquals("nper ", x, n);    
          
          r = 2; y = 120; f = -6472951200d; p = 12000; t = true;
          n = FinanceLib.nper(r, y, p, f, t);
          x = 12; 
          assertEquals("nper ", x, n);
      }
  }
  
  
  
  1.1                  jakarta-poi/src/scratchpad/testcases/org/apache/poi/hssf/record/formula/functions/TestMathX.java
  
  Index: TestMathX.java
  ===================================================================
  /*
   * Created on May 23, 2005
   *
   */
  package org.apache.poi.hssf.record.formula.functions;
  
  
  /**
   * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
   *  
   */
  public class TestMathX extends AbstractNumericTestCase {
  
      public void testAcosh() {
          double d = 0;
  
          d = MathX.acosh(0);
          assertTrue("Acosh 0 is NaN", Double.isNaN(d));
  
          d = MathX.acosh(1);
          assertEquals("Acosh 1 ", 0, d);
  
          d = MathX.acosh(-1);
          assertTrue("Acosh -1 is NaN", Double.isNaN(d));
  
          d = MathX.acosh(100);
          assertEquals("Acosh 100 ", 5.298292366d, d);
  
          d = MathX.acosh(101.001);
          assertEquals("Acosh 101.001 ", 5.308253091d, d);
  
          d = MathX.acosh(200000);
          assertEquals("Acosh 200000 ", 12.89921983d, d);
  
      }
  
      public void testAsinh() {
          double d = 0;
  
          d = MathX.asinh(0);
          assertEquals("asinh 0", d, 0);
  
          d = MathX.asinh(1);
          assertEquals("asinh 1 ", 0.881373587, d);
  
          d = MathX.asinh(-1);
          assertEquals("asinh -1 ", -0.881373587, d);
  
          d = MathX.asinh(-100);
          assertEquals("asinh -100 ", -5.298342366, d);
  
          d = MathX.asinh(100);
          assertEquals("asinh 100 ", 5.298342366, d);
  
          d = MathX.asinh(200000);
          assertEquals("asinh 200000", 12.899219826096400, d);
  
          d = MathX.asinh(-200000);
          assertEquals("asinh -200000 ", -12.899223853137, d);
  
      }
  
      public void testAtanh() {
          double d = 0;
          d = MathX.atanh(0);
          assertEquals("atanh 0", d, 0);
  
          d = MathX.atanh(1);
          assertEquals("atanh 1 ", Double.POSITIVE_INFINITY, d);
  
          d = MathX.atanh(-1);
          assertEquals("atanh -1 ", Double.NEGATIVE_INFINITY, d);
  
          d = MathX.atanh(-100);
          assertEquals("atanh -100 ", Double.NaN, d);
  
          d = MathX.atanh(100);
          assertEquals("atanh 100 ", Double.NaN, d);
  
          d = MathX.atanh(200000);
          assertEquals("atanh 200000", Double.NaN, d);
  
          d = MathX.atanh(-200000);
          assertEquals("atanh -200000 ", Double.NaN, d);
  
          d = MathX.atanh(0.1);
          assertEquals("atanh 0.1", 0.100335348, d);
  
          d = MathX.atanh(-0.1);
          assertEquals("atanh -0.1 ", -0.100335348, d);
  
      }
  
      public void testCosh() {
          double d = 0;
          d = MathX.cosh(0);
          assertEquals("cosh 0", 1, d);
  
          d = MathX.cosh(1);
          assertEquals("cosh 1 ", 1.543080635, d);
  
          d = MathX.cosh(-1);
          assertEquals("cosh -1 ", 1.543080635, d);
  
          d = MathX.cosh(-100);
          assertEquals("cosh -100 ", 1.344058570908070E+43, d);
  
          d = MathX.cosh(100);
          assertEquals("cosh 100 ", 1.344058570908070E+43, d);
  
          d = MathX.cosh(15);
          assertEquals("cosh 15", 1634508.686, d);
  
          d = MathX.cosh(-15);
          assertEquals("cosh -15 ", 1634508.686, d);
  
          d = MathX.cosh(0.1);
          assertEquals("cosh 0.1", 1.005004168, d);
  
          d = MathX.cosh(-0.1);
          assertEquals("cosh -0.1 ", 1.005004168, d);
  
      }
  
      public void testTanh() {
          double d = 0;
          d = MathX.tanh(0);
          assertEquals("tanh 0", 0, d);
  
          d = MathX.tanh(1);
          assertEquals("tanh 1 ", 0.761594156, d);
  
          d = MathX.tanh(-1);
          assertEquals("tanh -1 ", -0.761594156, d);
  
          d = MathX.tanh(-100);
          assertEquals("tanh -100 ", -1, d);
  
          d = MathX.tanh(100);
          assertEquals("tanh 100 ", 1, d);
  
          d = MathX.tanh(15);
          assertEquals("tanh 15", 1, d);
  
          d = MathX.tanh(-15);
          assertEquals("tanh -15 ", -1, d);
  
          d = MathX.tanh(0.1);
          assertEquals("tanh 0.1", 0.099667995, d);
  
          d = MathX.tanh(-0.1);
          assertEquals("tanh -0.1 ", -0.099667995, d);
  
      }
  
      public void testMax() {
          double[] d = new double[100];
          d[0] = 1.1;     d[1] = 2.1;     d[2] = 3.1;     d[3] = 4.1; 
          d[4] = 5.1;     d[5] = 6.1;     d[6] = 7.1;     d[7] = 8.1;
          d[8] = 9.1;     d[9] = 10.1;    d[10] = 11.1;   d[11] = 12.1;
          d[12] = 13.1;   d[13] = 14.1;   d[14] = 15.1;   d[15] = 16.1;
          d[16] = 17.1;   d[17] = 18.1;   d[18] = 19.1;   d[19] = 20.1; 
          
          double m = MathX.max(d);
          assertEquals("Max ", 20.1, m);
          
          d = new double[1000];
          m = MathX.max(d);
          assertEquals("Max ", 0, m);
          
          d[0] = -1.1;     d[1] = 2.1;     d[2] = -3.1;     d[3] = 4.1; 
          d[4] = -5.1;     d[5] = 6.1;     d[6] = -7.1;     d[7] = 8.1;
          d[8] = -9.1;     d[9] = 10.1;    d[10] = -11.1;   d[11] = 12.1;
          d[12] = -13.1;   d[13] = 14.1;   d[14] = -15.1;   d[15] = 16.1;
          d[16] = -17.1;   d[17] = 18.1;   d[18] = -19.1;   d[19] = 20.1; 
          m = MathX.max(d);
          assertEquals("Max ", 20.1, m);
          
          d = new double[20];
          d[0] = -1.1;     d[1] = -2.1;     d[2] = -3.1;     d[3] = -4.1; 
          d[4] = -5.1;     d[5] = -6.1;     d[6] = -7.1;     d[7] = -8.1;
          d[8] = -9.1;     d[9] = -10.1;    d[10] = -11.1;   d[11] = -12.1;
          d[12] = -13.1;   d[13] = -14.1;   d[14] = -15.1;   d[15] = -16.1;
          d[16] = -17.1;   d[17] = -18.1;   d[18] = -19.1;   d[19] = -20.1; 
          m = MathX.max(d);
          assertEquals("Max ", -1.1, m);
          
      }
  
      public void testMin() {
          double[] d = new double[100];
          d[0] = 1.1;     d[1] = 2.1;     d[2] = 3.1;     d[3] = 4.1; 
          d[4] = 5.1;     d[5] = 6.1;     d[6] = 7.1;     d[7] = 8.1;
          d[8] = 9.1;     d[9] = 10.1;    d[10] = 11.1;   d[11] = 12.1;
          d[12] = 13.1;   d[13] = 14.1;   d[14] = 15.1;   d[15] = 16.1;
          d[16] = 17.1;   d[17] = 18.1;   d[18] = 19.1;   d[19] = 20.1; 
          
          double m = MathX.min(d);
          assertEquals("Min ", 0, m);
          
          d = new double[20];
          d[0] = 1.1;     d[1] = 2.1;     d[2] = 3.1;     d[3] = 4.1; 
          d[4] = 5.1;     d[5] = 6.1;     d[6] = 7.1;     d[7] = 8.1;
          d[8] = 9.1;     d[9] = 10.1;    d[10] = 11.1;   d[11] = 12.1;
          d[12] = 13.1;   d[13] = 14.1;   d[14] = 15.1;   d[15] = 16.1;
          d[16] = 17.1;   d[17] = 18.1;   d[18] = 19.1;   d[19] = 20.1; 
          
          m = MathX.min(d);
          assertEquals("Min ", 1.1, m);
          
          d = new double[1000];
          m = MathX.min(d);
          assertEquals("Min ", 0, m);
          
          d[0] = -1.1;     d[1] = 2.1;     d[2] = -3.1;     d[3] = 4.1; 
          d[4] = -5.1;     d[5] = 6.1;     d[6] = -7.1;     d[7] = 8.1;
          d[8] = -9.1;     d[9] = 10.1;    d[10] = -11.1;   d[11] = 12.1;
          d[12] = -13.1;   d[13] = 14.1;   d[14] = -15.1;   d[15] = 16.1;
          d[16] = -17.1;   d[17] = 18.1;   d[18] = -19.1;   d[19] = 20.1; 
          m = MathX.min(d);
          assertEquals("Min ", -19.1, m);
          
          d = new double[20];
          d[0] = -1.1;     d[1] = -2.1;     d[2] = -3.1;     d[3] = -4.1; 
          d[4] = -5.1;     d[5] = -6.1;     d[6] = -7.1;     d[7] = -8.1;
          d[8] = -9.1;     d[9] = -10.1;    d[10] = -11.1;   d[11] = -12.1;
          d[12] = -13.1;   d[13] = -14.1;   d[14] = -15.1;   d[15] = -16.1;
          d[16] = -17.1;   d[17] = -18.1;   d[18] = -19.1;   d[19] = -20.1; 
          m = MathX.min(d);
          assertEquals("Min ", -20.1, m);
      }
  
      public void testProduct() {
          double[] d = new double[100];
          d[0] = 1.1;     d[1] = 2.1;     d[2] = 3.1;     d[3] = 4.1; 
          d[4] = 5.1;     d[5] = 6.1;     d[6] = 7.1;     d[7] = 8.1;
          d[8] = 9.1;     d[9] = 10.1;    d[10] = 11.1;   d[11] = 12.1;
          d[12] = 13.1;   d[13] = 14.1;   d[14] = 15.1;   d[15] = 16.1;
          d[16] = 17.1;   d[17] = 18.1;   d[18] = 19.1;   d[19] = 20.1; 
          
          double m = MathX.min(d);
          assertEquals("Min ", 0, m);
          
          d = new double[20];
          d[0] = 1.1;     d[1] = 2.1;     d[2] = 3.1;     d[3] = 4.1; 
          d[4] = 5.1;     d[5] = 6.1;     d[6] = 7.1;     d[7] = 8.1;
          d[8] = 9.1;     d[9] = 10.1;    d[10] = 11.1;   d[11] = 12.1;
          d[12] = 13.1;   d[13] = 14.1;   d[14] = 15.1;   d[15] = 16.1;
          d[16] = 17.1;   d[17] = 18.1;   d[18] = 19.1;   d[19] = 20.1; 
          
          m = MathX.min(d);
          assertEquals("Min ", 1.1, m);
          
          d = new double[1000];
          m = MathX.min(d);
          assertEquals("Min ", 0, m);
          
          d[0] = -1.1;     d[1] = 2.1;     d[2] = -3.1;     d[3] = 4.1; 
          d[4] = -5.1;     d[5] = 6.1;     d[6] = -7.1;     d[7] = 8.1;
          d[8] = -9.1;     d[9] = 10.1;    d[10] = -11.1;   d[11] = 12.1;
          d[12] = -13.1;   d[13] = 14.1;   d[14] = -15.1;   d[15] = 16.1;
          d[16] = -17.1;   d[17] = 18.1;   d[18] = -19.1;   d[19] = 20.1; 
          m = MathX.min(d);
          assertEquals("Min ", -19.1, m);
          
          d = new double[20];
          d[0] = -1.1;     d[1] = -2.1;     d[2] = -3.1;     d[3] = -4.1; 
          d[4] = -5.1;     d[5] = -6.1;     d[6] = -7.1;     d[7] = -8.1;
          d[8] = -9.1;     d[9] = -10.1;    d[10] = -11.1;   d[11] = -12.1;
          d[12] = -13.1;   d[13] = -14.1;   d[14] = -15.1;   d[15] = -16.1;
          d[16] = -17.1;   d[17] = -18.1;   d[18] = -19.1;   d[19] = -20.1; 
          m = MathX.min(d);
          assertEquals("Min ", -20.1, m);
      }
  
      public void testMod() {
      }
  
      public void testNChooseK() {
          int n=100;
          int k=50;
          double d = MathX.nChooseK(n, k);
          assertEquals("NChooseK ", 1.00891344545564E29, d);
          
          n = -1; k = 1;
          d = MathX.nChooseK(n, k);
          assertEquals("NChooseK ", Double.NaN, d);
          
          n = 1; k = -1;
          d = MathX.nChooseK(n, k);
          assertEquals("NChooseK ", Double.NaN, d);
          
          n = 0; k = 1;
          d = MathX.nChooseK(n, k);
          assertEquals("NChooseK ", Double.NaN, d);
          
          n = 1; k = 0;
          d = MathX.nChooseK(n, k);
          assertEquals("NChooseK ", 1, d);
          
          n = 10; k = 9;
          d = MathX.nChooseK(n, k);
          assertEquals("NChooseK ", 10, d);
          
          n = 10; k = 10;
          d = MathX.nChooseK(n, k);
          assertEquals("NChooseK ", 1, d);
          
          n = 10; k = 1;
          d = MathX.nChooseK(n, k);
          assertEquals("NChooseK ", 10, d);
          
          n = 1000; k = 1;
          d = MathX.nChooseK(n, k);
          assertEquals("NChooseK ", 1000, d); // awesome ;)
          
          n = 1000; k = 2;
          d = MathX.nChooseK(n, k);
          assertEquals("NChooseK ", 499500, d); // awesome ;)
          
          n = 13; k = 7;
          d = MathX.nChooseK(n, k);
          assertEquals("NChooseK ", 1716, d);
          
      }
  
      public void testSign() {
          final short minus = -1;
          final short zero = 0;
          final short plus = 1;
          double d = 0;
          
          
          assertEquals("Sign ", minus, MathX.sign(minus));
          assertEquals("Sign ", plus, MathX.sign(plus));
          assertEquals("Sign ", zero, MathX.sign(zero));
          
          d = 0;
          assertEquals("Sign ", zero, MathX.sign(d));
          
          d = -1.000001;
          assertEquals("Sign ", minus, MathX.sign(d));
          
          d = -.000001;
          assertEquals("Sign ", minus, MathX.sign(d));
          
          d = -1E-200;
          assertEquals("Sign ", minus, MathX.sign(d));
          
          d = Double.NEGATIVE_INFINITY;
          assertEquals("Sign ", minus, MathX.sign(d));
          
          d = -200.11;
          assertEquals("Sign ", minus, MathX.sign(d));
          
          d = -2000000000000.11;
          assertEquals("Sign ", minus, MathX.sign(d));
          
          d = 1.000001;
          assertEquals("Sign ", plus, MathX.sign(d));
          
          d = .000001;
          assertEquals("Sign ", plus, MathX.sign(d));
          
          d = 1E-200;
          assertEquals("Sign ", plus, MathX.sign(d));
          
          d = Double.POSITIVE_INFINITY;
          assertEquals("Sign ", plus, MathX.sign(d));
          
          d = 200.11;
          assertEquals("Sign ", plus, MathX.sign(d));
          
          d = 2000000000000.11;
          assertEquals("Sign ", plus, MathX.sign(d));
          
      }
  
      public void testSinh() {
          double d = 0;
          d = MathX.sinh(0);
          assertEquals("sinh 0", 0, d);
  
          d = MathX.sinh(1);
          assertEquals("sinh 1 ", 1.175201194, d);
  
          d = MathX.sinh(-1);
          assertEquals("sinh -1 ", -1.175201194, d);
  
          d = MathX.sinh(-100);
          assertEquals("sinh -100 ", -1.344058570908070E+43, d);
  
          d = MathX.sinh(100);
          assertEquals("sinh 100 ", 1.344058570908070E+43, d);
  
          d = MathX.sinh(15);
          assertEquals("sinh 15", 1634508.686, d);
  
          d = MathX.sinh(-15);
          assertEquals("sinh -15 ", -1634508.686, d);
  
          d = MathX.sinh(0.1);
          assertEquals("sinh 0.1", 0.10016675, d);
  
          d = MathX.sinh(-0.1);
          assertEquals("sinh -0.1 ", -0.10016675, d);
  
      }
  
      public void testSum() {
          double[] d = new double[100];
          d[0] = 1.1;     d[1] = 2.1;     d[2] = 3.1;     d[3] = 4.1; 
          d[4] = 5.1;     d[5] = 6.1;     d[6] = 7.1;     d[7] = 8.1;
          d[8] = 9.1;     d[9] = 10.1;    d[10] = 11.1;   d[11] = 12.1;
          d[12] = 13.1;   d[13] = 14.1;   d[14] = 15.1;   d[15] = 16.1;
          d[16] = 17.1;   d[17] = 18.1;   d[18] = 19.1;   d[19] = 20.1; 
          
          double s = MathX.sum(d);
          assertEquals("Sum ", 212, s);
          
          d = new double[1000];
          s = MathX.sum(d);
          assertEquals("Sum ", 0, s);
          
          d[0] = -1.1;     d[1] = 2.1;     d[2] = -3.1;     d[3] = 4.1; 
          d[4] = -5.1;     d[5] = 6.1;     d[6] = -7.1;     d[7] = 8.1;
          d[8] = -9.1;     d[9] = 10.1;    d[10] = -11.1;   d[11] = 12.1;
          d[12] = -13.1;   d[13] = 14.1;   d[14] = -15.1;   d[15] = 16.1;
          d[16] = -17.1;   d[17] = 18.1;   d[18] = -19.1;   d[19] = 20.1; 
          s = MathX.sum(d);
          assertEquals("Sum ", 10, s);
          
          d[0] = -1.1;     d[1] = -2.1;     d[2] = -3.1;     d[3] = -4.1; 
          d[4] = -5.1;     d[5] = -6.1;     d[6] = -7.1;     d[7] = -8.1;
          d[8] = -9.1;     d[9] = -10.1;    d[10] = -11.1;   d[11] = -12.1;
          d[12] = -13.1;   d[13] = -14.1;   d[14] = -15.1;   d[15] = -16.1;
          d[16] = -17.1;   d[17] = -18.1;   d[18] = -19.1;   d[19] = -20.1; 
          s = MathX.sum(d);
          assertEquals("Sum ", -212, s);
          
      }
  
      public void testSumproduct() {
          double d = 0;
          double[][] darr = new double[][]
                 {{0   ,0.11   ,23.23},
                  {1  ,0.22   ,46.46},
                  {2  ,0.33   ,69.69},
                  {3  ,0.44   ,92.92},
                  {4  ,0.55   ,116.15},
                  {5  ,0.66   ,139.38},
                  {6  ,0.77   ,162.61},
                  {7  ,0.88   ,185.84},
                  {8  ,0.99   ,209.07},
                  {9  ,1.1    ,232.3},
                  {10 ,1.21   ,255.53}};
          d = MathX.sumproduct(darr);
          assertEquals("Sumproduct ", 4.243234425E+22, d);
          darr = new double[][]
                 {{0  ,0.11   ,23.23},
                  {0  ,0.22   ,46.46},
                  {0  ,0.33   ,69.69},
                  {0  ,0.44   ,92.92},
                  {0  ,0.55   ,116.15},
                  {0  ,0.66   ,139.38},
                  {0  ,0.77   ,162.61},
                  {0  ,0.88   ,185.84},
                  {0  ,0.99   ,209.07},
                  {0  ,1.1    ,232.3},
                  {0  ,1.21   ,255.53}};
          d = MathX.sumproduct(darr);
          assertEquals("Sumproduct ", 4.243234425E+22, d);
          
          darr = new double[][]
                 {{0, 0, 0, 0, 0, 0, 0, 0},
                  {0.11, 0.22, 0.33, 0.44, 0.55, 0.66, 0.77, 0.88},
                  {23.23, 46.46, 69.69, 92.92, 116.15, 139.38, 162.61, 185.84}};
          d = MathX.sumproduct(darr);
          assertEquals("Sumproduct ", 0, d);
  
          darr = new double[][]
                 {{0, 1, 2, 3, 4, 5, 6, 7},
                  {0.11, 0.22, 0.33, 0.44, 0.55, 0.66, 0.77, 0.88},
                  {23.23, 46.46, 69.69, 92.92, 116.15, 139.38, 162.61, 185.84}};
          d = MathX.sumproduct(darr);
          assertEquals("Sumproduct ", 2790.3876, d);
  
          
      }
  
      public void testSumsq() {
          double[] d = new double[100];
          d[0] = 1.1;     d[1] = 2.1;     d[2] = 3.1;     d[3] = 4.1; 
          d[4] = 5.1;     d[5] = 6.1;     d[6] = 7.1;     d[7] = 8.1;
          d[8] = 9.1;     d[9] = 10.1;    d[10] = 11.1;   d[11] = 12.1;
          d[12] = 13.1;   d[13] = 14.1;   d[14] = 15.1;   d[15] = 16.1;
          d[16] = 17.1;   d[17] = 18.1;   d[18] = 19.1;   d[19] = 20.1; 
          
          double s = MathX.sumsq(d);
          assertEquals("Sumsq ", 2912.2, s);
          
          d = new double[1000];
          s = MathX.sumsq(d);
          assertEquals("Sumsq ", 0, s);
          
          d[0] = -1.1;     d[1] = 2.1;     d[2] = -3.1;     d[3] = 4.1; 
          d[4] = -5.1;     d[5] = 6.1;     d[6] = -7.1;     d[7] = 8.1;
          d[8] = -9.1;     d[9] = 10.1;    d[10] = -11.1;   d[11] = 12.1;
          d[12] = -13.1;   d[13] = 14.1;   d[14] = -15.1;   d[15] = 16.1;
          d[16] = -17.1;   d[17] = 18.1;   d[18] = -19.1;   d[19] = 20.1; 
          s = MathX.sumsq(d);
          assertEquals("Sumsq ", 2912.2, s);
          
          d[0] = -1.1;     d[1] = -2.1;     d[2] = -3.1;     d[3] = -4.1; 
          d[4] = -5.1;     d[5] = -6.1;     d[6] = -7.1;     d[7] = -8.1;
          d[8] = -9.1;     d[9] = -10.1;    d[10] = -11.1;   d[11] = -12.1;
          d[12] = -13.1;   d[13] = -14.1;   d[14] = -15.1;   d[15] = -16.1;
          d[16] = -17.1;   d[17] = -18.1;   d[18] = -19.1;   d[19] = -20.1; 
          s = MathX.sumsq(d);
          assertEquals("Sumsq ", 2912.2, s);
      }
  
      public void testFactorial() {
          int n = 0;
          double s = 0;
          
          n = 0;
          s = MathX.factorial(n);
          assertEquals("Factorial ", 1, s);
          
          n = 1;
          s = MathX.factorial(n);
          assertEquals("Factorial ", 1, s);
          
          n = 10;
          s = MathX.factorial(n);
          assertEquals("Factorial ", 3628800, s);
          
          n = 99;
          s = MathX.factorial(n);
          assertEquals("Factorial ", 9.33262154439E+155, s);
          
          n = -1;
          s = MathX.factorial(n);
          assertEquals("Factorial ", Double.NaN, s);
          
          n = Integer.MAX_VALUE;
          s = MathX.factorial(n);
          assertEquals("Factorial ", Double.POSITIVE_INFINITY, s);
      }
  
      public void testSumx2my2() {
          double d = 0;
          double[] xarr = null;
          double[] yarr = null;
          
          xarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
          yarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
          d = MathX.sumx2my2(xarr, yarr);
          assertEquals("sumx2my2 ", 100, d);
          
          xarr = new double[]{-1, -2, -3, -4, -5, -6, -7, -8, -9, -10};
          yarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
          d = MathX.sumx2my2(xarr, yarr);
          assertEquals("sumx2my2 ", 100, d);
          
          xarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
          yarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
          d = MathX.sumx2my2(xarr, yarr);
          assertEquals("sumx2my2 ", -100, d);
          
          xarr = new double[]{10};
          yarr = new double[]{9};
          d = MathX.sumx2my2(xarr, yarr);
          assertEquals("sumx2my2 ", 19, d);
          
          xarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
          yarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
          d = MathX.sumx2my2(xarr, yarr);
          assertEquals("sumx2my2 ", 0, d);
          
      }
  
      public void testSumx2py2() {
          double d = 0;
          double[] xarr = null;
          double[] yarr = null;
          
          xarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
          yarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
          d = MathX.sumx2py2(xarr, yarr);
          assertEquals("sumx2py2 ", 670, d);
          
          xarr = new double[]{-1, -2, -3, -4, -5, -6, -7, -8, -9, -10};
          yarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
          d = MathX.sumx2py2(xarr, yarr);
          assertEquals("sumx2py2 ", 670, d);
          
          xarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
          yarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
          d = MathX.sumx2py2(xarr, yarr);
          assertEquals("sumx2py2 ", 670, d);
          
          xarr = new double[]{10};
          yarr = new double[]{9};
          d = MathX.sumx2py2(xarr, yarr);
          assertEquals("sumx2py2 ", 181, d);
          
          xarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
          yarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
          d = MathX.sumx2py2(xarr, yarr);
          assertEquals("sumx2py2 ", 770, d);
      }
  
      public void testSumxmy2() {
          double d = 0;
          double[] xarr = null;
          double[] yarr = null;
          
          xarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
          yarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
          d = MathX.sumxmy2(xarr, yarr);
          assertEquals("sumxmy2 ", 10, d);
          
          xarr = new double[]{-1, -2, -3, -4, -5, -6, -7, -8, -9, -10};
          yarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
          d = MathX.sumxmy2(xarr, yarr);
          assertEquals("sumxmy2 ", 1330, d);
          
          xarr = new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
          yarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
          d = MathX.sumxmy2(xarr, yarr);
          assertEquals("sumxmy2 ", 10, d);
          
          xarr = new double[]{10};
          yarr = new double[]{9};
          d = MathX.sumxmy2(xarr, yarr);
          assertEquals("sumxmy2 ", 1, d);
          
          xarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
          yarr = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
          d = MathX.sumxmy2(xarr, yarr);
          assertEquals("sumxmy2 ", 0, d);
      }
  
      public void testRound() {
          double d = 0;
          int p = 0;
          
          d = 0; p = 0;
          assertEquals("round ", 0, MathX.round(d, p));
          
          d = 10; p = 0;
          assertEquals("round ", 10, MathX.round(d, p));
          
          d = 123.23; p = 0;
          assertEquals("round ", 123, MathX.round(d, p));
          
          d = -123.23; p = 0;
          assertEquals("round ", -123, MathX.round(d, p));
          
          d = 123.12; p = 2;
          assertEquals("round ", 123.12, MathX.round(d, p));
          
          d = 88.123459; p = 5;
          assertEquals("round ", 88.12346, MathX.round(d, p));
          
          d = 0; p = 2;
          assertEquals("round ", 0, MathX.round(d, p));
          
          d = 0; p = -1;
          assertEquals("round ", 0, MathX.round(d, p));
          
          d = 0.01; p = -1;
          assertEquals("round ", 0, MathX.round(d, p));
  
          d = 123.12; p = -2;
          assertEquals("round ", 100, MathX.round(d, p));
          
          d = 88.123459; p = -3;
          assertEquals("round ", 0, MathX.round(d, p));
          
          d = 49.00000001; p = -1;
          assertEquals("round ", 50, MathX.round(d, p));
          
          d = 149.999999; p = -2;
          assertEquals("round ", 100, MathX.round(d, p));
          
          d = 150.0; p = -2;
          assertEquals("round ", 200, MathX.round(d, p));
      }
  
      public void testRoundDown() {
          double d = 0;
          int p = 0;
          
          d = 0; p = 0;
          assertEquals("roundDown ", 0, MathX.roundDown(d, p));
          
          d = 10; p = 0;
          assertEquals("roundDown ", 10, MathX.roundDown(d, p));
          
          d = 123.99; p = 0;
          assertEquals("roundDown ", 123, MathX.roundDown(d, p));
          
          d = -123.99; p = 0;
          assertEquals("roundDown ", -123, MathX.roundDown(d, p));
          
          d = 123.99; p = 2;
          assertEquals("roundDown ", 123.99, MathX.roundDown(d, p));
          
          d = 88.123459; p = 5;
          assertEquals("roundDown ", 88.12345, MathX.roundDown(d, p));
          
          d = 0; p = 2;
          assertEquals("roundDown ", 0, MathX.roundDown(d, p));
          
          d = 0; p = -1;
          assertEquals("roundDown ", 0, MathX.roundDown(d, p));
          
          d = 0.01; p = -1;
          assertEquals("roundDown ", 0, MathX.roundDown(d, p));
  
          d = 199.12; p = -2;
          assertEquals("roundDown ", 100, MathX.roundDown(d, p));
          
          d = 88.123459; p = -3;
          assertEquals("roundDown ", 0, MathX.roundDown(d, p));
          
          d = 99.00000001; p = -1;
          assertEquals("roundDown ", 90, MathX.roundDown(d, p));
          
          d = 100.00001; p = -2;
          assertEquals("roundDown ", 100, MathX.roundDown(d, p));
          
          d = 150.0; p = -2;
          assertEquals("roundDown ", 100, MathX.roundDown(d, p));
      }
  
      public void testRoundUp() {
          double d = 0;
          int p = 0;
          
          d = 0; p = 0;
          assertEquals("roundUp ", 0, MathX.roundUp(d, p));
          
          d = 10; p = 0;
          assertEquals("roundUp ", 10, MathX.roundUp(d, p));
          
          d = 123.23; p = 0;
          assertEquals("roundUp ", 124, MathX.roundUp(d, p));
          
          d = -123.23; p = 0;
          assertEquals("roundUp ", -124, MathX.roundUp(d, p));
          
          d = 123.12; p = 2;
          assertEquals("roundUp ", 123.12, MathX.roundUp(d, p));
          
          d = 88.123459; p = 5;
          assertEquals("roundUp ", 88.12346, MathX.roundUp(d, p));
          
          d = 0; p = 2;
          assertEquals("roundUp ", 0, MathX.roundUp(d, p));
          
          d = 0; p = -1;
          assertEquals("roundUp ", 0, MathX.roundUp(d, p));
          
          d = 0.01; p = -1;
          assertEquals("roundUp ", 10, MathX.roundUp(d, p));
  
          d = 123.12; p = -2;
          assertEquals("roundUp ", 200, MathX.roundUp(d, p));
          
          d = 88.123459; p = -3;
          assertEquals("roundUp ", 1000, MathX.roundUp(d, p));
          
          d = 49.00000001; p = -1;
          assertEquals("roundUp ", 50, MathX.roundUp(d, p));
          
          d = 149.999999; p = -2;
          assertEquals("roundUp ", 200, MathX.roundUp(d, p));
          
          d = 150.0; p = -2;
          assertEquals("roundUp ", 200, MathX.roundUp(d, p));
      }
  
      public void testCeiling() {
          double d = 0;
          double s = 0;
          
          d = 0; s = 0;
          assertEquals("ceiling ", 0, MathX.ceiling(d, s));
          
          d = 1; s = 0;
          assertEquals("ceiling ", 0, MathX.ceiling(d, s));
          
          d = 0; s = 1;
          assertEquals("ceiling ", 0, MathX.ceiling(d, s));
          
          d = -1; s = 0;
          assertEquals("ceiling ", 0, MathX.ceiling(d, s));
          
          d = 0; s = -1;
          assertEquals("ceiling ", 0, MathX.ceiling(d, s));
          
          d = 10; s = 1.11;
          assertEquals("ceiling ", 11.1, MathX.ceiling(d, s));
          
          d = 11.12333; s = 0.03499;
          assertEquals("ceiling ", 11.12682, MathX.ceiling(d, s));
          
          d = -11.12333; s = 0.03499;
          assertEquals("ceiling ", Double.NaN, MathX.ceiling(d, s));
          
          d = 11.12333; s = -0.03499;
          assertEquals("ceiling ", Double.NaN, MathX.ceiling(d, s));
          
          d = -11.12333; s = -0.03499;
          assertEquals("ceiling ", -11.12682, MathX.ceiling(d, s));
          
          d = 100; s = 0.001;
          assertEquals("ceiling ", 100, MathX.ceiling(d, s));
          
          d = -0.001; s = -9.99;
          assertEquals("ceiling ", -9.99, MathX.ceiling(d, s));
          
          d = 4.42; s = 0.05;
          assertEquals("ceiling ", 4.45, MathX.ceiling(d, s));
          
          d = 0.05; s = 4.42;
          assertEquals("ceiling ", 4.42, MathX.ceiling(d, s));
          
          d = 0.6666; s = 3.33;
          assertEquals("ceiling ", 3.33, MathX.ceiling(d, s));
          
          d = 2d/3; s = 3.33;
          assertEquals("ceiling ", 3.33, MathX.ceiling(d, s));
      }
  
      public void testFloor() {
          double d = 0;
          double s = 0;
          
          d = 0; s = 0;
          assertEquals("floor ", 0, MathX.floor(d, s));
          
          d = 1; s = 0;
          assertEquals("floor ", Double.NaN, MathX.floor(d, s));
          
          d = 0; s = 1;
          assertEquals("floor ", 0, MathX.floor(d, s));
          
          d = -1; s = 0;
          assertEquals("floor ", Double.NaN, MathX.floor(d, s));
          
          d = 0; s = -1;
          assertEquals("floor ", 0, MathX.floor(d, s));
          
          d = 10; s = 1.11;
          assertEquals("floor ", 9.99, MathX.floor(d, s));
          
          d = 11.12333; s = 0.03499;
          assertEquals("floor ", 11.09183, MathX.floor(d, s));
          
          d = -11.12333; s = 0.03499;
          assertEquals("floor ", Double.NaN, MathX.floor(d, s));
          
          d = 11.12333; s = -0.03499;
          assertEquals("floor ", Double.NaN, MathX.floor(d, s));
          
          d = -11.12333; s = -0.03499;
          assertEquals("floor ", -11.09183, MathX.floor(d, s));
          
          d = 100; s = 0.001;
          assertEquals("floor ", 100, MathX.floor(d, s));
          
          d = -0.001; s = -9.99;
          assertEquals("floor ", 0, MathX.floor(d, s));
          
          d = 4.42; s = 0.05;
          assertEquals("floor ", 4.4, MathX.floor(d, s));
          
          d = 0.05; s = 4.42;
          assertEquals("floor ", 0, MathX.floor(d, s));
          
          d = 0.6666; s = 3.33;
          assertEquals("floor ", 0, MathX.floor(d, s));
          
          d = 2d/3; s = 3.33;
          assertEquals("floor ", 0, MathX.floor(d, s));
      }
  
  }
  
  
  
  1.1                  jakarta-poi/src/scratchpad/testcases/org/apache/poi/hssf/record/formula/functions/TestStatsLib.java
  
  Index: TestStatsLib.java
  ===================================================================
  /*
   * Created on May 30, 2005
   *
   */
  package org.apache.poi.hssf.record.formula.functions;
  
  
  /**
   * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
   *
   */
  public class TestStatsLib extends AbstractNumericTestCase {
  
      public void testDevsq() {
          double[] v = null;
          double d, x = 0;
          
          v = new double[] {1,2,3,4,5,6,7,8,9,10};
          d = StatsLib.devsq(v);
          x = 82.5;
          assertEquals("devsq ", x, d);
          
          v = new double[] {1,1,1,1,1,1,1,1,1,1};
          d = StatsLib.devsq(v);
          x = 0;
          assertEquals("devsq ", x, d);
          
          v = new double[] {0,0,0,0,0,0,0,0,0,0};
          d = StatsLib.devsq(v);
          x = 0;
          assertEquals("devsq ", x, d);
          
          v = new double[] {1,2,1,2,1,2,1,2,1,2};
          d = StatsLib.devsq(v);
          x = 2.5;
          assertEquals("devsq ", x, d);
          
          v = new double[] {123.12,33.3333,2d/3d,5.37828,0.999};
          d = StatsLib.devsq(v);
          x = 10953.7416965767;
          assertEquals("devsq ", x, d);
          
          v = new double[] {-1,-2,-3,-4,-5,-6,-7,-8,-9,-10};
          d = StatsLib.devsq(v);
          x = 82.5;
          assertEquals("devsq ", x, d);
      }
  
      public void testKthLargest() {
          double[] v = null;
          double d, x = 0;
          
          v = new double[] {1,2,3,4,5,6,7,8,9,10};
          d = StatsLib.kthLargest(v, 3);
          x = 8;
          assertEquals("kthLargest ", x, d);
          
          v = new double[] {1,1,1,1,1,1,1,1,1,1};
          d = StatsLib.kthLargest(v, 3);
          x = 1;
          assertEquals("kthLargest ", x, d);
          
          v = new double[] {0,0,0,0,0,0,0,0,0,0};
          d = StatsLib.kthLargest(v, 3);
          x = 0;
          assertEquals("kthLargest ", x, d);
          
          v = new double[] {1,2,1,2,1,2,1,2,1,2};
          d = StatsLib.kthLargest(v, 3);
          x = 2;
          assertEquals("kthLargest ", x, d);
          
          v = new double[] {123.12,33.3333,2d/3d,5.37828,0.999};
          d = StatsLib.kthLargest(v, 3);
          x = 5.37828;
          assertEquals("kthLargest ", x, d);
          
          v = new double[] {-1,-2,-3,-4,-5,-6,-7,-8,-9,-10};
          d = StatsLib.kthLargest(v, 3);
          x = -3;
          assertEquals("kthLargest ", x, d);
      }
  
      public void testKthSmallest() {
      }
  
      public void testAvedev() {
          double[] v = null;
          double d, x = 0;
          
          v = new double[] {1,2,3,4,5,6,7,8,9,10};
          d = StatsLib.avedev(v);
          x = 2.5;
          assertEquals("avedev ", x, d);
          
          v = new double[] {1,1,1,1,1,1,1,1,1,1};
          d = StatsLib.avedev(v);
          x = 0;
          assertEquals("avedev ", x, d);
          
          v = new double[] {0,0,0,0,0,0,0,0,0,0};
          d = StatsLib.avedev(v);
          x = 0;
          assertEquals("avedev ", x, d);
          
          v = new double[] {1,2,1,2,1,2,1,2,1,2};
          d = StatsLib.avedev(v);
          x = 0.5;
          assertEquals("avedev ", x, d);
          
          v = new double[] {123.12,33.3333,2d/3d,5.37828,0.999};
          d = StatsLib.avedev(v);
          x = 36.42176053333;
          assertEquals("avedev ", x, d);
          
          v = new double[] {-1,-2,-3,-4,-5,-6,-7,-8,-9,-10};
          d = StatsLib.avedev(v);
          x = 2.5;
          assertEquals("avedev ", x, d);
      }
  
      public void testMedian() {
          double[] v = null;
          double d, x = 0;
          
          v = new double[] {1,2,3,4,5,6,7,8,9,10};
          d = StatsLib.median(v);
          x = 5.5;
          assertEquals("median ", x, d);
          
          v = new double[] {1,1,1,1,1,1,1,1,1,1};
          d = StatsLib.median(v);
          x = 1;
          assertEquals("median ", x, d);
          
          v = new double[] {0,0,0,0,0,0,0,0,0,0};
          d = StatsLib.median(v);
          x = 0;
          assertEquals("median ", x, d);
          
          v = new double[] {1,2,1,2,1,2,1,2,1,2};
          d = StatsLib.median(v);
          x = 1.5;
          assertEquals("median ", x, d);
          
          v = new double[] {123.12,33.3333,2d/3d,5.37828,0.999};
          d = StatsLib.median(v);
          x = 5.37828;
          assertEquals("median ", x, d);
          
          v = new double[] {-1,-2,-3,-4,-5,-6,-7,-8,-9,-10};
          d = StatsLib.median(v);
          x = -5.5;
          assertEquals("median ", x, d);
          
          v = new double[] {-2,-3,-4,-5,-6,-7,-8,-9,-10};
          d = StatsLib.median(v);
          x = -6;
          assertEquals("median ", x, d);
          
          v = new double[] {1,2,3,4,5,6,7,8,9};
          d = StatsLib.median(v);
          x = 5;
          assertEquals("median ", x, d);
      }
  
      public void testMode() {
          double[] v = null;
          double d, x = 0;
          
          v = new double[] {1,2,3,4,5,6,7,8,9,10};
          d = StatsLib.mode(v);
          x = Double.NaN;
          assertEquals("mode ", x, d);
          
          v = new double[] {1,1,1,1,1,1,1,1,1,1};
          d = StatsLib.mode(v);
          x = 1;
          assertEquals("mode ", x, d);
          
          v = new double[] {0,0,0,0,0,0,0,0,0,0};
          d = StatsLib.mode(v);
          x = 0;
          assertEquals("mode ", x, d);
          
          v = new double[] {1,2,1,2,1,2,1,2,1,2};
          d = StatsLib.mode(v);
          x = 1;
          assertEquals("mode ", x, d);
          
          v = new double[] {123.12,33.3333,2d/3d,5.37828,0.999};
          d = StatsLib.mode(v);
          x = Double.NaN;
          assertEquals("mode ", x, d);
          
          v = new double[] {-1,-2,-3,-4,-5,-6,-7,-8,-9,-10};
          d = StatsLib.mode(v);
          x = Double.NaN;
          assertEquals("mode ", x, d);
          
          v = new double[] {1,2,3,4,1,1,1,1,0,0,0,0,0};
          d = StatsLib.mode(v);
          x = 1;
          assertEquals("mode ", x, d);
          
          v = new double[] {0,1,2,3,4,1,1,1,0,0,0,0,1};
          d = StatsLib.mode(v);
          x = 0;
          assertEquals("mode ", x, d);
      }
  
      public void testStddev() {
          double[] v = null;
          double d, x = 0;
          
          v = new double[] {1,2,3,4,5,6,7,8,9,10};
          d = StatsLib.stdev(v);
          x = 3.02765035410;
          assertEquals("stdev ", x, d);
          
          v = new double[] {1,1,1,1,1,1,1,1,1,1};
          d = StatsLib.stdev(v);
          x = 0;
          assertEquals("stdev ", x, d);
          
          v = new double[] {0,0,0,0,0,0,0,0,0,0};
          d = StatsLib.stdev(v);
          x = 0;
          assertEquals("stdev ", x, d);
          
          v = new double[] {1,2,1,2,1,2,1,2,1,2};
          d = StatsLib.stdev(v);
          x = 0.52704627669;
          assertEquals("stdev ", x, d);
          
          v = new double[] {123.12,33.3333,2d/3d,5.37828,0.999};
          d = StatsLib.stdev(v);
          x = 52.33006233652;
          assertEquals("stdev ", x, d);
          
          v = new double[] {-1,-2,-3,-4,-5,-6,-7,-8,-9,-10};
          d = StatsLib.stdev(v);
          x = 3.02765035410;
          assertEquals("stdev ", x, d);
      }
  }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: poi-dev-unsubscribe@jakarta.apache.org
Mailing List:    http://jakarta.apache.org/site/mail2.html#poi
The Apache Jakarta POI Project: http://jakarta.apache.org/poi/