| /* |
| * 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 static java.util.Objects.requireNonNull; |
| |
| import org.apache.tuweni.bytes.Bytes; |
| import org.apache.tuweni.bytes.Bytes32; |
| |
| import java.math.BigInteger; |
| import java.util.function.Function; |
| |
| /** |
| * Base class for {@link UInt256Value}. |
| * |
| * <p> |
| * This class is abstract as it is not meant to be used directly, but it has no abstract methods. As mentioned in |
| * {@link UInt256Value}, this is used to create strongly-typed type aliases of {@link UInt256}. In other words, this |
| * allow to "tag" numbers with the unit of what they represent for the type-system, which can help clarity, but also |
| * forbid mixing numbers that are mean to be of different units (the strongly-typed part). |
| * |
| * <p> |
| * This class implements {@link UInt256Value}, but also adds a few operations that take a {@link UInt256} directly, for |
| * instance {@link #multiply(UInt256)}. The rational is that multiplying a given quantity of something by a "raw" number |
| * is always meaningful, and return a new quantity of the same thing. |
| * |
| * @param <T> The concrete type of the value. |
| */ |
| public abstract class BaseUInt256Value<T extends UInt256Value<T>> implements UInt256Value<T> { |
| |
| private final UInt256 value; |
| private final Function<UInt256, T> ctor; |
| |
| /** |
| * @param value The value to instantiate this {@code UInt256Value} with. |
| * @param ctor A constructor for the concrete type. |
| */ |
| protected BaseUInt256Value(UInt256 value, Function<UInt256, T> ctor) { |
| requireNonNull(value); |
| requireNonNull(ctor); |
| this.value = value; |
| this.ctor = ctor; |
| } |
| |
| /** |
| * @param value An unsigned value to instantiate this {@code UInt256Value} with. |
| * @param ctor A constructor for the concrete type. |
| */ |
| protected BaseUInt256Value(long value, Function<UInt256, T> ctor) { |
| requireNonNull(ctor); |
| this.value = UInt256.valueOf(value); |
| this.ctor = ctor; |
| } |
| |
| /** |
| * @param value An unsigned value to instantiate this {@code UInt256Value} with. |
| * @param ctor A constructor for the concrete type. |
| */ |
| protected BaseUInt256Value(BigInteger value, Function<UInt256, T> ctor) { |
| requireNonNull(value); |
| requireNonNull(ctor); |
| this.value = UInt256.valueOf(value); |
| this.ctor = ctor; |
| } |
| |
| /** |
| * Return a copy of this value, or itself if immutable. |
| * |
| * <p> |
| * The default implementation of this method returns a copy using the constructor for the concrete type and the bytes |
| * returned from {@link #toBytes()}. Most implementations will want to override this method to instead return |
| * {@code this}. |
| * |
| * @return A copy of this value, or itself if immutable. |
| */ |
| protected T copy() { |
| return ctor.apply(value); |
| } |
| |
| /** |
| * Return the zero value for this type. |
| * |
| * <p> |
| * The default implementation of this method returns a value obtained from calling the concrete type constructor with |
| * an argument of {@link Bytes32#ZERO}. Most implementations will want to override this method to instead return a |
| * static constant. |
| * |
| * @return The zero value for this type. |
| */ |
| protected T zero() { |
| return ctor.apply(UInt256.ZERO); |
| } |
| |
| @Override |
| public T add(T value) { |
| return add(value.toUInt256()); |
| } |
| |
| /** |
| * Returns a value that is {@code (this + value)}. |
| * |
| * @param value The amount to be added to this value. |
| * @return {@code this + value} |
| */ |
| public T add(UInt256 value) { |
| if (value.isZero()) { |
| return copy(); |
| } |
| return ctor.apply(this.value.add(value)); |
| } |
| |
| @Override |
| public T add(long value) { |
| if (value == 0) { |
| return copy(); |
| } |
| return ctor.apply(this.value.add(value)); |
| } |
| |
| @Override |
| public T addMod(T value, UInt256 modulus) { |
| return addMod(value.toUInt256(), 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. |
| */ |
| public T addMod(UInt256 value, UInt256 modulus) { |
| return ctor.apply(this.value.addMod(value, modulus)); |
| } |
| |
| @Override |
| public T addMod(long value, UInt256 modulus) { |
| return ctor.apply(this.value.addMod(value, modulus)); |
| } |
| |
| @Override |
| public T addMod(long value, long modulus) { |
| return ctor.apply(this.value.addMod(value, modulus)); |
| } |
| |
| @Override |
| public T subtract(T value) { |
| return subtract(value.toUInt256()); |
| } |
| |
| /** |
| * Returns a value that is {@code (this - value)}. |
| * |
| * @param value The amount to be subtracted from this value. |
| * @return {@code this - value} |
| */ |
| public T subtract(UInt256 value) { |
| if (value.isZero()) { |
| return copy(); |
| } |
| return ctor.apply(this.value.subtract(value)); |
| } |
| |
| @Override |
| public T subtract(long value) { |
| if (value == 0) { |
| return copy(); |
| } |
| return ctor.apply(this.value.subtract(value)); |
| } |
| |
| @Override |
| public T multiply(T value) { |
| return multiply(value.toUInt256()); |
| } |
| |
| /** |
| * Returns a value that is {@code (this * value)}. |
| * |
| * @param value The amount to multiply this value by. |
| * @return {@code this * value} |
| */ |
| public T multiply(UInt256 value) { |
| if (isZero() || value.isZero()) { |
| return zero(); |
| } |
| if (value.equals(UInt256.ONE)) { |
| return copy(); |
| } |
| return ctor.apply(this.value.multiply(value)); |
| } |
| |
| @Override |
| public T multiply(long value) { |
| if (value == 0 || isZero()) { |
| return zero(); |
| } |
| if (value == 1) { |
| return copy(); |
| } |
| return ctor.apply(this.value.multiply(value)); |
| } |
| |
| @Override |
| public T multiplyMod(T value, UInt256 modulus) { |
| return multiplyMod(value.toUInt256(), 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. |
| */ |
| public T multiplyMod(UInt256 value, UInt256 modulus) { |
| return ctor.apply(this.value.multiplyMod(value, modulus)); |
| } |
| |
| @Override |
| public T multiplyMod(long value, UInt256 modulus) { |
| return ctor.apply(this.value.multiplyMod(value, modulus)); |
| } |
| |
| @Override |
| public T multiplyMod(long value, long modulus) { |
| return ctor.apply(this.value.multiplyMod(value, modulus)); |
| } |
| |
| @Override |
| public T divide(T value) { |
| return divide(value.toUInt256()); |
| } |
| |
| /** |
| * 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. |
| */ |
| public T divide(UInt256 value) { |
| return ctor.apply(this.value.divide(value)); |
| } |
| |
| @Override |
| public T divide(long value) { |
| return ctor.apply(this.value.divide(value)); |
| } |
| |
| @Override |
| public T divideCeil(T value) { |
| return divideCeil(value.toUInt256()); |
| } |
| |
| /** |
| * 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. |
| */ |
| public T divideCeil(UInt256 value) { |
| return ctor.apply(this.value.divideCeil(value)); |
| } |
| |
| @Override |
| public T divideCeil(long value) { |
| return ctor.apply(this.value.divideCeil(value)); |
| } |
| |
| @Override |
| public T pow(UInt256 exponent) { |
| return ctor.apply(this.value.pow(exponent)); |
| } |
| |
| @Override |
| public T pow(long exponent) { |
| return ctor.apply(this.value.pow(exponent)); |
| } |
| |
| @Override |
| public T mod(UInt256 modulus) { |
| return ctor.apply(this.value.mod(modulus)); |
| } |
| |
| @Override |
| public T mod(long modulus) { |
| return ctor.apply(this.value.mod(modulus)); |
| } |
| |
| @Override |
| public T mod0(UInt256 modulus) { |
| return ctor.apply(this.value.mod0(modulus)); |
| } |
| |
| @Override |
| public T mod0(long modulus) { |
| return ctor.apply(this.value.mod0(modulus)); |
| } |
| |
| @Override |
| public int compareTo(T other) { |
| return compareTo(other.toUInt256()); |
| } |
| |
| /** |
| * Compare two {@link UInt256} values. |
| * |
| * @param other The value to compare to. |
| * @return A negative integer, zero, or a positive integer as this value is less than, equal to, or greater than the |
| * specified value. |
| */ |
| public int compareTo(UInt256 other) { |
| return this.value.compareTo(other); |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (obj == this) { |
| return true; |
| } |
| if (!(obj instanceof UInt256Value)) { |
| return false; |
| } |
| UInt256Value<?> other = (UInt256Value<?>) obj; |
| return this.value.equals(other.toUInt256()); |
| } |
| |
| @Override |
| public int hashCode() { |
| return value.hashCode(); |
| } |
| |
| @Override |
| public String toString() { |
| return value.toString(); |
| } |
| |
| @Override |
| public UInt256 toUInt256() { |
| return value; |
| } |
| |
| @Override |
| public Bytes32 toBytes() { |
| return value.toBytes(); |
| } |
| |
| @Override |
| public Bytes toMinimalBytes() { |
| return value.toMinimalBytes(); |
| } |
| } |