gfx/skia/trunk/include/utils/SkRandom.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /*
michael@0 2 * Copyright 2006 The Android Open Source Project
michael@0 3 *
michael@0 4 * Use of this source code is governed by a BSD-style license that can be
michael@0 5 * found in the LICENSE file.
michael@0 6 */
michael@0 7
michael@0 8 #ifndef SkRandom_DEFINED
michael@0 9 #define SkRandom_DEFINED
michael@0 10
michael@0 11 #include "SkScalar.h"
michael@0 12
michael@0 13 /** \class SkLCGRandom
michael@0 14
michael@0 15 Utility class that implements pseudo random 32bit numbers using a fast
michael@0 16 linear equation. Unlike rand(), this class holds its own seed (initially
michael@0 17 set to 0), so that multiple instances can be used with no side-effects.
michael@0 18 */
michael@0 19 class SkLCGRandom {
michael@0 20 public:
michael@0 21 SkLCGRandom() : fSeed(0) {}
michael@0 22 SkLCGRandom(uint32_t seed) : fSeed(seed) {}
michael@0 23
michael@0 24 /** Return the next pseudo random number as an unsigned 32bit value.
michael@0 25 */
michael@0 26 uint32_t nextU() { uint32_t r = fSeed * kMul + kAdd; fSeed = r; return r; }
michael@0 27
michael@0 28 /** Return the next pseudo random number as a signed 32bit value.
michael@0 29 */
michael@0 30 int32_t nextS() { return (int32_t)this->nextU(); }
michael@0 31
michael@0 32 /** Return the next pseudo random number as an unsigned 16bit value.
michael@0 33 */
michael@0 34 U16CPU nextU16() { return this->nextU() >> 16; }
michael@0 35
michael@0 36 /** Return the next pseudo random number as a signed 16bit value.
michael@0 37 */
michael@0 38 S16CPU nextS16() { return this->nextS() >> 16; }
michael@0 39
michael@0 40 /**
michael@0 41 * Returns value [0...1) as a float
michael@0 42 */
michael@0 43 float nextF() {
michael@0 44 // const is 1 / (2^32 - 1)
michael@0 45 return (float)(this->nextU() * 2.32830644e-10);
michael@0 46 }
michael@0 47
michael@0 48 /**
michael@0 49 * Returns value [min...max) as a float
michael@0 50 */
michael@0 51 float nextRangeF(float min, float max) {
michael@0 52 return min + this->nextF() * (max - min);
michael@0 53 }
michael@0 54
michael@0 55 /** Return the next pseudo random number, as an unsigned value of
michael@0 56 at most bitCount bits.
michael@0 57 @param bitCount The maximum number of bits to be returned
michael@0 58 */
michael@0 59 uint32_t nextBits(unsigned bitCount) {
michael@0 60 SkASSERT(bitCount > 0 && bitCount <= 32);
michael@0 61 return this->nextU() >> (32 - bitCount);
michael@0 62 }
michael@0 63
michael@0 64 /** Return the next pseudo random unsigned number, mapped to lie within
michael@0 65 [min, max] inclusive.
michael@0 66 */
michael@0 67 uint32_t nextRangeU(uint32_t min, uint32_t max) {
michael@0 68 SkASSERT(min <= max);
michael@0 69 uint32_t range = max - min + 1;
michael@0 70 if (0 == range) {
michael@0 71 return this->nextU();
michael@0 72 } else {
michael@0 73 return min + this->nextU() % range;
michael@0 74 }
michael@0 75 }
michael@0 76
michael@0 77 /** Return the next pseudo random unsigned number, mapped to lie within
michael@0 78 [0, count).
michael@0 79 */
michael@0 80 uint32_t nextULessThan(uint32_t count) {
michael@0 81 SkASSERT(count > 0);
michael@0 82 return this->nextRangeU(0, count - 1);
michael@0 83 }
michael@0 84
michael@0 85 /** Return the next pseudo random number expressed as an unsigned SkFixed
michael@0 86 in the range [0..SK_Fixed1).
michael@0 87 */
michael@0 88 SkFixed nextUFixed1() { return this->nextU() >> 16; }
michael@0 89
michael@0 90 /** Return the next pseudo random number expressed as a signed SkFixed
michael@0 91 in the range (-SK_Fixed1..SK_Fixed1).
michael@0 92 */
michael@0 93 SkFixed nextSFixed1() { return this->nextS() >> 15; }
michael@0 94
michael@0 95 /** Return the next pseudo random number expressed as a SkScalar
michael@0 96 in the range [0..SK_Scalar1).
michael@0 97 */
michael@0 98 SkScalar nextUScalar1() { return SkFixedToScalar(this->nextUFixed1()); }
michael@0 99
michael@0 100 /** Return the next pseudo random number expressed as a SkScalar
michael@0 101 in the range [min..max).
michael@0 102 */
michael@0 103 SkScalar nextRangeScalar(SkScalar min, SkScalar max) {
michael@0 104 return this->nextUScalar1() * (max - min) + min;
michael@0 105 }
michael@0 106
michael@0 107 /** Return the next pseudo random number expressed as a SkScalar
michael@0 108 in the range (-SK_Scalar1..SK_Scalar1).
michael@0 109 */
michael@0 110 SkScalar nextSScalar1() { return SkFixedToScalar(this->nextSFixed1()); }
michael@0 111
michael@0 112 /** Return the next pseudo random number as a bool.
michael@0 113 */
michael@0 114 bool nextBool() { return this->nextU() >= 0x80000000; }
michael@0 115
michael@0 116 /** A biased version of nextBool().
michael@0 117 */
michael@0 118 bool nextBiasedBool(SkScalar fractionTrue) {
michael@0 119 SkASSERT(fractionTrue >= 0 && fractionTrue <= SK_Scalar1);
michael@0 120 return this->nextUScalar1() <= fractionTrue;
michael@0 121 }
michael@0 122
michael@0 123 /**
michael@0 124 * Return the next pseudo random number as a signed 64bit value.
michael@0 125 */
michael@0 126 int64_t next64() {
michael@0 127 int64_t hi = this->nextS();
michael@0 128 return (hi << 32) | this->nextU();
michael@0 129 }
michael@0 130
michael@0 131 /**
michael@0 132 * Return the current seed. This allows the caller to later reset to the
michael@0 133 * same seed (using setSeed) so it can generate the same sequence.
michael@0 134 */
michael@0 135 int32_t getSeed() const { return fSeed; }
michael@0 136
michael@0 137 /** Set the seed of the random object. The seed is initialized to 0 when the
michael@0 138 object is first created, and is updated each time the next pseudo random
michael@0 139 number is requested.
michael@0 140 */
michael@0 141 void setSeed(int32_t seed) { fSeed = (uint32_t)seed; }
michael@0 142
michael@0 143 private:
michael@0 144 // See "Numerical Recipes in C", 1992 page 284 for these constants
michael@0 145 enum {
michael@0 146 kMul = 1664525,
michael@0 147 kAdd = 1013904223
michael@0 148 };
michael@0 149 uint32_t fSeed;
michael@0 150 };
michael@0 151
michael@0 152 /** \class SkRandom
michael@0 153
michael@0 154 Utility class that implements pseudo random 32bit numbers using Marsaglia's
michael@0 155 multiply-with-carry "mother of all" algorithm. Unlike rand(), this class holds
michael@0 156 its own state, so that multiple instances can be used with no side-effects.
michael@0 157
michael@0 158 Has a large period and all bits are well-randomized.
michael@0 159 */
michael@0 160 class SkRandom {
michael@0 161 public:
michael@0 162 SkRandom() { init(0); }
michael@0 163 SkRandom(uint32_t seed) { init(seed); }
michael@0 164 SkRandom(const SkRandom& rand) : fK(rand.fK), fJ(rand.fJ) {}
michael@0 165
michael@0 166 SkRandom& operator=(const SkRandom& rand) {
michael@0 167 fK = rand.fK;
michael@0 168 fJ = rand.fJ;
michael@0 169
michael@0 170 return *this;
michael@0 171 }
michael@0 172
michael@0 173 /** Return the next pseudo random number as an unsigned 32bit value.
michael@0 174 */
michael@0 175 uint32_t nextU() {
michael@0 176 fK = kKMul*(fK & 0xffff) + (fK >> 16);
michael@0 177 fJ = kJMul*(fJ & 0xffff) + (fJ >> 16);
michael@0 178 return (((fK << 16) | (fK >> 16)) + fJ);
michael@0 179 }
michael@0 180
michael@0 181 /** Return the next pseudo random number as a signed 32bit value.
michael@0 182 */
michael@0 183 int32_t nextS() { return (int32_t)this->nextU(); }
michael@0 184
michael@0 185 /** Return the next pseudo random number as an unsigned 16bit value.
michael@0 186 */
michael@0 187 U16CPU nextU16() { return this->nextU() >> 16; }
michael@0 188
michael@0 189 /** Return the next pseudo random number as a signed 16bit value.
michael@0 190 */
michael@0 191 S16CPU nextS16() { return this->nextS() >> 16; }
michael@0 192
michael@0 193 /**
michael@0 194 * Returns value [0...1) as an IEEE float
michael@0 195 */
michael@0 196 float nextF() {
michael@0 197 unsigned int floatint = 0x3f800000 | (this->nextU() >> 9);
michael@0 198 float f = SkBits2Float(floatint) - 1.0f;
michael@0 199 return f;
michael@0 200 }
michael@0 201
michael@0 202 /**
michael@0 203 * Returns value [min...max) as a float
michael@0 204 */
michael@0 205 float nextRangeF(float min, float max) {
michael@0 206 return min + this->nextF() * (max - min);
michael@0 207 }
michael@0 208
michael@0 209 /** Return the next pseudo random number, as an unsigned value of
michael@0 210 at most bitCount bits.
michael@0 211 @param bitCount The maximum number of bits to be returned
michael@0 212 */
michael@0 213 uint32_t nextBits(unsigned bitCount) {
michael@0 214 SkASSERT(bitCount > 0 && bitCount <= 32);
michael@0 215 return this->nextU() >> (32 - bitCount);
michael@0 216 }
michael@0 217
michael@0 218 /** Return the next pseudo random unsigned number, mapped to lie within
michael@0 219 [min, max] inclusive.
michael@0 220 */
michael@0 221 uint32_t nextRangeU(uint32_t min, uint32_t max) {
michael@0 222 SkASSERT(min <= max);
michael@0 223 uint32_t range = max - min + 1;
michael@0 224 if (0 == range) {
michael@0 225 return this->nextU();
michael@0 226 } else {
michael@0 227 return min + this->nextU() % range;
michael@0 228 }
michael@0 229 }
michael@0 230
michael@0 231 /** Return the next pseudo random unsigned number, mapped to lie within
michael@0 232 [0, count).
michael@0 233 */
michael@0 234 uint32_t nextULessThan(uint32_t count) {
michael@0 235 SkASSERT(count > 0);
michael@0 236 return this->nextRangeU(0, count - 1);
michael@0 237 }
michael@0 238
michael@0 239 /** Return the next pseudo random number expressed as an unsigned SkFixed
michael@0 240 in the range [0..SK_Fixed1).
michael@0 241 */
michael@0 242 SkFixed nextUFixed1() { return this->nextU() >> 16; }
michael@0 243
michael@0 244 /** Return the next pseudo random number expressed as a signed SkFixed
michael@0 245 in the range (-SK_Fixed1..SK_Fixed1).
michael@0 246 */
michael@0 247 SkFixed nextSFixed1() { return this->nextS() >> 15; }
michael@0 248
michael@0 249 /** Return the next pseudo random number expressed as a SkScalar
michael@0 250 in the range [0..SK_Scalar1).
michael@0 251 */
michael@0 252 SkScalar nextUScalar1() { return SkFixedToScalar(this->nextUFixed1()); }
michael@0 253
michael@0 254 /** Return the next pseudo random number expressed as a SkScalar
michael@0 255 in the range [min..max).
michael@0 256 */
michael@0 257 SkScalar nextRangeScalar(SkScalar min, SkScalar max) {
michael@0 258 return this->nextUScalar1() * (max - min) + min;
michael@0 259 }
michael@0 260
michael@0 261 /** Return the next pseudo random number expressed as a SkScalar
michael@0 262 in the range (-SK_Scalar1..SK_Scalar1).
michael@0 263 */
michael@0 264 SkScalar nextSScalar1() { return SkFixedToScalar(this->nextSFixed1()); }
michael@0 265
michael@0 266 /** Return the next pseudo random number as a bool.
michael@0 267 */
michael@0 268 bool nextBool() { return this->nextU() >= 0x80000000; }
michael@0 269
michael@0 270 /** A biased version of nextBool().
michael@0 271 */
michael@0 272 bool nextBiasedBool(SkScalar fractionTrue) {
michael@0 273 SkASSERT(fractionTrue >= 0 && fractionTrue <= SK_Scalar1);
michael@0 274 return this->nextUScalar1() <= fractionTrue;
michael@0 275 }
michael@0 276
michael@0 277 /**
michael@0 278 * Return the next pseudo random number as a signed 64bit value.
michael@0 279 */
michael@0 280 int64_t next64() {
michael@0 281 int64_t hi = this->nextS();
michael@0 282 return (hi << 32) | this->nextU();
michael@0 283 }
michael@0 284
michael@0 285 /** Reset the random object.
michael@0 286 */
michael@0 287 void setSeed(uint32_t seed) { init(seed); }
michael@0 288
michael@0 289 private:
michael@0 290 // Initialize state variables with LCG.
michael@0 291 // We must ensure that both J and K are non-zero, otherwise the
michael@0 292 // multiply-with-carry step will forevermore return zero.
michael@0 293 void init(uint32_t seed) {
michael@0 294 fK = NextLCG(seed);
michael@0 295 if (0 == fK) {
michael@0 296 fK = NextLCG(fK);
michael@0 297 }
michael@0 298 fJ = NextLCG(fK);
michael@0 299 if (0 == fJ) {
michael@0 300 fJ = NextLCG(fJ);
michael@0 301 }
michael@0 302 SkASSERT(0 != fK && 0 != fJ);
michael@0 303 }
michael@0 304 static uint32_t NextLCG(uint32_t seed) { return kMul*seed + kAdd; }
michael@0 305
michael@0 306 // See "Numerical Recipes in C", 1992 page 284 for these constants
michael@0 307 // For the LCG that sets the initial state from a seed
michael@0 308 enum {
michael@0 309 kMul = 1664525,
michael@0 310 kAdd = 1013904223
michael@0 311 };
michael@0 312 // Constants for the multiply-with-carry steps
michael@0 313 enum {
michael@0 314 kKMul = 30345,
michael@0 315 kJMul = 18000,
michael@0 316 };
michael@0 317
michael@0 318 uint32_t fK;
michael@0 319 uint32_t fJ;
michael@0 320 };
michael@0 321
michael@0 322 #endif

mercurial