| /* |
| * Copyright (C) 2011 The Guava Authors |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.google.common.math; |
| |
| import java.math.BigInteger; |
| import java.util.Random; |
| |
| /** |
| * Utilities for benchmarks. |
| * |
| * In many cases, we wish to vary the order of magnitude of the input as much as we |
| * want to vary the input itself, so most methods which generate values use |
| * an exponential distribution varying the order of magnitude of the generated values |
| * uniformly at random. |
| * |
| * @author Louis Wasserman |
| */ |
| final class MathBenchmarking { |
| static final int ARRAY_SIZE = 0x10000; |
| static final int ARRAY_MASK = 0x0ffff; |
| static final Random RANDOM_SOURCE = new Random(314159265358979L); |
| static final int MAX_EXPONENT = 100; |
| |
| /* |
| * Duplicated from LongMath. |
| * binomial(biggestBinomials[k], k) fits in a long, but not |
| * binomial(biggestBinomials[k] + 1, k). |
| */ |
| static final int[] biggestBinomials = |
| {Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, 3810779, 121977, 16175, 4337, 1733, |
| 887, 534, 361, 265, 206, 169, 143, 125, 111, 101, 94, 88, 83, 79, 76, 74, 72, 70, 69, 68, |
| 67, 67, 66, 66, 66, 66}; |
| |
| /** |
| * Generates values in a distribution equivalent to randomNonNegativeBigInteger |
| * but omitting zero. |
| */ |
| static BigInteger randomPositiveBigInteger(int numBits) { |
| BigInteger result; |
| do { |
| result = randomNonNegativeBigInteger(numBits); |
| } while (result.signum() == 0); |
| return result; |
| } |
| |
| /** |
| * Generates a number in [0, 2^numBits) with an exponential distribution. |
| * The floor of the log2 of the result is chosen uniformly at random in |
| * [0, numBits), and then the result is chosen in that range uniformly at random. |
| * Zero is treated as having log2 == 0. |
| */ |
| static BigInteger randomNonNegativeBigInteger(int numBits) { |
| int digits = RANDOM_SOURCE.nextInt(numBits); |
| if (digits == 0) { |
| return new BigInteger(1, RANDOM_SOURCE); |
| } else { |
| return new BigInteger(digits, RANDOM_SOURCE) |
| .setBit(digits); |
| } |
| } |
| |
| /** |
| * Equivalent to calling randomPositiveBigInteger(numBits) and then flipping |
| * the sign with 50% probability. |
| */ |
| static BigInteger randomNonZeroBigInteger(int numBits) { |
| BigInteger result = randomPositiveBigInteger(numBits); |
| return RANDOM_SOURCE.nextBoolean() ? result : result.negate(); |
| } |
| |
| /** |
| * Chooses a number in (-2^numBits, 2^numBits) at random, with density |
| * concentrated in numbers of lower magnitude. |
| */ |
| static BigInteger randomBigInteger(int numBits) { |
| while (true) { |
| if (RANDOM_SOURCE.nextBoolean()) { |
| return randomNonNegativeBigInteger(numBits); |
| } |
| BigInteger neg = randomNonNegativeBigInteger(numBits).negate(); |
| if (neg.signum() != 0) { |
| return neg; |
| } |
| } |
| } |
| |
| /** |
| * Generates a number in [0, 2^numBits) with an exponential distribution. |
| * The floor of the log2 of the absolute value of the result is chosen uniformly |
| * at random in [0, numBits), and then the result is chosen from those possibilities |
| * uniformly at random. |
| * |
| * Zero is treated as having log2 == 0. |
| */ |
| static double randomDouble(int maxExponent) { |
| double result = RANDOM_SOURCE.nextDouble(); |
| result = Math.scalb(result, RANDOM_SOURCE.nextInt(maxExponent + 1)); |
| return RANDOM_SOURCE.nextBoolean() ? result : -result; |
| } |
| |
| /** |
| * Returns a random integer between zero and {@code MAX_EXPONENT}. |
| */ |
| static int randomExponent() { |
| return RANDOM_SOURCE.nextInt(MAX_EXPONENT + 1); |
| } |
| |
| static double randomPositiveDouble() { |
| return Math.exp(randomDouble(6)); |
| } |
| } |