jdk/test/micro/org/openjdk/bench/java/lang/StrictMathExtraBench.java
2025-10-31 14:00:55 +00:00

675 lines
19 KiB
Java

/*
* Copyright (c) 2025, 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.
*
* 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 org.openjdk.bench.java.lang;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
import java.util.Random;
import java.util.concurrent.TimeUnit;
@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Fork(3)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@BenchmarkMode(Mode.AverageTime)
public class StrictMathExtraBench {
public static final int SIZE = 1022;
private static final Random rnd = new Random(42);
@State(Scope.Thread)
public static class RangeState {
final double[] values = new double[SIZE];
final double min, max;
final boolean signed;
public RangeState(boolean signed, double min, double max) {
this.min = min;
this.max = max;
this.signed = signed;
}
public RangeState(double min, double max) {
this(true, min, max);
}
@Setup
public void setup() {
for (int i = 0; i < values.length; i++) {
values[i] = rnd.nextDouble(min, max);
if (signed & rnd.nextBoolean()) {
values[i] = -values[i];
}
}
}
}
public static class RangeSubnormal extends RangeState {
public RangeSubnormal() {
super(0, Double.MIN_NORMAL);
}
}
public static class RangeNormal extends RangeState {
public RangeNormal() {
super(Double.MIN_NORMAL, Double.MAX_VALUE);
}
}
public static class RangePositiveSubnormal extends RangeState {
public RangePositiveSubnormal() {
super(false, 0, Double.MIN_NORMAL);
}
}
public static class RangePositiveNormal extends RangeState {
public RangePositiveNormal() {
super(false, Double.MIN_NORMAL, Double.MAX_VALUE);
}
}
public static class RangePiQuarter extends RangeState {
public RangePiQuarter() {
super(Double.MIN_NORMAL, Math.PI / 4);
}
}
public static class RangePiQuarterTo3PiQuarter extends RangeState {
public RangePiQuarterTo3PiQuarter() {
super(Math.PI / 4, 3 * Math.PI / 4);
}
}
public static class Range3PiQuarterToPiHalfTwo19 extends RangeState {
public Range3PiQuarterToPiHalfTwo19() {
super(3 * Math.PI / 4, 0x1.0p19 * Math.PI / 2);
}
}
public static class RangeBeyondPiHalfTwo19 extends RangeState {
public RangeBeyondPiHalfTwo19() {
super(0x1.0p19 * Math.PI / 2, Double.MAX_VALUE);
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void sin_subnormal(Blackhole bh, RangeSubnormal r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.sin(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void sin_pi_quarter(Blackhole bh, RangePiQuarter r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.sin(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void sin_3pi_quarter(Blackhole bh, RangePiQuarterTo3PiQuarter r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.sin(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void sin_pi_half_two19(Blackhole bh, Range3PiQuarterToPiHalfTwo19 r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.sin(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void sin_beyond_pi_half_two19(Blackhole bh, RangeBeyondPiHalfTwo19 r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.sin(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void cos_subnormal(Blackhole bh, RangeSubnormal r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.cos(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void cos_pi_quarter(Blackhole bh, RangePiQuarter r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.cos(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void cos_3pi_quarter(Blackhole bh, RangePiQuarterTo3PiQuarter r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.cos(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void cos_pi_half_two19(Blackhole bh, Range3PiQuarterToPiHalfTwo19 r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.cos(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void cos_beyond_pi_half_two19(Blackhole bh, RangeBeyondPiHalfTwo19 r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.cos(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void tan_subnormal(Blackhole bh, RangeSubnormal r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.tan(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void tan_pi_quarter(Blackhole bh, RangePiQuarter r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.tan(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void tan_3pi_quarter(Blackhole bh, RangePiQuarterTo3PiQuarter r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.tan(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void tan_pi_half_two19(Blackhole bh, Range3PiQuarterToPiHalfTwo19 r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.tan(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void tan_beyond_pi_half_two19(Blackhole bh, RangeBeyondPiHalfTwo19 r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.tan(v));
}
}
public static class RangeHalf extends RangeState {
public RangeHalf() {
super(Double.MIN_NORMAL, 0.5);
}
}
public static class RangeHalfToOne extends RangeState {
public RangeHalfToOne() {
super(0.5, 1.0);
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void asin_subnormal(Blackhole bh, RangeSubnormal r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.asin(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void asin_half(Blackhole bh, RangeHalf r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.asin(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void asin_one(Blackhole bh, RangeHalfToOne r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.asin(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void acos_subnormal(Blackhole bh, RangeSubnormal r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.acos(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void acos_half(Blackhole bh, RangeHalf r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.acos(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void acos_one(Blackhole bh, RangeHalfToOne r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.acos(v));
}
}
public static class RangeTwo66 extends RangeState {
public RangeTwo66() {
super(Double.MIN_NORMAL, 0x1.0p66);
}
}
public static class RangeBeyondTwo66 extends RangeState {
public RangeBeyondTwo66() {
super(0x1.0p66, Double.MAX_VALUE);
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void atan_subnormal(Blackhole bh, RangeSubnormal r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.atan(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void atan_two66(Blackhole bh, RangeTwo66 r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.atan(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void atan_beyond_two66(Blackhole bh, RangeBeyondTwo66 r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.atan(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void atan2_subnormal(Blackhole bh, RangeSubnormal r0, RangeSubnormal r1) {
double[] values0 = r0.values;
double[] values1 = r1.values;
for (int i = 0; i < values0.length; i++) {
bh.consume(StrictMath.atan2(values0[i], values1[i]));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void atan2_normal(Blackhole bh, RangeNormal r0, RangeNormal r1) {
double[] values0 = r0.values;
double[] values1 = r1.values;
for (int i = 0; i < values0.length; i++) {
bh.consume(StrictMath.atan2(values0[i], values1[i]));
}
}
private static final double LN2 = Math.log(2)/Math.log(Math.E);
public static class RangeHalfLn2 extends RangeState {
public RangeHalfLn2() {
super(Double.MIN_NORMAL, LN2 / 2);
}
}
public static class RangeBeyondHalfLn2 extends RangeState {
public RangeBeyondHalfLn2() {
super(LN2 / 2, Double.MAX_VALUE);
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void exp_subnormal(Blackhole bh, RangeSubnormal r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.exp(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void exp_half_ln2(Blackhole bh, RangeHalfLn2 r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.exp(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void exp_beyond_half_ln2(Blackhole bh, RangeBeyondHalfLn2 r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.exp(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void log_subnormal(Blackhole bh, RangePositiveSubnormal r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.log(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void log_normal(Blackhole bh, RangePositiveNormal r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.log(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void log10_subnormal(Blackhole bh, RangePositiveSubnormal r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.log10(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void log10_normal(Blackhole bh, RangePositiveNormal r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.log10(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void log1p_subnormal(Blackhole bh, RangePositiveSubnormal r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.log1p(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void log1p_normal(Blackhole bh, RangePositiveNormal r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.log1p(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void cbrt_subnormal(Blackhole bh, RangeSubnormal r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.cbrt(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void cbrt_normal(Blackhole bh, RangeNormal r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.cbrt(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void pow_subnormal(Blackhole bh, RangeSubnormal r0, RangeSubnormal r1) {
double[] values0 = r0.values;
double[] values1 = r1.values;
for (int i = 0; i < values0.length; i++) {
bh.consume(StrictMath.pow(values0[i], values1[i]));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void pow_normal(Blackhole bh, RangeNormal r0, RangeNormal r1) {
double[] values0 = r0.values;
double[] values1 = r1.values;
for (int i = 0; i < values0.length; i++) {
bh.consume(StrictMath.pow(values0[i], values1[i]));
}
}
public static class Range22 extends RangeState {
public Range22() {
super(Double.MIN_NORMAL, 22);
}
}
public static class RangeBeyond22 extends RangeState {
public RangeBeyond22() {
super(22, Double.MAX_VALUE);
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void sinh_subnormal(Blackhole bh, RangeSubnormal r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.sinh(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void sinh_22(Blackhole bh, RangeTwoNeg54 r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.sinh(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void sinh_beyond_22(Blackhole bh, RangeBeyond22 r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.sinh(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void cosh_subnormal(Blackhole bh, RangeSubnormal r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.cosh(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void cosh_22(Blackhole bh, RangeTwoNeg54 r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.cosh(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void cosh_beyond_22(Blackhole bh, RangeBeyond22 r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.cosh(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void tanh_subnormal(Blackhole bh, RangeSubnormal r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.tanh(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void tanh_22(Blackhole bh, RangeTwoNeg54 r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.tanh(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void hypot_subnormal(Blackhole bh, RangeSubnormal r0, RangeSubnormal r1) {
double[] values0 = r0.values;
double[] values1 = r1.values;
for (int i = 0; i < values0.length; i++) {
bh.consume(StrictMath.hypot(values0[i], values1[i]));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void hypot_normal(Blackhole bh, RangeNormal r0, RangeNormal r1) {
double[] values0 = r0.values;
double[] values1 = r1.values;
for (int i = 0; i < values0.length; i++) {
bh.consume(StrictMath.hypot(values0[i], values1[i]));
}
}
public static class RangeTwoNeg54 extends RangeState {
public RangeTwoNeg54() {
super(Double.MIN_NORMAL, 0x1.0p-54);
}
}
public static class RangeTwoNeg54ToHalfLn2 extends RangeState {
public RangeTwoNeg54ToHalfLn2() {
super(0x1.0p-54, LN2 / 2);
}
}
public static class RangeHalfLn2To56Ln2 extends RangeState {
public RangeHalfLn2To56Ln2() {
super(LN2 / 2, 56 * LN2);
}
}
public static class RangeBeyond56Ln2 extends RangeState {
public RangeBeyond56Ln2() {
super(56 * LN2, Double.MAX_VALUE);
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void expm1_two_neg_54(Blackhole bh, RangeTwoNeg54 r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.expm1(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void expm1_half_ln2(Blackhole bh, RangeTwoNeg54ToHalfLn2 r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.expm1(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void expm1_56ln2(Blackhole bh, RangeHalfLn2To56Ln2 r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.expm1(v));
}
}
@Benchmark
@OperationsPerInvocation(SIZE)
public void expm1_beyond_56ln2(Blackhole bh, RangeBeyond56Ln2 r) {
double[] values = r.values;
for (double v : values) {
bh.consume(StrictMath.expm1(v));
}
}
}