Int128.avt

Переключить прокрутку окна
Загрузить этот исходный код

/*
    Реализация среды исполнения языка программирования
    Объектно-ориентированный продвинутый векторный транслятор

    Copyright © 2021, 2024 Малик Разработчик

    Это свободная программа: вы можете перераспространять ее и/или изменять
    ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
    в каком она была опубликована Фондом свободного программного обеспечения;
    либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.

    Эта программа распространяется в надежде, что она будет полезной,
    но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
    или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
    общественной лицензии GNU.

    Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
    вместе с этой программой. Если это не так, см.
    <https://www.gnu.org/licenses/>.
*/

package avt.lang.math;

import avt.lang.array.*;

public final class Int128(Object, Numeric, Comparable, Cloneable)
{
    public static final long2 MIN_VALUE = new long2 { 0x0000000000000000L, 0x8000000000000000L };
    public static final long2 MAX_VALUE = new long2 { 0xffffffffffffffffL, 0x7fffffffffffffffL };

    private static final int REAL_SIGN_MASK = 0x00008000;

    private static final int FLOAT_SIGNIFICAND_MASK = 0x007fffff;
    private static final int FLOAT_SIGN_MASK        = 0x80000000;

    private static final long DOUBLE_SIGNIFICAND_MASK = 0x000fffffffffffffL;
    private static final long DOUBLE_SIGN_MASK        = 0x8000000000000000L;

    private static final long FLOAT_ROUND_MASK  = 0x0000008000000000L;
    private static final long DOUBLE_ROUND_MASK = 0x0000000000000400L;

    public static native int signum(long2 value);

    public static native int compare(long2 value0, long2 value1);

    public static native int compareUnsigned(long2 value0, long2 value1);

    public static native long2 neg(long2 value);

    public static native long2 mul(long2 value0, long2 value1);

    public static native long2 div(long2 value0, long2 value1);

    public static native long2 divUnsigned(long2 value0, long2 value1);

    public static native long2 rem(long2 value0, long2 value1);

    public static native long2 remUnsigned(long2 value0, long2 value1);

    public static native long2 add(long2 value0, long2 value1);

    public static native long2 sub(long2 value0, long2 value1);

    public static native long2 max(long2 value0, long2 value1);

    public static native long2 maxUnsigned(long2 value0, long2 value1);

    public static native long2 min(long2 value0, long2 value1);

    public static native long2 minUnsigned(long2 value0, long2 value1);

    public static native long2 shiftLeft(long2 value, int bits);

    public static native long2 shiftRight(long2 value, int bits);

    public static native long2 shiftRightUnsigned(long2 value, int bits);

    public static native long2 rotateLeft(long2 value, int bits);

    public static native long2 rotateRight(long2 value, int bits);

    public static native long2 fromLong(long value);

    public static long2 parse(CharArray string) { return parse(string, 10); }

    public static long2 parse(CharArray string, int radix) {
        int length = string == null ? 0 : string.length;
        if(length <= 0)
        {
            throw new NumberFormatException(avt.lang.package.getResourceString("illegal-argument.number-format"));
        }
        if(radix < Char.MIN_RADIX || radix > Char.MAX_RADIX)
        {
            throw new NumberFormatException(String.format(avt.lang.package.getResourceString("illegal-argument.number-format.radix"), new Object[] { new Int(radix) }));
        }
        boolean negative = false;
        int index = 0;
        long2 limit = new long2 { 0x0000000000000001L, 0x8000000000000000L };
        if(string[0] == '-')
        {
            negative = true;
            limit = sub(limit, 1);
            index++;
        }
        long2 longradix = radix;
        long2 mulmin = div(limit, longradix);
        long2 result = 0;
        if(index < length)
        {
            long2 digit = Char.toDigit(string[index++], radix);
            if((long) digit < 0L)
            {
                throw new NumberFormatException(avt.lang.package.getResourceString("illegal-argument.number-format"));
            }
            result = neg(digit);
        }
        while(index < length)
        {
            long2 digit = Char.toDigit(string[index++], radix);
            if((long) digit < 0L || compare(result, mulmin) < 0 || compare(result = mul(result, longradix), add(limit, digit)) < 0)
            {
                throw new NumberFormatException(avt.lang.package.getResourceString("illegal-argument.number-format"));
            }
            result = sub(result, digit);
        }
        if(negative)
        {
            if(index <= 1)
            {
                throw new NumberFormatException(avt.lang.package.getResourceString("illegal-argument.number-format"));
            }
            return result;
        }
        return neg(result);
    }

    public static long2 parseUnsigned(CharArray string) { return parseUnsigned(string, 10); }

    public static long2 parseUnsigned(CharArray string, int radix) {
        int length = string == null ? 0 : string.length;
        if(length <= 0)
        {
            throw new NumberFormatException(avt.lang.package.getResourceString("illegal-argument.number-format"));
        }
        if(radix < Char.MIN_RADIX || radix > Char.MAX_RADIX)
        {
            throw new NumberFormatException(String.format(avt.lang.package.getResourceString("illegal-argument.number-format.radix"), new Object[] { new Int(radix) }));
        }
        int index = 1;
        long2 longradix = radix;
        long2 mulmin = divUnsigned(new long2 { 0xffffffffffffffffL, 0xffffffffffffffffL }, longradix);
        long2 result = Char.toDigit(string[0], radix);
        if((long) result < 0L)
        {
            throw new NumberFormatException(avt.lang.package.getResourceString("illegal-argument.number-format"));
        }
        while(index < length)
        {
            long2 digit = Char.toDigit(string[index++], radix);
            if((long) digit < 0L || compareUnsigned(result, mulmin) > 0 || compareUnsigned(result = mul(result, longradix), sub(new long2 { 0xffffffffffffffffL, 0xffffffffffffffffL }, digit)) > 0)
            {
                throw new NumberFormatException(avt.lang.package.getResourceString("illegal-argument.number-format"));
            }
            result = add(result, digit);
        }
        return result;
    }

