From b9a1074423e64bdde4ef0c693f02a3a7429a6786 Mon Sep 17 00:00:00 2001 From: Avik Sengupta Date: Tue, 14 Jun 2005 17:41:33 +0000 Subject: [PATCH] Amol's formula eval additions. Missed these files, sorry git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@353717 13f79535-47bb-0310-9956-ffa450edef68 --- .../record/formula/functions/FinanceLib.java | 133 +++ .../hssf/record/formula/functions/MathX.java | 571 +++++++++++ .../MultiOperandNumericFunction.java | 221 +++++ .../record/formula/functions/StatsLib.java | 158 ++++ .../formula/functions/TextFunction.java | 92 ++ .../formula/functions/XYNumericFunction.java | 190 ++++ .../functions/AbstractNumericTestCase.java | 57 ++ .../formula/functions/TestFinanceLib.java | 167 ++++ .../record/formula/functions/TestMathX.java | 893 ++++++++++++++++++ .../formula/functions/TestStatsLib.java | 246 +++++ 10 files changed, 2728 insertions(+) create mode 100644 src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/FinanceLib.java create mode 100644 src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/MathX.java create mode 100644 src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/MultiOperandNumericFunction.java create mode 100644 src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/StatsLib.java create mode 100644 src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/TextFunction.java create mode 100644 src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/XYNumericFunction.java create mode 100644 src/scratchpad/testcases/org/apache/poi/hssf/record/formula/functions/AbstractNumericTestCase.java create mode 100644 src/scratchpad/testcases/org/apache/poi/hssf/record/formula/functions/TestFinanceLib.java create mode 100644 src/scratchpad/testcases/org/apache/poi/hssf/record/formula/functions/TestMathX.java create mode 100644 src/scratchpad/testcases/org/apache/poi/hssf/record/formula/functions/TestStatsLib.java diff --git a/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/FinanceLib.java b/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/FinanceLib.java new file mode 100644 index 0000000000..90378c8081 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/FinanceLib.java @@ -0,0 +1,133 @@ +/* + * 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. + * Glossary of terms/abbreviations: + *
+ * + * For more info on the terms/abbreviations please use the references below + * (hyperlinks are subject to change): + *
Online References: + *
    + *
  1. GNU Emacs Calc 2.02 Manual: http://theory.uwinnipeg.ca/gnu/calc/calc_203.html
  2. + *
  3. Yahoo Financial Glossary: http://biz.yahoo.com/f/g/nn.html#y
  4. + *
+ */ +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; iIf 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. + *

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. + *

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. + *

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. + *

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. + *

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 + *
+ * If d > 0, returns short 1 + *
+ * If d == 0, returns short 0 + *

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 0) { + product = 1; + for (int i=0, iSize=values.length; i + * When n and s are "valid" arguments, the returned value is: Math.floor(n/s) * s; + *
+ * n and s are invalid if any of following conditions are true: + *

+ * 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(..). + *

+ * When n and s are "valid" arguments, the returned value is: Math.ceiling(n/s) * s; + *
+ * n and s are invalid if any of following conditions are true: + *

+ * 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; + } + + /** + *
for all n >= 1; factorial n = n * (n-1) * (n-2) * ... * 1 + *
else if n == 0; factorial n = 1 + *
else if n < 0; factorial n = Double.NaN + *
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. + *
The result has the sign of the divisor. + *
Examples: + * + * 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 + * 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 + * 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 + * 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 getMaxNumOperands()) { + break outer; + } + else { + for (int i=0, iSize=operands.length; i 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 0) { + if (values[0] == null) + break outer; + int len = values[0].length; + for (int i=1, iSize=values.length; i 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 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 + * 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. + *
+ * 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; + } +} diff --git a/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/TextFunction.java b/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/TextFunction.java new file mode 100644 index 0000000000..860b74c16a --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/TextFunction.java @@ -0,0 +1,92 @@ +/* + * 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 < amolweb at ya hoo dot com > + * + */ +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; + } +} diff --git a/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/XYNumericFunction.java b/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/XYNumericFunction.java new file mode 100644 index 0000000000..6ab874a579 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/XYNumericFunction.java @@ -0,0 +1,190 @@ +/* + * 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 < amolweb at ya hoo dot com > + * + */ +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= 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; + } +} diff --git a/src/scratchpad/testcases/org/apache/poi/hssf/record/formula/functions/AbstractNumericTestCase.java b/src/scratchpad/testcases/org/apache/poi/hssf/record/formula/functions/AbstractNumericTestCase.java new file mode 100644 index 0000000000..76cc19f13a --- /dev/null +++ b/src/scratchpad/testcases/org/apache/poi/hssf/record/formula/functions/AbstractNumericTestCase.java @@ -0,0 +1,57 @@ +/* + * Created on May 29, 2005 + * + */ +package org.apache.poi.hssf.record.formula.functions; + +import junit.framework.TestCase; + +/** + * @author Amol S. Deshmukh < amolweb at ya hoo dot com > + * + */ +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); + } + +} diff --git a/src/scratchpad/testcases/org/apache/poi/hssf/record/formula/functions/TestFinanceLib.java b/src/scratchpad/testcases/org/apache/poi/hssf/record/formula/functions/TestFinanceLib.java new file mode 100644 index 0000000000..b8bffc25f3 --- /dev/null +++ b/src/scratchpad/testcases/org/apache/poi/hssf/record/formula/functions/TestFinanceLib.java @@ -0,0 +1,167 @@ +/* + * Created on May 23, 2005 + * + */ +package org.apache.poi.hssf.record.formula.functions; + + +/** + * @author Amol S. Deshmukh < amolweb at ya hoo dot com > + * + */ +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); + } +} diff --git a/src/scratchpad/testcases/org/apache/poi/hssf/record/formula/functions/TestMathX.java b/src/scratchpad/testcases/org/apache/poi/hssf/record/formula/functions/TestMathX.java new file mode 100644 index 0000000000..baf82340e4 --- /dev/null +++ b/src/scratchpad/testcases/org/apache/poi/hssf/record/formula/functions/TestMathX.java @@ -0,0 +1,893 @@ +/* + * Created on May 23, 2005 + * + */ +package org.apache.poi.hssf.record.formula.functions; + + +/** + * @author Amol S. Deshmukh < amolweb at ya hoo dot com > + * + */ +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)); + } + +} diff --git a/src/scratchpad/testcases/org/apache/poi/hssf/record/formula/functions/TestStatsLib.java b/src/scratchpad/testcases/org/apache/poi/hssf/record/formula/functions/TestStatsLib.java new file mode 100644 index 0000000000..15ee280291 --- /dev/null +++ b/src/scratchpad/testcases/org/apache/poi/hssf/record/formula/functions/TestStatsLib.java @@ -0,0 +1,246 @@ +/* + * Created on May 30, 2005 + * + */ +package org.apache.poi.hssf.record.formula.functions; + + +/** + * @author Amol S. Deshmukh < amolweb at ya hoo dot com > + * + */ +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); + } +}