/* * Licensed to the Apache Software Foundation (ASF) Under one or more * contributor license agreements. See the NOTICE file distributed with * this work for Additional information regarding copyright ownership. * The ASF licenses this file to You Under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed Under the License is distributed on an "AS Is" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations Under the License. */ /* * Created on May 19, 2005 * */ namespace HH.WMS.Utils.NPOI.SS.Formula.Functions { using System; /** * @author Amol S. Deshmukh < amolweb at ya hoo dot com > * 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 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. * 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. * If n Is NaN, returned value Is NaN. * @param n * @param p */ public static double round(double n, int p) { double retval; if (double.IsNaN(n) || double.IsInfinity(n)) { retval = double.NaN; } else { //if (p != 0) //{ decimal temp = (decimal)Math.Pow(10, p); retval = (double)(Math.Round((decimal)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 */ public static double roundUp(double n, int p) { double retval; if (double.IsNaN(n) || double.IsInfinity(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 */ public static double roundDown(double n, int p) { double retval; if (double.IsNaN(n) || double.IsInfinity(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, MidpointRounding.AwayFromZero) / 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 */ public static short sign(double d) { return (short)((d == 0) ? 0 : (d < 0) ? -1 : 1); } /** * average of all values * @param values */ 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 */ 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 */ 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 */ 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 */ public static double min(double[] values) { double min = double.PositiveInfinity; 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 */ public static double max(double[] values) { double max = double.NegativeInfinity; 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(..). * * 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 */ 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 */ 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.Ceiling(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 */ 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.PositiveInfinity; } } 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 */ 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); result = n % d; } else { //double t = Math.Abs(n / d); //t = t - (long)t; //t = Math.Ceiling(t) - t; //result = sign(d) * Math.Abs(t * d); result = ((n % d) + d) % d; } return result; } /** * inverse hyperbolic cosine * @param d */ public static double acosh(double d) { return Math.Log(Math.Sqrt(Math.Pow(d, 2) - 1) + d); } /** * inverse hyperbolic sine * @param d */ public static double asinh(double d) { double d2 = d * d; return Math.Log(Math.Sqrt(d * d + 1) + d); } /** * inverse hyperbolic tangent * @param d */ public static double atanh(double d) { return Math.Log((1 + d) / (1 - d)) / 2; } /** * hyperbolic cosine * @param d */ 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 */ 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 */ 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 */ 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 (IndexOutOfRangeException) { 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) *
* 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 xarr * @param yarr */ 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 (IndexOutOfRangeException) { 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) *
* 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 xarr * @param yarr */ 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 (IndexOutOfRangeException ) { 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 ) *
* 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 xarr * @param yarr */ 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 (IndexOutOfRangeException ) { 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 */ 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; } } }