8222029: Optimize Math.floorMod
Reviewed-by: aph, darcy
This commit is contained in:
parent
0f4b0947ff
commit
8ee30d4fbe
@ -1274,7 +1274,12 @@ public final class Math {
|
||||
* @since 1.8
|
||||
*/
|
||||
public static int floorMod(int x, int y) {
|
||||
return x - floorDiv(x, y) * y;
|
||||
int mod = x % y;
|
||||
// if the signs are different and modulo not zero, adjust result
|
||||
if ((mod ^ y) < 0 && mod != 0) {
|
||||
mod += y;
|
||||
}
|
||||
return mod;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1301,7 +1306,7 @@ public final class Math {
|
||||
*/
|
||||
public static int floorMod(long x, int y) {
|
||||
// Result cannot overflow the range of int.
|
||||
return (int)(x - floorDiv(x, y) * y);
|
||||
return (int)floorMod(x, (long)y);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1327,7 +1332,12 @@ public final class Math {
|
||||
* @since 1.8
|
||||
*/
|
||||
public static long floorMod(long x, long y) {
|
||||
return x - floorDiv(x, y) * y;
|
||||
long mod = x % y;
|
||||
// if the signs are different and modulo not zero, adjust result
|
||||
if ((x ^ y) < 0 && mod != 0) {
|
||||
mod += y;
|
||||
}
|
||||
return mod;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -91,6 +91,10 @@ public class DivModTests {
|
||||
testIntFloorDivMod(Integer.MIN_VALUE, 3, -715827883, 1);
|
||||
testIntFloorDivMod(Integer.MIN_VALUE + 1, 3, -715827883, 2);
|
||||
testIntFloorDivMod(Integer.MIN_VALUE + 1, -1, Integer.MAX_VALUE, 0);
|
||||
testIntFloorDivMod(Integer.MAX_VALUE, Integer.MAX_VALUE, 1, 0);
|
||||
testIntFloorDivMod(Integer.MAX_VALUE, Integer.MIN_VALUE, -1, -1);
|
||||
testIntFloorDivMod(Integer.MIN_VALUE, Integer.MIN_VALUE, 1, 0);
|
||||
testIntFloorDivMod(Integer.MIN_VALUE, Integer.MAX_VALUE, -2, 2147483646);
|
||||
// Special case of integer overflow
|
||||
testIntFloorDivMod(Integer.MIN_VALUE, -1, Integer.MIN_VALUE, 0);
|
||||
}
|
||||
@ -179,6 +183,10 @@ public class DivModTests {
|
||||
testLongFloorDivMod(Long.MIN_VALUE, 3L, Long.MIN_VALUE / 3L - 1L, 1L);
|
||||
testLongFloorDivMod(Long.MIN_VALUE + 1L, 3L, Long.MIN_VALUE / 3L - 1L, 2L);
|
||||
testLongFloorDivMod(Long.MIN_VALUE + 1, -1, Long.MAX_VALUE, 0L);
|
||||
testLongFloorDivMod(Long.MAX_VALUE, Long.MAX_VALUE, 1L, 0L);
|
||||
testLongFloorDivMod(Long.MAX_VALUE, Long.MIN_VALUE, -1L, -1L);
|
||||
testLongFloorDivMod(Long.MIN_VALUE, Long.MIN_VALUE, 1L, 0L);
|
||||
testLongFloorDivMod(Long.MIN_VALUE, Long.MAX_VALUE, -2L, 9223372036854775806L);
|
||||
// Special case of integer overflow
|
||||
testLongFloorDivMod(Long.MIN_VALUE, -1, Long.MIN_VALUE, 0L);
|
||||
}
|
||||
@ -283,6 +291,10 @@ public class DivModTests {
|
||||
testLongIntFloorDivMod(Long.MIN_VALUE, 3, Long.MIN_VALUE / 3L - 1L, 1L);
|
||||
testLongIntFloorDivMod(Long.MIN_VALUE + 1L, 3, Long.MIN_VALUE / 3L - 1L, 2L);
|
||||
testLongIntFloorDivMod(Long.MIN_VALUE + 1, -1, Long.MAX_VALUE, 0L);
|
||||
testLongIntFloorDivMod(Long.MAX_VALUE, Integer.MAX_VALUE, 4294967298L, 1);
|
||||
testLongIntFloorDivMod(Long.MAX_VALUE, Integer.MIN_VALUE, -4294967296L, -1);
|
||||
testLongIntFloorDivMod(Long.MIN_VALUE, Integer.MIN_VALUE, 4294967296L, 0);
|
||||
testLongIntFloorDivMod(Long.MIN_VALUE, Integer.MAX_VALUE, -4294967299L, 2147483645);
|
||||
// Special case of integer overflow
|
||||
testLongIntFloorDivMod(Long.MIN_VALUE, -1, Long.MIN_VALUE, 0L);
|
||||
}
|
||||
|
95
test/micro/org/openjdk/bench/java/lang/MathBench.java
Normal file
95
test/micro/org/openjdk/bench/java/lang/MathBench.java
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) 2014 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.Benchmark;
|
||||
import org.openjdk.jmh.annotations.BenchmarkMode;
|
||||
import org.openjdk.jmh.annotations.CompilerControl;
|
||||
import org.openjdk.jmh.annotations.Mode;
|
||||
import org.openjdk.jmh.annotations.OutputTimeUnit;
|
||||
import org.openjdk.jmh.annotations.Param;
|
||||
import org.openjdk.jmh.annotations.Scope;
|
||||
import org.openjdk.jmh.annotations.Setup;
|
||||
import org.openjdk.jmh.annotations.State;
|
||||
import org.openjdk.jmh.annotations.Threads;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
@OutputTimeUnit(TimeUnit.NANOSECONDS)
|
||||
@State(Scope.Thread)
|
||||
public class MathBench {
|
||||
|
||||
@Param("0")
|
||||
public long seed;
|
||||
|
||||
public int dividend;
|
||||
public int divisor;
|
||||
|
||||
public long longDividend;
|
||||
public long longDivisor;
|
||||
|
||||
@Setup
|
||||
public void setupValues() {
|
||||
Random random = new Random(seed);
|
||||
dividend = Math.abs(random.nextInt() + 4711);
|
||||
divisor = Math.abs(random.nextInt(dividend) + 17);
|
||||
longDividend = Math.abs(random.nextLong() + 4711L);
|
||||
longDivisor = Math.abs(random.nextLong() + longDividend);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@CompilerControl(CompilerControl.Mode.DONT_INLINE)
|
||||
public int floorModIntIntPositive() {
|
||||
return Math.floorMod(dividend, divisor);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@CompilerControl(CompilerControl.Mode.DONT_INLINE)
|
||||
public int floorModIntInt() {
|
||||
return Math.floorMod( dividend, divisor) +
|
||||
Math.floorMod( dividend, -divisor) +
|
||||
Math.floorMod(-dividend, divisor) +
|
||||
Math.floorMod(-dividend, -divisor);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@CompilerControl(CompilerControl.Mode.DONT_INLINE)
|
||||
public int floorModLongInt() {
|
||||
return Math.floorMod( longDividend, divisor) +
|
||||
Math.floorMod( longDividend, -divisor) +
|
||||
Math.floorMod(-longDividend, divisor) +
|
||||
Math.floorMod(-longDividend, -divisor);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@CompilerControl(CompilerControl.Mode.DONT_INLINE)
|
||||
public long floorModLongLong() {
|
||||
return Math.floorMod( longDividend, longDivisor) +
|
||||
Math.floorMod( longDividend, -longDivisor) +
|
||||
Math.floorMod(-longDividend, longDivisor) +
|
||||
Math.floorMod(-longDividend, -longDivisor);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user