| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE |
| * file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file |
| * to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the |
| * License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
| * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations under the License. |
| */ |
| package org.apache.tuweni.units.bigints; |
| |
| |
| import org.apache.tuweni.bytes.Bytes; |
| import org.apache.tuweni.bytes.Bytes32; |
| |
| import java.math.BigInteger; |
| |
| /** |
| * Represents a 256-bit (32 bytes) unsigned integer value. |
| * |
| * <p> |
| * A {@link UInt256Value} is an unsigned integer value stored with 32 bytes, so whose value can range between 0 and |
| * 2^256-1. |
| * |
| * <p> |
| * This interface defines operations for value types with a 256-bit precision range. The methods provided by this |
| * interface take parameters of the same type (and also {@code long}. This provides type safety by ensuring calculations |
| * cannot mix different {@code UInt256Value} types. |
| * |
| * <p> |
| * Where only a pure numerical 256-bit value is required, {@link UInt256} should be used. |
| * |
| * <p> |
| * It is strongly advised to extend {@link BaseUInt256Value} rather than implementing this interface directly. Doing so |
| * provides type safety in that quantities of different units cannot be mixed accidentally. |
| * |
| * @param <T> The concrete type of the value. |
| */ |
| public interface UInt256Value<T extends UInt256Value<T>> extends Comparable<T> { |
| |
| /** |
| * @return True if this is the value 0. |
| */ |
| default boolean isZero() { |
| return toBytes().isZero(); |
| } |
| |
| /** |
| * Returns a value that is {@code (this + value)}. |
| * |
| * @param value The amount to be added to this value. |
| * @return {@code this + value} |
| */ |
| T add(T value); |
| |
| /** |
| * Returns a value that is {@code (this + value)}. |
| * |
| * <p>This notation can be used in Kotlin with the {@code +} operator. |
| * |
| * @param value The amount to be added to this value. |
| * @return {@code this + value} |
| */ |
| default T plus(T value) { |
| return add(value); |
| } |
| |
| /** |
| * Returns a value that is {@code (this + value)}. |
| * |
| * <p>This notation can be used in Kotlin with the {@code +} operator. |
| * |
| * @param value The amount to be added to this value. |
| * @return {@code this + value} |
| */ |
| default T plus(long value) { |
| return add(value); |
| } |
| |
| /** |
| * Returns a value that is {@code (this + value)}. |
| * |
| * @param value the amount to be added to this value |
| * @return {@code this + value} |
| * @throws ArithmeticException if the result of the addition overflows |
| */ |
| default T addExact(T value) { |
| T result = add(value); |
| if (compareTo(result) > 0) { |
| throw new ArithmeticException("UInt256 overflow"); |
| } |
| return result; |
| } |
| |
| /** |
| * Returns a value that is {@code (this + value)}. |
| * |
| * @param value The amount to be added to this value. |
| * @return {@code this + value} |
| */ |
| T add(long value); |
| |
| /** |
| * Returns a value that is {@code (this + value)}. |
| * |
| * @param value the amount to be added to this value |
| * @return {@code this + value} |
| * @throws ArithmeticException if the result of the addition overflows |
| */ |
| default T addExact(long value) { |
| T result = add(value); |
| if ((value > 0 && compareTo(result) > 0) || (value < 0 && compareTo(result) < 0)) { |
| throw new ArithmeticException("UInt256 overflow"); |
| } |
| return result; |
| } |
| |
| /** |
| * Returns a value equivalent to {@code ((this + value) mod modulus)}. |
| * |
| * @param value The amount to be added to this value. |
| * @param modulus The modulus. |
| * @return {@code (this + value) mod modulus} |
| * @throws ArithmeticException {@code modulus} == 0. |
| */ |
| T addMod(T value, UInt256 modulus); |
| |
| /** |
| * Returns a value equivalent to {@code ((this + value) mod modulus)}. |
| * |
| * @param value The amount to be added to this value. |
| * @param modulus The modulus. |
| * @return {@code (this + value) mod modulus} |
| * @throws ArithmeticException {@code modulus} == 0. |
| */ |
| T addMod(long value, UInt256 modulus); |
| |
| /** |
| * Returns a value equivalent to {@code ((this + value) mod modulus)}. |
| * |
| * @param value The amount to be added to this value. |
| * @param modulus The modulus. |
| * @return {@code (this + value) mod modulus} |
| * @throws ArithmeticException {@code modulus} ≤ 0. |
| */ |
| T addMod(long value, long modulus); |
| |
| /** |
| * Returns a value that is {@code (this - value)}. |
| * |
| * @param value The amount to be subtracted from this value. |
| * @return {@code this - value} |
| */ |
| T subtract(T value); |
| |
| /** |
| * Returns a value that is {@code (this - value)}. |
| * |
| * @param value the amount to be subtracted to this value |
| * @return {@code this - value} |
| * @throws ArithmeticException if the result of the addition overflows |
| */ |
| default T subtractExact(T value) { |
| T result = subtract(value); |
| if (compareTo(result) < 0) { |
| throw new ArithmeticException("UInt256 overflow"); |
| } |
| return result; |
| } |
| |
| /** |
| * Returns a value that is {@code (this - value)}. |
| * |
| * @param value The amount to be subtracted from this value. |
| * @return {@code this - value} |
| */ |
| T subtract(long value); |
| |
| /** |
| * Returns a value that is {@code (this - value)}. |
| * |
| * @param value the amount to be subtracted to this value |
| * @return {@code this - value} |
| * @throws ArithmeticException if the result of the addition overflows |
| */ |
| default T subtractExact(long value) { |
| T result = subtract(value); |
| if ((value > 0 && compareTo(result) < 0) || (value < 0 && compareTo(result) > 0)) { |
| throw new ArithmeticException("UInt256 overflow"); |
| } |
| return result; |
| } |
| |
| /** |
| * Returns a value that is {@code (this * value)}. |
| * |
| * @param value The amount to multiply this value by. |
| * @return {@code this * value} |
| */ |
| T multiply(T value); |
| |
| /** |
| * Returns a value that is {@code (this * value)}. |
| * |
| * @param value The amount to multiply this value by. |
| * @return {@code this * value} |
| * @throws ArithmeticException {@code value} < 0. |
| */ |
| T multiply(long value); |
| |
| /** |
| * Returns a value that is {@code ((this * value) mod modulus)}. |
| * |
| * @param value The amount to multiply this value by. |
| * @param modulus The modulus. |
| * @return {@code (this * value) mod modulus} |
| * @throws ArithmeticException {@code value} < 0 or {@code modulus} == 0. |
| */ |
| T multiplyMod(T value, UInt256 modulus); |
| |
| /** |
| * Returns a value that is {@code ((this * value) mod modulus)}. |
| * |
| * @param value The amount to multiply this value by. |
| * @param modulus The modulus. |
| * @return {@code (this * value) mod modulus} |
| * @throws ArithmeticException {@code value} < 0 or {@code modulus} == 0. |
| */ |
| T multiplyMod(long value, UInt256 modulus); |
| |
| /** |
| * Returns a value that is {@code ((this * value) mod modulus)}. |
| * |
| * @param value The amount to multiply this value by. |
| * @param modulus The modulus. |
| * @return {@code (this * value) mod modulus} |
| * @throws ArithmeticException {@code value} < 0 or {@code modulus} ≤ 0. |
| */ |
| T multiplyMod(long value, long modulus); |
| |
| /** |
| * Returns a value that is {@code (this / value)}. |
| * |
| * @param value The amount to divide this value by. |
| * @return {@code this / value} |
| * @throws ArithmeticException {@code value} == 0. |
| */ |
| T divide(T value); |
| |
| /** |
| * Returns a value that is {@code (this / value)}. |
| * |
| * @param value The amount to divide this value by. |
| * @return {@code this / value} |
| * @throws ArithmeticException {@code value} ≤ 0. |
| */ |
| T divide(long value); |
| |
| /** |
| * Returns a value that is {@code ceiling(this / value)}. |
| * |
| * @param value The amount to divide this value by. |
| * @return {@code this / value + ( this % value == 0 ? 0 : 1)} |
| * @throws ArithmeticException {@code value} == 0. |
| */ |
| T divideCeil(T value); |
| |
| /** |
| * Returns a value that is {@code ceiling(this / value)}. |
| * |
| * @param value The amount to divide this value by. |
| * @return {@code this / value + ( this % value == 0 ? 0 : 1)} |
| * @throws ArithmeticException {@code value} == 0. |
| */ |
| T divideCeil(long value); |
| |
| /** |
| * Returns a value that is {@code (this<sup>exponent</sup> mod 2<sup>256</sup>)} |
| * |
| * <p> |
| * This calculates an exponentiation over the modulus of {@code 2^256}. |
| * |
| * <p> |
| * Note that {@code exponent} is an {@link UInt256} rather than of the type {@code T}. |
| * |
| * @param exponent The exponent to which this value is to be raised. |
| * @return {@code this<sup>exponent</sup> mod 2<sup>256</sup>} |
| */ |
| T pow(UInt256 exponent); |
| |
| /** |
| * Returns a value that is {@code (this<sup>exponent</sup> mod 2<sup>256</sup>)} |
| * |
| * <p> |
| * This calculates an exponentiation over the modulus of {@code 2^256}. |
| * |
| * @param exponent The exponent to which this value is to be raised. |
| * @return {@code this<sup>exponent</sup> mod 2<sup>256</sup>} |
| */ |
| T pow(long exponent); |
| |
| /** |
| * Returns a value that is {@code (this mod modulus)}. |
| * |
| * @param modulus The modulus. |
| * @return {@code this mod modulus}. |
| * @throws ArithmeticException {@code modulus} == 0. |
| */ |
| T mod(UInt256 modulus); |
| |
| /** |
| * Returns a value that is {@code (this mod modulus)}. |
| * |
| * @param modulus The modulus. |
| * @return {@code this mod modulus}. |
| * @throws ArithmeticException {@code modulus} ≤ 0. |
| */ |
| T mod(long modulus); |
| |
| /** |
| * Returns a value that is {@code (this mod modulus)}, or 0 if modulus is 0. |
| * |
| * @param modulus The modulus. |
| * @return {@code this mod modulus}. |
| */ |
| T mod0(UInt256 modulus); |
| |
| /** |
| * Returns a value that is {@code (this mod modulus)}, or 0 if modulus is 0. |
| * |
| * @param modulus The modulus. |
| * @return {@code this mod modulus}. |
| */ |
| T mod0(long modulus); |
| |
| /** |
| * @return True if this value fits a java {@code int} (i.e. is less or equal to {@code Integer.MAX_VALUE}). |
| */ |
| default boolean fitsInt() { |
| // Ints are 4 bytes, so anything but the 4 last bytes must be zeroes |
| Bytes32 bytes = toBytes(); |
| for (int i = 0; i < Bytes32.SIZE - 4; i++) { |
| if (bytes.get(i) != 0) |
| return false; |
| } |
| // Lastly, the left-most byte of the int must not start with a 1. |
| return bytes.get(Bytes32.SIZE - 4) >= 0; |
| } |
| |
| /** |
| * @return This value as a java {@code int} assuming it is small enough to fit an {@code int}. |
| * @throws ArithmeticException If the value does not fit an {@code int}, that is if {@code !fitsInt()}. |
| */ |
| default int intValue() { |
| if (!fitsInt()) { |
| throw new ArithmeticException("Value does not fit a 4 byte int"); |
| } |
| return toBytes().getInt(Bytes32.SIZE - 4); |
| } |
| |
| /** |
| * @return True if this value fits a java {@code long} (i.e. is less or equal to {@code Long.MAX_VALUE}). |
| */ |
| default boolean fitsLong() { |
| // Longs are 8 bytes, so anything but the 8 last bytes must be zeroes |
| for (int i = 0; i < Bytes32.SIZE - 8; i++) { |
| if (toBytes().get(i) != 0) |
| return false; |
| } |
| // Lastly, the left-most byte of the long must not start with a 1. |
| return toBytes().get(Bytes32.SIZE - 8) >= 0; |
| } |
| |
| /** |
| * @return This value as a java {@code long} assuming it is small enough to fit a {@code long}. |
| * @throws ArithmeticException If the value does not fit a {@code long}, that is if {@code !fitsLong()}. |
| */ |
| default long toLong() { |
| if (!fitsLong()) { |
| throw new ArithmeticException("Value does not fit a 8 byte long"); |
| } |
| return toBytes().getLong(Bytes32.SIZE - 8); |
| } |
| |
| /** |
| * @return This value as a {@link BigInteger}. |
| */ |
| default BigInteger toBigInteger() { |
| return toBytes().toUnsignedBigInteger(); |
| } |
| |
| /** |
| * This value represented as an hexadecimal string. |
| * |
| * <p> |
| * Note that this representation includes all the 32 underlying bytes, no matter what the integer actually represents |
| * (in other words, it can have many leading zeros). For a shorter representation that don't include leading zeros, |
| * use {@link #toShortHexString}. |
| * |
| * @return This value represented as an hexadecimal string. |
| */ |
| default String toHexString() { |
| return toBytes().toHexString(); |
| } |
| |
| /** @return This value represented as a minimal hexadecimal string (without any leading zero). */ |
| default String toShortHexString() { |
| return toBytes().toShortHexString(); |
| } |
| |
| /** |
| * Convert this value to a {@link UInt256}. |
| * |
| * @return This value as a {@link UInt256}. |
| */ |
| UInt256 toUInt256(); |
| |
| /** |
| * @return The value as bytes. |
| */ |
| Bytes32 toBytes(); |
| |
| /** |
| * @return The value as bytes without any leading zero bytes. |
| */ |
| Bytes toMinimalBytes(); |
| |
| /** |
| * @return the number of zero bits preceding the highest-order ("leftmost") one-bit in the binary representation of |
| * this value, or 256 if the value is equal to zero. |
| */ |
| default int numberOfLeadingZeros() { |
| return toBytes().numberOfLeadingZeros(); |
| } |
| |
| /** |
| * @return The number of bits following and including the highest-order ("leftmost") one-bit in the binary |
| * representation of this value, or zero if all bits are zero. |
| */ |
| default int bitLength() { |
| return toBytes().bitLength(); |
| } |
| } |