|
18 | 18 | #include <cstdlib> |
19 | 19 | #include <cmath> |
20 | 20 | #include <cctype> |
| 21 | +#include <climits> |
21 | 22 | #include <sstream> |
22 | 23 | #include <string> |
23 | 24 | #include <iomanip> |
|
30 | 31 | #include "wincrypt.h" |
31 | 32 | #endif |
32 | 33 |
|
| 34 | +#if defined __GNUC__ && ! defined __llvm__ |
| 35 | + #define GCC_VERSION (__GNUC__ * 10000 \ |
| 36 | + + __GNUC_MINOR__ * 100 \ |
| 37 | + + __GNUC_PATCHLEVEL__) |
| 38 | + #if GCC_VERSION < 40500 |
| 39 | + #include <tr1/random> |
| 40 | + #define IMPLEMENT_TR1 |
| 41 | + #define tr1ns std::tr1 |
| 42 | + #define uniform_real_distribution uniform_real |
| 43 | + #else |
| 44 | + #include <random> |
| 45 | + #define tr1ns std |
| 46 | + #endif |
| 47 | +#else |
| 48 | + #include <random> |
| 49 | + #define tr1ns std |
| 50 | +#endif |
| 51 | + |
33 | 52 | #define ARG(argname, argtype) get_arg<argtype>(argname, env, sig, pstate, backtrace) |
34 | 53 | #define ARGR(argname, argtype, lo, hi) get_arg_r(argname, env, sig, pstate, lo, hi, backtrace) |
35 | 54 | #define ARGM(argname, argtype, ctx) get_arg_m(argname, env, sig, pstate, backtrace, ctx) |
@@ -229,9 +248,43 @@ namespace Sass { |
229 | 248 | // random_device degrades sharply once the entropy pool |
230 | 249 | // is exhausted. For practical use, random_device is |
231 | 250 | // generally only used to seed a PRNG such as mt19937. |
232 | | - static std::mt19937 rand(static_cast<unsigned int>(GetSeed())); |
| 251 | + static tr1ns::mt19937 rand(static_cast<unsigned int>(GetSeed())); |
| 252 | + |
| 253 | + tr1ns::uniform_real_distribution<> std_dist(0, 1); |
| 254 | + #ifdef IMPLEMENT_TR1 |
| 255 | + tr1ns::variate_generator < |
| 256 | + tr1ns::mt19937, |
| 257 | + tr1ns::uniform_real_distribution <double> |
| 258 | + > gen_std_dist(rand, std_dist); |
| 259 | + #endif |
| 260 | + |
| 261 | + // Using ULONG_MAX here seems to fail on Mac OSX Clang!? |
| 262 | + tr1ns::uniform_real_distribution<> full_dist(0, 4294967296); |
| 263 | + #ifdef IMPLEMENT_TR1 |
| 264 | + tr1ns::variate_generator < |
| 265 | + tr1ns::mt19937, |
| 266 | + tr1ns::uniform_real_distribution <double> |
| 267 | + > gen_full_dist(rand, full_dist); |
| 268 | + #endif |
| 269 | + |
| 270 | + // helper function to retrieve a random number in interval |
| 271 | + // works around some compiler issues with older gcc versions |
| 272 | + static double random(double min, double max) |
| 273 | + { |
| 274 | + tr1ns::uniform_real_distribution<> distributor(min, max); |
| 275 | + #ifdef IMPLEMENT_TR1 |
| 276 | + tr1ns::variate_generator < |
| 277 | + tr1ns::mt19937, |
| 278 | + tr1ns::uniform_real_distribution <> |
| 279 | + > gen(rand, distributor); |
| 280 | + distributor(rand); |
| 281 | + return gen(); |
| 282 | + #else |
| 283 | + return distributor(rand); |
| 284 | + #endif |
| 285 | + } |
233 | 286 |
|
234 | | - // features |
| 287 | + // supported features lookup table |
235 | 288 | static std::set<std::string> features { |
236 | 289 | "global-variable-shadowing", |
237 | 290 | "extend-selector-pseudoclass", |
@@ -1188,13 +1241,19 @@ namespace Sass { |
1188 | 1241 | err << "Expected $limit to be an integer but got `" << v << "` for `random`"; |
1189 | 1242 | error(err.str(), pstate); |
1190 | 1243 | } |
1191 | | - std::uniform_real_distribution<> distributor(1, v + 1); |
1192 | | - uint_fast32_t distributed = static_cast<uint_fast32_t>(distributor(rand)); |
| 1244 | + // std::uniform_real_distribution<> distributor(1, v + 1); |
| 1245 | + // uint_fast32_t distributed = static_cast<uint_fast32_t>(distributor(rand)); |
| 1246 | + uint_fast32_t distributed = random(1, v + 1); |
1193 | 1247 | return SASS_MEMORY_NEW(ctx.mem, Number, pstate, (double)distributed); |
1194 | 1248 | } |
1195 | 1249 | else if (b) { |
1196 | | - std::uniform_real_distribution<> distributor(0, 1); |
1197 | | - double distributed = static_cast<double>(distributor(rand)); |
| 1250 | + // std::uniform_real_distribution<> distributor(0, 1); |
| 1251 | + // double distributed = static_cast<double>(distributor(rand)); |
| 1252 | + #ifdef IMPLEMENT_TR1 |
| 1253 | + double distributed = gen_std_dist(); |
| 1254 | + #else |
| 1255 | + double distributed = std_dist(rand); |
| 1256 | + #endif |
1198 | 1257 | return SASS_MEMORY_NEW(ctx.mem, Number, pstate, distributed); |
1199 | 1258 | } else if (v) { |
1200 | 1259 | throw Exception::InvalidArgumentType(pstate, "random", "$limit", "number", v); |
@@ -1932,8 +1991,11 @@ namespace Sass { |
1932 | 1991 | BUILT_IN(unique_id) |
1933 | 1992 | { |
1934 | 1993 | std::stringstream ss; |
1935 | | - std::uniform_real_distribution<> distributor(0, 4294967296); // 16^8 |
1936 | | - uint_fast32_t distributed = static_cast<uint_fast32_t>(distributor(rand)); |
| 1994 | + #ifdef IMPLEMENT_TR1 |
| 1995 | + uint_fast32_t distributed = gen_full_dist(); |
| 1996 | + #else |
| 1997 | + uint_fast32_t distributed = full_dist(rand); |
| 1998 | + #endif |
1937 | 1999 | ss << "u" << std::setfill('0') << std::setw(8) << std::hex << distributed; |
1938 | 2000 | return SASS_MEMORY_NEW(ctx.mem, String_Quoted, pstate, ss.str()); |
1939 | 2001 | } |
|
0 commit comments