/* * @(#) src/net/sf/ivmaidns/util/UnsignedLong.java -- * Class for unsigned 'long' wrappers. ** * Copyright (c) 2000 Ivan Maidanski <ivmai@mail.ru> * All rights reserved. */ /* * This 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, or (at your option) * any later version. ** * This software 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 (GPL) for more details. ** * Linking this library statically or dynamically with other modules is * making a combined work based on this library. Thus, the terms and * conditions of the GNU General Public License cover the whole * combination. ** * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package net.sf.ivmaidns.util; import java.io.EOFException; import java.io.InputStream; import java.io.IOException; import java.io.OutputStream; /** * Class for unsigned 'long' wrappers. ** * This class wraps a primitive unsigned <CODE>long</CODE> value * (like <CODE>Long</CODE> class). The class also contains * <CODE>static</CODE> methods for the unsigned <CODE>long</CODE> * integer arithmetic: comparison, median, multiplication (simple * and modular), division, remainder, power, logarithm, factorial, * 'greatest common divisor', modular inversion, conversion to/from * a byte array (in the direct and reversed orders), stream bits * writing/reading, conversion to/from a string (in some given * radix). ** * @see UnsignedInt * @see LongVector * @see ByteVector * @see PseudoRandom * @see JavaConsts ** * @version 2.0 * @author Ivan Maidanski */ public final class UnsignedLong extends Number implements Immutable, ReallyCloneable, Sortable { /** * The class version unique identifier for serialization * interoperability. ** * @since 1.1 */ private static final long serialVersionUID = -458543887421779763L; /** * The wrapped (encapsulated) unsigned <CODE>long</CODE> value. ** * Important notes: this value is constant. ** * @serial ** * @see UnsignedLong#UnsignedLong(long) * @see #valueOf(java.lang.String) * @see #clone() * @see #hashCode() * @see #intValue() * @see #longValue() * @see #floatValue() * @see #doubleValue() * @see #equals(java.lang.Object) * @see #greaterThan(java.lang.Object) * @see #toString() */ protected long unsignedValue; /** * Constructs a new object that represents the specified primitive * unsigned <CODE>long</CODE> value. ** * @param unsignedValue * the unsigned value to be wrapped. ** * @see #valueOf(java.lang.String) * @see #clone() * @see #intValue() * @see #longValue() * @see #equals(java.lang.Object) * @see #greaterThan(java.lang.Object) * @see #toString() */ public UnsignedLong(long unsignedValue) { this.unsignedValue = unsignedValue; } /** * Converts <CODE>long</CODE> value into its hash code value. ** * The bits of the specified value are mixed in a particular order * to produce a single <CODE>int</CODE> 'hash' value. ** * @param value * the signed/unsigned value to be hashed. * @return * the resulting hash code value. ** * @see #hashCode() * @see #intValue() ** * @since 1.1 */ public static final int hashCode(long value) { return (int)((value >> (JavaConsts.INT_SIZE - 1)) >> 1) ^ (int)value; } /** * Tests whether the first specified unsigned integer is greater * than the second one. ** * @param unsignedA * the first compared unsigned value. * @param unsignedB * the second compared unsigned value. * @return * <CODE>true</CODE> if and only if <VAR>unsignedA</VAR> is greater * than <VAR>unsignedB</VAR> (in the unsigned manner). ** * @see #greaterOrEqual(long, long) * @see #compare(long, long) * @see #min(long, long) * @see #max(long, long) * @see #median(long, long, long) * @see #greaterThan(java.lang.Object) */ public static final boolean greater(long unsignedA, long unsignedB) { if ((unsignedA ^ unsignedB) >= 0L) unsignedA = unsignedB - unsignedA; return unsignedA < 0L; } /** * Tests whether the first specified unsigned integer is greater or * equal to the second one. ** * @param unsignedA * the first compared unsigned value. * @param unsignedB * the second compared unsigned value. * @return * <CODE>true</CODE> if and only if <VAR>unsignedA</VAR> is not less * than <VAR>unsignedB</VAR> (in the unsigned manner). ** * @see #greater(long, long) * @see #compare(long, long) * @see #min(long, long) * @see #max(long, long) * @see #median(long, long, long) * @see #equals(java.lang.Object) * @see #greaterThan(java.lang.Object) */ public static final boolean greaterOrEqual(long unsignedA, long unsignedB) { if ((unsignedA ^ unsignedB) >= 0L) unsignedB = unsignedA - unsignedB; return unsignedB >= 0L; } /** * Compares two given unsigned integer values. ** * This method returns a signed integer indicating * 'less-equal-greater' relation between the specified * <CODE>long</CODE> values. ** * @param unsignedA * the first compared unsigned value. * @param unsignedB * the second compared unsigned value. * @return * a negative integer, zero, or a positive integer as * <VAR>valueA</VAR> is less than, equal to, or greater than * <VAR>valueB</VAR> (in the unsigned manner). ** * @see #signedCompare(long, long) * @see #greater(long, long) * @see #greaterOrEqual(long, long) * @see #min(long, long) * @see #max(long, long) * @see #median(long, long, long) * @see #equals(java.lang.Object) * @see #greaterThan(java.lang.Object) */ public static final int compare(long unsignedA, long unsignedB) { int cmp = 0; if ((unsignedA ^ unsignedB) < 0L || (unsignedA = unsignedB - unsignedA) != 0L) { cmp = -1; if (unsignedA < 0L) cmp = 1; } return cmp; } /** * Compares two given (signed) integer values. ** * This method returns a signed integer indicating * 'less-equal-greater' relation between the specified * <CODE>long</CODE> values. ** * @param valueA * the first compared (signed) value. * @param valueB * the second compared (signed) value. * @return * a negative integer, zero, or a positive integer as * <VAR>valueA</VAR> is less than, equal to, or greater than * <VAR>valueB</VAR>. ** * @see #compare(long, long) * @see #signedMedian(long, long, long) ** * @since 2.0 */ public static final int signedCompare(long valueA, long valueB) { int cmp = 0; if (valueA != valueB) { cmp = -1; if (valueA > valueB) cmp = 1; } return cmp; } /** * Returns the minimum of two given unsigned integer values. ** * @param unsignedA * the first unsigned value. * @param unsignedB * the second unsigned value. * @return * <VAR>unsignedA</VAR> if <VAR>unsignedA</VAR> is less (in the * unsigned manner) than <VAR>unsignedB</VAR>, else * <VAR>unsignedB</VAR>. ** * @see #max(long, long) * @see #median(long, long, long) * @see #greater(long, long) * @see #greaterOrEqual(long, long) * @see #compare(long, long) */ public static final long min(long unsignedA, long unsignedB) { long delta = unsignedB; if ((unsignedA ^ unsignedB) >= 0L) delta = unsignedA - unsignedB; if (delta >= 0L) unsignedA = unsignedB; return unsignedA; } /** * Returns the maximum of two given unsigned integer values. ** * @param unsignedA * the first unsigned value. * @param unsignedB * the second unsigned value. * @return * <VAR>unsignedA</VAR> if <VAR>unsignedA</VAR> is greater (in the * unsigned manner) than <VAR>unsignedB</VAR>, else * <VAR>unsignedB</VAR>. ** * @see #min(long, long) * @see #median(long, long, long) * @see #greater(long, long) * @see #greaterOrEqual(long, long) * @see #compare(long, long) */ public static final long max(long unsignedA, long unsignedB) { long delta = unsignedB; if ((unsignedA ^ unsignedB) >= 0L) delta = unsignedA - unsignedB; if (delta >= 0L) unsignedB = unsignedA; return unsignedB; } /** * Returns the 'median' (middle value) of three given unsigned * integer values. ** * @param unsignedA * the first unsigned value. * @param unsignedB * the second unsigned value. * @param unsignedC * the third unsigned value. * @return * <VAR>unsignedA</VAR>, <VAR>unsignedB</VAR> or * <VAR>unsignedC</VAR> according to which one of these values is * between (in the unsigned manner) the other values. ** * @see #signedMedian(long, long, long) * @see #min(long, long) * @see #max(long, long) * @see #greater(long, long) * @see #greaterOrEqual(long, long) * @see #compare(long, long) ** * @since 1.1 */ public static final long median(long unsignedA, long unsignedB, long unsignedC) { long delta; if (((delta = unsignedA) ^ unsignedB) >= 0L) delta = unsignedB - unsignedA; if (delta >= 0L) { delta = unsignedA; unsignedA = unsignedB; unsignedB = delta; } if (((delta = unsignedC) ^ unsignedA) >= 0L) delta = unsignedA - unsignedC; if (delta >= 0L) { if (((unsignedA = unsignedB) ^ unsignedC) >= 0L) unsignedB = unsignedC - unsignedA; if (unsignedB >= 0L) unsignedA = unsignedC; } return unsignedA; } /** * Returns the 'median' (middle value) of three given (signed) * integer values. ** * @param valueA * the first (signed) value. * @param valueB * the second (signed) value. * @param valueC * the third (signed) value. * @return * <VAR>valueA</VAR>, <VAR>valueB</VAR> or <VAR>valueC</VAR> * according to which one of these values is between the other * values. ** * @see #median(long, long, long) * @see #signedCompare(long, long) ** * @since 1.1 */ public static final long signedMedian(long valueA, long valueB, long valueC) { if (valueA <= valueB) { long delta = valueA; valueA = valueB; valueB = delta; } if (valueA >= valueC && (valueA = valueB) <= valueC) valueA = valueC; return valueA; } /** * Returns the highest half of 'long' (full) product of two given * unsigned integers. ** * @param unsignedA * the first unsigned value. * @param unsignedB * the second unsigned value. * @return * the (unsigned) top half of <VAR>unsignedA</VAR> multiplied by * <VAR>unsignedB</VAR>. ** * @see #divHigh(long, long, long) * @see #mulLow(long, long) * @see #mulDiv(long, long, long, boolean) * @see #mulMod(long, long, long) * @see #power(long, int) * @see #factorial(int) */ public static final long mulHigh(long unsignedA, long unsignedB) { long highA = unsignedA >>> (JavaConsts.LONG_SIZE >> 1); long highB = unsignedB >>> (JavaConsts.LONG_SIZE >> 1); unsignedA &= ~(-1L << (JavaConsts.LONG_SIZE >> 1)); unsignedB &= ~(-1L << (JavaConsts.LONG_SIZE >> 1)); unsignedA = ((unsignedA * unsignedB) >>> (JavaConsts.LONG_SIZE >> 1)) + unsignedA * highB; unsignedA += unsignedB *= highA; highA = highA * highB + (unsignedA >>> (JavaConsts.LONG_SIZE >> 1)); if ((unsignedA ^ unsignedB) >= 0L) unsignedB = unsignedA - unsignedB; if (unsignedB < 0L) highA -= -1L << (JavaConsts.LONG_SIZE >> 1); return highA; } /** * Returns the lowest half of 'long' (full) product of two given * unsigned integers. ** * @param unsignedA * the first unsigned value. * @param unsignedB * the second unsigned value. * @return * the (unsigned) bottom half of <VAR>unsignedA</VAR> multiplied by * <VAR>unsignedB</VAR>. ** * @see #divLow(long, long, long) * @see #remLow(long, long, long) * @see #mulHigh(long, long) * @see #mulDiv(long, long, long, boolean) * @see #mulMod(long, long, long) * @see #power(long, int) * @see #factorial(int) */ public static final long mulLow(long unsignedA, long unsignedB) { return unsignedA * unsignedB; } /** * Returns the result of integer division of one given unsigned * value by another one. ** * @param unsignedA * the first unsigned value. * @param unsignedB * the second unsigned value. * @return * the unsigned result of <VAR>unsignedA</VAR> divided by * <VAR>unsignedB</VAR>. * @exception ArithmeticException * if <VAR>unsignedB</VAR> is <CODE>0</CODE>. ** * @see #mulLow(long, long) * @see #rem(long, long) * @see #divHigh(long, long, long) * @see #divLow(long, long, long) * @see #mulDiv(long, long, long, boolean) * @see #gcd(long, long) * @see #inverseMod(long, long) */ public static final long div(long unsignedA, long unsignedB) throws ArithmeticException { long unsignedRes = 0L; if (unsignedA >= 0L) { if (unsignedB >= 0L) unsignedRes = unsignedA / unsignedB; } else if (unsignedB >= 0L && (unsignedA -= (unsignedRes = ((unsignedA >>> 1) / unsignedB) << 1) * unsignedB) < 0L || unsignedA >= unsignedB) unsignedRes++; return unsignedRes; } /** * Returns the highest half of the result of integer division of * join of two given halves of unsigned value by another one. ** * The result is the same as of * <CODE>div(unsignedHighA, unsignedB)</CODE>. ** * @param unsignedHighA * the top half of the first unsigned value. * @param unsignedLowA * the bottom half of the first unsigned value. * @param unsignedB * the second unsigned value. * @return * the top half of the unsigned result of joined * <VAR>unsignedHighA</VAR>:<VAR>unsignedLowA</VAR> divided by * <VAR>unsignedB</VAR>. * @exception ArithmeticException * if <VAR>unsignedB</VAR> is <CODE>0</CODE>. ** * @see #divLow(long, long, long) * @see #mulHigh(long, long) * @see #mulLow(long, long) * @see #div(long, long) * @see #mulDiv(long, long, long, boolean) */ public static final long divHigh(long unsignedHighA, long unsignedLowA, long unsignedB) throws ArithmeticException { return div(unsignedHighA, unsignedB); } /** * Returns the lowest half of the result of integer division of join * of two given halves of unsigned value by another one. ** * @param unsignedHighA * the top half of the first unsigned value. * @param unsignedLowA * the bottom half of the first unsigned value. * @param unsignedB * the second unsigned value. * @return * the bottom half of the unsigned result of joined * <VAR>unsignedHighA</VAR>:<VAR>unsignedLowA</VAR> divided by * <VAR>unsignedB</VAR>. * @exception ArithmeticException * if <VAR>unsignedB</VAR> is <CODE>0</CODE>. ** * @see #divHigh(long, long, long) * @see #remLow(long, long, long) * @see #mulHigh(long, long) * @see #mulLow(long, long) * @see #div(long, long) * @see #mulDiv(long, long, long, boolean) * @see #gcd(long, long) */ public static final long divLow(long unsignedHighA, long unsignedLowA, long unsignedB) throws ArithmeticException { if ((unsignedHighA = rem(unsignedHighA, unsignedB)) == 0L) return div(unsignedLowA, unsignedB); long unsignedRes; if ((unsignedB & (-1L << (JavaConsts.LONG_SIZE >> 1))) == 0L) { unsignedRes = div(unsignedHighA = (unsignedHighA << (JavaConsts.LONG_SIZE >> 1)) | (unsignedLowA >>> (JavaConsts.LONG_SIZE >> 1)), unsignedB); return (unsignedRes << (JavaConsts.LONG_SIZE >> 1)) | div(((unsignedHighA - unsignedRes * unsignedB) << (JavaConsts.LONG_SIZE >> 1)) | unsignedLowA & ~(-1L << (JavaConsts.LONG_SIZE >> 1)), unsignedB); } if ((unsignedB & ~(-1L << (JavaConsts.LONG_SIZE >> 1))) == 0L) { unsignedB >>>= JavaConsts.LONG_SIZE >> 1; return (div(unsignedHighA, unsignedB) << (JavaConsts.LONG_SIZE >> 1)) | div((rem(unsignedHighA, unsignedB) << (JavaConsts.LONG_SIZE >> 1)) | (unsignedLowA >>> (JavaConsts.LONG_SIZE >> 1)), unsignedB); } unsignedRes = 0L; for (int shift = JavaConsts.LONG_SIZE; shift-- > 0; unsignedLowA <<= 1) { long oldHighA = unsignedHighA; unsignedHighA <<= 1; if (unsignedLowA < 0L) unsignedHighA++; unsignedRes <<= 1; if (oldHighA < 0L || ((unsignedHighA ^ unsignedB) >= 0L ? unsignedHighA - unsignedB : unsignedB) >= 0L) { unsignedHighA -= unsignedB; unsignedRes++; } } return unsignedRes; } /** * Returns the remainder of integer division of one given unsigned * value by another one. ** * The result is the same as of * <CODE>(unsignedA - div(unsignedA, unsignedB) * unsignedB)</CODE>. ** * @param unsignedA * the first unsigned value. * @param unsignedB * the second unsigned value. * @return * the unsigned remainder when <VAR>unsignedA</VAR> is divided by * <VAR>unsignedB</VAR>. * @exception ArithmeticException * if <VAR>unsignedB</VAR> is <CODE>0</CODE>. ** * @see #mulLow(long, long) * @see #div(long, long) * @see #remLow(long, long, long) * @see #inverseMod(long, long) */ public static final long rem(long unsignedA, long unsignedB) throws ArithmeticException { if (unsignedA >= 0L) { if (unsignedB >= 0L) unsignedA %= unsignedB; } else if (unsignedB >= 0L && (unsignedA = (((unsignedA >>> 1) % unsignedB) << 1) | unsignedA & 1L) < 0L || unsignedA >= unsignedB) unsignedA -= unsignedB; return unsignedA; } /** * Returns the remainder of integer division of join of two given * halves of unsigned value by another one. ** * @param unsignedHighA * the top half of the first unsigned value. * @param unsignedLowA * the bottom half of the first unsigned value. * @param unsignedB * the second unsigned value. * @return * the unsigned remainder when joined * <VAR>unsignedHighA</VAR>:<VAR>unsignedLowA</VAR> is divided by * <VAR>unsignedB</VAR>. * @exception ArithmeticException * if <VAR>unsignedB</VAR> is <CODE>0</CODE>. ** * @see #rem(long, long) * @see #divLow(long, long, long) * @see #mulHigh(long, long) * @see #mulLow(long, long) * @see #mulMod(long, long, long) */ public static final long remLow(long unsignedHighA, long unsignedLowA, long unsignedB) throws ArithmeticException { if ((unsignedHighA = rem(unsignedHighA, unsignedB)) == 0L) return rem(unsignedLowA, unsignedB); if ((unsignedB & (-1L << (JavaConsts.LONG_SIZE >> 1))) == 0L) return rem((rem((unsignedHighA << (JavaConsts.LONG_SIZE >> 1)) | (unsignedLowA >>> (JavaConsts.LONG_SIZE >> 1)), unsignedB) << (JavaConsts.LONG_SIZE >> 1)) | unsignedLowA & ~(-1L << (JavaConsts.LONG_SIZE >> 1)), unsignedB); if ((unsignedB & ~(-1L << (JavaConsts.LONG_SIZE >> 1))) == 0L) { unsignedB >>>= JavaConsts.LONG_SIZE >> 1; return (rem((rem(unsignedHighA, unsignedB) << (JavaConsts.LONG_SIZE >> 1)) | (unsignedLowA >>> (JavaConsts.LONG_SIZE >> 1)), unsignedB) << (JavaConsts.LONG_SIZE >> 1)) | unsignedLowA & ~(-1L << (JavaConsts.LONG_SIZE >> 1)); } for (int shift = JavaConsts.LONG_SIZE; shift-- > 0; unsignedLowA <<= 1) { long oldHighA = unsignedHighA; unsignedHighA <<= 1; if (unsignedLowA < 0L) unsignedHighA++; if (oldHighA < 0L || ((unsignedHighA ^ unsignedB) >= 0L ? unsignedHighA - unsignedB : unsignedB) >= 0L) unsignedHighA -= unsignedB; } return unsignedHighA; } /** * Returns a given value involved to the power of the specified * degree. ** * Overflow is not checked. If <VAR>degree</VAR> is negative then * <CODE>0</CODE> is returned. Important notes: <VAR>value</VAR> may * be signed or unsigned. ** * @param value * the signed/unsigned value to be involved to the power. * @param degree * the degree of the power. * @return * the signed/unsigned result of involving <VAR>value</VAR> to the * power of <VAR>degree</VAR>. ** * @see #mulLow(long, long) * @see #binLog(long) * @see #factorial(int) ** * @since 1.1 */ public static final long power(long value, int degree) { long res = 0L; if (degree >= 0) if (((2L - value) | value) < 0L) { for (res = 1L; degree > 0; value *= value, degree >>= 1) if ((degree & 1) != 0) res *= value; } else if (degree == 0 || value != 0L) { res = 1L; if (value == 2L) if (degree < JavaConsts.LONG_SIZE) res <<= degree; else res = 0L; } return res; } /** * Returns the integer part of binary logarithm of a given unsigned * value. ** * If <VAR>unsignedValue</VAR> is zero then <CODE>-1</CODE> is * returned, else the result is in the range from <CODE>0</CODE> to * <CODE>(JavaConsts LONG_SIZE - 1)</CODE>, inclusive. ** * @param unsignedValue * the unsigned argument of the logarithm. * @return * the result of logarithm computation for <VAR>unsignedValue</VAR>. ** * @see #power(long, int) * @see #factorial(int) ** * @since 1.2 */ public static final int binLog(long unsignedValue) { int res = -1; while ((unsignedValue & ~JavaConsts.INT_LMASK) != 0L) { unsignedValue >>>= JavaConsts.INT_SIZE; res += JavaConsts.INT_SIZE; } for (int value = (int)unsignedValue; value != 0; value >>>= 1, res++); return res; } /** * Computes the factorial of a given value. ** * Overflow is not checked. If <VAR>value</VAR> is negative or zero * then <CODE>0</CODE> is returned. ** * @param value * the factorial argument. * @return * the unsigned result of the factorial computation for * <VAR>value</VAR>. ** * @see #mulLow(long, long) * @see #power(long, int) * @see #binLog(long) ** * @since 1.1 */ public static final long factorial(int value) { long unsignedRes = 0L; if (value > 0) for (unsignedRes = 1L; value > 1; unsignedRes *= value--); return unsignedRes; } /** * Computes the greatest 'common divisor' (gcd) of two given * unsigned non-zero values. ** * Important notes: zero value (for any argument or result) is * treated as the largest unsigned <CODE>long</CODE> value plus one. ** * @param unsignedA * the first unsigned value. * @param unsignedB * the second unsigned value. * @return * the unsigned greatest common divisor of both <VAR>unsignedA</VAR> * and <VAR>unsignedB</VAR>. ** * @see #inverseMod(long, long) * @see #mulMod(long, long, long) * @see #mulDiv(long, long, long, boolean) * @see #binLog(long) ** * @since 1.1 */ public static final long gcd(long unsignedA, long unsignedB) { int shift = 0; long delta; if (unsignedA == 0L || unsignedB == 0L) if (((int)unsignedA & 1) == 0) { unsignedA = ((unsignedA - 1L) >>> 1) + 1L; if (((int)unsignedB & 1) == 0) { shift = 1; unsignedB = ((unsignedB - 1L) >>> 1) + 1L; } } else unsignedB = ~(-1L >>> 1); if (unsignedA != 1L) while (unsignedA != unsignedB) if (((int)unsignedA & 1) == 0) { unsignedA >>>= 1; if (((int)unsignedB & 1) == 0) { shift++; unsignedB >>>= 1; } } else if (((int)unsignedB & 1) == 0) unsignedB >>>= 1; else if ((delta = (unsignedA >>> 1) - (unsignedB >>> 1)) > 0L) unsignedA = delta; else unsignedB = -delta; return unsignedA << shift; } /** * Computes the modular 'inversion' of a given unsigned value. ** * It is the inverse operation for modular multiplication. That is, * if both <VAR>unsignedA</VAR> and <VAR>unsignedMax</VAR> are * non-zero and <CODE>gcd(unsignedA, unsignedMax + 1) == 1</CODE> * then <CODE>mulMod(result, unsignedA, unsignedMax)</CODE> is * <CODE>1</CODE>. The result of modular inversion is in the range * from <CODE>1</CODE> to <CODE>max(unsignedMax, 1)</CODE>, * inclusive. ** * @param unsignedA * the unsigned value to inverse. * @param unsignedMax * the unsigned maximum for modular multiplication. * @return * the unsigned result (not zero) of modular inversion of * <VAR>unsignedA</VAR> with respect to <VAR>unsignedMax</VAR>. ** * @see #mulMod(long, long, long) * @see #gcd(long, long) * @see #div(long, long) * @see #rem(long, long) ** * @since 1.1 */ public static final long inverseMod(long unsignedA, long unsignedMax) { long unsignedB, unsignedRes = 1L; if (unsignedA < 0L) { if (++unsignedMax > 0L && (unsignedA = (((unsignedA >>> 1) % unsignedMax) << 1) | unsignedA & 1L) < 0L || unsignedA >= unsignedMax) unsignedA -= unsignedMax; } else if (++unsignedMax > 0L) unsignedA %= unsignedMax; if (unsignedA != 0L && (unsignedB = unsignedMax - unsignedA) != unsignedA) { long unsignedQ = 0L, unsignedDiv, max = unsignedMax; if (unsignedA < 0L) { unsignedMax = unsignedA; unsignedRes = -1L; unsignedB = unsignedMax - (unsignedA = unsignedB); unsignedQ = 1L; } if ((unsignedB = unsignedMax - (unsignedDiv = (((unsignedB >>> 1) / unsignedA) << 1) + 1L) * unsignedA) < 0L || unsignedB >= unsignedA) { unsignedB -= unsignedA; unsignedDiv++; } while (unsignedB > 0L) { unsignedMax = unsignedA; unsignedA = unsignedB; unsignedRes = unsignedQ - (unsignedB = unsignedRes) * unsignedDiv; unsignedQ = unsignedB; unsignedB = unsignedMax - (unsignedDiv = unsignedMax / unsignedA) * unsignedA; } if (unsignedRes < 0L) unsignedRes += max; } return unsignedRes; } /** * Computes the modular 'multiplication' of two given unsigned * values. ** * This method returns the remainder of the result of integer * division of 'long' (full) product of <VAR>unsignedA</VAR> and * <VAR>unsignedB</VAR> by (<VAR>unsignedMax</VAR> plus one). The * result is in the range from <CODE>0</CODE> to * <VAR>unsignedMax</VAR>, inclusive. ** * @param unsignedA * the first unsigned value to multiply. * @param unsignedB * the second unsigned value to multiply. * @param unsignedMax * the unsigned maximum value for the result to have. * @return * the unsigned result of modular multiplication of * <VAR>unsignedA</VAR> and <VAR>unsignedB</VAR> with respect to * <VAR>unsignedMax</VAR>. ** * @see #inverseMod(long, long) * @see #gcd(long, long) * @see #mulDiv(long, long, long, boolean) * @see #mulHigh(long, long) * @see #remLow(long, long, long) ** * @since 1.1 */ public static final long mulMod(long unsignedA, long unsignedB, long unsignedMax) { long unsignedRes = 0L; if (unsignedA != 0L && unsignedB != 0L) { unsignedRes = unsignedA * unsignedB; if (++unsignedMax != 0L) unsignedRes = remLow(mulHigh(unsignedA, unsignedB), unsignedRes, unsignedMax); } return unsignedRes; } /** * Returns the lowest half of the result of integer division of * 'long' (full) product of the first two given unsigned non-zero * values by the third given unsigned non-zero value. ** * Important notes: zero value (for any argument) is treated as * the largest unsigned <CODE>long</CODE> value plus one. ** * @param unsignedA * the first unsigned value. * @param unsignedB * the second unsigned value. * @param unsignedC * the unsigned divisor value. * @param roundUp * <CODE>true</CODE> if the result of division is rounded upwards * (to the nearest greater integer value), else it is rounded * towards zero. * @return * the bottom half of the unsigned result of <VAR>unsignedA</VAR> * multiplied by <VAR>unsignedB</VAR> and divided by * <VAR>unsignedC</VAR>. ** * @see #mulHigh(long, long) * @see #mulLow(long, long) * @see #divLow(long, long, long) * @see #gcd(long, long) * @see #mulMod(long, long, long) * @see #inverseMod(long, long) */ public static final long mulDiv(long unsignedA, long unsignedB, long unsignedC, boolean roundUp) { long unsignedHigh; if (unsignedA == 0L || unsignedA == unsignedC) { unsignedHigh = unsignedB; unsignedB = unsignedA; unsignedA = unsignedHigh; } if (unsignedB != unsignedC) { if (unsignedB != 0L) { unsignedHigh = mulHigh(unsignedA, unsignedB); unsignedB *= unsignedA; unsignedA = unsignedHigh; } if (roundUp) { if (unsignedB == 0L) unsignedA--; unsignedB--; } else if ((unsignedA | unsignedB) == 0L) { unsignedA = -1L; unsignedB = -unsignedC; roundUp = true; } if (unsignedC != 0L) unsignedA = divLow(unsignedA, unsignedB, unsignedC); if (roundUp) unsignedA++; } return unsignedA; } /** * Puts a given value into the specified byte array. ** * This method splits <VAR>unsignedValue</VAR> to separate bytes and * puts them into <VAR>bytes</VAR> array sequentially (the last put * byte is the lowest of <VAR>unsignedValue</VAR>), starting at * <VAR>offset</VAR>. Negative <VAR>len</VAR> is treated as zero. If * an exception is thrown then <VAR>bytes</VAR> remains changed. * Else <VAR>bytes</VAR> content is altered. Important notes: if * <VAR>len</VAR> is greater than * <CODE>JavaConsts LONG_LENGTH</CODE> then <VAR>unsignedValue</VAR> * is zero-extended. ** * @param bytes * the byte array (must be non-<CODE>null</CODE>) to put to. * @param offset * the first array index (must be in the range) to put at. * @param unsignedValue * the value, containing the bytes (in its lowest part) to be put. * @param len * the amount of bytes to put. * @exception NullPointerException * if <VAR>bytes</VAR> is <CODE>null</CODE>. * @exception ArrayIndexOutOfBoundsException * if <VAR>len</VAR> is positive and (<VAR>offset</VAR> is negative * or is greater than <CODE>length</CODE> of <VAR>bytes</VAR> minus * <VAR>len</VAR>). ** * @see #toByteArray(long, int) * @see #getFromByteArray(byte[], int, int) * @see #putToIntelArray(byte[], int, long, int) * @see #writeBits(java.io.OutputStream, long, int) ** * @since 1.1 */ public static final void putToByteArray(byte[] bytes, int offset, long unsignedValue, int len) throws NullPointerException, ArrayIndexOutOfBoundsException { if (len > 0) { byte temp; for (temp = bytes[offset + len - 1]; len > JavaConsts.LONG_LENGTH; bytes[offset++] = 0, len--); len *= JavaConsts.BYTE_SIZE; while ((len -= JavaConsts.BYTE_SIZE) >= 0) bytes[offset++] = (byte)(unsignedValue >>> len); } len = bytes.length; } /** * Converts a given value into a byte array. ** * This method splits <VAR>unsignedValue</VAR> to separate bytes and * sequentially puts them into a newly created byte array (the last * put byte is the lowest of <VAR>unsignedValue</VAR>) of * <VAR>len</VAR> length. Negative <VAR>len</VAR> is treated as * zero. Important notes: if <VAR>len</VAR> is greater than * <CODE>JavaConsts LONG_LENGTH</CODE> then <VAR>unsignedValue</VAR> * is zero-extended. ** * @param unsignedValue * the value, containing the bytes (in its lowest part) to be put. * @param len * the amount of bytes to put (<CODE>length</CODE> of the array to * create). * @return * a newly created byte array (not <CODE>null</CODE>, with * <CODE>length</CODE> the same as non-negative <VAR>len</VAR>), * containing the bytes of <VAR>unsignedValue</VAR>. * @exception OutOfMemoryError * if there is not enough memory. ** * @see #putToByteArray(byte[], int, long, int) * @see #getFromByteArray(byte[], int, int) * @see #toIntelArray(long, int) * @see #writeBits(java.io.OutputStream, long, int) ** * @since 1.1 */ public static final byte[] toByteArray(long unsignedValue, int len) { if (len <= 0) len = 0; byte[] bytes = new byte[len]; putToByteArray(bytes, 0, unsignedValue, len); return bytes; } /** * Converts the specified region of a given byte array into an * unsigned value. ** * This method gets the elements of <VAR>bytes</VAR> array * sequentially starting at <VAR>offset</VAR> and joins them into an * unsigned value (the last got byte is the lowest of the result). * Negative <VAR>len</VAR> is treated as zero. <VAR>bytes</VAR> * content is not modified. ** * @param bytes * the byte array (must be non-<CODE>null</CODE>) to get from. * @param offset * the first array index (must be in the range) to get at. * @param len * the amount of bytes to get. * @return * an unsigned value, containing the got bytes (in its lowest part). * @exception NullPointerException * if <VAR>bytes</VAR> is <CODE>null</CODE>. * @exception ArrayIndexOutOfBoundsException * if <VAR>len</VAR> is positive and (<VAR>offset</VAR> is negative * or is greater than <CODE>length</CODE> of <VAR>bytes</VAR> minus * <VAR>len</VAR>). ** * @see #putToByteArray(byte[], int, long, int) * @see #toByteArray(long, int) * @see #getFromIntelArray(byte[], int, int) * @see #readBits(java.io.InputStream, int) ** * @since 1.1 */ public static final long getFromByteArray(byte[] bytes, int offset, int len) throws NullPointerException, ArrayIndexOutOfBoundsException { long unsignedValue = 0L; if (len > 0) do { unsignedValue = (unsignedValue << JavaConsts.BYTE_SIZE) | bytes[offset++] & JavaConsts.BYTE_MASK; } while (--len > 0); len = bytes.length; return unsignedValue; } /** * Puts a given value into the specified byte array in the reversed * order. ** * This method splits <VAR>unsignedValue</VAR> to separate bytes and * puts them into <VAR>bytes</VAR> array sequentially but in the * reversed ('Intel') order (the first put byte is the lowest of * <VAR>unsignedValue</VAR>), starting at <VAR>offset</VAR> (and * moving forward). Negative <VAR>len</VAR> is treated as zero. If * an exception is thrown then <VAR>bytes</VAR> remains changed. * Else <VAR>bytes</VAR> content is altered. Important notes: if * <VAR>len</VAR> is greater than * <CODE>JavaConsts LONG_LENGTH</CODE> then <VAR>unsignedValue</VAR> * is zero-extended. ** * @param bytes * the byte array (must be non-<CODE>null</CODE>) to put to. * @param offset * the first array index (must be in the range) to put at. * @param unsignedValue * the value, containing the bytes (in its lowest part) to be put. * @param len * the amount of bytes to put. * @exception NullPointerException * if <VAR>bytes</VAR> is <CODE>null</CODE>. * @exception ArrayIndexOutOfBoundsException * if <VAR>len</VAR> is positive and (<VAR>offset</VAR> is negative * or is greater than <CODE>length</CODE> of <VAR>bytes</VAR> minus * <VAR>len</VAR>). ** * @see #toIntelArray(long, int) * @see #getFromIntelArray(byte[], int, int) * @see #putToByteArray(byte[], int, long, int) ** * @since 2.0 */ public static final void putToIntelArray(byte[] bytes, int offset, long unsignedValue, int len) throws NullPointerException, ArrayIndexOutOfBoundsException { if (len > 0) { byte temp; temp = bytes[offset + len - 1]; do { bytes[offset++] = (byte)unsignedValue; if (--len <= 0) break; unsignedValue >>>= JavaConsts.BYTE_SIZE; } while (true); } len = bytes.length; } /** * Converts a given value in the reversed order into a byte array. ** * This method splits <VAR>unsignedValue</VAR> to separate bytes and * sequentially puts them into a newly created byte array but in the * reversed ('Intel') order (the first put byte is the lowest of * <VAR>unsignedValue</VAR>) of <VAR>len</VAR> length. Negative * <VAR>len</VAR> is treated as zero. Important notes: if * <VAR>len</VAR> is greater than * <CODE>JavaConsts LONG_LENGTH</CODE> then <VAR>unsignedValue</VAR> * is zero-extended. ** * @param unsignedValue * the value, containing the bytes (in its lowest part) to be put. * @param len * the amount of bytes to put (<CODE>length</CODE> of the array to * create). * @return * a newly created byte array (not <CODE>null</CODE>, with * <CODE>length</CODE> the same as non-negative <VAR>len</VAR>), * containing the bytes of <VAR>unsignedValue</VAR>. * @exception OutOfMemoryError * if there is not enough memory. ** * @see #putToIntelArray(byte[], int, long, int) * @see #getFromIntelArray(byte[], int, int) * @see #toByteArray(long, int) ** * @since 2.0 */ public static final byte[] toIntelArray(long unsignedValue, int len) { if (len <= 0) len = 0; byte[] bytes = new byte[len]; putToIntelArray(bytes, 0, unsignedValue, len); return bytes; } /** * Converts the specified region of a given byte array into an * unsigned value in the reversed order. ** * This method gets the elements of <VAR>bytes</VAR> array * sequentially but in the reversed ('Intel') order, starting at * <VAR>offset</VAR> (and moving forward) and joins them into an * unsigned value (the first got byte is the lowest of the result). * Negative <VAR>len</VAR> is treated as zero. <VAR>bytes</VAR> * content is not modified. ** * @param bytes * the byte array (must be non-<CODE>null</CODE>) to get from. * @param offset * the first array index (must be in the range) to get at. * @param len * the amount of bytes to get. * @return * an unsigned value, containing the got bytes (in its lowest part). * @exception NullPointerException * if <VAR>bytes</VAR> is <CODE>null</CODE>. * @exception ArrayIndexOutOfBoundsException * if <VAR>len</VAR> is positive and (<VAR>offset</VAR> is negative * or is greater than <CODE>length</CODE> of <VAR>bytes</VAR> minus * <VAR>len</VAR>). ** * @see #putToIntelArray(byte[], int, long, int) * @see #toIntelArray(long, int) * @see #getFromByteArray(byte[], int, int) ** * @since 2.0 */ public static final long getFromIntelArray(byte[] bytes, int offset, int len) throws NullPointerException, ArrayIndexOutOfBoundsException { long unsignedValue = 0; if (len > 0) { byte temp; temp = bytes[offset + len - 1]; if (len >= JavaConsts.LONG_LENGTH) len = JavaConsts.LONG_LENGTH; int shift = 0; do { unsignedValue |= (long)(bytes[offset++] & JavaConsts.BYTE_MASK) << shift; if (--len <= 0) break; shift += JavaConsts.BYTE_SIZE; } while (true); } len = bytes.length; return unsignedValue; } /** * Writes a group of bits to a given output stream. ** * Negative <VAR>count</VAR> is treated as zero. Important notes: if * <VAR>count</VAR> is greater than * <CODE>JavaConsts LONG_SIZE</CODE> then the specified value * (containing the bits to write) is zero-extended; <VAR>out</VAR> * is a byte-oriented stream, so given bits are padded with zeros * (on the most significant side); the bits are written starting * from the most significant one. ** * @param out * the stream (must be non-<CODE>null</CODE>) to write to. * @param unsignedValue * the unsigned value, containing bits (in its lowest part) to be * written. * @param count * the amount of bits to be written. * @exception NullPointerException * if <VAR>out</VAR> is <CODE>null</CODE>. * @exception IOException * if an I/O error occurs. ** * @see #readBits(java.io.InputStream, int) ** * @since 1.1 */ public static final void writeBits(OutputStream out, long unsignedValue, int count) throws NullPointerException, IOException { out.equals(out); if (count > 0) { int shift; if ((shift = count % JavaConsts.BYTE_SIZE) > 0) out.write((count -= shift) >= JavaConsts.LONG_SIZE ? 0 : (int)(unsignedValue >>> count) & ~(-1 << shift)); while (count > JavaConsts.LONG_SIZE) { out.write(0); count -= JavaConsts.BYTE_SIZE; } while ((count -= JavaConsts.BYTE_SIZE) >= 0) out.write((int)(unsignedValue >>> count)); } } /** * Reads a group of bits from a given input stream. ** * Negative <VAR>count</VAR> is treated as zero. If the * end-of-stream is detected then <CODE>EOFException</CODE> * (subclass of <CODE>IOException</CODE>) is thrown. Important * notes: if <VAR>count</VAR> is greater than * <CODE>JavaConsts LONG_SIZE</CODE> then the result contains only * tail (the least significant) read bits portion fit the result; * <VAR>in</VAR> is a byte-oriented stream, so padding bits are read * but set to zero (on the most significant side); the bits are read * starting from the most significant one. ** * @param in * the stream (must be non-<CODE>null</CODE>) to read from. * @param count * the amount of bits to be read. * @return * an unsigned value, containing read bits (in its lowest part, the * highest part of the result is set to zero if <VAR>count</VAR> is * less than <CODE>JavaConsts LONG_SIZE</CODE>). * @exception NullPointerException * if <VAR>in</VAR> is <CODE>null</CODE>. * @exception IOException * if the end-of-stream has been reached or an I/O error occurs. ** * @see #writeBits(java.io.OutputStream, long, int) ** * @since 1.1 */ public static final long readBits(InputStream in, int count) throws NullPointerException, IOException { in.equals(in); long unsignedValue = 0L; if (count > 0) { int shift; if ((shift = count % JavaConsts.BYTE_SIZE) > 0) { if ((unsignedValue = in.read()) < 0L) throw new EOFException(); unsignedValue &= ~(-1 << shift); count -= shift; } while ((count -= JavaConsts.BYTE_SIZE) >= 0) if ((shift = in.read()) >= 0) unsignedValue = shift & JavaConsts.BYTE_MASK | (unsignedValue << JavaConsts.BYTE_SIZE); else throw new EOFException(); } return unsignedValue; } /** * Converts a given signed/unsigned value into its string * representation in the specified radix. ** * <VAR>value</VAR> is unsigned only if <VAR>isUnsigned</VAR> and * not <VAR>forceSign</VAR>. If <VAR>forceSign</VAR> then result * always has a sign (if <VAR>isUnsigned</VAR> then the positive * sign is space else '+' character) else result has a sign ('-' * character) if <VAR>value</VAR> is negative. The result is * left-padded with spaces (before the sign prefix) if * <VAR>minLength</VAR> is negative else with '0' characters (after * the sign prefix). The absolute value of <VAR>minLength</VAR> * specifies the minimal length of the result (anyhow, the result * contains at least one digit). The full digits character set is * '0' through '9', 'A' through 'Z' and 'a' through 'z'. If the * specified radix is invalid (less than two or too big) then it is * corrected to the nearest valid one. ** * @param value * the signed/unsigned value to be converted. * @param isUnsigned * <CODE>true</CODE> if <VAR>value</VAR> must be treated as an * unsigned value (but only if not <VAR>forceSign</VAR>), else * <VAR>value</VAR> is signed. * @param forceSign * <CODE>true</CODE> if and only if the result must always have a * sign (positive or negative). * @param radix * the radix (any value) to be used as a base of the value string * format. * @param upperCase * <CODE>true</CODE> if and only if (digit) characters in the result * are in the upper case. * @param minLength * the minimal length of the result (absolute value) and pad prefix * specifier (if negative then space padding else zero padding). * @return * the string representation (not <CODE>null</CODE>, with * <CODE>length()</CODE> not less than * <CODE>max(abs(minLength), 1)</CODE>) of <VAR>value</VAR> in the * specified radix. * @exception OutOfMemoryError * if there is not enough memory. ** * @see #toBinaryString(long, int) * @see #toOctalString(long, int) * @see #toString(long, boolean) * @see #toHexString(long, boolean, int) * @see #parse(java.lang.String, int, int, boolean, int) * @see #decode(java.lang.String, int, int) */ public static final String toString(long value, boolean isUnsigned, boolean forceSign, int radix, boolean upperCase, int minLength) { char[] chars; int offset, zeroPrefix; if (radix <= 2) radix = 2; if (radix >= ('9' - '0' + 1) + ('Z' - 'A' + 1)) radix = ('9' - '0' + 1) + ('Z' - 'A' + 1); if ((zeroPrefix = minLength) < 0 && (minLength = -minLength) < 0) minLength--; if ((offset = (JavaConsts.LONG_SIZE + 1) - minLength) > 0) minLength = JavaConsts.LONG_SIZE + 1; else offset = 0; chars = new char[minLength]; if (forceSign || !isUnsigned) if (value < 0L) { isUnsigned = forceSign = false; value = -value; } else if (!forceSign) isUnsigned = true; int digit = (int)value; if ((digit -= (int)(value = ((value >>> 1) / radix) << 1) * radix) >= radix) { digit -= radix; value++; } do { if (digit > '9' - '0') { digit += 'a' - '9' - 1; if (upperCase) digit -= 'a' - 'A'; } chars[--minLength] = (char)(digit + '0'); if (value <= 0L) break; digit = (int)value; digit -= (int)(value /= radix) * radix; } while (true); if (zeroPrefix > 0) { if ((forceSign || !isUnsigned) && offset + 1 > 0) offset++; while (offset < minLength) chars[--minLength] = '0'; } if (!isUnsigned) chars[--minLength] = (char)(forceSign ? '+' : '-'); else if (forceSign) chars[--minLength] = ' '; while (offset < minLength) chars[--minLength] = ' '; return new String(chars, minLength, chars.length - minLength); } /** * Converts a given signed/unsigned value into its decimal string * representation. ** * @param value * the signed/unsigned value to be converted. * @param isUnsigned * <CODE>true</CODE> if <VAR>value</VAR> must be treated as an * unsigned value, else <VAR>value</VAR> is signed. * @return * the string representation (not <CODE>null</CODE>, with non-zero * <CODE>length()</CODE>) of <VAR>value</VAR> in the decimal radix. * @exception OutOfMemoryError * if there is not enough memory. ** * @see #toString(long, boolean, boolean, int, boolean, int) * @see #toBinaryString(long, int) * @see #toOctalString(long, int) * @see #toHexString(long, boolean, int) * @see #parse(java.lang.String, int, int, boolean, int) * @see #decode(java.lang.String, int, int) */ public static final String toString(long value, boolean isUnsigned) { int minLength; char[] chars = new char[minLength = (JavaConsts.LONG_SIZE - 1) / 3 + 2]; if (!isUnsigned) if (value < 0L) value = -value; else isUnsigned = true; int digit = (int)value; if ((digit -= (int)(value = ((value >>> 1) / ('9' - '0' + 1)) << 1) * ('9' - '0' + 1)) > '9' - '0') { digit -= '9' - '0' + 1; value++; } do { chars[--minLength] = (char)(digit + '0'); if (value <= 0L) break; digit = (int)value; digit -= (int)(value /= '9' - '0' + 1) * ('9' - '0' + 1); } while (true); if (!isUnsigned) chars[--minLength] = '-'; return new String(chars, minLength, chars.length - minLength); } /** * Converts a given unsigned value into its binary string * representation. ** * The result is left-padded with spaces if <VAR>minLength</VAR> is * negative else with '0' characters. The absolute value of * <VAR>minLength</VAR> specifies the minimal length of the result * (anyhow, the result contains at least one digit). ** * @param unsignedValue * the unsigned value to be converted. * @param minLength * the minimal length of the result (absolute value) and pad prefix * specifier (if negative then space padding else zero padding). * @return * the string representation (not <CODE>null</CODE>, with * <CODE>length()</CODE> not less than * <CODE>max(abs(minLength), 1)</CODE>) of <VAR>unsignedValue</VAR> * in the binary radix. * @exception OutOfMemoryError * if there is not enough memory. ** * @see #toString(long, boolean, boolean, int, boolean, int) * @see #toOctalString(long, int) * @see #toString(long, boolean) * @see #toHexString(long, boolean, int) * @see #parse(java.lang.String, int, int, boolean, int) */ public static final String toBinaryString(long unsignedValue, int minLength) { char[] chars; int offset; char prefix = '0'; if (minLength < 0) if ((minLength = -minLength) < 0) minLength--; else prefix = ' '; if ((offset = JavaConsts.LONG_SIZE - minLength) > 0) minLength = JavaConsts.LONG_SIZE; else offset = 0; chars = new char[minLength]; do { chars[--minLength] = (char)(((int)unsignedValue & 1) + '0'); } while ((unsignedValue >>>= 1) != 0L); while (offset < minLength) chars[--minLength] = prefix; return new String(chars, minLength, chars.length - minLength); } /** * Converts a given unsigned value into its octal string * representation. ** * The result is left-padded with spaces if <VAR>minLength</VAR> is * negative else with '0' characters. The absolute value of * <VAR>minLength</VAR> specifies the minimal length of the result * (anyhow, the result contains at least one digit). ** * @param unsignedValue * the unsigned value to be converted. * @param minLength * the minimal length of the result (absolute value) and pad prefix * specifier (if negative then space padding else zero padding). * @return * the string representation (not <CODE>null</CODE>, with * <CODE>length()</CODE> not less than * <CODE>max(abs(minLength), 1)</CODE>) of <VAR>unsignedValue</VAR> * in the octal radix. * @exception OutOfMemoryError * if there is not enough memory. ** * @see #toString(long, boolean, boolean, int, boolean, int) * @see #toBinaryString(long, int) * @see #toString(long, boolean) * @see #toHexString(long, boolean, int) * @see #parse(java.lang.String, int, int, boolean, int) * @see #decode(java.lang.String, int, int) */ public static final String toOctalString(long unsignedValue, int minLength) { char[] chars; int offset; char prefix = '0'; if (minLength < 0) if ((minLength = -minLength) < 0) minLength--; else prefix = ' '; if ((offset = ((JavaConsts.LONG_SIZE - 1) / 3 + 1) - minLength) > 0) minLength = (JavaConsts.LONG_SIZE - 1) / 3 + 1; else offset = 0; chars = new char[minLength]; do { chars[--minLength] = (char)(((int)unsignedValue & ((1 << 3) - 1)) + '0'); } while ((unsignedValue >>>= 3) != 0L); while (offset < minLength) chars[--minLength] = prefix; return new String(chars, minLength, chars.length - minLength); } /** * Converts a given unsigned value into its hexadecimal string * representation. ** * The result is left-padded with spaces if <VAR>minLength</VAR> is * negative else with '0' characters. The absolute value of * <VAR>minLength</VAR> specifies the minimal length of the result * (anyhow, the result contains at least one digit). ** * @param unsignedValue * the unsigned value to be converted. * @param upperCase * <CODE>true</CODE> if and only if (digit) characters in the result * are in the upper case. * @param minLength * the minimal length of the result (absolute value) and pad prefix * specifier (if negative then space padding else zero padding). * @return * the string representation (not <CODE>null</CODE>, with * <CODE>length()</CODE> not less than * <CODE>max(abs(minLength), 1)</CODE>) of <VAR>unsignedValue</VAR> * in the hexadecimal radix. * @exception OutOfMemoryError * if there is not enough memory. ** * @see #toString(long, boolean, boolean, int, boolean, int) * @see #toBinaryString(long, int) * @see #toOctalString(long, int) * @see #toString(long, boolean) * @see #parse(java.lang.String, int, int, boolean, int) * @see #decode(java.lang.String, int, int) */ public static final String toHexString(long unsignedValue, boolean upperCase, int minLength) { char[] chars; int digit, offset; char prefix = '0'; if (minLength < 0) if ((minLength = -minLength) < 0) minLength--; else prefix = ' '; if ((offset = (((JavaConsts.LONG_SIZE - 1) >> 2) + 1) - minLength) > 0) minLength = ((JavaConsts.LONG_SIZE - 1) >> 2) + 1; else offset = 0; chars = new char[minLength]; do { if ((digit = (int)unsignedValue & ((1 << 4) - 1)) > '9' - '0') { digit += 'a' - '9' - 1; if (upperCase) digit -= 'a' - 'A'; } chars[--minLength] = (char)(digit + '0'); } while ((unsignedValue >>>= 4) != 0L); while (offset < minLength) chars[--minLength] = prefix; return new String(chars, minLength, chars.length - minLength); } /** * Parses a given string region as a signed/unsigned integer in the * specified radix. ** * Leading spaces (before the sign prefix) are ignored. Sign prefix * ('+' or '-') is permitted only if not <VAR>isUnsigned</VAR>. Any * leading '0' characters (after the sign prefix or leading spaces) * are ignored too. The next characters in the string region must * all be digits of the specified radix (the full digits character * set is '0' through '9', 'A' through 'Z' and 'a' through 'z'). * Number overflow is checked properly (<CODE>ParserException</CODE> * is thrown if overflow occurs). If the specified radix is invalid * (less than two or too big) then it is corrected to the nearest * valid one. Important notes: use <CODE>('9' - '0' + 1)</CODE> to * parse a decimal number. ** * @param str * the string (must be non-<CODE>null</CODE>), which region to * parse. * @param beginIndex * the string region beginning index (must be in the range), * inclusive. * @param endIndex * the string region ending index (must be in the range), exclusive. * @param isUnsigned * <CODE>true</CODE> if and only if the result must be an unsigned * value. * @param radix * the radix (any value) to be used as a base of the value string * format. * @return * a signed/unsigned integer value represented by <VAR>str</VAR> * region. * @exception NullPointerException * if <VAR>str</VAR> is <CODE>null</CODE>. * @exception StringIndexOutOfBoundsException * if <VAR>beginIndex</VAR> is negative, or if <VAR>endIndex</VAR> * is less than <VAR>beginIndex</VAR> or is greater than * <CODE>length()</CODE> of <VAR>str</VAR>. * @exception ParserException * if <VAR>str</VAR> region cannot be parsed as a signed/unsigned * integer (<VAR>error</VAR> is set to <CODE>1</CODE>, * <CODE>2</CODE> or <CODE>3</CODE> in the exception, meaning an * illegal character is found, number overflow occurs or unexpected * end of region is encountered at <VAR>index</VAR>, respectively). ** * @see #toString(long, boolean, boolean, int, boolean, int) * @see #toBinaryString(long, int) * @see #toOctalString(long, int) * @see #toString(long, boolean) * @see #toHexString(long, boolean, int) * @see #decode(java.lang.String, int, int) * @see #valueOf(java.lang.String) */ public static final long parse(String str, int beginIndex, int endIndex, boolean isUnsigned, int radix) throws NullPointerException, StringIndexOutOfBoundsException, ParserException { long value = str.length(); if (beginIndex < 0) throw new StringIndexOutOfBoundsException(beginIndex); if (endIndex < beginIndex || endIndex > (int)value) throw new StringIndexOutOfBoundsException(endIndex); if (radix <= 2) radix = 2; if (radix >= ('9' - '0' + 1) + ('Z' - 'A' + 1)) radix = ('9' - '0' + 1) + ('Z' - 'A' + 1); beginIndex--; char ch = ' '; while (++beginIndex < endIndex && (ch = str.charAt(beginIndex)) == ' '); boolean negative = false; if (!isUnsigned) { if (ch == '-') { negative = true; beginIndex++; } if (ch == '+') beginIndex++; } if (beginIndex < endIndex) { long limit; if (~((int)(limit = ((-1L >>> 1) / radix) << 1) * radix) >= radix) limit++; value = 0L; do { if ((ch = (char)(str.charAt(beginIndex) - '0')) > '9' - '0') { ch -= 'A' - '0'; if (ch >= 'a' - 'A') ch -= 'a' - 'A'; if (ch < (char)-('9' - '0' + 1)) ch += '9' - '0' + 1; } if (ch >= radix || (value = value * radix + ch) >= 0L && value < ch) break; if (++beginIndex >= endIndex) { if (!isUnsigned) { beginIndex--; if (negative) { if ((value = -value) > 0L) break; } else if (value < 0L) break; } return value; } } while (((limit - value) | value) >= 0L); } throw new ParserException(str, beginIndex, beginIndex < endIndex ? (ch >= radix ? 1 : 2) : 3); } /** * Decodes a given string region as an unsigned * octal/decimal/hexadecimal integer value. ** * The following unsigned <CODE>long</CODE> value formats are * accepted: decimal, hexadecimal (with '0x', '0X' or '#' prefix) * and octal (with '0' prefix). Leading spaces (before the prefix) * are ignored. Sign prefix is not permitted. Leading '0' characters * (after the prefix) are ignored too. ** * @param str * the string (must be non-<CODE>null</CODE>), which region to * parse. * @param beginIndex * the string region beginning index (must be in the range), * inclusive. * @param endIndex * the string region ending index (must be in the range), exclusive. * @return * an unsigned integer value represented by <VAR>str</VAR> region. * @exception NullPointerException * if <VAR>str</VAR> is <CODE>null</CODE>. * @exception StringIndexOutOfBoundsException * if <VAR>beginIndex</VAR> is negative, or if <VAR>endIndex</VAR> * is less than <VAR>beginIndex</VAR> or is greater than * <CODE>length()</CODE> of <VAR>str</VAR>. * @exception ParserException * if <VAR>str</VAR> region cannot be parsed (decoded) as an * unsigned integer (<VAR>error</VAR> is set to <CODE>1</CODE>, * <CODE>2</CODE> or <CODE>3</CODE> in the exception, meaning an * illegal character is found, number overflow occurs or unexpected * end of region is encountered at <VAR>index</VAR>, respectively). ** * @see #parse(java.lang.String, int, int, boolean, int) * @see #toString(long, boolean, boolean, int, boolean, int) * @see #toOctalString(long, int) * @see #toString(long, boolean) * @see #toHexString(long, boolean, int) * @see #valueOf(java.lang.String) */ public static final long decode(String str, int beginIndex, int endIndex) throws NullPointerException, StringIndexOutOfBoundsException, ParserException { char ch = ' '; int radix = '9' - '0' + 1; if (((str.length() - endIndex) | beginIndex) >= 0) { beginIndex--; while (++beginIndex < endIndex && (ch = str.charAt(beginIndex)) == ' '); if (ch == '#' || ch == '0' && beginIndex + 1 < endIndex) { radix = 1 << 3; if (ch == '#' || (ch = str.charAt(++beginIndex)) == 'X' || ch == 'x') { radix = 1 << 4; if (++beginIndex < endIndex) ch = str.charAt(beginIndex); } if (ch == ' ') beginIndex--; } } return parse(str, beginIndex, endIndex, true, radix); } /** * Converts a given string to an instance of this class. ** * This method returns a new <CODE>UnsignedLong</CODE> object * initialized to the unsigned decimal integer value of the * specified string. ** * @param str * the string (must be non-<CODE>null</CODE>, representing a valid * unsigned decimal integer) to be parsed. * @return * a newly constructed <CODE>UnsignedLong</CODE> instance (not * <CODE>null</CODE>) initialized to the value represented by * <VAR>str</VAR>. * @exception NullPointerException * if <VAR>str</VAR> is <CODE>null</CODE>. * @exception ParserException * if <VAR>str</VAR> cannot be parsed as an unsigned integer * (<VAR>error</VAR> is set to <CODE>1</CODE>, <CODE>2</CODE> or * <CODE>3</CODE> in the exception, meaning an illegal character is * found, number overflow occurs or unexpected end of string is * encountered at <VAR>index</VAR>, respectively). * @exception OutOfMemoryError * if there is not enough memory. ** * @see UnsignedLong#UnsignedLong(long) * @see #parse(java.lang.String, int, int, boolean, int) * @see #decode(java.lang.String, int, int) * @see #longValue() * @see #toString() */ public static UnsignedLong valueOf(String str) throws NullPointerException, ParserException { return new UnsignedLong(parse(str, 0, str.length(), true, '9' - '0' + 1)); } /** * Returns the value of <CODE>this</CODE> number as * <CODE>int</CODE>. ** * The result is the same as of <CODE>(int)longValue()</CODE>. ** * @return * the numeric <CODE>int</CODE> value represented by the object. ** * @see UnsignedLong#UnsignedLong(long) * @see #longValue() * @see #floatValue() * @see #doubleValue() * @see #toString() */ public int intValue() { return (int)this.unsignedValue; } /** * Returns the value of <CODE>this</CODE> number as * <CODE>long</CODE>. ** * @return * the numeric <CODE>long</CODE> value represented by the object. ** * @see UnsignedLong#UnsignedLong(long) * @see #intValue() * @see #floatValue() * @see #doubleValue() * @see #toString() */ public long longValue() { return this.unsignedValue; } /** * Returns the value of <CODE>this</CODE> number as * <CODE>float</CODE>. ** * The result is the same as of <CODE>(float)doubleValue()</CODE>. * Important notes: this may involve rounding; the result is always * non-negative. ** * @return * the numeric <CODE>float</CODE> value represented by the object. ** * @see UnsignedLong#UnsignedLong(long) * @see #intValue() * @see #longValue() * @see #doubleValue() * @see #toString() */ public float floatValue() { long unsignedValue = this.unsignedValue; return (unsignedValue >>> 1) * 2.0F + ((int)unsignedValue & 1); } /** * Returns the value of <CODE>this</CODE> number as * <CODE>double</CODE>. ** * Important notes: this may involve rounding; the result is always * non-negative. ** * @return * the numeric <CODE>double</CODE> value represented by the object. ** * @see UnsignedLong#UnsignedLong(long) * @see #intValue() * @see #longValue() * @see #floatValue() * @see #toString() */ public double doubleValue() { long unsignedValue = this.unsignedValue; return (unsignedValue >>> 1) * 2.0D + ((int)unsignedValue & 1); } /** * Creates and returns a copy of <CODE>this</CODE> object. ** * The result is the same as of * <CODE>new UnsignedLong(longValue())</CODE>. ** * @return * a copy (not <CODE>null</CODE> and != <CODE>this</CODE>) of * <CODE>this</CODE> instance. * @exception OutOfMemoryError * if there is not enough memory. ** * @see UnsignedLong#UnsignedLong(long) * @see #valueOf(java.lang.String) * @see #longValue() * @see #equals(java.lang.Object) */ public Object clone() { Object obj; try { if ((obj = super.clone()) instanceof UnsignedLong && obj != this) return obj; } catch (CloneNotSupportedException e) {} throw new InternalError("CloneNotSupportedException"); } /** * Returns a hash code value for the object. ** * The bits of the wrapped unsigned <CODE>long</CODE> value are * mixed in a particular order to produce a single <CODE>int</CODE> * 'hash' value. The result is the same as of * <CODE>hashCode(longValue())</CODE>. ** * @return * a hash code value for <CODE>this</CODE> object. ** * @see #hashCode(long) * @see #longValue() * @see #equals(java.lang.Object) */ public int hashCode() { return hashCode(this.unsignedValue); } /** * Indicates whether <CODE>this</CODE> object is equal to the * specified one. ** * This method returns <CODE>true</CODE> if and only if * <VAR>obj</VAR> is instance of <CODE>this</CODE> class, and the * wrapped values of <CODE>this</CODE> and of <VAR>obj</VAR> are * equal. ** * @param obj * the second compared object (may be <CODE>null</CODE>). * @return * <CODE>true</CODE> if and only if <CODE>this</CODE> value is the * same as <VAR>obj</VAR> value. ** * @see #compare(long, long) * @see #longValue() * @see #hashCode() * @see #greaterThan(java.lang.Object) */ public boolean equals(Object obj) { return obj == this || obj instanceof UnsignedLong && ((UnsignedLong)obj).unsignedValue == this.unsignedValue; } /** * Tests for being semantically greater than the argument. ** * The result is <CODE>true</CODE> if and only if <VAR>obj</VAR> is * instance of <CODE>this</CODE> class and the wrapped value of * <CODE>this</CODE> object is greater (in the unsigned manner) than * the wrapped value of the specified object. ** * @param obj * the second compared object (may be <CODE>null</CODE>). * @return * <CODE>true</CODE> if <VAR>obj</VAR> is comparable with * <CODE>this</CODE> and <CODE>this</CODE> object is greater than * <VAR>obj</VAR>, else <CODE>false</CODE>. ** * @see #greater(long, long) * @see #compare(long, long) * @see #longValue() * @see #equals(java.lang.Object) ** * @since 2.0 */ public boolean greaterThan(Object obj) { long unsignedA = 0L; if (obj != this && obj instanceof UnsignedLong) { long unsignedB = ((UnsignedLong)obj).unsignedValue; if (((unsignedA = this.unsignedValue) ^ unsignedB) >= 0L) unsignedA = unsignedB - unsignedA; } return unsignedA < 0L; } /** * Converts <CODE>this</CODE> object to its 'in-line' string * representation. ** * The wrapped value is converted to its unsigned decimal * representation and returned as a string, exactly as by * <CODE>toString(longValue(), true)</CODE>. ** * @return * the string representation (not <CODE>null</CODE>, with non-zero * <CODE>length()</CODE>) of <CODE>this</CODE> object. * @exception OutOfMemoryError * if there is not enough memory. ** * @see UnsignedLong#UnsignedLong(long) * @see #longValue() * @see #toString(long, boolean) * @see #toString(long, boolean, boolean, int, boolean, int) * @see #valueOf(java.lang.String) */ public String toString() { return toString(this.unsignedValue, true); } }