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

org.apfloat.internal.IntCRTMath Maven / Gradle / Ivy

/*
 * Apfloat arbitrary precision arithmetic library
 * Copyright (C) 2002-2017  Mikko Tommila
 *
 * 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
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
package org.apfloat.internal;

import static org.apfloat.internal.IntModConstants.*;
import static org.apfloat.internal.IntRadixConstants.*;

/**
 * Basic arithmetic for calculating the Chinese Remainder
 * Theorem. Works for the int type.
 *
 * @version 1.6
 * @author Mikko Tommila
 */

public class IntCRTMath
    extends IntBaseMath
{
    /**
     * Creates a carry-CRT math using the specified radix.
     *
     * @param radix The radix that will be used.
     */

    public IntCRTMath(int radix)
    {
        super(radix);
        this.base = BASE[radix];
    }

    /**
     * Multiplies two words by one word to produce a result of three words.
     * Most significant word is stored first.
     *
     * @param src Source array, first multiplicand.
     * @param factor Second multiplicand.
     * @param dst Destination array.
     */

    public final void multiply(int[] src, int factor, int[] dst)
    {
        long tmp = (long) src[1] * (long) factor;
        int carry = (int) (tmp >>> MAX_POWER_OF_TWO_BITS);

        dst[2] = (int) tmp & BASE_MASK;     // = tmp % MAX_POWER_OF_TWO_BASE

        tmp = (long) src[0] * (long) factor + carry;
        carry = (int) (tmp >>> MAX_POWER_OF_TWO_BITS);

        dst[1] = (int) tmp & BASE_MASK;     // = tmp % MAX_POWER_OF_TWO_BASE

        dst[0] = carry;
    }

    /**
     * Compares three words. Most significant word is stored first.
     *
     * @param src1 First operand.
     * @param src2 Second operand.
     *
     * @return Less than zero if src1 < src2, greater than zero if src1 > src2 and zero if src1 == src2.
     */

    public final int compare(int[] src1, int[] src2)
    {
        int result = src1[0] - src2[0];

        if (result != 0)
        {
            return result;
        }

        result = src1[1] - src2[1];

        if (result != 0)
        {
            return result;
        }

        return src1[2] - src2[2];
    }

    /**
     * Adds three words. Most significant word is stored first.
     *
     * @param src First operand.
     * @param srcDst Second operand, and destination of the operation.
     *
     * @return Overflow carry bit.
     */

    public final int add(int[] src, int[] srcDst)
    {
        int result = srcDst[2] + src[2],
            carry = (result < 0 ? 1 : 0);
        result = (result < 0 ? result - MAX_POWER_OF_TWO_BASE : result);

        srcDst[2] = result;

        result = srcDst[1] + src[1] + carry;
        carry = (result < 0 ? 1 : 0);
        result = (result < 0 ? result - MAX_POWER_OF_TWO_BASE : result);

        srcDst[1] = result;

        result = srcDst[0] + src[0] + carry;
        carry = (result < 0 ? 1 : 0);
        result = (result < 0 ? result - MAX_POWER_OF_TWO_BASE : result);

        srcDst[0] = result;

        return carry;
    }

    /**
     * Subtracts three words. Most significant word is stored first.
     *
     * @param src First operand.
     * @param srcDst Second operand, and destination of the operation.
     */

    public final void subtract(int[] src, int[] srcDst)
    {
        int result = srcDst[2] - src[2],
            carry = (result < 0 ? 1 : 0);
        result = (result < 0 ? result + MAX_POWER_OF_TWO_BASE : result);

        srcDst[2] = result;

        result = srcDst[1] - src[1] - carry;
        carry = (result < 0 ? 1 : 0);
        result = (result < 0 ? result + MAX_POWER_OF_TWO_BASE : result);

        srcDst[1] = result;

        result = srcDst[0] - src[0] - carry;
        // carry = (result < 0 ? 1 : 0);
        result = (result < 0 ? result + MAX_POWER_OF_TWO_BASE : result);

        srcDst[0] = result;
    }

    /**
     * Divides three words by the base to produce two words. Most significant word is stored first.
     *
     * @param srcDst Source and destination of the operation.
     *
     * @return Remainder of the division.
     */

    public final int divide(int[] srcDst)
    {
        long tmp = ((long) srcDst[0] << MAX_POWER_OF_TWO_BITS) + srcDst[1];
        int result = (int) (tmp / this.base),
            carry = (int) tmp - result * this.base;     // = tmp % this.base

        srcDst[0] = 0;
        srcDst[1] = result;

        tmp = ((long) carry << MAX_POWER_OF_TWO_BITS) + srcDst[2];
        result = (int) (tmp / this.base);
        carry = (int) tmp - result * this.base;         // = tmp % this.base

        srcDst[2] = result;

        return carry;
    }

    private static final long serialVersionUID = 6698972116690441263L;

    private static final int BASE_MASK = (1 << MAX_POWER_OF_TWO_BITS) - 1;

    private int base;
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy