/*
 This file is part of the software framework JStatCom, 
 a library for building applications for data based analysis.

 Copyright (C) 2000-2005  Alexander Benkwitz, Markus Kraetzig

 This library is free software; you can redistribute it and/or modify
 it under the terms of the GNU Lesser General Public License as
 published by the Free Software Foundation; either version 2.1 of the
 License, or (at your option) any later version.

 This library 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
 Lesser General Public License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 USA
 */

package com.jstatcom.util;

/**
 * This class is a collection of some mathematical functions. It can be used in
 * addition to the Math class.
 * 
 * @author A. Benkwitz, Markus Kraetzig
 */
public final class UMath {
    /**
     * Private constructor to avoid invocation.
     */
    private UMath() {
    }

    /**
     * Transforms arbitrary double values to a
     * double in the interval (-10,-1] or [1,10) and a power of
     * 10. It breaks number to a number of the form #.####... and a power of 10.
     * { mant,pow } = base10(arg) with mant * 10^pow == arg
     * returnValue[0]=mant, returnValue[1]=pow.
     * If arg is NaN or +/-INF, then {arg, 0} is
     * returned.
     * 
     * @param arg
     *            the number to break
     * 
     * @return two dimensional double array
     *         
     */
    public static double[] base10(double arg) {

        if (arg == Double.POSITIVE_INFINITY || arg == Double.NEGATIVE_INFINITY)
            return new double[] { arg, 0 };

        if (!(arg <= 0 || arg > 0)) // must be NaN then
            return new double[] { Double.NaN, 0 };

        if (arg == 0)
            return new double[] { 0, 0 };

        double a = Math.abs(arg);
        int i = 0;
        if (a < 1) {
            // case: absolute value of arg smaller than 1
            i = 1;
            while (a * Math.pow(10, ++i) < 10)
                ;
            i--;
            return new double[] { round(arg * Math.pow(10, i), 18 - i), -1 * i };
        }
        if (a < 10) {
            // case: absolute value of arg smaller than 10, but bigger or equal
            // 1
            return new double[] { arg, 0 };
        }
        // case: absolute value of arg bigger or equal 10
        i = 1;
        while (Math.pow(10, ++i) < a)
            ;
        i--;
        return new double[] { (arg / Math.pow(10, i)), i };

    }

    /**
     * Computes the closest multiple of unit for
     * value. If value is just in the middle
     * between two multiples of unit, the higher multiple is
     * choosen, for example 15 == closestMultiple(13, 5), 
     * 10 == closestMultiple(12, 5), 8 == closestMultiple(7, 4).
     * 
     * @param value
     *            defines a closest multiple of unit
     * @param unit
     *            defines the steps
     * @return closest multiple of unit for value,
     *         returns value if (unit == 1), returns 0
     *         if (unit == 0)
     */
    public static int closestMultiple(int value, int unit) {
        if (unit == 0)
            return 0;

        if (unit == 1 || unit == -1)
            return value;

        double uu = Math.abs(unit);
        return (int) round(value / uu, 0) * unit * sign(unit);

    }

    /**
     * Rounds the arg to a number with n decimal
     * digits, for example 2.368=round(2.367849,3) If
     * arg is NaN or +/-INF, then arg is returned.
     * 
     * @param arg
     *            the number to round
     * @param n
     *            the number of decimal digits to round for
     * 
     * @return the rounded number
     */
    public static double round(double arg, int n) {
        if (arg == Double.POSITIVE_INFINITY || arg == Double.NEGATIVE_INFINITY)
            return arg;

        if (!(arg <= 0 || arg > 0)) // must be NaN then
            return Double.NaN;

        return Math.round(Math.pow(10, n) * arg) / Math.pow(10, n);
    }

    /**
     * Returns -1 if arg is smaller than zero and 1 if it is
     * greater or equal to zero.
     * 
     * @param arg
     *            the number to check the sign for
     * @return -1 if (arg < 0), otherwise 1
     */
    public static int sign(int arg) {
        if (arg < 0)
            return -1;

        return 1;
    }
}
 

Ads help maintain this website.