All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.openl.util.math.MathUtils Maven / Gradle / Ivy

package org.openl.util.math;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.Arrays;

import org.openl.util.ArrayTool;

/**
 * @author DLiauchuk
 */
public class MathUtils {

    private static  double[] numberArrayToDoubleArray(T[] values) {
        if (values == null) {
            return null;
        }
        double[] doubleArray = new double[values.length];
        for (int i = 0; i < values.length; i++) {
            if (values[i] != null) {
                doubleArray[i] = values[i].doubleValue();
            }
        }
        return doubleArray;
    }

    private static double[] byteArrayToDoubleArray(byte[] values) {
        if (values == null) {
            return null;
        }
        double[] doubleArray = new double[values.length];
        for (int i = 0; i < values.length; i++) {
            doubleArray[i] = values[i];
        }
        return doubleArray;
    }

    private static double[] shortArrayToDoubleArray(short[] values) {
        if (values == null) {
            return null;
        }
        double[] doubleArray = new double[values.length];
        for (int i = 0; i < values.length; i++) {
            doubleArray[i] = values[i];
        }
        return doubleArray;
    }

    private static double[] intArrayToDoubleArray(int[] values) {
        if (values == null) {
            return null;
        }
        double[] doubleArray = new double[values.length];
        for (int i = 0; i < values.length; i++) {
            doubleArray[i] = values[i];
        }
        return doubleArray;
    }

    private static double[] longArrayToDoubleArray(long[] values) {
        if (values == null) {
            return null;
        }
        double[] doubleArray = new double[values.length];
        for (int i = 0; i < values.length; i++) {
            doubleArray[i] = values[i];
        }
        return doubleArray;
    }

    private static double[] floatArrayToDoubleArray(float[] values) {
        if (values == null) {
            return null;
        }
        double[] doubleArray = new double[values.length];
        for (int i = 0; i < values.length; i++) {
            doubleArray[i] = values[i];
        }
        return doubleArray;
    }

    // SMALL
    public static > T small(T[] values, int position) {
        if (values == null) {
            return null;
        }
        int index = position - 1;
        values = ArrayTool.removeNulls(values);
        validateIndex(index < 0 || values.length <= index, position);
        T[] v = values.clone();
        Arrays.sort(v);
        return v[index];
    }

    public static Byte small(byte[] values, int position) {
        if (values == null) {
            return null;
        }
        int index = position - 1;
        validateIndex(index < 0 || values.length <= index, position);
        byte[] v = values.clone();
        Arrays.sort(v);
        return v[index];
    }

    public static Short small(short[] values, int position) {
        if (values == null) {
            return null;
        }
        int index = position - 1;
        validateIndex(index < 0 || values.length <= index, position);
        short[] v = values.clone();
        Arrays.sort(v);
        return v[index];
    }

    public static Integer small(int[] values, int position) {
        if (values == null) {
            return null;
        }
        int index = position - 1;
        validateIndex(index < 0 || values.length <= index, position);
        int[] v = values.clone();
        Arrays.sort(v);
        return v[index];
    }

    public static Long small(long[] values, int position) {
        if (values == null) {
            return null;
        }
        int index = position - 1;
        validateIndex(index < 0 || values.length <= index, position);
        long[] v = values.clone();
        Arrays.sort(v);
        return v[index];
    }

    public static Float small(float[] values, int position) {
        if (values == null) {
            return null;
        }
        int index = position - 1;
        validateIndex(index < 0 || values.length <= index, position);
        float[] v = values.clone();
        Arrays.sort(v);
        return v[index];
    }

    public static Double small(double[] values, int position) {
        if (values == null) {
            return null;
        }
        int index = position - 1;
        validateIndex(index < 0 || values.length <= index, position);
        double[] v = values.clone();
        Arrays.sort(v);
        return v[index];
    }

    // BIG
    public static > T big(T[] values, int position) {
        if (values == null) {
            return null;
        }
        int index = position - 1;
        values = ArrayTool.removeNulls(values);
        validateIndex(index < 0 || values.length <= index, position);
        T[] v = values.clone();
        Arrays.sort(v);
        return v[v.length - 1 - index];
    }

