All Downloads are FREE. Search and download functionalities are using the official Maven repository.

fj.test.Rand Maven / Gradle / Ivy

Go to download

Functional Java is an open source library that supports closures for the Java programming language

The newest version!
package fj.test;

import fj.F;
import fj.data.Option;

import java.util.Random;

import static fj.data.Option.none;
import static fj.data.Option.some;
import static java.lang.Math.max;
import static java.lang.Math.min;

/**
 * A random number generator.
 *
 * @version %build.number%
 */
public final class Rand {
  private final F, F>> f;
  private final F, F>> g;

  // TODO Change to F when rand(f,g) is removed
  private final Option> optOnReseed;

  private Rand(
      F, F>> f,
      F, F>> g,
      Option> optOnReseed) {

    this.f = f;
    this.g = g;
    this.optOnReseed = optOnReseed;
  }

  /**
   * Randomly chooses a value between the given range (inclusive).
   *
   * @param seed The seed to use for random generation.
   * @param from The minimum value to choose.
   * @param to   The maximum value to choose.
   * @return A random value in the given range.
   */
  public int choose(final long seed, final int from, final int to) {
    return f.f(some(seed)).f(from).f(to);
  }

  /**
   * Randomly chooses a value between the given range (inclusive).
   *
   * @param from The minimum value to choose.
   * @param to   The maximum value to choose.
   * @return A random value in the given range.
   */
  public int choose(final int from, final int to) {
    return f.f(Option.none()).f(from).f(to);
  }

  public long choose(final long from, final long to) {
    return g.f(Option.none()).f((double) from).f((double) to).longValue();
  }
  /**
   * Randomly chooses a value between the given range (inclusive).
   *
   * @param seed The seed to use for random generation.
   * @param from The minimum value to choose.
   * @param to   The maximum value to choose.
   * @return A random value in the given range.
   */
  public double choose(final long seed, final double from, final double to) {
    return g.f(some(seed)).f(from).f(to);
  }

  /**
   * Randomly chooses a value between the given range (inclusive).
   *
   * @param from The minimum value to choose.
   * @param to   The maximum value to choose.
   * @return A random value in the given range.
   */
  public double choose(final double from, final double to) {
    return g.f(Option.none()).f(from).f(to);
  }

  /**
   * Gives this random generator a new seed.
   *
   * @param seed The seed of the new random generator.
   * @return A random generator with the given seed.
   */
  public Rand reseed(long seed) {
    return optOnReseed.option(
        () -> {
          throw new IllegalStateException("reseed() called on a Rand created with deprecated rand() method");
        },
        onReseed -> onReseed.f(seed));
  }

  /**
   * Constructs a random generator from the given functions that supply a range to produce a
   * result.
   * 

* Calling {@link #reseed(long)} on an instance returned from this method will * result in an exception being thrown. * * @deprecated As of release 4.6, use {@link #rand(F, F, F)}. * * @param f The integer random generator. * @param g The floating-point random generator. * @return A random generator from the given functions that supply a range to produce a result. */ // TODO Change Option> optOnReseed to F onReseed when removing this method @Deprecated public static Rand rand( F, F>> f, F, F>> g) { return new Rand(f, g, none()); } /** * Constructs a reseedable random generator from the given functions that supply a range to produce a * result. * * @param f The integer random generator. * @param g The floating-point random generator. * @param onReseed Function to create a reseeded Rand. * @return A random generator from the given functions that supply a range to produce a result. */ public static Rand rand( F, F>> f, F, F>> g, F onReseed) { return new Rand(f, g, some(onReseed)); } /** * A standard random generator that uses {@link Random}. */ public static final Rand standard = createStandard(new Random()); private static Rand createStandard(Random defaultRandom) { return rand( optSeed -> from -> to -> standardChooseInt(optSeed.option(() -> defaultRandom, Random::new), from, to), optSeed -> from -> to -> standardChooseDbl(optSeed.option(() -> defaultRandom, Random::new), from, to), newSeed -> createStandard(new Random(newSeed))); } /* * Returns a uniformly distributed value between min(from,to) (inclusive) and max(from,to) (inclusive). */ private static int standardChooseInt(Random random, int from, int to) { int result; if (from != to) { int min = min(from, to); int max = max(from, to); long range = (1L + max) - min; long bound = Long.MAX_VALUE - (Long.MAX_VALUE % range); long r = random.nextLong() & Long.MAX_VALUE; while (r >= bound) { // Ensure uniformity r = random.nextLong() & Long.MAX_VALUE; } result = (int) ((r % range) + min); } else { result = from; } return result; } /* * Returns a uniformly distributed value between min(from,to) (inclusive) and max(from,to) (exclusive) * * In theory, this differs from the choose() contract, which specifies a closed interval. * In practice, the difference shouldn't matter. */ private static double standardChooseDbl(Random random, double from, double to) { double min = min(from, to); double max = max(from, to); return ((max - min) * random.nextDouble()) + min; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy