diff --git a/src/java.base/share/classes/java/lang/Integral.java b/src/java.base/share/classes/java/lang/Integral.java new file mode 100644 index 00000000000..93f6326494f --- /dev/null +++ b/src/java.base/share/classes/java/lang/Integral.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang; + +/** + * Indicates an integral type that supports: + * + * + * and participates in operator overloading of all those operators. + * + * @param The integral type + */ +public interface Integral + extends Numerical, Orderable { + + /** + * {@return the AND of the two operands, binary operator "{@code &}"} + * + * @param op1 the first operand + * @param op2 the second operand + */ + IT and(IT op1, IT op2); + + /** + * {@return the OR of the two operands, binary operator "{@code |}"} + * + * @param op1 the first operand + * @param op2 the second operand + */ + IT or(IT op1, IT op2); + + /** + * {@return the XOR of the two operands, binary operator "{@code ^}"} + * + * @param op1 the first operand + * @param op2 the second operand + */ + IT xor(IT op1, IT op2); + + /** + * {@return the complement of the operand, unary operator "{@code ~}"} + * + * @param op1 the operand + * @throws UnsupportedOperationException if complement is not supposed + */ + IT complement(IT op1); + + /** + * {@return the first operand left shifted by the distance + * indicated by the second operand, binary operator "{@code <<"}} + * + * @param x the operand to be shifted + * @param shiftDistance the shift distance + */ + IT shiftLeft(IT x, int shiftDistance); + + /** + * {@return the first operand right shifted by the distance + * indicated by the second operand, operator "{@code >>}"} + * + * @param x the operand to be shifted + * @param shiftDistance the shift distance + */ + IT shiftRight(IT x, int shiftDistance); + + /** + * {@return the first operand right shifted, unsigned, by the + * distance indicated by the second operand, operator "{@code >>>}"} + * + * @param x the operand to be shifted + * @param shiftDistance the shift distance + * @throws UnsupportedOperationException if unsigned right shift is not supposed + */ + IT shiftRightUnsigned(IT x, int shiftDistance); +} diff --git a/src/java.base/share/classes/java/lang/Numerical.java b/src/java.base/share/classes/java/lang/Numerical.java new file mode 100644 index 00000000000..3837a312ab5 --- /dev/null +++ b/src/java.base/share/classes/java/lang/Numerical.java @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang; + +/** + * Indicates a type supports the basic binary arithmetic operations of + * addition, subtraction, multiplication, (optionally) division, and + * (optionally) remainder, ({@code +}, {@code -}, {@code *}, {@code + * /}, {@code %}, respectively), as well as (optionally) negation (unary + * {@code -}), and participates in operator overloading of those + * operators. + * + *

The intention of this interface is to enable types that + * customarily support numerical notions of addition, subtraction, + * multiplication and division to enjoy operator overloading syntax + * even if the underlying algebraic properties do not hold because of + * limitations in approximation. This includes algebraic + * fields and field-like numbers as well as algebraic + * rings and ring-links numbers. + * + *

For example, mathematical integers form a ring and, including + * Euclidean division support, integers support the operations in + * this interface. Fields also support the operations in + * question. Commonly used fields include rational numbers, real + * numbers, and complex numbers. A field has a set of values and + * operations on those values. The operations have various properties + * known as the field axioms. These include associativity + * of addition and multiplication, commutativity of addition and + * multiplication, and multiplication distributing over + * addition. Fields can be {@linkplain Orderable ordered} (rational + * numbers, real numbers) or unordered (complex numbers). + * + *

Types used to approximate a field, such as a floating-point type + * used to approximate real numbers, will both approximate the set of + * values of the field and the set of properties over the supported + * operations. In particular, properties like associativity of + * addition are not expected to hold for a floating-point + * type. + * + * @apiNote + * A particular numerical type may support returning a number of that + * type for all arguments to add, subtract, multiply, and (possibly) + * divide. An operation having that property is said to be + * closed over that operation. For example, built-in {@code + * int} arithmetic is closed over add, subtract, and multiply, but is + * not closed under divide since an {@code + * ArithmeticException} is thrown on a zero divisor. Built-in + * arithmetic on {@code float} and {@code double} is closed under all + * of add, subtract, multiply, and divide, with infinities and NaN + * (not-a-number) being returned for cases that would otherwise be + * exceptional. + * + *

A given numerical type implementing this interface may or may + * not be closed under any particular operation. If it is not + * closed, the conditions where an exception is thrown should be + * documented with the expected outcome being throwing an {@code + * ArithmeticException} rather than returning a value. + * + *

Future work: consider interactions with / support from {@link + * java.util.Formatter} and numerical types. + * + * @param The numerical type + * @see Orderable + */ +public interface Numerical { + /** + * Addition operation, binary operator "{@code +}". + * + * @param addend the first operand + * @param augend the second operand + * @return the sum of the operands + * @throws ArithmeticException if the numerical type does not + * allow adding the operands in question + */ + NT add(NT addend, NT augend); + + /** + * Subtraction operation, binary operator "{@code -}". + * + * @implSpec + * The default implementation returns the sum of the first + * operand with the negation of the second operand. + * + * @param minuend the first operand + * @param subtrahend the second operand + * @return the difference of the operands + * @throws ArithmeticException if the numerical type does not + * allow subtracting the operands in question + */ + default NT subtract(NT minuend, NT subtrahend) { + return this.add(minuend, this.negate(subtrahend)); + } + + /** + * Multiplication operation, binary operator "{@code *}". + * + * @param multiplier the first operand + * @param multiplicand the second operand + * @return the product of the operands + * @throws ArithmeticException if the numerical type does not + * allow multiplying the operands in question + */ + NT multiply(NT multiplier, NT multiplicand); + + /** + * Division operation, binary operator "{@code /}". + * + * @apiNote + * Numerical types can have different policies regarding how + * divisors equal to zero are handled. Many types will throw an + * {@code ArithmeticException} in those cases. However, other + * types like {@linkplain StandardFloatingPoint floating-point + * types} can return a special value like NaN (not-a-number). + * + * @throws ArithmeticException if the divisor is zero and zero + * divisors are not allowed + * @throws UnsupportedOperationException if division is not supported + * @param dividend the first operand + * @param divisor the second operand + * @return the quotient of the operands + */ + NT divide(NT dividend, NT divisor); + + /** + * Remainder operation, binary operator "{@code %}". + * + * @apiNote + * Numerical types can have different policies regarding how + * divisors equal to zero are handled. Many types will throw an + * {@code ArithmeticException} in those cases. However, other + * types like {@linkplain StandardFloatingPoint floating-point + * types} can return a special value like NaN (not-a-number). + * + * @throws ArithmeticException if the divisor is zero and zero + * divisors are not allowed + * @throws UnsupportedOperationException if remainder is not supported + * @param dividend the first operand + * @param divisor the second operand + * @return the quotient of the operands + */ + NT remainder(NT dividend, NT divisor); + + /** + * Unary plus operation, unary operator "{@code +}". + * + * @apiNote + * It this needed? Default to returning this/operand? Or just to + * be be no-op not recognized for overloading? + * + * @implSpec + * The default implementation returns the operand. + * + * @param operand the operand + * @return unary plus of the operand + */ + default NT plus(NT operand) { + return operand; + } + + /** + * Negation operation, unary operator "{@code -}". + * + * @throws UnsupportedOperationException if negation is not supported + * @param operand the operand + * @return the negation of the operand + * @throws ArithmeticException if the numerical type does not + * allow negating the operand in question + */ + NT negate(NT operand); +} diff --git a/src/java.base/share/classes/java/lang/Orderable.java b/src/java.base/share/classes/java/lang/Orderable.java new file mode 100644 index 00000000000..f241d0dcea8 --- /dev/null +++ b/src/java.base/share/classes/java/lang/Orderable.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang; + +// TODO: could make this interface sealed and only allow an +// "OrderedNumerics" implementation or make this interface extend +// Numerical directly. + +/** + * Indicates a type supports ordered comparison operations ({@code + * <}, {@code <=}, {@code >}, {@code >=}) and participates in operator + * overloading of those operators. + * + *