    public static Byte big(byte[] values, int position) {
        if (values == null) {
            return null;
        }
        int index = position - 1;
        validateIndex(index < 0 || values.length <= index, position);
        byte[] v = values.clone();
        Arrays.sort(v);
        return v[v.length - 1 - index];
    }

    public static Short big(short[] values, int position) {
        if (values == null) {
            return null;
        }
        int index = position - 1;
        validateIndex(index < 0 || values.length <= index, position);
        short[] v = values.clone();
        Arrays.sort(v);
        return v[v.length - 1 - index];
    }

    public static Integer big(int[] values, int position) {
        if (values == null) {
            return null;
        }
        int index = position - 1;
        validateIndex(index < 0 || values.length <= index, position);
        int[] v = values.clone();
        Arrays.sort(v);
        return v[v.length - 1 - index];
    }

    public static Long big(long[] values, int position) {
        if (values == null) {
            return null;
        }
        int index = position - 1;
        validateIndex(index < 0 || values.length <= index, position);
        long[] v = values.clone();
        Arrays.sort(v);
        return v[v.length - 1 - index];
    }

    public static Float big(float[] values, int position) {
        if (values == null) {
            return null;
        }
        int index = position - 1;
        validateIndex(index < 0 || values.length <= index, position);
        float[] v = values.clone();
        Arrays.sort(v);
        return v[v.length - 1 - index];
    }

    public static Double big(double[] values, int position) {
        if (values == null) {
            return null;
        }
        int index = position - 1;
        validateIndex(index < 0 || values.length <= index, position);
        double[] v = values.clone();
        Arrays.sort(v);
        return v[v.length - 1 - index];
    }

    private static void validateIndex(boolean throwException, int position) {
        if (throwException) {
            throw new IllegalArgumentException(
                    String.format("There is no position '%d' in the given array.", position));
        }
    }

    // SUM
    public static Byte sum(byte[] values) {
        if (values == null) {
            return null;
        }
        byte sum = 0;
        for (byte a : values) {
            sum = (byte) (sum + a);
        }
        return sum;
    }

    public static Short sum(short[] values) {
        if (values == null) {
            return null;
        }
        short sum = 0;
        for (short a : values) {
            sum = (short) (sum + a);
        }
        return sum;
    }

    public static Integer sum(int[] values) {
        if (values == null) {
            return null;
        }
        int sum = 0;
        for (int a : values) {
            sum = sum + a;
        }
        return sum;
    }

    public static Long sum(long[] values) {
        if (values == null) {
            return null;
        }
        long sum = 0;
        for (long a : values) {
            sum = sum + a;
        }
        return sum;
    }

    public static Float sum(float[] values) {
        if (values == null) {
            return null;
        }
        float sum = 0;
        for (float a : values) {
            sum = sum + a;
        }
        return sum;
    }

    public static Double sum(double[] values) {
        if (values == null) {
            return null;
        }
        double sum = 0;
        for (double a : values) {
            sum = sum + a;
        }
        return sum;
    }

    // MEDIAN
    public static  Double median(T[] values) {
        if (values == null) {
            return null;
        }
        values = ArrayTool.removeNulls(values);
        if (values.length == 0) {
            return null;
        }
        double[] doubleArray = numberArrayToDoubleArray(values);
        return median(doubleArray);
    }

    public static Float median(Float[] values) {
        Double median = median((Number[]) values);
        return median == null ? null : median.floatValue();
    }

