1 /* 2 * Copyright (C) 2011 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.common.math; 18 19 import static com.google.common.math.MathBenchmarking.ARRAY_MASK; 20 import static com.google.common.math.MathBenchmarking.ARRAY_SIZE; 21 import static com.google.common.math.MathBenchmarking.RANDOM_SOURCE; 22 import static com.google.common.math.MathBenchmarking.randomBigInteger; 23 import static com.google.common.math.MathBenchmarking.randomNonNegativeBigInteger; 24 25 import com.google.caliper.BeforeExperiment; 26 import com.google.caliper.Benchmark; 27 import com.google.caliper.Param; 28 29 /** 30 * Benchmarks against the Apache Commons Math utilities. 31 * 32 * <p>Note: the Apache benchmarks are not open sourced to avoid the extra dependency. 33 * 34 * @author Louis Wasserman 35 */ 36 public class ApacheBenchmark { 37 private enum Impl { 38 GUAVA { 39 @Override factorialDouble(int n)40 public double factorialDouble(int n) { 41 return DoubleMath.factorial(n); 42 } 43 44 @Override gcdInt(int a, int b)45 public int gcdInt(int a, int b) { 46 return IntMath.gcd(a, b); 47 } 48 49 @Override gcdLong(long a, long b)50 public long gcdLong(long a, long b) { 51 return LongMath.gcd(a, b); 52 } 53 54 @Override binomialCoefficient(int n, int k)55 public long binomialCoefficient(int n, int k) { 56 return LongMath.binomial(n, k); 57 } 58 59 @Override noAddOverflow(int a, int b)60 public boolean noAddOverflow(int a, int b) { 61 try { 62 int unused = IntMath.checkedAdd(a, b); 63 return true; 64 } catch (ArithmeticException e) { 65 return false; 66 } 67 } 68 69 @Override noAddOverflow(long a, long b)70 public boolean noAddOverflow(long a, long b) { 71 try { 72 long unused = LongMath.checkedAdd(a, b); 73 return true; 74 } catch (ArithmeticException e) { 75 return false; 76 } 77 } 78 79 @Override noMulOverflow(int a, int b)80 public boolean noMulOverflow(int a, int b) { 81 try { 82 int unused = IntMath.checkedMultiply(a, b); 83 return true; 84 } catch (ArithmeticException e) { 85 return false; 86 } 87 } 88 89 @Override noMulOverflow(long a, long b)90 public boolean noMulOverflow(long a, long b) { 91 try { 92 long unused = LongMath.checkedMultiply(a, b); 93 return true; 94 } catch (ArithmeticException e) { 95 return false; 96 } 97 } 98 }; 99 factorialDouble(int n)100 public abstract double factorialDouble(int n); 101 binomialCoefficient(int n, int k)102 public abstract long binomialCoefficient(int n, int k); 103 gcdInt(int a, int b)104 public abstract int gcdInt(int a, int b); 105 gcdLong(long a, long b)106 public abstract long gcdLong(long a, long b); 107 noAddOverflow(int a, int b)108 public abstract boolean noAddOverflow(int a, int b); 109 noAddOverflow(long a, long b)110 public abstract boolean noAddOverflow(long a, long b); 111 noMulOverflow(int a, int b)112 public abstract boolean noMulOverflow(int a, int b); 113 noMulOverflow(long a, long b)114 public abstract boolean noMulOverflow(long a, long b); 115 } 116 117 private final int[] factorials = new int[ARRAY_SIZE]; 118 private final int[][] binomials = new int[ARRAY_SIZE][2]; 119 private final int[][] nonnegInt = new int[ARRAY_SIZE][2]; 120 private final long[][] nonnegLong = new long[ARRAY_SIZE][2]; 121 private final int[][] intsToAdd = new int[ARRAY_SIZE][2]; 122 private final int[][] intsToMul = new int[ARRAY_SIZE][2]; 123 private final long[][] longsToAdd = new long[ARRAY_SIZE][2]; 124 private final long[][] longsToMul = new long[ARRAY_SIZE][2]; 125 126 @Param({"APACHE", "GUAVA"}) 127 Impl impl; 128 129 @BeforeExperiment setUp()130 void setUp() { 131 for (int i = 0; i < ARRAY_SIZE; i++) { 132 factorials[i] = RANDOM_SOURCE.nextInt(200); 133 for (int j = 0; j < 2; j++) { 134 nonnegInt[i][j] = randomNonNegativeBigInteger(Integer.SIZE - 2).intValue(); 135 nonnegLong[i][j] = randomNonNegativeBigInteger(Long.SIZE - 2).longValue(); 136 } 137 do { 138 for (int j = 0; j < 2; j++) { 139 intsToAdd[i][j] = randomBigInteger(Integer.SIZE - 2).intValue(); 140 } 141 } while (!Impl.GUAVA.noAddOverflow(intsToAdd[i][0], intsToAdd[i][1])); 142 do { 143 for (int j = 0; j < 2; j++) { 144 longsToAdd[i][j] = randomBigInteger(Long.SIZE - 2).longValue(); 145 } 146 } while (!Impl.GUAVA.noAddOverflow(longsToAdd[i][0], longsToAdd[i][1])); 147 do { 148 for (int j = 0; j < 2; j++) { 149 intsToMul[i][j] = randomBigInteger(Integer.SIZE - 2).intValue(); 150 } 151 } while (!Impl.GUAVA.noMulOverflow(intsToMul[i][0], intsToMul[i][1])); 152 do { 153 for (int j = 0; j < 2; j++) { 154 longsToMul[i][j] = randomBigInteger(Long.SIZE - 2).longValue(); 155 } 156 } while (!Impl.GUAVA.noMulOverflow(longsToMul[i][0], longsToMul[i][1])); 157 158 int k = binomials[i][1] = RANDOM_SOURCE.nextInt(MathBenchmarking.biggestBinomials.length); 159 binomials[i][0] = RANDOM_SOURCE.nextInt(MathBenchmarking.biggestBinomials[k] - k) + k; 160 } 161 } 162 163 @Benchmark factorialDouble(int reps)164 long factorialDouble(int reps) { 165 long tmp = 0; 166 for (int i = 0; i < reps; i++) { 167 int j = i & ARRAY_MASK; 168 tmp += Double.doubleToRawLongBits(impl.factorialDouble(factorials[j])); 169 } 170 return tmp; 171 } 172 173 @Benchmark intGCD(int reps)174 int intGCD(int reps) { 175 int tmp = 0; 176 for (int i = 0; i < reps; i++) { 177 int j = i & ARRAY_MASK; 178 tmp += impl.gcdInt(nonnegInt[j][0], nonnegInt[j][1]); 179 } 180 return tmp; 181 } 182 183 @Benchmark longGCD(int reps)184 long longGCD(int reps) { 185 long tmp = 0; 186 for (int i = 0; i < reps; i++) { 187 int j = i & ARRAY_MASK; 188 tmp += impl.gcdLong(nonnegLong[j][0], nonnegLong[j][1]); 189 } 190 return tmp; 191 } 192 193 @Benchmark binomialCoefficient(int reps)194 long binomialCoefficient(int reps) { 195 long tmp = 0; 196 for (int i = 0; i < reps; i++) { 197 int j = i & ARRAY_MASK; 198 tmp += impl.binomialCoefficient(binomials[j][0], binomials[j][1]); 199 } 200 return tmp; 201 } 202 203 @Benchmark intAddOverflow(int reps)204 int intAddOverflow(int reps) { 205 int tmp = 0; 206 for (int i = 0; i < reps; i++) { 207 int j = i & ARRAY_MASK; 208 if (impl.noAddOverflow(intsToAdd[j][0], intsToAdd[j][1])) { 209 tmp++; 210 } 211 } 212 return tmp; 213 } 214 215 @Benchmark longAddOverflow(int reps)216 int longAddOverflow(int reps) { 217 int tmp = 0; 218 for (int i = 0; i < reps; i++) { 219 int j = i & ARRAY_MASK; 220 if (impl.noAddOverflow(longsToAdd[j][0], longsToAdd[j][1])) { 221 tmp++; 222 } 223 } 224 return tmp; 225 } 226 227 @Benchmark intMulOverflow(int reps)228 int intMulOverflow(int reps) { 229 int tmp = 0; 230 for (int i = 0; i < reps; i++) { 231 int j = i & ARRAY_MASK; 232 if (impl.noMulOverflow(intsToMul[j][0], intsToMul[j][1])) { 233 tmp++; 234 } 235 } 236 return tmp; 237 } 238 239 @Benchmark longMulOverflow(int reps)240 int longMulOverflow(int reps) { 241 int tmp = 0; 242 for (int i = 0; i < reps; i++) { 243 int j = i & ARRAY_MASK; 244 if (impl.noMulOverflow(longsToMul[j][0], longsToMul[j][1])) { 245 tmp++; 246 } 247 } 248 return tmp; 249 } 250 } 251