From 39aa9b770377fd647d4d03143ab6f463df2a5959 Mon Sep 17 00:00:00 2001
From: Marcel Greter <marcel.greter@ocbnet.ch>
Date: Sat, 18 May 2019 19:29:24 +0200
Subject: [PATCH 02/12] Add random number generator with TR1 implementation
---
src/fn_numbers.cpp | 75 +++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 68 insertions(+), 7 deletions(-)
diff --git a/src/fn_numbers.cpp b/src/fn_numbers.cpp
index 28befb5a..ae5dc59e 100644
--- a/src/fn_numbers.cpp
+++ b/src/fn_numbers.cpp
@@ -21,6 +21,24 @@
#include "wincrypt.h"
#endif
+#if defined __GNUC__ && ! defined __llvm__
+ #define GCC_VERSION (__GNUC__ * 10000 \
+ + __GNUC_MINOR__ * 100 \
+ + __GNUC_PATCHLEVEL__)
+ #if GCC_VERSION < 40500
+ #include <tr1/random>
+ #define IMPLEMENT_TR1
+ #define tr1ns std::tr1
+ #define uniform_real_distribution uniform_real
+ #else
+ #include <random>
+ #define tr1ns std
+ #endif
+#else
+ #include <random>
+ #define tr1ns std
+#endif
+
namespace Sass {
namespace Functions {
@@ -51,7 +69,41 @@ namespace Sass {
// random_device degrades sharply once the entropy pool
// is exhausted. For practical use, random_device is
// generally only used to seed a PRNG such as mt19937.
- static std::mt19937 rand(static_cast<unsigned int>(GetSeed()));
+ static tr1ns::mt19937 rand(static_cast<unsigned int>(GetSeed()));
+
+ tr1ns::uniform_real_distribution<> std_dist(0, 1);
+ #ifdef IMPLEMENT_TR1
+ tr1ns::variate_generator <
+ tr1ns::mt19937,
+ tr1ns::uniform_real_distribution <double>
+ > gen_std_dist(rand, std_dist);
+ #endif
+
+ // Using ULONG_MAX here seems to fail on Mac OSX Clang!?
+ tr1ns::uniform_real_distribution<> full_dist(0, 4294967296);
+ #ifdef IMPLEMENT_TR1
+ tr1ns::variate_generator <
+ tr1ns::mt19937,
+ tr1ns::uniform_real_distribution <double>
+ > gen_full_dist(rand, full_dist);
+ #endif
+
+ // helper function to retrieve a random number in interval
+ // works around some compiler issues with older gcc versions
+ static double random(double min, double max)
+ {
+ tr1ns::uniform_real_distribution<> distributor(min, max);
+ #ifdef IMPLEMENT_TR1
+ tr1ns::variate_generator <
+ tr1ns::mt19937,
+ tr1ns::uniform_real_distribution <>
+ > gen(rand, distributor);
+ distributor(rand);
+ return gen();
+ #else
+ return distributor(rand);
+ #endif
+ }
///////////////////
// NUMBER FUNCTIONS
@@ -157,13 +209,19 @@ namespace Sass {
err << "Expected $limit to be an integer but got " << lv << " for `random'";
error(err.str(), pstate, traces);
}
- std::uniform_real_distribution<> distributor(1, lv + 1);
- uint_fast32_t distributed = static_cast<uint_fast32_t>(distributor(rand));
+ // std::uniform_real_distribution<> distributor(1, lv + 1);
+ // uint_fast32_t distributed = static_cast<uint_fast32_t>(distributor(rand));
+ uint_fast32_t distributed = random(1, lv + 1);
return SASS_MEMORY_NEW(Number, pstate, (double)distributed);
}
else if (b) {
- std::uniform_real_distribution<> distributor(0, 1);
- double distributed = static_cast<double>(distributor(rand));
+ // std::uniform_real_distribution<> distributor(0, 1);
+ // double distributed = static_cast<double>(distributor(rand));
+ #ifdef IMPLEMENT_TR1
+ double distributed = gen_std_dist();
+ #else
+ double distributed = std_dist(rand);
+ #endif
return SASS_MEMORY_NEW(Number, pstate, distributed);
} else if (v) {
traces.push_back(Backtrace(pstate));
@@ -178,8 +236,11 @@ namespace Sass {
BUILT_IN(unique_id)
{
std::stringstream ss;
- std::uniform_real_distribution<> distributor(0, 4294967296); // 16^8
- uint_fast32_t distributed = static_cast<uint_fast32_t>(distributor(rand));
+ #ifdef IMPLEMENT_TR1
+ uint_fast32_t distributed = gen_full_dist();
+ #else
+ uint_fast32_t distributed = full_dist(rand);
+ #endif
ss << "u" << std::setfill('0') << std::setw(8) << std::hex << distributed;
return SASS_MEMORY_NEW(String_Quoted, pstate, ss.str());
}
--
2.21.0.windows.1