1 /* 2 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 25 package micro.benchmarks; 26 27 import java.math.BigInteger; 28 import java.util.Random; 29 30 import org.openjdk.jmh.annotations.Benchmark; 31 import org.openjdk.jmh.annotations.Scope; 32 import org.openjdk.jmh.annotations.State; 33 import org.openjdk.jmh.annotations.Warmup; 34 35 /* 36 * Benchmarks cost of BigInteger intrinsics: 37 * 38 * montgomeryMultiply, montgomerySquare, mulAdd, multiplyToLen, squareToLen 39 */ 40 public class BigIntegerBenchmark extends BenchmarkBase { 41 42 @State(Scope.Benchmark) 43 public static class ThreadState { 44 BigInteger[] data = randomBigInteger(100); 45 BigInteger[] result = new BigInteger[100]; 46 47 static BigInteger[] randomBigInteger(int len) { 48 BigInteger[] data = new BigInteger[len]; 49 Random r = new Random(17); 50 for (int i = 0; i < data.length; i++) { 51 data[i] = new BigInteger(r.nextInt(16384) + 512, r); 52 } 53 return data; 54 } 55 } 56 57 @Benchmark 58 @Warmup(iterations = 5) 59 public void bigIntMul(ThreadState state) { 60 BigInteger[] data = state.data; 61 for (int i = 1; i < data.length; i++) { 62 BigInteger[] result = state.result; 63 result[i] = data[i - 1].multiply(data[i]); 64 } 65 } 66 67 @Benchmark 68 @Warmup(iterations = 5) 69 public void bigIntMulAdd(ThreadState state) { 70 BigInteger[] data = state.data; 71 for (int i = 0; i < data.length; i++) { 72 BigInteger[] result = state.result; 73 // Using BigInteger.square() when length is suitable. 74 // Using BigInteger.mulAdd() when length is suitable. 75 result[i] = data[i].multiply(data[i]); 76 } 77 } 78 79 @Benchmark 80 @Warmup(iterations = 5) 81 public void bigIntMontgomeryMul(ThreadState state) { 82 BigInteger[] data = state.data; 83 BigInteger exp = BigInteger.valueOf(2); 84 85 for (int i = 0; i < data.length; i++) { 86 BigInteger[] result = state.result; 87 int rsh = data[i].bitLength() / 2 + 3; 88 // The "odd" path. 89 // Using BigInteger.montgomeryMultiply(). 90 // Using BigInteger.montgomerySquare(). 91 // Using BigInteger.mulAdd() when length is suitable. 92 result[i] = data[i].modPow(exp, data[i].shiftRight(rsh).setBit(0)); 93 } 94 } 95 96 @Benchmark 97 @Warmup(iterations = 5) 98 public void bigIntMontgomerySqr(ThreadState state) { 99 BigInteger[] data = state.data; 100 BigInteger exp = BigInteger.valueOf(2); 101 102 for (int i = 0; i < data.length; i++) { 103 BigInteger[] result = state.result; 104 int rsh = data[i].bitLength() / 2 + 3; 105 // The "even" path. 106 // Using BigInteger.montgomeryMultiply(). 107 // Using BigInteger.montgomerySquare(). 108 // Using BigInteger.mulAdd() when length is suitable. 109 result[i] = data[i].modPow(exp, data[i].shiftRight(rsh).clearBit(0)); 110 } 111 } 112 }