/* * Copyright 2010-2015 Institut Pasteur. * * This file is part of Icy. * * Icy is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Icy is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Icy. If not, see <http://www.gnu.org/licenses/>. */ package icy.math; /** * Math utilities class. * * @author stephane */ public class MathUtil { public static final String INFINITE_STRING = "\u221E"; public static final double POW2_8_DOUBLE = Math.pow(2, 8); public static final float POW2_8_FLOAT = (float) POW2_8_DOUBLE; public static final double POW2_16_DOUBLE = Math.pow(2, 16); public static final float POW2_16_FLOAT = (float) POW2_16_DOUBLE; public static final double POW2_32_DOUBLE = Math.pow(2, 32); public static final float POW2_32_FLOAT = (float) POW2_32_DOUBLE; public static final double POW2_64_DOUBLE = Math.pow(2, 64); public static final float POW2_64_FLOAT = (float) POW2_64_DOUBLE; /** * @deprecated please use {@link UnitUtil#getBytesString(double)} instead. */ @Deprecated public static String getBytesString(double value) { return UnitUtil.getBytesString(value); } public static double frac(double value) { return value - Math.floor(value); } /** * Normalize an array * * @param array * elements to normalize */ public static void normalize(float[] array) { final float max = ArrayMath.max(array); if (max != 0) divide(array, max); else { final float min = ArrayMath.min(array); if (min != 0) divide(array, min); } } /** * Normalize an array * * @param array * elements to normalize */ public static void normalize(double[] array) { final double max = ArrayMath.max(array); if (max != 0) divide(array, max); else { final double min = ArrayMath.min(array); if (min != 0) divide(array, min); } } /** * Replace all values in the array by their logarithm<br> * Be careful, all values should be >0 values * * @param array * elements to logarithm */ public static void log(double[] array) { final int len = array.length; for (int i = 0; i < len; i++) array[i] = Math.log(array[i]); } /** * Replace all values in the array by their logarithm<br> * Be careful, all values should be >0 values * * @param array * elements to logarithm */ public static void log(float[] array) { final int len = array.length; for (int i = 0; i < len; i++) array[i] = (float) Math.log(array[i]); } /** * Add the the specified value to all elements in an array * * @param array * elements to modify * @param value */ public static void add(double[] array, double value) { final int len = array.length; for (int i = 0; i < len; i++) array[i] = array[i] + value; } /** * Add the the specified value to all elements in an array * * @param array * elements to modify * @param value */ public static void add(float[] array, float value) { final int len = array.length; for (int i = 0; i < len; i++) array[i] = array[i] + value; } /** * Multiply and add all elements in an array by the specified values * * @param array * elements to modify * @param mulValue * @param addValue */ public static void madd(double[] array, double mulValue, double addValue) { final int len = array.length; for (int i = 0; i < len; i++) array[i] = (array[i] * mulValue) + addValue; } /** * Multiply and add all elements in an array by the specified values * * @param array * elements to modify * @param mulValue * @param addValue */ public static void madd(float[] array, float mulValue, float addValue) { final int len = array.length; for (int i = 0; i < len; i++) array[i] = (array[i] * mulValue) + addValue; } /** * Multiply all elements in an array by the specified value * * @param array * elements to modify * @param value * value to multiply by */ public static void mul(double[] array, double value) { final int len = array.length; for (int i = 0; i < len; i++) array[i] = array[i] * value; } /** * Multiply all elements in an array by the specified value * * @param array * elements to modify * @param value * value to multiply by */ public static void mul(float[] array, float value) { final int len = array.length; for (int i = 0; i < len; i++) array[i] = array[i] * value; } /** * Divides all elements in an array by the specified value * * @param array * elements to modify * @param value * value used as divisor */ public static void divide(double[] array, double value) { if (value != 0d) { final int len = array.length; for (int i = 0; i < len; i++) array[i] = array[i] / value; } } /** * Divides all elements in an array by the specified value * * @param array * elements to modify * @param value * value used as divisor */ public static void divide(float[] array, float value) { if (value != 0d) { final int len = array.length; for (int i = 0; i < len; i++) array[i] = array[i] / value; } } /** * @deprecated use {@link ArrayMath#min(Object, boolean)} instead */ @Deprecated public static double min(Object array, boolean signed) { return ArrayMath.min(array, signed); } /** * @deprecated use {@link ArrayMath#min(byte[], boolean)} instead */ @Deprecated public static int min(byte[] array, boolean signed) { return ArrayMath.min(array, signed); } /** * @deprecated use {@link ArrayMath#min(short[], boolean)} instead */ @Deprecated public static int min(short[] array, boolean signed) { return ArrayMath.min(array, signed); } /** * @deprecated use {@link ArrayMath#min(int[], boolean)} instead */ @Deprecated public static long min(int[] array, boolean signed) { return ArrayMath.min(array, signed); } /** * @deprecated use {@link ArrayMath#min(float[])} instead */ @Deprecated public static float min(float[] array) { return ArrayMath.min(array); } /** * @deprecated use {@link ArrayMath#min(double[])} instead */ @Deprecated public static double min(double[] array) { return ArrayMath.min(array); } /** * @deprecated use {@link ArrayMath#max(Object, boolean)} instead */ @Deprecated public static double max(Object array, boolean signed) { return ArrayMath.max(array, signed); } /** * @deprecated use {@link ArrayMath#max(byte[], boolean)} instead */ @Deprecated public static int max(byte[] array, boolean signed) { return ArrayMath.max(array, signed); } /** * @deprecated use {@link ArrayMath#max(short[], boolean)} instead */ @Deprecated public static int max(short[] array, boolean signed) { return ArrayMath.max(array, signed); } /** * @deprecated use {@link ArrayMath#max(int[], boolean)} instead */ @Deprecated public static long max(int[] array, boolean signed) { return ArrayMath.max(array, signed); } /** * @deprecated use {@link ArrayMath#max(float[])} instead */ @Deprecated public static float max(float[] array) { return ArrayMath.max(array); } /** * @deprecated use {@link ArrayMath#max(double[])} instead */ @Deprecated public static double max(double[] array) { return ArrayMath.max(array); } /** * Round specified value to specified number of significant digit.<br> * If keepInteger is true then integer part of number is entirely conserved.<br> * If <i>numDigit</i> is <= 0 then the value stay unchanged. */ public static double roundSignificant(double d, int numDigit, boolean keepInteger) { if ((numDigit <= 0) ||(d == 0d)) return d; final double digit = Math.ceil(Math.log10(Math.abs(d))); if ((digit >= numDigit) && keepInteger) return Math.round(d); return round(d, numDigit - (int) digit); } /** * Round specified value to specified number of significant digit. */ public static double roundSignificant(double d, int numDigit) { return roundSignificant(d, numDigit, false); } /** * Round specified value to specified number of decimal. */ public static double round(double d, int numDecimal) { final double pow = Math.pow(10, numDecimal); return Math.round(d * pow) / pow; } /** * Return the previous multiple of "mul" for the specified value * <ul> * <li>prevMultiple(200, 64) = 192</li> * </ul> * * @param value * @param mul */ public static double prevMultiple(double value, double mul) { if (mul == 0) return 0d; return Math.floor(value / mul) * mul; } /** * Return the next multiple of "mul" for the specified value * <ul> * <li>nextMultiple(200, 64) = 256</li> * </ul> * * @param value * @param mul */ public static double nextMultiple(double value, double mul) { if (mul == 0) return 0d; return Math.ceil(value / mul) * mul; } /** * Return the next power of 2 for the specified value * <ul> * <li>nextPow2(17) = 32</li> * <li>nextPow2(16) = 32</li> * <li>nextPow2(-12) = -8</li> * <li>nextPow2(-8) = -4</li> * </ul> * * @param value * @return next power of 2 */ public static long nextPow2(long value) { long result; if (value < 0) { result = -1; while (result > value) result <<= 1; result >>= 1; } else { result = 1; while (result <= value) result <<= 1; } return result; } /** * Return the next power of 2 mask for the specified value * <ul> * <li>nextPow2Mask(17) = 31</li> * <li>nextPow2Mask(16) = 31</li> * <li>nextPow2Mask(-12) = -8</li> * <li>nextPow2Mask(-8) = -4</li> * </ul> * * @param value * @return next power of 2 mask */ public static long nextPow2Mask(long value) { final long result = nextPow2(value); if (value > 0) return result - 1; return result; } /** * Return the previous power of 2 for the specified value * <ul> * <li>prevPow2(17) = 16</li> * <li>prevPow2(16) = 8</li> * <li>prevPow2(-12) = -16</li> * <li>prevPow2(-8) = -16</li> * </ul> * * @param value * @return previous power of 2 */ public static long prevPow2(long value) { long result; if (value < 0) { result = -1; while (result >= value) result <<= 1; } else { result = 1; while (result < value) result <<= 1; result >>= 1; } return result; } /** * Return the next power of 10 for the specified value * <ul> * <li>nextPow10(0.0067) = 0.01</li> * <li>nextPow10(-28.7) = -10</li> * </ul> * * @param value */ public static double nextPow10(double value) { if (value == 0) return 0; else if (value < 0) return -Math.pow(10, Math.floor(Math.log10(-value))); else return Math.pow(10, Math.ceil(Math.log10(value))); } /** * Return the previous power of 10 for the specified value * <ul> * <li>prevPow10(0.0067) = 0.001</li> * <li>prevPow10(-28.7) = -100</li> * </ul> * * @param value */ public static double prevPow10(double value) { if (value == 0) return 0; else if (value < 0) return -Math.pow(10, Math.ceil(Math.log10(-value))); else return Math.pow(10, Math.floor(Math.log10(value))); } /** * Format the specified degree angle to stay in [0..360[ range */ public static double formatDegreeAngle(double angle) { final double res = angle % 360d; if (res < 0) return 360d + res; return res; } /** * Format the specified degree angle to stay in [-180..180] range */ public static double formatDegreeAngle2(double angle) { final double res = angle % 360d; if (res < -180d) return 360d + res; if (res > 180d) return res - 360d; return res; } /** * Format the specified degree angle to stay in [0..2PI[ range */ public static double formatRadianAngle(double angle) { final double res = angle % (2 * Math.PI); if (res < 0) return (2 * Math.PI) + res; return res; } /** * Format the specified degree angle to stay in [-PI..PI] range */ public static double formatRadianAngle2(double angle) { final double res = angle % (2 * Math.PI); if (res < -Math.PI) return (2 * Math.PI) + res; if (res > Math.PI) return res - (2 * Math.PI); return res; } /** * Return the value in <code>source</code> which is the closest to <code>value</code> Returns * <code>0</code> if source is null or empty. */ public static double closest(double value, double[] source) { if ((source == null) || (source.length == 0)) return 0d; double result = source[0]; double minDelta = Math.abs(value - result); for (double d : source) { final double delta = Math.abs(value - d); if (delta < minDelta) { result = d; minDelta = delta; } } return result; } /** * Calculate the cubic root of the specified value. */ public static double cubicRoot(double value) { return Math.pow(value, 1d / 3d); } }