TOOD: discuss tricotomy of exactly one of less than, greater + * than, and equal to usually holding between two operands, + * but not for floating-point types with NaN, etc. + * + * @param The type supporting ordered comparison + * @see Comparable + */ +public interface Orderable { + /** + * {@return {@code true} if the first operand is less than the second + * operand and {@code false} otherwise} + * + * The method corresponds to the less than operator, "{@code <}". + * + * @param op1 the first operand + * @param op2 the second operand + */ + boolean lessThan(OC op1, OC op2); + + /** + * {@return {@code true} if the first operand is less than or + * equal to the second operand and {@code false} otherwise} + * + * The method corresponds to the less than operator, "{@code <=}". + * + * @implSpec + * Rough draft: the default implementation returns the result of + * {@code (lessThan(op1, op2) || op1.equals(op2))}. + * + * @param op1 the first operand + * @param op2 the second operand + */ + default boolean lessThanEqual(OC op1, OC op2) { + return lessThan(op1, op2) || op1.equals(op2); + } + + /** + * {@return {@code true} if the first operand is greater than the + * second operand and {@code false} otherwise} + * + * The method corresponds to the greater than operator, "{@code >}". + * + * @implSpec + * Rough draft: the default implementation returns the result of + * {@code !lessThanEqual(op1, op2)}. + * + * @param op1 the first operand + * @param op2 the second operand + */ + default boolean greaterThan(OC op1, OC op2) { + return !lessThanEqual(op1, op2); + } + + /** + * {@return {@code true} if the first operand is greater than or + * equal to the second operand and {@code false} otherwise} + * + * The method corresponds to the greater than operator, "{@code >=}". + * + * @implSpec + * Rough draft: the default implementation returns the result of + * {@code !lessThan(op1, op2)}. + * + * @param op1 the first operand + * @param op2 the second operand + */ + default boolean greaterThanEqual(OC op1, OC op2) { + return !lessThan(op1, op2); + } + + /** + * {@return the smaller of the two operands} + * + * @apiNote + * Subtypes of this interface can define policies concerning which + * operand to return if they are the same size. + * + * @implSpec + * Rough draft: the default implementation returns the result of + * {@code (lessThanEqual(op1, op2) ? op1 : op2)}. + * + * @param op1 the first operand + * @param op2 the second operand + */ + default OC min(OC op1, OC op2) { + return lessThanEqual(op1, op2) ? op1 : op2; + } + + /** + * {@return the larger of the two operands} + * + * @apiNote + * Subtypes of this interface can define policies concerning which + * operand to return if they are the same size. + * + * @implSpec + * Rough draft: the default implementation returns the result of + * {@code (greaterThanEqual(op1, op2) ? op1 : op2)}. + * + * @param op1 the first operand + * @param op2 the second operand + */ + default OC max(OC op1, OC op2) { + return greaterThanEqual(op1, op2) ? op1 : op2; + } +} diff --git a/src/java.base/share/classes/java/lang/StandardFloatingPoint.java b/src/java.base/share/classes/java/lang/StandardFloatingPoint.java new file mode 100644 index 00000000000..b62e84d7f10 --- /dev/null +++ b/src/java.base/share/classes/java/lang/StandardFloatingPoint.java @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang; + +/** + * Indicate a floating-point type in the style of an IEEE 754 standard + * floating-point type. + * + *

TODO: write-up about what being an IEEE 754 standard + * floating-point type means and implies. + * + * @apiNote + * Possible future work: separate subinterface for decimal IEEE 754 + * types. + * + * @param The standard floating-point type + */ +public interface StandardFloatingPoint + extends Numerical, Orderable { + + /** + * {@inheritDoc Numerical} + * + * @apiNote + * Explain returning NaN on a zero divisor, etc. + * + * @param dividend {@inheritDoc Numerical} + * @param divisor {@inheritDoc Numerical} + * @return {@inheritDoc Numerical} + */ + // Note: NOT inheritDoc'ing ArithmeticException on a zero divisor + @Override + SFP divide(SFP dividend, SFP divisor); + + /** + * {@inheritDoc Numerical} + * + * @apiNote + * Explain behavior on a zero divisor, rounding policy, etc. + * + * @param dividend {@inheritDoc Numerical} + * @param divisor {@inheritDoc Numerical} + * @return {@inheritDoc Numerical} + */ + // Note: NOT inheritDoc'ing ArithmeticException on a zero divisor + @Override + SFP remainder(SFP dividend, SFP divisor); + + /** + * {@inheritDoc Orderable} + * + *

TODO: Need to augment Orderable interface spec with IEEE 754 + * aware one. + * + * @param op1 {@inheritDoc Orderable} + * @param op2 {@inheritDoc Orderable} + */ + @Override + boolean lessThan(SFP op1, SFP op2); + + /** + * {@inheritDoc Orderable} + * + *

TODO: Need to augment Orderable interface spec with IEEE 754 + * aware one. + * + * @apiNote + * Explain all the IEEE 754-isms. + * + * @implSpec + * Rough draft: the default implementation returns the result of + * {@code Orderable.super.lessThanEqual(op1, op2)}. + * + * @param op1 the {@inheritDoc Orderable} + * @param op2 the {@inheritDoc Orderable} + */ + @Override + default boolean lessThanEqual(SFP op1, SFP op2) { + return Orderable.super.lessThanEqual(op1, op2); + } + + /** + * {@inheritDoc Orderable} + * + *

TODO: Need to augment Orderable interface spec with IEEE 754 + * aware one. + * + * @apiNote + * Explain all the IEEE 754-isms. + * + * @implSpec + * Rough draft: the default implementation returns the result of + * {@code !lessThanEqual(op1, op2) && !isUnordered(op1, op2)}. + * + * @param op1 {@inheritDoc Orderable} + * @param op2 {@inheritDoc Orderable} + */ + @Override + default boolean greaterThan(SFP op1, SFP op2) { + return !lessThanEqual(op1, op2) && !isUnordered(op1, op2); + } + + /** + * {@inheritDoc Orderable} + * + *

TODO: Need to augment Orderable interface spec with IEEE 754 + * aware one. + * + * @apiNote + * Explain all the IEEE 754-isms. + * + * @implSpec + * Rough draft: the default implementation returns the result of + * {@code !lessThan(op1, op2) && !isUnordered(op1, op2)}. + * + * @param op1 {@inheritDoc Orderable} + * @param op2 {@inheritDoc Orderable} + */ + @Override + default boolean greaterThanEqual(SFP op1, SFP op2) { + return !lessThan(op1, op2) && !isUnordered(op1, op2); + } + + /** + * {@return {@code true} if the operands are unordered and {@code false} otherwise} + * + * @implSpec + * Rough draft: the default implementation returns the result of + * {@code isNaN(op1) || isNaN(op2)}. + * + * @param op1 the first operand + * @param op2 the second operand + */ + default boolean isUnordered(SFP op1, SFP op2) { + return isNaN(op1) || isNaN(op2); + } + + /** + * {@inheritDoc Orderable} + * + * @apiNote + * TODO: Explain all the IEEE 754-isms, write default method. + * + * @param op1 {@inheritDoc Orderable} + * @param op2 {@inheritDoc Orderable} + */ + @Override + SFP min(SFP op1, SFP op2); + + /** + * {@inheritDoc Orderable} + * + * @apiNote + * TODO: Explain all the IEEE 754-isms, write default method. + * + * @param op1 {@inheritDoc Orderable} + * @param op2 {@inheritDoc Orderable} + */ + @Override + SFP max(SFP op1, SFP op2); + + /** + * {@return the square root of the operand} The square root is + * computed using the round to nearest rounding policy. + * + * @apiNote + * This method corresponds to the squareRoot operation defined in + * IEEE 754. + * + * @param radicand the argument to have its square root taken + * + */ + SFP sqrt(SFP radicand); + + /** + * Returns the fused multiply add of the three arguments; that is, + * returns the exact product of the first two arguments summed + * with the third argument and then rounded once to the nearest + * floating-point value. + * + * @apiNote This method corresponds to the fusedMultiplyAdd + * operation defined in IEEE 754. + * + * @param a a value + * @param b a value + * @param c a value + * + * @return (a × b + c) + * computed, as if with unlimited range and precision, and rounded + * once to the nearest floating-point value + */ + SFP fma(SFP a, SFP b, SFP c); + + /** + * Returns {@code true} if the specified number is a + * Not-a-Number (NaN) value, {@code false} otherwise. + * + * @apiNote + * This method corresponds to the isNaN operation defined in IEEE + * 754. + * + * @param operand the value to be tested. + * @return {@code true} if the argument is NaN; + * {@code false} otherwise. + */ + boolean isNaN(SFP operand); + + /** + * Returns {@code true} if the specified number is infinitely + * large in magnitude, {@code false} otherwise. + * + * @apiNote + * This method corresponds to the isInfinite operation defined in + * IEEE 754. + * + * @param operand the value to be tested. + * @return {@code true} if the argument is positive infinity or + * negative infinity; {@code false} otherwise. + */ + boolean isInfinite(SFP operand); + + /** + * Returns {@code true} if the argument is a finite floating-point + * value; returns {@code false} otherwise (for NaN and infinity + * arguments). + * + * @apiNote + * This method corresponds to the isFinite operation defined in + * IEEE 754. + * + * @implSpec + * Rough draft: the default implementation returns the result of + * {@code !isInfinite(operand) && !isNaN(operand)}. + * + * @param operand the {@code SFP} value to be tested + * @return {@code true} if the argument is a finite + * floating-point value, {@code false} otherwise. + */ + default boolean isFinite(SFP operand) { + return !isInfinite(operand) && !isNaN(operand); + } + + /** + * Returns the size of an ulp of the argument. + * + *

Special Cases: + *

    + *
  • If the argument is NaN, then the result is NaN. + *
  • If the argument is positive or negative infinity, then the + * result is positive infinity. + *
  • If the argument is positive or negative zero, then the result is + * the minimum value of the format. + *
+ * + * @param operand the floating-point value whose ulp is to be returned + * @return the size of an ulp of the argument + */ + SFP ulp(SFP operand); + + /** + * Returns a hexadecimal string representation of the argument. + * + * @param operand the value to be converted. + * @return a hex string representation of the argument. + * + */ + String toHexString(SFP operand); + + // Possible TODO: + // scaleBy + // nextUp/nextDown + // ... +}