Fixed documentation in folly/Random.h
[folly.git] / folly / Random.h
index 8930526edd239aea14ff8ecc4c741231edb4e0c7..52f1f17c39e0ab8a26f40c2420463d5a1416dc50 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2017 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * limitations under the License.
  */
 
-#ifndef FOLLY_RANDOM_H_
+#pragma once
 #define FOLLY_RANDOM_H_
 
 #include <type_traits>
 #include <random>
 #include <stdint.h>
-#include <folly/ThreadLocal.h>
+#include <folly/Portability.h>
 
-#if __GNUC_PREREQ(4, 8) && !defined(ANDROID)
+#if FOLLY_HAVE_EXTRANDOM_SFMT19937
 #include <ext/random>
-#define FOLLY_USE_SIMD_PRNG 1
 #endif
 
 namespace folly {
@@ -41,7 +40,7 @@ namespace folly {
  * However, if you are worried about performance, you can memoize the TLS
  * lookups that get the per thread state by manually using this class:
  *
- * ThreadLocalPRNG rng = Random::threadLocalPRNG()
+ * ThreadLocalPRNG rng;
  * for (...) {
  *   Random::rand32(rng);
  * }
@@ -64,19 +63,11 @@ class ThreadLocalPRNG {
   }
   friend class Random;
 
-  ThreadLocalPRNG() {
-    local_ = localInstance.get();
-    if (!local_) {
-      local_ = initLocal();
-    }
-  }
+  ThreadLocalPRNG();
 
- private:
   class LocalInstancePRNG;
-  static LocalInstancePRNG* initLocal();
-  static folly::ThreadLocalPtr<ThreadLocalPRNG::LocalInstancePRNG>
-    localInstance;
 
+ private:
   static result_type getImpl(LocalInstancePRNG* local);
   LocalInstancePRNG* local_;
 };
@@ -85,14 +76,14 @@ class ThreadLocalPRNG {
 class Random {
 
  private:
-  template<class RNG>
+  template <class RNG>
   using ValidRNG = typename std::enable_if<
-   std::is_unsigned<typename std::result_of<RNG&()>::type>::value,
-   RNG>::type;
+      std::is_unsigned<typename std::result_of<RNG&()>::type>::value,
+      RNG>::type;
 
  public:
   // Default generator type.
-#if FOLLY_USE_SIMD_PRNG
+#if FOLLY_HAVE_EXTRANDOM_SFMT19937
   typedef __gnu_cxx::sfmt19937 DefaultGenerator;
 #else
   typedef std::mt19937 DefaultGenerator;
@@ -124,8 +115,8 @@ class Random {
    * to create a RNG with a good seed in production, and seed it yourself
    * in test.
    */
-  template <class RNG = DefaultGenerator>
-  static void seed(ValidRNG<RNG>& rng);
+  template <class RNG = DefaultGenerator, class /* EnableIf */ = ValidRNG<RNG>>
+  static void seed(RNG& rng);
 
   /**
    * Create a new RNG, seeded with a good seed.
@@ -135,104 +126,153 @@ class Random {
    * to create a RNG with a good seed in production, and seed it yourself
    * in test.
    */
-  template <class RNG = DefaultGenerator>
-  static ValidRNG<RNG> create();
+  template <class RNG = DefaultGenerator, class /* EnableIf */ = ValidRNG<RNG>>
+  static RNG create();
 
   /**
    * Returns a random uint32_t
    */
-  template<class RNG = ThreadLocalPRNG>
-  static uint32_t rand32(ValidRNG<RNG> rng = RNG()) {
-    uint32_t r = rng.operator()();
-    return r;
+  static uint32_t rand32() {
+    return rand32(ThreadLocalPRNG());
+  }
+
+  /**
+   * Returns a random uint32_t given a specific RNG
+   */
+  template <class RNG, class /* EnableIf */ = ValidRNG<RNG>>
+  static uint32_t rand32(RNG&& rng) {
+    return rng();
   }
 
   /**
    * Returns a random uint32_t in [0, max). If max == 0, returns 0.
    */
-  template<class RNG = ThreadLocalPRNG>
-  static uint32_t rand32(uint32_t max, ValidRNG<RNG> rng = RNG()) {
-    if (max == 0) {
-      return 0;
-    }
+  static uint32_t rand32(uint32_t max) {
+    return rand32(0, max, ThreadLocalPRNG());
+  }
 
-    return std::uniform_int_distribution<uint32_t>(0, max - 1)(rng);
+  /**
+   * Returns a random uint32_t in [0, max) given a specific RNG.
+   * If max == 0, returns 0.
+   */
+  template <class RNG = ThreadLocalPRNG, class /* EnableIf */ = ValidRNG<RNG>>
+  static uint32_t rand32(uint32_t max, RNG&& rng) {
+    return rand32(0, max, rng);
   }
 
   /**
    * Returns a random uint32_t in [min, max). If min == max, returns 0.
    */
-  template<class RNG = ThreadLocalPRNG>
-  static uint32_t rand32(uint32_t min,
-                         uint32_t max,
-                         ValidRNG<RNG> rng = RNG()) {
+  static uint32_t rand32(uint32_t min, uint32_t max) {
+    return rand32(min, max, ThreadLocalPRNG());
+  }
+
+  /**
+   * Returns a random uint32_t in [min, max) given a specific RNG.
+   * If min == max, returns 0.
+   */
+  template <class RNG = ThreadLocalPRNG, class /* EnableIf */ = ValidRNG<RNG>>
+  static uint32_t rand32(uint32_t min, uint32_t max, RNG&& rng) {
     if (min == max) {
       return 0;
     }
-
     return std::uniform_int_distribution<uint32_t>(min, max - 1)(rng);
   }
 
   /**
    * Returns a random uint64_t
    */
-  template<class RNG = ThreadLocalPRNG>
-  static uint64_t rand64(ValidRNG<RNG> rng = RNG()) {
-    return ((uint64_t) rng() << 32) | rng();
+  static uint64_t rand64() {
+    return rand64(ThreadLocalPRNG());
+  }
+
+  /**
+   * Returns a random uint64_t
+   */
+  template <class RNG = ThreadLocalPRNG, class /* EnableIf */ = ValidRNG<RNG>>
+  static uint64_t rand64(RNG&& rng) {
+    return ((uint64_t)rng() << 32) | rng();
   }
 
   /**
    * Returns a random uint64_t in [0, max). If max == 0, returns 0.
    */
-  template<class RNG = ThreadLocalPRNG>
-  static uint64_t rand64(uint64_t max, ValidRNG<RNG> rng = RNG()) {
-    if (max == 0) {
-      return 0;
-    }
+  static uint64_t rand64(uint64_t max) {
+    return rand64(0, max, ThreadLocalPRNG());
+  }
 
-    return std::uniform_int_distribution<uint64_t>(0, max - 1)(rng);
+  /**
+   * Returns a random uint64_t in [0, max). If max == 0, returns 0.
+   */
+  template <class RNG = ThreadLocalPRNG, class /* EnableIf */ = ValidRNG<RNG>>
+  static uint64_t rand64(uint64_t max, RNG&& rng) {
+    return rand64(0, max, rng);
   }
 
   /**
    * Returns a random uint64_t in [min, max). If min == max, returns 0.
    */
-  template<class RNG = ThreadLocalPRNG>
-  static uint64_t rand64(uint64_t min,
-                         uint64_t max,
-                         ValidRNG<RNG> rng = RNG()) {
+  static uint64_t rand64(uint64_t min, uint64_t max) {
+    return rand64(min, max, ThreadLocalPRNG());
+  }
+
+  /**
+   * Returns a random uint64_t in [min, max). If min == max, returns 0.
+   */
+  template <class RNG = ThreadLocalPRNG, class /* EnableIf */ = ValidRNG<RNG>>
+  static uint64_t rand64(uint64_t min, uint64_t max, RNG&& rng) {
     if (min == max) {
       return 0;
     }
-
     return std::uniform_int_distribution<uint64_t>(min, max - 1)(rng);
   }
 
   /**
    * Returns true 1/n of the time. If n == 0, always returns false
    */
-  template<class RNG = ThreadLocalPRNG>
-  static bool oneIn(uint32_t n, ValidRNG<RNG> rng = RNG()) {
+  static bool oneIn(uint32_t n) {
+    return oneIn(n, ThreadLocalPRNG());
+  }
+
+  /**
+   * Returns true 1/n of the time. If n == 0, always returns false
+   */
+  template <class RNG = ThreadLocalPRNG, class /* EnableIf */ = ValidRNG<RNG>>
+  static bool oneIn(uint32_t n, RNG&& rng) {
     if (n == 0) {
       return false;
     }
+    return rand32(0, n, rng) == 0;
+  }
 
-    return rand32(n, rng) == 0;
+  /**
+   * Returns a double in [0, 1)
+   */
+  static double randDouble01() {
+    return randDouble01(ThreadLocalPRNG());
   }
 
   /**
    * Returns a double in [0, 1)
    */
-  template<class RNG = ThreadLocalPRNG>
-  static double randDouble01(ValidRNG<RNG> rng = RNG()) {
-    return std::generate_canonical<double, std::numeric_limits<double>::digits>
-      (rng);
+  template <class RNG = ThreadLocalPRNG, class /* EnableIf */ = ValidRNG<RNG>>
+  static double randDouble01(RNG&& rng) {
+    return std::generate_canonical<double, std::numeric_limits<double>::digits>(
+        rng);
+  }
+
+  /**
+    * Returns a double in [min, max), if min == max, returns 0.
+    */
+  static double randDouble(double min, double max) {
+    return randDouble(min, max, ThreadLocalPRNG());
   }
 
   /**
     * Returns a double in [min, max), if min == max, returns 0.
     */
-  template<class RNG = ThreadLocalPRNG>
-  static double randDouble(double min, double max, ValidRNG<RNG> rng = RNG()) {
+  template <class RNG = ThreadLocalPRNG, class /* EnableIf */ = ValidRNG<RNG>>
+  static double randDouble(double min, double max, RNG&& rng) {
     if (std::fabs(max - min) < std::numeric_limits<double>::epsilon()) {
       return 0;
     }
@@ -254,5 +294,3 @@ inline uint32_t randomNumberSeed() {
 }
 
 #include <folly/Random-inl.h>
-
-#endif