MathUtil.java Source code

Java tutorial

Introduction

Here is the source code for MathUtil.java

Source

/*
 * MathUtil.java
 *
 * Copyright (C) 2005-2008 Tommi Laukkanen
 * http://www.substanceofcode.com
 *
 * This program 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 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

//package com.substanceofcode.util;

/**
 * Utility methods for mathematical problems.
 * 
 * @author Tommi Laukkanen
 */
public class MathUtil {

    /** Square root from 3 */
    final static public double SQRT3 = 1.732050807568877294;
    /** Log10 constant */
    final static public double LOG10 = 2.302585092994045684;
    /** ln(0.5) constant */
    final static public double LOGdiv2 = -0.6931471805599453094;
    public final static double EVal = 2.718281828459045235;

    /** Creates a new instance of MathUtil */
    private MathUtil() {
    }

    /**
     * Returns the value of the first argument raised to the power of the second
     * argument.
     * 
     * @author Mario Sansone
     */
    public static int pow(int base, int exponent) {
        boolean reciprocal = false;
        if (exponent < 0) {
            reciprocal = true;
        }
        int result = 1;
        while (exponent-- > 0) {
            result *= base;
        }
        return reciprocal ? 1 / result : result;
    }

    public static double pow(double base, int exponent) {
        boolean reciprocal = false;
        if (exponent < 0) {
            reciprocal = true;
        }
        double result = 1;
        while (exponent-- > 0) {
            result *= base;
        }
        return reciprocal ? 1 / result : result;
    }

    /** Arcus cos */
    static public double acos(double x) {
        double f = asin(x);
        if (f == Double.NaN) {
            return f;
        }
        return Math.PI / 2 - f;
    }

    /** Arcus sin */
    static public double asin(double x) {
        if (x < -1. || x > 1.) {
            return Double.NaN;
        }
        if (x == -1.) {
            return -Math.PI / 2;
        }
        if (x == 1) {
            return Math.PI / 2;
        }
        return atan(x / Math.sqrt(1 - x * x));
    }

    /** Arcus tan */
    static public double atan(double x) {
        boolean signChange = false;
        boolean Invert = false;
        int sp = 0;
        double x2, a;
        // check up the sign change
        if (x < 0.) {
            x = -x;
            signChange = true;
        }
        // check up the invertation
        if (x > 1.) {
            x = 1 / x;
            Invert = true;
        }
        // process shrinking the domain until x<PI/12
        while (x > Math.PI / 12) {
            sp++;
            a = x + SQRT3;
            a = 1 / a;
            x = x * SQRT3;
            x = x - 1;
            x = x * a;
        }
        // calculation core
        x2 = x * x;
        a = x2 + 1.4087812;
        a = 0.55913709 / a;
        a = a + 0.60310579;
        a = a - (x2 * 0.05160454);
        a = a * x;
        // process until sp=0
        while (sp > 0) {
            a = a + Math.PI / 6;
            sp--;
        }
        // invertation took place
        if (Invert) {
            a = Math.PI / 2 - a;
        }
        // sign change took place
        if (signChange) {
            a = -a;
        }
        //
        return a;
    }

    public static double log(double x) {
        if (x < 0) {
            return Double.NaN;
        }
        //
        if (x == 1) {
            return 0d;
        }

        if (x == 0) {
            return Double.NEGATIVE_INFINITY;
        }
        //
        if (x > 1) {
            x = 1 / x;
            return -1 * _log(x);
        }
        return _log(x);
    }

    public static double _log(double x) {

        double f = 0.0;
        // Make x to close at 1
        int appendix = 0;
        while (x > 0 && x < 1) {
            x = x * 2;
            appendix++;
        }
        //
        x = x / 2;
        appendix--;
        //
        double y1 = x - 1;
        double y2 = x + 1;
        double y = y1 / y2;
        //
        double k = y;
        y2 = k * y;
        //
        for (long i = 1; i < 50; i += 2) {
            f = f + (k / i);
            k = k * y2;
        }
        //
        f = f * 2;
        for (int i = 0; i < appendix; i++) {
            f = f + (LOGdiv2);
        }
        //
        return f;
    }

    /**
     * Replacement for missing Math.pow(double, double)
     * 
     * @param x
     * @param y
     * @return
     */
    public static double pow(double x, double y) {
        // Convert the real power to a fractional form
        int den = 1024; // declare the denominator to be 1024

        /*
         * Conveniently 2^10=1024, so taking the square root 10 times will yield
         * our estimate for n. In our example n^3=8^2 n^1024 = 8^683.
         */

        int num = (int) (y * den); // declare numerator

        int iterations = 10; /*
                             * declare the number of square root iterations
                             * associated with our denominator, 1024.
                             */

        double n = Double.MAX_VALUE; /*
                                     * we initialize our estimate, setting it to
                                     * max
                                     */

        while (n >= Double.MAX_VALUE && iterations > 1) {
            /*
             * We try to set our estimate equal to the right hand side of the
             * equation (e.g., 8^2048). If this number is too large, we will
             * have to rescale.
             */

            n = x;

            for (int i = 1; i < num; i++) {
                n *= x;
            }

            /*
             * here, we handle the condition where our starting point is too
             * large
             */
            if (n >= Double.MAX_VALUE) {
                iterations--; /* reduce the iterations by one */

                den = (int) (den / 2); /* redefine the denominator */

                num = (int) (y * den); // redefine the numerator
            }
        }

        /*************************************************
         ** We now have an appropriately sized right-hand-side. Starting with
         * this estimate for n, we proceed.
         **************************************************/
        for (int i = 0; i < iterations; i++) {
            n = Math.sqrt(n);
        }

        // Return our estimate
        return n;
    }

    public final static int abs(int in) {
        if (in < 0.0) {
            return in * -1;
        }
        return in;
    }

    public final static long abs(long in) {
        if (in < 0.0) {
            return in * -1;
        }
        return in;
    }

    public final static double abs(double in) {
        if (in < 0.0) {
            return in * -1.0;
        }
        return in;
    }
}