/******************************************************************************* * Copyright 2017 Capital One Services, LLC and Bitwise, Inc. * Licensed 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 *******************************************************************************/ package hydrograph.engine.transformation.standardfunctions; import hydrograph.engine.transformation.standardfunctions.helper.StandardFunctionHelper; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.Random; import java.util.regex.Matcher; import java.util.regex.Pattern; import static hydrograph.engine.transformation.standardfunctions.helper.StandardFunctionHelper.convertComparableObjectToString; /** * The Class NumericFunctions. * * @author Bitwise * */ public class NumericFunctions { /** * Retains just the decimal numbers 0-9 excluding the decimal point from the * {@code inputValue} * * @param inputValue * the value from which the decimals are to be retained * @return the decimals from the {@code inputValue} * * @deprecated This method is deprecated, Use * {@link NumericFunctions#decimalStrip(String inputValue)} * instead */ @SuppressWarnings("unchecked") @Deprecated public static <T> T decimalStrip(T inputValue) { if (inputValue == null) return null; String input = StandardFunctionHelper.convertComparableObjectToString(inputValue); String filter = input.replaceAll("[^0-9-]", ""); if (!filter.equals("")) { String regx = "^(-)(0+)(.*)|^(0+)(.*)"; Matcher match = Pattern.compile(regx).matcher(filter); if (match.find()) { if (match.group(1) != null) return (T) (match.group(1) + match.group(3)); else return (T) (match.group(5)); } return (T) (filter); } return (T) "0"; } /** * Retains just the decimal numbers 0-9 excluding the decimal point from the * {@code inputValue} * * @param inputValue * the value from which the decimals are to be retained * @return the decimals from the {@code inputValue} */ public static String decimalStrip(String inputValue) { if (inputValue == null) return null; String filter = inputValue.replaceAll("[^0-9-]", ""); if (!filter.equals("")) { String regx = "^(-)(0+)(.*)|^(0+)(.*)"; Matcher match = Pattern.compile(regx).matcher(filter); if (match.find()) { if (match.group(1) != null) return (match.group(1) + match.group(3)); else return (match.group(5)); } return (filter); } return "0"; } /** * Retains just the decimal numbers 0-9 including decimal point as specified * in {@code decimalPoint} from the {@code inputValue} * * @param inputValue * the value from which the decimals are to be retained * @param # includeDecimalPoint * @return the decimals from the {@code inputValue} * @deprecated This method is deprecated, Use * {@link NumericFunctions#decimalStrip(String inputValue, String decimal_point)} * instead */ @SuppressWarnings("unchecked") @Deprecated public static <T> T decimalStrip(T inputValue, T decimal_point) { if (inputValue == null) return null; String input = StandardFunctionHelper.convertComparableObjectToString(inputValue); String filter = input.replaceAll("[^0-9-\\" + decimal_point + "]", ""); // filter = input.replaceAll("[\\.]+$", ""); if (!filter.equals("")) { String regx = "^(-)(0+)(.*)|^(0+)(.*)"; Matcher match = Pattern.compile(regx).matcher(filter); if (match.find()) { if (match.group(1) != null) return (T) (match.group(1) + match.group(3)); else return (T) (match.group(5)); } return (T) (filter); } return (T) "0"; } /** * Retains just the decimal numbers 0-9 including decimal point as specified * in {@code decimalPoint} from the {@code inputValue} * * @param inputValue * the value from which the decimals are to be retained * @param # includeDecimalPoint * @return the decimals from the {@code inputValue} */ public static String decimalStrip(String inputValue, String decimal_point) { if (inputValue == null) return null; String filter = inputValue.replaceAll("[^0-9-\\" + decimal_point + "]", ""); // filter = input.replaceAll("[\\.]+$", ""); if (!filter.equals("")) { String regx = "^(-)(0+)(.*)|^(0+)(.*)"; Matcher match = Pattern.compile(regx).matcher(filter); if (match.find()) { if (match.group(1) != null) return (match.group(1) + match.group(3)); else return (match.group(5)); } return (filter); } return "0"; } /** * Returns the absolute value of the argument * * @param inputValue * whose absolute value is to be determined * @return the absolute value of the argument */ @SuppressWarnings("unchecked") public static <T> T mathAbs(T inputValue) { if (inputValue == null) return null; if (inputValue.getClass().getCanonicalName().equals("java.math.BigDecimal")) return (T) new BigDecimal(inputValue.toString()).abs(); else if (inputValue.getClass().getCanonicalName().equals("java.lang.Float")) return (T) new Float(Math.abs((Float) inputValue)); else if (inputValue.getClass().getCanonicalName().equals("java.lang.Long")) return (T) new Long(Math.abs((Long) inputValue)); else if (inputValue.getClass().getCanonicalName().equals("java.lang.Integer")) return (T) new Integer(Math.abs((Integer) inputValue)); else if (inputValue.getClass().getCanonicalName().equals("java.lang.Short")) return (T) new Short((short) Math.abs((Short) inputValue)); return (T) Double.valueOf(Math.abs((Double) inputValue)); } /** * Returns a pseudorandom, uniformly distributed {@Code int} value between 0 * (inclusive) and the specified value (exclusive), drawn from this random * number generator's sequence. * * @param n * the bound on the random number to be returned. Must be * positive. * @return the next pseudorandom, uniformly distributed int value between * {@code 0} (inclusive) and {@code n} (exclusive) from this random * number generator's sequence */ public static <T> Integer random(T n) { int n1 = 0; if (n == null) return null; Random r = new Random(); if (n instanceof Double) n1 = (int) Math.floor((Double) n); else if (n instanceof Float) n1 = Math.round((Float) n); else if (n instanceof BigDecimal) n1 = ((BigDecimal) n).intValue(); else if (n instanceof Long) n1 = ((Long) n).intValue(); else if (n instanceof Short) n1 = ((Short) n).intValue(); else n1 = (Integer) n; return r.nextInt(n1); } public static <T> Double getDoubleFromComparable(T inputValue) { return Double.parseDouble(convertComparableObjectToString(inputValue)); } /** * Rounds the {@code inputValue} to specified number of digits to the right of the decimal point. * This function rounds the number depending on the "{@code numberOfDigits} + 1" digit. * * @param inputValue the double value to be rounded * @param numberOfDigits the number of digits to round the {@code inputValue} * @return rounded {@code inputValue} value */ public static Float round(Float inputValue, int numberOfDigits) { if (inputValue == null) return null; BigDecimal bigDecimal = new BigDecimal(inputValue); bigDecimal = bigDecimal.setScale(numberOfDigits, RoundingMode.HALF_UP); return bigDecimal.floatValue(); } /** * Rounds the {@code inputValue} to specified number of digits to the right of the decimal point. * This function rounds the number depending on the "{@code numberOfDigits} + 1" digit. * * @param inputValue the double value to be rounded * @param numberOfDigits the number of digits to round the {@code inputValue} * @return rounded {@code inputValue} value */ public static Double round(Double inputValue, int numberOfDigits) { if (inputValue == null) return null; BigDecimal bigDecimal = new BigDecimal(inputValue); bigDecimal = bigDecimal.setScale(numberOfDigits, RoundingMode.HALF_UP); return bigDecimal.doubleValue(); } /** * Rounds the {@code inputValue} to specified number of digits to the right of the decimal point. * This function rounds the number depending on the "{@code numberOfDigits} + 1" digit. * * @param inputValue the double value to be rounded * @param numberOfDigits the number of digits to round the {@code inputValue} * @return rounded {@code inputValue} value */ public static BigDecimal round(BigDecimal inputValue, int numberOfDigits) { if (inputValue == null) return null; BigDecimal bigDecimal = inputValue.setScale(numberOfDigits, RoundingMode.HALF_UP); return bigDecimal; } /** * Rounds the {@code inputValue} to specified number of digits to the right of the decimal point. * This function always rounds up the number irrespective of the "{@code numberOfDigits} + 1" digit. * * @param inputValue the float value to be rounded up * @param numberOfDigits the number of digits to round up the {@code inputValue} * @return rounded up {@code inputValue} value */ public static Float roundUp(Float inputValue, int numberOfDigits) { if (inputValue == null) return null; BigDecimal bigDecimal = new BigDecimal(inputValue); bigDecimal = bigDecimal.setScale(numberOfDigits, BigDecimal.ROUND_UP); return bigDecimal.floatValue(); } /** * Rounds the {@code inputValue} to specified number of digits to the right of the decimal point. * This function always rounds up the number irrespective of the "{@code numberOfDigits} + 1" digit. * * @param inputValue the double value to be rounded up * @param numberOfDigits the number of digits to round up the {@code inputValue} * @return rounded up {@code inputValue} value */ public static Double roundUp(Double inputValue, int numberOfDigits) { if (inputValue == null) return null; BigDecimal bigDecimal = new BigDecimal(inputValue); bigDecimal = bigDecimal.setScale(numberOfDigits, BigDecimal.ROUND_UP); return bigDecimal.doubleValue(); } /** * Rounds the {@code inputValue} to specified number of digits to the right of the decimal point. * This function always rounds up the number irrespective of the "{@code numberOfDigits} + 1" digit. * * @param inputValue the BigDecimal value to be rounded up * @param numberOfDigits the number of digits to round up the {@code inputValue} * @return rounded up {@code inputValue} value */ public static BigDecimal roundUp(BigDecimal inputValue, int numberOfDigits) { if (inputValue == null) return null; BigDecimal roundedWithScale = inputValue.setScale(numberOfDigits, BigDecimal.ROUND_UP); return roundedWithScale; } /** * Rounds the {@code inputValue} to specified number of digits to the right of the decimal point. * This function always rounds down the number irrespective of the "{@code numberOfDigits} + 1" digit. * * @param inputValue the float value to be rounded down * @param numberOfDigits the number of digits to round down the {@code inputValue} * @return rounded down {@code inputValue} value */ public static Float roundDown(Float inputValue, int numberOfDigits) { if (inputValue == null) return null; BigDecimal bigDecimal = new BigDecimal(inputValue); bigDecimal = bigDecimal.setScale(numberOfDigits, BigDecimal.ROUND_DOWN); return bigDecimal.floatValue(); } /** * Rounds the {@code inputValue} to specified number of digits to the right of the decimal point. * This function always rounds down the number irrespective of the "{@code numberOfDigits} + 1" digit. * * @param inputValue the double value to be rounded down * @param numberOfDigits the number of digits to round down the {@code inputValue} * @return rounded down {@code inputValue} value */ public static Double roundDown(Double inputValue, int numberOfDigits) { if (inputValue == null) return null; BigDecimal bigDecimal = new BigDecimal(inputValue); bigDecimal = bigDecimal.setScale(numberOfDigits, BigDecimal.ROUND_DOWN); return bigDecimal.doubleValue(); } /** * Rounds the {@code inputValue} to specified number of digits to the right of the decimal point. * This function always rounds down the number irrespective of the "{@code numberOfDigits} + 1" digit. * * @param inputValue the BigDecimal value to be rounded down * @param numberOfDigits the number of digits to round down the {@code inputValue} * @return rounded down {@code inputValue} value */ public static BigDecimal roundDown(BigDecimal inputValue, int numberOfDigits) { if (inputValue == null) return null; BigDecimal roundedWithScale = inputValue.setScale(numberOfDigits, BigDecimal.ROUND_DOWN); return roundedWithScale; } /** * Truncates the {@code inputValue} to specified number of digits to the right of the decimal point. * If {@code numberOfDigits} is greater than the number of digits to the right of {@code input} then the * function returns {@code input} value. It does not add trailing zeros. * * @param inputValue the float value to be truncated * @param numberOfDigits the number of digits to truncate to the right of the decimal point * @return truncated {@code input} value */ public static Float truncate(Float inputValue, int numberOfDigits) { if (inputValue == null) return null; BigDecimal bigDecimal = new BigDecimal(inputValue); BigDecimal roundedWithScale = bigDecimal.setScale(numberOfDigits, RoundingMode.DOWN).stripTrailingZeros(); return roundedWithScale.floatValue(); } /** * Truncates the {@code inputValue} to specified number of digits to the right of the decimal point. * If {@code numberOfDigits} is greater than the number of digits to the right of {@code input} then the * function returns {@code input} value. It does not add trailing zeros. * * @param inputValue the double value to be truncated * @param numberOfDigits the number of digits to truncate to the right of the decimal point * @return truncated {@code input} value */ public static Double truncate(Double inputValue, int numberOfDigits) { if (inputValue == null) return null; BigDecimal bigDecimal = new BigDecimal(inputValue); bigDecimal = bigDecimal.setScale(numberOfDigits, RoundingMode.DOWN).stripTrailingZeros(); return bigDecimal.doubleValue(); } /** * Truncates the {@code inputValue} to specified number of digits to the right of the decimal point. * If {@code numberOfDigits} is greater than the number of digits to the right of {@code input} then the * function returns {@code input} value. It does not add trailing zeros. * * @param inputValue the BigDecimal value to be truncated * @param numberOfDigits the number of digits to truncate to the right of the decimal point * @return truncated {@code input} value */ public static BigDecimal truncate(BigDecimal inputValue, int numberOfDigits) { if (inputValue == null) return null; BigDecimal roundedWithScale = inputValue.setScale(numberOfDigits, RoundingMode.DOWN).stripTrailingZeros(); return roundedWithScale; } /** * Returns the smallest integer value greater than or equal to {@code inputValue} * * @param inputValue the value whose ceiling is to be retrieved * @return the smallest integer value greater than or equal to {@code inputValue} */ public static Float ceil(Float inputValue) { if (inputValue == null) return null; Double value = Math.ceil(inputValue); return value.floatValue(); } /** * Returns the smallest integer value greater than or equal to {@code inputValue} * * @param inputValue the value whose ceiling is to be retrieved * @return the smallest integer value greater than or equal to {@code inputValue} */ public static Double ceil(Double inputValue) { if (inputValue == null) return null; Double value = Math.ceil(inputValue); return value; } /** * Returns the smallest integer value greater than or equal to {@code inputValue} * * @param inputValue the value whose ceiling is to be retrieved * @return the smallest integer value greater than or equal to {@code inputValue} */ public static BigDecimal ceil(BigDecimal inputValue) { if (inputValue == null) return null; Double value = Math.ceil(inputValue.doubleValue()); return new BigDecimal(value); } /** * Returns the largest integer value that is less than or equal to {@code inputValue} * * @param number the value whose floor value is to be retrieved * @return the largest integer value that is less than or equal to {@code inputValue} */ public static Float floor(Float number) { if (number == null) return null; Double value = Math.floor(number); return value.floatValue(); } /** * Returns the largest integer value that is less than or equal to {@code inputValue} * * @param number the value whose floor value is to be retrieved * @return the largest integer value that is less than or equal to {@code inputValue} */ public static Double floor(Double number) { if (number == null) return null; Double value = Math.floor(number); return value; } /** * Returns the largest integer value that is less than or equal to {@code inputValue} * * @param number the value whose floor value is to be retrieved * @return the largest integer value that is less than or equal to {@code inputValue} */ public static BigDecimal floor(BigDecimal number) { if (number == null) return null; Double value = Math.floor(number.doubleValue()); return new BigDecimal(value); } /** * Returns the length of {@code inputValue} * * @param inputValue the value whose length is to be retrieved * @return length of {@code inputValue} */ public static Integer length(Integer inputValue) { if (inputValue == null) return null; return String.valueOf(inputValue).length(); } /** * Returns the length of {@code inputValue} * * @param inputValue the value whose length is to be retrieved * @return length of {@code inputValue} */ public static Integer length(Long inputValue) { if (inputValue == null) return null; Integer length = String.valueOf(inputValue).length(); return length; } /** * Returns the length of {@code inputValue} * * @param inputValue the value whose length is to be retrieved * @return length of {@code inputValue} */ public static Integer length(Float inputValue) { if (inputValue == null) return null; Integer length = String.valueOf(inputValue).length(); return length; } /** * Returns the length of {@code inputValue} * * @param inputValue the value whose length is to be retrieved * @return length of {@code inputValue} */ public static Integer length(Double inputValue) { if (inputValue == null) return null; Integer length = String.valueOf(inputValue).length(); return length; } /** * Returns the length of {@code inputValue} * * @param inputValue the value whose length is to be retrieved * @return length of {@code inputValue} */ public static Integer length(Short inputValue) { if (inputValue == null) return null; Integer length = String.valueOf(inputValue).length(); return length; } }