    public static BigDecimal median(BigInteger[] values) {
        if (values == null) {
            return null;
        }
        values = ArrayTool.removeNulls(values);
        int length = values.length;
        if (length == 0) {
            return null;
        } else if (length == 1) {
            return new BigDecimal(values[0]);
        } else if (length == 2) {
            BigDecimal v = new BigDecimal(values[0].add(values[1]));
            return v.divide(BigDecimal.valueOf(2));
        }
        BigInteger[] copy = Arrays.copyOf(values, length);
        Arrays.sort(copy);
        length--;
        int index = length >> 1;
        if (length % 2 == 0) {
            return new BigDecimal(copy[index]);
        } else {
            BigDecimal v = new BigDecimal(copy[index].add(copy[index + 1]));
            return v.divide(BigDecimal.valueOf(2));
        }
    }

    public static BigDecimal median(BigDecimal[] values) {
        if (values == null) {
            return null;
        }
        values = ArrayTool.removeNulls(values);
        int length = values.length;
        if (length == 0) {
            return null;
        } else if (length == 1) {
            return values[0];
        } else if (length == 2) {
            BigDecimal v = values[0].add(values[1]);
            return new BigDecimal("0.5").multiply(v);
        }
        BigDecimal[] copy = Arrays.copyOf(values, length);
        Arrays.sort(copy);
        length--;
        int index = length >> 1;
        if (length % 2 == 0) {
            return copy[index];
        } else {
            BigDecimal v = copy[index].add(copy[index + 1]);
            return new BigDecimal("0.5").multiply(v);
        }
    }

    public static Double median(double[] values) {
        if (values == null) {
            return null;
        }
        int length = values.length;
        if (length == 0) {
            return null;
        } else if (length == 1) {
            return values[0];
        } else if (length == 2) {
            return (values[0] + values[1]) * 0.5;
        }
        double[] copy = Arrays.copyOf(values, length);
        Arrays.sort(copy);
        length--;
        int index = length >> 1;
        if (length % 2 == 0) {
            return copy[index];
        } else {
            return (copy[index] + copy[index + 1]) * 0.5;
        }
    }

    public static Double median(byte[] values) {
        return median(byteArrayToDoubleArray(values));
    }

    public static Double median(short[] values) {
        return median(shortArrayToDoubleArray(values));
    }

    public static Double median(int[] values) {
        return median(intArrayToDoubleArray(values));
    }

    public static Double median(long[] values) {
        return median(longArrayToDoubleArray(values));
    }

    public static Float median(float[] values) {
        Double median = median(floatArrayToDoubleArray(values));
        return median == null ? null : median.floatValue();
    }

    // MOD is implemented as in Excel.
    public static byte mod(byte number, byte divisor) {
        long quotient = quotient(number, divisor);

        byte intPart = (byte) quotient;
        if (quotient < 0) {
            intPart--;
        }
        return (byte) (number - intPart * divisor);
    }

    public static short mod(short number, short divisor) {
        long quotient = quotient(number, divisor);

        short intPart = (short) quotient;
        if (quotient < 0) {
            intPart--;
        }
        return (short) (number - intPart * divisor);
    }

    public static int mod(int number, int divisor) {
        long quotient = quotient(number, divisor);

        int intPart = (int) quotient;
        if (quotient < 0) {
            intPart--;
        }
        return number - intPart * divisor;
    }

    public static long mod(long number, long divisor) {
        long quotient = quotient(number, divisor);

        long intPart = quotient;
        if (quotient < 0) {
            intPart--;
        }
        return number - intPart * divisor;
    }

    public static float mod(float number, float divisor) {
        long quotient = quotient(number, divisor);

        float intPart = quotient;
        if (quotient < 0) {
            intPart--;
        }
        return number - intPart * divisor;
    }

    public static double mod(double number, double divisor) {
        long quotient = quotient(number, divisor);

        double intPart = quotient;
        if (quotient < 0) {
            intPart--;
        }
        return number - intPart * divisor;
    }

    // MOD for wrapper types
    public static Byte mod(Byte number, Byte divisor) {
        if (number == null || divisor == null) {
            return (byte) 0;
        }
        return mod((byte) number, (byte) divisor);
    }

    public static Short mod(Short number, Short divisor) {
        if (number == null || divisor == null) {
            return (short) 0;
        }
        return mod((short) number, (short) divisor);
    }

