|
30 | 30 | #include "wincrypt.h"
|
31 | 31 | #endif
|
32 | 32 |
|
| 33 | +#if defined __GNUC__ && ! defined __llvm__ |
| 34 | + #define GCC_VERSION (__GNUC__ * 10000 \ |
| 35 | + + __GNUC_MINOR__ * 100 \ |
| 36 | + + __GNUC_PATCHLEVEL__) |
| 37 | + #if GCC_VERSION < 40500 |
| 38 | + #include <tr1/random> |
| 39 | + #define IMPLEMENT_TR1 |
| 40 | + #define tr1ns std::tr1 |
| 41 | + #define uniform_real_distribution uniform_real |
| 42 | + #else |
| 43 | + #include <random> |
| 44 | + #define tr1ns std |
| 45 | + #endif |
| 46 | +#else |
| 47 | + #include <random> |
| 48 | + #define tr1ns std |
| 49 | +#endif |
| 50 | + |
33 | 51 | #define ARG(argname, argtype) get_arg<argtype>(argname, env, sig, pstate, backtrace)
|
34 | 52 | #define ARGR(argname, argtype, lo, hi) get_arg_r(argname, env, sig, pstate, lo, hi, backtrace)
|
35 | 53 | #define ARGM(argname, argtype, ctx) get_arg_m(argname, env, sig, pstate, backtrace, ctx)
|
@@ -215,9 +233,43 @@ namespace Sass {
|
215 | 233 | // random_device degrades sharply once the entropy pool
|
216 | 234 | // is exhausted. For practical use, random_device is
|
217 | 235 | // generally only used to seed a PRNG such as mt19937.
|
218 |
| - static std::mt19937 rand(static_cast<unsigned int>(GetSeed())); |
| 236 | + static tr1ns::mt19937 rand(static_cast<unsigned int>(GetSeed())); |
| 237 | + |
| 238 | + tr1ns::uniform_real_distribution<> std_dist(0, 1); |
| 239 | + #ifdef IMPLEMENT_TR1 |
| 240 | + tr1ns::variate_generator < |
| 241 | + tr1ns::mt19937, |
| 242 | + tr1ns::uniform_real_distribution <double> |
| 243 | + > gen_std_dist(rand, std_dist); |
| 244 | + #endif |
| 245 | + |
| 246 | + // Using ULONG_MAX here seems to fail on Mac OSX Clang!? |
| 247 | + tr1ns::uniform_real_distribution<> full_dist(0, 4294967296); |
| 248 | + #ifdef IMPLEMENT_TR1 |
| 249 | + tr1ns::variate_generator < |
| 250 | + tr1ns::mt19937, |
| 251 | + tr1ns::uniform_real_distribution <double> |
| 252 | + > gen_full_dist(rand, full_dist); |
| 253 | + #endif |
| 254 | + |
| 255 | + // helper function to retrieve a random number in interval |
| 256 | + // works around some compiler issues with older gcc versions |
| 257 | + static double random(double min, double max) |
| 258 | + { |
| 259 | + tr1ns::uniform_real_distribution<> distributor(min, max); |
| 260 | + #ifdef IMPLEMENT_TR1 |
| 261 | + tr1ns::variate_generator < |
| 262 | + tr1ns::mt19937, |
| 263 | + tr1ns::uniform_real_distribution <> |
| 264 | + > gen(rand, distributor); |
| 265 | + distributor(rand); |
| 266 | + return gen(); |
| 267 | + #else |
| 268 | + return distributor(rand); |
| 269 | + #endif |
| 270 | + } |
219 | 271 |
|
220 |
| - // features |
| 272 | + // supported features lookup table |
221 | 273 | static std::set<std::string> features {
|
222 | 274 | "global-variable-shadowing",
|
223 | 275 | "extend-selector-pseudoclass",
|
@@ -1205,13 +1257,19 @@ namespace Sass {
|
1205 | 1257 | err << "Expected $limit to be an integer but got " << lv << " for `random'";
|
1206 | 1258 | error(err.str(), pstate);
|
1207 | 1259 | }
|
1208 |
| - std::uniform_real_distribution<> distributor(1, lv + 1); |
1209 |
| - uint_fast32_t distributed = static_cast<uint_fast32_t>(distributor(rand)); |
| 1260 | + // std::uniform_real_distribution<> distributor(1, lv + 1); |
| 1261 | + // uint_fast32_t distributed = static_cast<uint_fast32_t>(distributor(rand)); |
| 1262 | + uint_fast32_t distributed = random(1, lv + 1); |
1210 | 1263 | return SASS_MEMORY_NEW(Number, pstate, (double)distributed);
|
1211 | 1264 | }
|
1212 | 1265 | else if (b) {
|
1213 |
| - std::uniform_real_distribution<> distributor(0, 1); |
1214 |
| - double distributed = static_cast<double>(distributor(rand)); |
| 1266 | + // std::uniform_real_distribution<> distributor(0, 1); |
| 1267 | + // double distributed = static_cast<double>(distributor(rand)); |
| 1268 | + #ifdef IMPLEMENT_TR1 |
| 1269 | + double distributed = gen_std_dist(); |
| 1270 | + #else |
| 1271 | + double distributed = std_dist(rand); |
| 1272 | + #endif |
1215 | 1273 | return SASS_MEMORY_NEW(Number, pstate, distributed);
|
1216 | 1274 | } else if (v) {
|
1217 | 1275 | throw Exception::InvalidArgumentType(pstate, "random", "$limit", "number", v);
|
@@ -1987,8 +2045,11 @@ namespace Sass {
|
1987 | 2045 | BUILT_IN(unique_id)
|
1988 | 2046 | {
|
1989 | 2047 | std::stringstream ss;
|
1990 |
| - std::uniform_real_distribution<> distributor(0, 4294967296); // 16^8 |
1991 |
| - uint_fast32_t distributed = static_cast<uint_fast32_t>(distributor(rand)); |
| 2048 | + #ifdef IMPLEMENT_TR1 |
| 2049 | + uint_fast32_t distributed = gen_full_dist(); |
| 2050 | + #else |
| 2051 | + uint_fast32_t distributed = full_dist(rand); |
| 2052 | + #endif |
1992 | 2053 | ss << "u" << std::setfill('0') << std::setw(8) << std::hex << distributed;
|
1993 | 2054 | return SASS_MEMORY_NEW(String_Quoted, pstate, ss.str());
|
1994 | 2055 | }
|
|
0 commit comments