    public static native float toFloat(long2 value);

    public static native double toDouble(long2 value);

    public static native real toReal(long2 value);

    public static String toBinaryString(long2 value) { return toShiftUnsignedString(value, 1); }

    public static String toOctalString(long2 value) { return toShiftUnsignedString(value, 3); }

    public static String toHexString(long2 value) { return toShiftUnsignedString(value, 4); }

    public static String toString(long2 value) { return toString(value, 10); }

    public static String toString(long2 value, int radix) {
        boolean negative = signum(value) < 0;
        int index = 128;
        int length = index + 1;
        char[] buffer = new char[length];
        if(radix < Char.MIN_RADIX || radix > Char.MAX_RADIX) radix = 10;
        if(!negative) value = neg(value);
        for(long2 longradix = radix, long2 negradix = neg(longradix); compare(value, negradix) <= 0; value = div(value, longradix)) buffer[index--] = Char.toChar((int) neg(rem(value, longradix)));
        buffer[index] = Char.toChar((int) neg(value));
        if(negative) buffer[--index] = '-';
        return new String(buffer, index, length - index);
    }

    public static String toUnsignedString(long2 value) { return toUnsignedString(value, 10); }

    public static String toUnsignedString(long2 value, int radix) {
        int index = 127;
        int length = index + 1;
        char[] buffer = new char[length];
        if(radix < Char.MIN_RADIX || radix > Char.MAX_RADIX) radix = 10;
        for(long2 longradix = radix; compareUnsigned(value, longradix) >= 0; value = divUnsigned(value, longradix)) buffer[index--] = Char.toChar((int) remUnsigned(value, longradix));
        buffer[index] = Char.toChar((int) value);
        return new String(buffer, index, length - index);
    }

    public static Int128 valueOf(byte value) { return new Int128(value); }

    public static Int128 valueOf(short value) { return new Int128(value); }

    public static Int128 valueOf(int value) { return new Int128(value); }

    public static Int128 valueOf(long value) { return new Int128(value); }

    public static Int128 valueOf(long2 value) { return new Int128(value); }

    public static Int128 valueOf(CharArray string) {
        long2 value = parse(string, 10);
        return new Int128(value);
    }

    public static Int128 valueOf(CharArray string, int radix) {
        long2 value = parse(string, radix);
        return new Int128(value);
    }

    private static String toShiftUnsignedString(long2 value, int shift) {
        int index = 128;
        int length = index;
        int mask = (1 << shift) - 1;
        char[] buffer = new char[length];
        do
        {
            buffer[--index] = Char.toChar((int) value & mask);
        } while((value = shiftRightUnsigned(value, shift)) != 0L);
        return new String(buffer, index, length - index);
    }

    private final long2 fldValue;

    public (byte value) { fldValue = fromLong(value); }

    public (short value) { fldValue = fromLong(value); }

    public (int value) { fldValue = fromLong(value); }

    public (long value) { fldValue = fromLong(value); }

    public (long2 value) { fldValue = value; }

    public boolean equals(Object anot) { return anot == this || anot instanceof Int128 && ((Int128) anot).fldValue == fldValue; }

    public int hashCode() {
        long2 hash0 = fldValue;
        long hash1 = hash0[0] ^ hash0[1];
        return (int) (hash1 ^ (hash1 >> 32));
    }

    public long hashCodeAsLong() {
        long2 hash = fldValue;
        return hash[0] ^ hash[1];
    }

    public long2 hashCodeAsLong2() { return fldValue; }

    public String toString() { return toString(fldValue, 10); }

    public byte asByte() { return (byte) fldValue; }

    public byte2 asByte2() { return (byte) fldValue; }

    public byte4 asByte4() { return (byte) fldValue; }

    public byte8 asByte8() { return (byte) fldValue; }

    public short asShort() { return (short) fldValue; }

    public short2 asShort2() { return (short) fldValue; }

    public short4 asShort4() { return (short) fldValue; }

    public short8 asShort8() { return (short) fldValue; }

    public int asInt() { return (int) fldValue; }

    public int2 asInt2() { return (int) fldValue; }

    public int4 asInt4() { return (int) fldValue; }

    public int8 asInt8() { return (int) fldValue; }

    public long asLong() { return (long) fldValue; }

    public long2 asLong2() { return (long) fldValue; }

    public long4 asLong4() { return (long) fldValue; }

    public long8 asLong8() { return (long) fldValue; }

    public float asFloat() { return toFloat(fldValue); }

    public float2 asFloat2() { return toFloat(fldValue); }

    public float4 asFloat4() { return toFloat(fldValue); }

    public float8 asFloat8() { return toFloat(fldValue); }

    public double asDouble() { return toDouble(fldValue); }

    public double2 asDouble2() { return toDouble(fldValue); }

    public double4 asDouble4() { return toDouble(fldValue); }

    public double8 asDouble8() { return toDouble(fldValue); }

    public real asReal() { return toReal(fldValue); }

    public int compareTo(Comparable anot) { return anot == this ? EQUALS : !(anot instanceof Int128) ? INDEFINITE : compare(fldValue, ((Int128) anot).fldValue); }

    public Int128 clone() { return new Int128(fldValue); }

    public int kind { read = 0 }

    public long2 int128Value { read = fldValue }
}