    public static Integer mod(Integer number, Integer divisor) {
        if (number == null || divisor == null) {
            return 0;
        }
        return mod((int) number, (int) divisor);
    }

    public static Long mod(Long number, Long divisor) {
        if (number == null || divisor == null) {
            return 0L;
        }
        return mod((long) number, (long) divisor);
    }

    public static Float mod(Float number, Float divisor) {
        if (number == null || divisor == null) {
            return 0f;
        }
        return mod((float) number, (float) divisor);
    }

    public static Double mod(Double number, Double divisor) {
        if (number == null || divisor == null) {
            return 0d;
        }
        return mod((double) number, (double) divisor);
    }

    // MOD for big numeric types
    public static BigInteger mod(BigInteger number, BigInteger divisor) {
        if (number == null || divisor == null) {
            return BigInteger.ZERO;
        }
        long quotient = quotient(number, divisor);

        long intPart = quotient;
        if (quotient < 0) {
            intPart--;
        }
        return number.subtract(BigInteger.valueOf(intPart).multiply(divisor));
    }

    public static BigDecimal mod(BigDecimal number, BigDecimal divisor) {
        if (number == null || divisor == null) {
            return BigDecimal.ZERO;
        }
        long quotient = quotient(number, divisor);

        long intPart = quotient;
        if (quotient < 0) {
            intPart--;
        }
        return number.subtract(BigDecimal.valueOf(intPart).multiply(divisor));
    }

    // QUAOTIENT
    public static long quotient(byte number, byte divisor) {
        return number / divisor;
    }

    public static long quotient(short number, short divisor) {
        return number / divisor;
    }

    public static long quotient(int number, int divisor) {
        return number / divisor;
    }

    public static long quotient(long number, long divisor) {
        return number / divisor;
    }

    public static long quotient(float number, float divisor) {
        return (long) (number / divisor);
    }

    public static long quotient(double number, double divisor) {
        return (long) (number / divisor);
    }

    // QUAOTIENT for wrapper types
    public static long quotient(Byte number, Byte divisor) {
        if (number == null || divisor == null) {
            return 0;
        }
        return quotient((byte) number, (byte) divisor);
    }

    public static long quotient(Short number, Short divisor) {
        if (number == null || divisor == null) {
            return 0;
        }
        return quotient((short) number, (short) divisor);
    }

    public static long quotient(Integer number, Integer divisor) {
        if (number == null || divisor == null) {
            return 0;
        }
        return quotient((int) number, (int) divisor);
    }

    public static long quotient(Long number, Long divisor) {
        if (number == null || divisor == null) {
            return 0;
        }
        return quotient((long) number, (long) divisor);
    }

    public static long quotient(Float number, Float divisor) {
        if (number == null || divisor == null) {
            return 0;
        }
        return quotient((float) number, (float) divisor);
    }

    public static long quotient(Double number, Double divisor) {
        if (number == null || divisor == null) {
            return 0;
        }
        return quotient((double) number, (double) divisor);
    }

    // QUAOTIENT for big numeric types
    public static long quotient(BigInteger number, BigInteger divisor) {
        if (number == null || divisor == null) {
            return 0;
        }
        return divide(number, divisor).longValue();
    }

    public static long quotient(BigDecimal number, BigDecimal divisor) {
        if (number == null || divisor == null) {
            return 0;
        }
        return divide(number, divisor).longValue();
    }

    /**
     * Divide one BigDecimal to another. When providing a result of divide operation, the precision '5' and
     * {@link RoundingMode#HALF_UP} settings are used.
     *
     * @return rounded to 5 values after comma and {@link RoundingMode#HALF_UP} value.
     */
    public static BigDecimal divide(BigDecimal number, BigDecimal divisor) {
        if (number == null || divisor == null) {
            return null;
        }
        return number.divide(divisor, MathContext.DECIMAL128);
    }

    public static BigInteger divide(BigInteger number, BigInteger divisor) {
        if (number == null || divisor == null) {
            return null;
        }
        return number.divide(divisor);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy