001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.geometry.examples.jmh;
018
019import org.apache.commons.rng.UniformRandomProvider;
020
021/** Class containing static utility methods for performance benchmarks.
022 */
023public final class BenchmarkUtils {
024
025    /** Default min exponent for random double values. */
026    public static final int DEFAULT_MIN_EXP = -64;
027
028    /** Default max exponent for random double values. */
029    public static final int DEFAULT_MAX_EXP = 64;
030
031    /** Utility class; no instantiation. */
032    private BenchmarkUtils() {}
033
034    /** Creates a random double number with a random sign and mantissa and a large, default
035     * range for the exponent. The numbers will not be uniform over the range.
036     * @param rng random number generator
037     * @return the random number
038     */
039    public static double randomDouble(final UniformRandomProvider rng) {
040        return randomDouble(DEFAULT_MIN_EXP, DEFAULT_MAX_EXP, rng);
041    }
042
043    /** Create a random double value with exponent in the range {@code [minExp, maxExp]}.
044     * @param minExp minimum exponent; must be less than {@code maxExp}
045     * @param maxExp maximum exponent; must be greater than {@code minExp}
046     * @param rng random number generator
047     * @return random double
048     */
049    public static double randomDouble(final int minExp, final int maxExp, final UniformRandomProvider rng) {
050        // Create random doubles using random bits in the sign bit and the mantissa.
051        final long mask = ((1L << 52) - 1) | 1L << 63;
052        final long bits = rng.nextLong() & mask;
053        // The exponent must be unsigned so + 1023 to the signed exponent
054        final long exp = rng.nextInt(maxExp - minExp + 1) + minExp + 1023;
055        return Double.longBitsToDouble(bits | (exp << 52));
056    }
057
058    /** Create an array of doubles populated using {@link #randomDouble(UniformRandomProvider)}.
059     * @param rng uniform random provider
060     * @param len array length
061     * @return array containing {@code len} random doubles
062     */
063    public static double[] randomDoubleArray(final int len, final UniformRandomProvider rng) {
064        return randomDoubleArray(len, DEFAULT_MIN_EXP, DEFAULT_MAX_EXP, rng);
065    }
066
067    /** Create an array with the given length containing random doubles with exponents in the range
068     * {@code [minExp, maxExp]}.
069     * @param len array length
070     * @param minExp minimum exponent; must be less than {@code maxExp}
071     * @param maxExp maximum exponent; must be greater than {@code minExp}
072     * @param rng random number generator
073     * @return array of random doubles
074     */
075    public static double[] randomDoubleArray(final int len, final int minExp, final int maxExp,
076            final UniformRandomProvider rng) {
077        final double[] arr = new double[len];
078        for (int i = 0; i < arr.length; ++i) {
079            arr[i] = randomDouble(minExp, maxExp, rng);
080        }
081        return arr;
082    }
083}