/*
 * Redberry: symbolic tensor computations.
 *
 * Copyright (c) 2010-2015:
 *   Stanislav Poslavsky   
 *   Bolotin Dmitriy       
 *
 * This file is part of Redberry.
 *
 * Redberry 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.
 *
 * Redberry 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 Redberry. If not, see .
 */
package cc.redberry.core.number;

import cc.redberry.core.tensor.Tensor;
import org.apache.commons.math3.fraction.BigFraction;

import java.math.BigInteger;

/**
 * @author Stanislav Poslavsky
 */
public final class NumberUtils {

    private NumberUtils() {
    }

    /**
     * Checks that an object is not null.
     *
     * @param o Object to be checked.
     * @throws NullPointerException if {@code o} is {@code null}.
     */
    static void checkNotNull(Object o)
            throws NullPointerException {
        if (o == null)
            throw new NullPointerException();
    }

    public static Numeric createNumeric(double d) {
        //todo review performance profit
        if (d == 0)
            return Numeric.ZERO;
        else if (d == 1)
            return Numeric.ONE;
        else if (d == Double.POSITIVE_INFINITY)
            return Numeric.POSITIVE_INFINITY;
        else if (d == Double.NEGATIVE_INFINITY)
            return Numeric.NEGATIVE_INFINITY;
        else if (d != d)// d is NaN
            return Numeric.NaN;
        else
            return new Numeric(d);
    }

    public static Rational createRational(BigFraction fraction) {
        //FUTURE investigate performance
        if (fraction.getNumerator().equals(BigInteger.ZERO))
            return Rational.ZERO;
        if (BigFraction.ONE.equals(fraction))
            return Rational.ONE;
        return new Rational(fraction);
    }

    private final static BigInteger TWO = new BigInteger("2");

    /**
     * Computes the integer square root of a number.
     *
     * @param n The number.
     * @return The integer square root, i.e. the largest number whose square
     *         doesn't exceed n.
     */
    public static BigInteger sqrt(BigInteger n) {
        if (n.signum() >= 0) {
            final int bitLength = n.bitLength();
            BigInteger root = BigInteger.ONE.shiftLeft(bitLength / 2);

            while (!isSqrtXXX(n, root))
                root = root.add(n.divide(root)).divide(TWO);
            return root;
        } else
            throw new ArithmeticException("square root of negative number");
    }

    private static boolean isSqrtXXX(BigInteger n, BigInteger root) {
        final BigInteger lowerBound = root.pow(2);
        final BigInteger upperBound = root.add(BigInteger.ONE).pow(2);
        return lowerBound.compareTo(n) <= 0
                && n.compareTo(upperBound) < 0;
    }

    public static boolean isSqrt(BigInteger n, BigInteger root) {
        return n.compareTo(root.pow(2)) == 0;
    }

    public static BigInteger TWO_BIG_INT = new BigInteger("2");

    public static boolean isIntegerOdd(Complex complex) {
        if (complex.isInteger())
            return !complex.getReal().bigIntValue().mod(TWO_BIG_INT).equals(BigInteger.ZERO);
        return false;
    }

    public static boolean isIntegerEven(Complex complex) {
        if (complex.isInteger())
            return complex.getReal().bigIntValue().mod(TWO_BIG_INT).equals(BigInteger.ZERO);
        return false;
    }

    public static boolean isZeroOrIndeterminate(Complex complex) {
        return complex.isZero() || complex.isInfinite() || complex.isNaN();
    }

    public static boolean isIndeterminate(Complex complex) {
        return complex.isInfinite() || complex.isNaN();
    }

    public static boolean isRealNegative(Complex complex) {
        return complex.isReal() && complex.getReal().signum() < 0;
    }

    public static boolean isRealNumerical(Tensor tensor) {
        if (tensor instanceof Complex && ((Complex) tensor).isReal())
            return true;
        for (Tensor t : tensor)
            if (!isRealNumerical(t))
                return false;
        return true;
    }

    public static BigInteger pow(BigInteger base, BigInteger exponent) {
        BigInteger result = BigInteger.ONE;
        while (exponent.signum() > 0) {
            if (exponent.testBit(0)) result = result.multiply(base);
            base = base.multiply(base);
            exponent = exponent.shiftRight(1);
        }
        return result;
    }

    public static long pow(long base, long exponent) {
        long result = 1;
        while (exponent > 0) {
            if (exponent % 2 == 1) result *= base;
            base *= base;
            exponent >>= 1;
        }
        return result;
    }

    public static BigInteger factorial(int n) {
        BigInteger result = BigInteger.ONE;
        while (n != 0) {
            result = result.multiply(BigInteger.valueOf(n));
            --n;
        }
        return result;
    }

    //    public static Boolean getSignOfNumerical(Tensor tensor) {
//        //todo write better code
//        if (!isRealNumerical(tensor))
//            return null;
//        return getSignOfNumerical1(tensor);
//    }
//
//    private static Boolean getSignOfNumerical1(Tensor tensor) {
//        if (tensor instanceof Complex) {
//            Complex complex = (Complex) tensor;
//            return complex.isReal() && complex.getReal().signum() < 0;
//        }
//        if (tensor instanceof Power) {
//            Tensor base = tensor.get(0),
//                    exponent = tensor.get(1);
//            Boolean baseSign = getSignOfNumerical1(base);
//            if (baseSign == null)
//                return null;
//
//            //base is positive
//            if (baseSign == false)
//                return false;
//
//            //base is negative
//            if (!(exponent instanceof Complex))
//                return null;
//
//            Real real = ((Complex) exponent).getReal();
//            if (real.isNumeric())
//                return null;
//            Rational rational = (Rational) real;
//            rational.ge
//
//            return null;
//        }
//    }
//
}

 

Ads help maintain this website.