From 75ac381c392d5e744f399a70275c6a1ed79d44f7 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Thu, 15 Jan 2026 20:47:30 -0800 Subject: [PATCH 1/7] 8338529: Initial iteration of numerics modeling interfaces --- .../share/classes/java/lang/Integral.java | 110 +++++++++ .../share/classes/java/lang/Numerical.java | 151 ++++++++++++ .../share/classes/java/lang/Orderable.java | 108 +++++++++ .../java/lang/StandardFloatingPoint.java | 224 ++++++++++++++++++ 4 files changed, 593 insertions(+) create mode 100644 src/java.base/share/classes/java/lang/Integral.java create mode 100644 src/java.base/share/classes/java/lang/Numerical.java create mode 100644 src/java.base/share/classes/java/lang/Orderable.java create mode 100644 src/java.base/share/classes/java/lang/StandardFloatingPoint.java 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..2ce84840bcd --- /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); +} \ No newline at end of file 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..ea7f3dca702 --- /dev/null +++ b/src/java.base/share/classes/java/lang/Numerical.java @@ -0,0 +1,151 @@ +/* + * 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. + * + *

In mathematical terms, various kinds of algebraic structures + * support the operations modeled by this interface. For example, + * integers with Euclidean division support the operations in question + * as do algebraic fields. Commonly used algebraic 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. + * + *

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 fields and field-like + * numbers as well as rings and ring-links numbers. + * + * @apiNote + * 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 + */ + 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 + */ + 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 + */ + NT multiply(NT multiplier, NT multiplicand); + + /** + * Division operation, binary operator "{@code /}". + * + * @throws ArithmeticException if the divisor is zero + * @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 %}". + * + * @throws ArithmeticException if the divisor is zero + * @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 + */ + 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..32da14028c1 --- /dev/null +++ b/src/java.base/share/classes/java/lang/Orderable.java @@ -0,0 +1,108 @@ +/* + * 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. + * + * @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 <=}". + * + * @param op1 the first operand + * @param op2 the second operand + */ + boolean lessThanEqual(OC op1, OC 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 >}". + * + * @param op1 the first operand + * @param op2 the second operand + */ + boolean greaterThan(OC op1, OC 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 >=}". + * + * @param op1 the first operand + * @param op2 the second operand + */ + boolean greaterThanEqual(OC op1, OC 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. + * + * @param op1 the first operand + * @param op2 the second operand + */ + OC min(OC op1, OC 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. + * + * @param op1 the first operand + * @param op2 the second operand + */ + OC max(OC op1, OC op2); +} \ No newline at end of file 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..a8a0cec1abf --- /dev/null +++ b/src/java.base/share/classes/java/lang/StandardFloatingPoint.java @@ -0,0 +1,224 @@ +/* + * 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. + * + * @apiNote + * Possible future work: separate subinterface for decimal IEEE 754 + * types. + * + * @param The standard floating-point type + */ +public interface StandardFloatingPoint + extends Numerical, Orderable { + + /** + * {@inheritDoc Orderable} + * TODO: Need to replace 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 replace Orderable interface spec with IEEE 754 + * aware one. + * + * @apiNote + * Explain all the IEEE 754-isms. + * + * @param op1 the {@inheritDoc Orderable} + * @param op2 the {@inheritDoc Orderable} + */ + @Override + boolean lessThanEqual(SFP op1, SFP op2); + + /** + * {@inheritDoc Orderable} + * TODO: Need to replace Orderable interface spec with IEEE 754 + * aware one. + * + * @apiNote + * Explain all the IEEE 754-isms. + * + * @param op1 {@inheritDoc Orderable} + * @param op2 {@inheritDoc Orderable} + */ + @Override + boolean greaterThan(SFP op1, SFP op2); + + /** + * {@inheritDoc Orderable} + * TODO: Need to replace Orderable interface spec with IEEE 754 + * aware one. + * + * @apiNote + * Explain all the IEEE 754-isms. + * + * @param op1 {@inheritDoc Orderable} + * @param op2 {@inheritDoc Orderable} + */ + @Override + boolean greaterThanEqual(SFP op1, SFP op2); + + /** + * {@inheritDoc Orderable} + * + * @apiNote + * TODO: Explain all the IEEE 754-isms. + * + * @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. + * + * @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. + * + * @param operand the {@code SFP} value to be tested + * @return {@code true} if the argument is a finite + * floating-point value, {@code false} otherwise. + */ + boolean isFinite(SFP 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 + // ... +} \ No newline at end of file From 8fc78adc6a7ec322814dafa8cf6ce024260fc2db Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Thu, 15 Jan 2026 20:56:59 -0800 Subject: [PATCH 2/7] Appease jcheck --- src/java.base/share/classes/java/lang/Integral.java | 2 +- src/java.base/share/classes/java/lang/Orderable.java | 2 +- .../share/classes/java/lang/StandardFloatingPoint.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/java.base/share/classes/java/lang/Integral.java b/src/java.base/share/classes/java/lang/Integral.java index 2ce84840bcd..93f6326494f 100644 --- a/src/java.base/share/classes/java/lang/Integral.java +++ b/src/java.base/share/classes/java/lang/Integral.java @@ -107,4 +107,4 @@ public interface Integral * @throws UnsupportedOperationException if unsigned right shift is not supposed */ IT shiftRightUnsigned(IT x, int shiftDistance); -} \ No newline at end of file +} diff --git a/src/java.base/share/classes/java/lang/Orderable.java b/src/java.base/share/classes/java/lang/Orderable.java index 32da14028c1..0eb53909968 100644 --- a/src/java.base/share/classes/java/lang/Orderable.java +++ b/src/java.base/share/classes/java/lang/Orderable.java @@ -105,4 +105,4 @@ public interface Orderable { * @param op2 the second operand */ OC max(OC op1, OC op2); -} \ No newline at end of file +} diff --git a/src/java.base/share/classes/java/lang/StandardFloatingPoint.java b/src/java.base/share/classes/java/lang/StandardFloatingPoint.java index a8a0cec1abf..5fac489077a 100644 --- a/src/java.base/share/classes/java/lang/StandardFloatingPoint.java +++ b/src/java.base/share/classes/java/lang/StandardFloatingPoint.java @@ -221,4 +221,4 @@ public interface StandardFloatingPoint // scaleBy // nextUp/nextDown // ... -} \ No newline at end of file +} From 0b633368fc160bf3c911f7e38f30d37c6ccbcfd2 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Thu, 15 Jan 2026 21:00:27 -0800 Subject: [PATCH 3/7] Appease jcheck some more. --- src/java.base/share/classes/java/lang/StandardFloatingPoint.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/java.base/share/classes/java/lang/StandardFloatingPoint.java b/src/java.base/share/classes/java/lang/StandardFloatingPoint.java index 5fac489077a..d38baaf3e88 100644 --- a/src/java.base/share/classes/java/lang/StandardFloatingPoint.java +++ b/src/java.base/share/classes/java/lang/StandardFloatingPoint.java @@ -42,7 +42,6 @@ public interface StandardFloatingPoint * {@inheritDoc Orderable} * TODO: Need to replace Orderable interface spec with IEEE 754 * aware one. - * * * @param op1 {@inheritDoc Orderable} * @param op2 {@inheritDoc Orderable} From 9a508b04d429618f23a1ca110a0deeb79528dd21 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Fri, 16 Jan 2026 11:11:19 -0800 Subject: [PATCH 4/7] Improve divide specifications. --- .../share/classes/java/lang/Numerical.java | 20 ++++++++++-- .../java/lang/StandardFloatingPoint.java | 31 +++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/java/lang/Numerical.java b/src/java.base/share/classes/java/lang/Numerical.java index ea7f3dca702..4cf33b82dd4 100644 --- a/src/java.base/share/classes/java/lang/Numerical.java +++ b/src/java.base/share/classes/java/lang/Numerical.java @@ -104,7 +104,15 @@ default NT subtract(NT minuend, NT subtrahend) { /** * Division operation, binary operator "{@code /}". * - * @throws ArithmeticException if the divisor is zero + * @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 @@ -115,7 +123,15 @@ default NT subtract(NT minuend, NT subtrahend) { /** * Remainder operation, binary operator "{@code %}". * - * @throws ArithmeticException if the divisor is zero + * @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 diff --git a/src/java.base/share/classes/java/lang/StandardFloatingPoint.java b/src/java.base/share/classes/java/lang/StandardFloatingPoint.java index d38baaf3e88..3ee436b6431 100644 --- a/src/java.base/share/classes/java/lang/StandardFloatingPoint.java +++ b/src/java.base/share/classes/java/lang/StandardFloatingPoint.java @@ -29,6 +29,9 @@ * 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. @@ -38,6 +41,34 @@ 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 replace Orderable interface spec with IEEE 754 From dc89df253861187fa1dae2454e41231f6df0f7b8 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Fri, 16 Jan 2026 11:59:05 -0800 Subject: [PATCH 5/7] Respond to review feedback; add default methods. --- .../share/classes/java/lang/Orderable.java | 46 ++++++++++++++++--- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/src/java.base/share/classes/java/lang/Orderable.java b/src/java.base/share/classes/java/lang/Orderable.java index 0eb53909968..f241d0dcea8 100644 --- a/src/java.base/share/classes/java/lang/Orderable.java +++ b/src/java.base/share/classes/java/lang/Orderable.java @@ -34,6 +34,10 @@ * <}, {@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 */ @@ -47,7 +51,7 @@ public interface Orderable { * @param op1 the first operand * @param op2 the second operand */ - boolean lessThan(OC op1, OC op2); + boolean lessThan(OC op1, OC op2); /** * {@return {@code true} if the first operand is less than or @@ -55,10 +59,16 @@ public interface Orderable { * * 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 */ - boolean lessThanEqual(OC op1, OC op2); + 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 @@ -66,10 +76,16 @@ public interface Orderable { * * 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 */ - boolean greaterThan(OC op1, OC op2); + default boolean greaterThan(OC op1, OC op2) { + return !lessThanEqual(op1, op2); + } /** * {@return {@code true} if the first operand is greater than or @@ -77,10 +93,16 @@ public interface Orderable { * * 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 */ - boolean greaterThanEqual(OC op1, OC op2); + default boolean greaterThanEqual(OC op1, OC op2) { + return !lessThan(op1, op2); + } /** * {@return the smaller of the two operands} @@ -89,10 +111,16 @@ public interface Orderable { * 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 */ - OC min(OC op1, OC op2); + default OC min(OC op1, OC op2) { + return lessThanEqual(op1, op2) ? op1 : op2; + } /** * {@return the larger of the two operands} @@ -101,8 +129,14 @@ public interface Orderable { * 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 */ - OC max(OC op1, OC op2); + default OC max(OC op1, OC op2) { + return greaterThanEqual(op1, op2) ? op1 : op2; + } } From 1a1713eca2f2874fd9af69df5f86e33ce81554f3 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Fri, 16 Jan 2026 12:45:54 -0800 Subject: [PATCH 6/7] Add default methods. --- .../java/lang/StandardFloatingPoint.java | 64 +++++++++++++++---- 1 file changed, 53 insertions(+), 11 deletions(-) diff --git a/src/java.base/share/classes/java/lang/StandardFloatingPoint.java b/src/java.base/share/classes/java/lang/StandardFloatingPoint.java index 3ee436b6431..b62e84d7f10 100644 --- a/src/java.base/share/classes/java/lang/StandardFloatingPoint.java +++ b/src/java.base/share/classes/java/lang/StandardFloatingPoint.java @@ -71,7 +71,8 @@ public interface StandardFloatingPoint /** * {@inheritDoc Orderable} - * TODO: Need to replace Orderable interface spec with IEEE 754 + * + *

TODO: Need to augment Orderable interface spec with IEEE 754 * aware one. * * @param op1 {@inheritDoc Orderable} @@ -82,51 +83,86 @@ public interface StandardFloatingPoint /** * {@inheritDoc Orderable} - * TODO: Need to replace Orderable interface spec with IEEE 754 + * + *

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 - boolean lessThanEqual(SFP op1, SFP op2); + default boolean lessThanEqual(SFP op1, SFP op2) { + return Orderable.super.lessThanEqual(op1, op2); + } /** * {@inheritDoc Orderable} - * TODO: Need to replace Orderable interface spec with IEEE 754 + * + *

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 - boolean greaterThan(SFP op1, SFP op2); + @Override + default boolean greaterThan(SFP op1, SFP op2) { + return !lessThanEqual(op1, op2) && !isUnordered(op1, op2); + } /** * {@inheritDoc Orderable} - * TODO: Need to replace Orderable interface spec with IEEE 754 + * + *

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 - boolean greaterThanEqual(SFP op1, SFP op2); + 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. + * TODO: Explain all the IEEE 754-isms, write default method. * * @param op1 {@inheritDoc Orderable} * @param op2 {@inheritDoc Orderable} @@ -138,7 +174,7 @@ public interface StandardFloatingPoint * {@inheritDoc Orderable} * * @apiNote - * TODO: Explain all the IEEE 754-isms. + * TODO: Explain all the IEEE 754-isms, write default method. * * @param op1 {@inheritDoc Orderable} * @param op2 {@inheritDoc Orderable} @@ -215,11 +251,17 @@ public interface StandardFloatingPoint * 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. */ - boolean isFinite(SFP operand); + default boolean isFinite(SFP operand) { + return !isInfinite(operand) && !isNaN(operand); + } /** * Returns the size of an ulp of the argument. From 7620d79df76a59d91c947593216c775b75854a96 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Tue, 20 Jan 2026 12:52:56 -0800 Subject: [PATCH 7/7] Add apiNote on closure under different operations, etc. --- .../share/classes/java/lang/Numerical.java | 66 +++++++++++++------ 1 file changed, 46 insertions(+), 20 deletions(-) diff --git a/src/java.base/share/classes/java/lang/Numerical.java b/src/java.base/share/classes/java/lang/Numerical.java index 4cf33b82dd4..3837a312ab5 100644 --- a/src/java.base/share/classes/java/lang/Numerical.java +++ b/src/java.base/share/classes/java/lang/Numerical.java @@ -33,18 +33,25 @@ * {@code -}), and participates in operator overloading of those * operators. * - *

In mathematical terms, various kinds of algebraic structures - * support the operations modeled by this interface. For example, - * integers with Euclidean division support the operations in question - * as do algebraic fields. Commonly used algebraic 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). + *

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 @@ -53,15 +60,26 @@ * addition are not expected to hold for a floating-point * type. * - *

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 fields and field-like - * numbers as well as rings and ring-links numbers. - * * @apiNote - * Future work: consider interactions with / support from {@link + * 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 @@ -74,6 +92,8 @@ public interface Numerical { * @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); @@ -87,6 +107,8 @@ public interface Numerical { * @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)); @@ -98,6 +120,8 @@ default NT subtract(NT minuend, NT subtrahend) { * @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); @@ -162,6 +186,8 @@ default NT plus(NT operand) { * @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); }