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

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/skia/trunk/include/utils/SkRandom.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,322 @@
     1.4 +/*
     1.5 + * Copyright 2006 The Android Open Source Project
     1.6 + *
     1.7 + * Use of this source code is governed by a BSD-style license that can be
     1.8 + * found in the LICENSE file.
     1.9 + */
    1.10 +
    1.11 +#ifndef SkRandom_DEFINED
    1.12 +#define SkRandom_DEFINED
    1.13 +
    1.14 +#include "SkScalar.h"
    1.15 +
    1.16 +/** \class SkLCGRandom
    1.17 +
    1.18 +    Utility class that implements pseudo random 32bit numbers using a fast
    1.19 +    linear equation. Unlike rand(), this class holds its own seed (initially
    1.20 +    set to 0), so that multiple instances can be used with no side-effects.
    1.21 +*/
    1.22 +class SkLCGRandom {
    1.23 +public:
    1.24 +    SkLCGRandom() : fSeed(0) {}
    1.25 +    SkLCGRandom(uint32_t seed) : fSeed(seed) {}
    1.26 +
    1.27 +    /** Return the next pseudo random number as an unsigned 32bit value.
    1.28 +    */
    1.29 +    uint32_t nextU() { uint32_t r = fSeed * kMul + kAdd; fSeed = r; return r; }
    1.30 +
    1.31 +    /** Return the next pseudo random number as a signed 32bit value.
    1.32 +    */
    1.33 +    int32_t nextS() { return (int32_t)this->nextU(); }
    1.34 +
    1.35 +    /** Return the next pseudo random number as an unsigned 16bit value.
    1.36 +    */
    1.37 +    U16CPU nextU16() { return this->nextU() >> 16; }
    1.38 +
    1.39 +    /** Return the next pseudo random number as a signed 16bit value.
    1.40 +    */
    1.41 +    S16CPU nextS16() { return this->nextS() >> 16; }
    1.42 +
    1.43 +    /**
    1.44 +     *  Returns value [0...1) as a float
    1.45 +     */
    1.46 +    float nextF() {
    1.47 +        // const is 1 / (2^32 - 1)
    1.48 +        return (float)(this->nextU() * 2.32830644e-10);
    1.49 +    }
    1.50 +
    1.51 +    /**
    1.52 +     *  Returns value [min...max) as a float
    1.53 +     */
    1.54 +    float nextRangeF(float min, float max) {
    1.55 +        return min + this->nextF() * (max - min);
    1.56 +    }
    1.57 +
    1.58 +    /** Return the next pseudo random number, as an unsigned value of
    1.59 +        at most bitCount bits.
    1.60 +        @param bitCount The maximum number of bits to be returned
    1.61 +    */
    1.62 +    uint32_t nextBits(unsigned bitCount) {
    1.63 +        SkASSERT(bitCount > 0 && bitCount <= 32);
    1.64 +        return this->nextU() >> (32 - bitCount);
    1.65 +    }
    1.66 +
    1.67 +    /** Return the next pseudo random unsigned number, mapped to lie within
    1.68 +        [min, max] inclusive.
    1.69 +    */
    1.70 +    uint32_t nextRangeU(uint32_t min, uint32_t max) {
    1.71 +        SkASSERT(min <= max);
    1.72 +        uint32_t range = max - min + 1;
    1.73 +        if (0 == range) {
    1.74 +            return this->nextU();
    1.75 +        } else {
    1.76 +            return min + this->nextU() % range;
    1.77 +        }
    1.78 +    }
    1.79 +
    1.80 +    /** Return the next pseudo random unsigned number, mapped to lie within
    1.81 +        [0, count).
    1.82 +     */
    1.83 +    uint32_t nextULessThan(uint32_t count) {
    1.84 +        SkASSERT(count > 0);
    1.85 +        return this->nextRangeU(0, count - 1);
    1.86 +    }
    1.87 +
    1.88 +    /** Return the next pseudo random number expressed as an unsigned SkFixed
    1.89 +        in the range [0..SK_Fixed1).
    1.90 +    */
    1.91 +    SkFixed nextUFixed1() { return this->nextU() >> 16; }
    1.92 +
    1.93 +    /** Return the next pseudo random number expressed as a signed SkFixed
    1.94 +        in the range (-SK_Fixed1..SK_Fixed1).
    1.95 +    */
    1.96 +    SkFixed nextSFixed1() { return this->nextS() >> 15; }
    1.97 +
    1.98 +    /** Return the next pseudo random number expressed as a SkScalar
    1.99 +        in the range [0..SK_Scalar1).
   1.100 +    */
   1.101 +    SkScalar nextUScalar1() { return SkFixedToScalar(this->nextUFixed1()); }
   1.102 +
   1.103 +    /** Return the next pseudo random number expressed as a SkScalar
   1.104 +        in the range [min..max).
   1.105 +    */
   1.106 +    SkScalar nextRangeScalar(SkScalar min, SkScalar max) {
   1.107 +        return this->nextUScalar1() * (max - min) + min;
   1.108 +    }
   1.109 +
   1.110 +    /** Return the next pseudo random number expressed as a SkScalar
   1.111 +        in the range (-SK_Scalar1..SK_Scalar1).
   1.112 +    */
   1.113 +    SkScalar nextSScalar1() { return SkFixedToScalar(this->nextSFixed1()); }
   1.114 +
   1.115 +    /** Return the next pseudo random number as a bool.
   1.116 +    */
   1.117 +    bool nextBool() { return this->nextU() >= 0x80000000; }
   1.118 +
   1.119 +    /** A biased version of nextBool().
   1.120 +     */
   1.121 +    bool nextBiasedBool(SkScalar fractionTrue) {
   1.122 +        SkASSERT(fractionTrue >= 0 && fractionTrue <= SK_Scalar1);
   1.123 +        return this->nextUScalar1() <= fractionTrue;
   1.124 +    }
   1.125 +
   1.126 +    /**
   1.127 +     *  Return the next pseudo random number as a signed 64bit value.
   1.128 +     */
   1.129 +    int64_t next64() {
   1.130 +        int64_t hi = this->nextS();
   1.131 +        return (hi << 32) | this->nextU();
   1.132 +    }
   1.133 +
   1.134 +    /**
   1.135 +     *  Return the current seed. This allows the caller to later reset to the
   1.136 +     *  same seed (using setSeed) so it can generate the same sequence.
   1.137 +     */
   1.138 +    int32_t getSeed() const { return fSeed; }
   1.139 +
   1.140 +    /** Set the seed of the random object. The seed is initialized to 0 when the
   1.141 +        object is first created, and is updated each time the next pseudo random
   1.142 +        number is requested.
   1.143 +    */
   1.144 +    void setSeed(int32_t seed) { fSeed = (uint32_t)seed; }
   1.145 +
   1.146 +private:
   1.147 +    //  See "Numerical Recipes in C", 1992 page 284 for these constants
   1.148 +    enum {
   1.149 +        kMul = 1664525,
   1.150 +        kAdd = 1013904223
   1.151 +    };
   1.152 +    uint32_t fSeed;
   1.153 +};
   1.154 +
   1.155 +/** \class SkRandom
   1.156 +
   1.157 + Utility class that implements pseudo random 32bit numbers using Marsaglia's
   1.158 + multiply-with-carry "mother of all" algorithm. Unlike rand(), this class holds
   1.159 + its own state, so that multiple instances can be used with no side-effects.
   1.160 +
   1.161 + Has a large period and all bits are well-randomized.
   1.162 + */
   1.163 +class SkRandom {
   1.164 +public:
   1.165 +    SkRandom() { init(0); }
   1.166 +    SkRandom(uint32_t seed) { init(seed); }
   1.167 +    SkRandom(const SkRandom& rand) : fK(rand.fK), fJ(rand.fJ) {}
   1.168 +
   1.169 +    SkRandom& operator=(const SkRandom& rand) {
   1.170 +        fK = rand.fK;
   1.171 +        fJ = rand.fJ;
   1.172 +
   1.173 +        return *this;
   1.174 +    }
   1.175 +
   1.176 +    /** Return the next pseudo random number as an unsigned 32bit value.
   1.177 +     */
   1.178 +    uint32_t nextU() {
   1.179 +        fK = kKMul*(fK & 0xffff) + (fK >> 16);
   1.180 +        fJ = kJMul*(fJ & 0xffff) + (fJ >> 16);
   1.181 +        return (((fK << 16) | (fK >> 16)) + fJ);
   1.182 +    }
   1.183 +
   1.184 +    /** Return the next pseudo random number as a signed 32bit value.
   1.185 +     */
   1.186 +    int32_t nextS() { return (int32_t)this->nextU(); }
   1.187 +
   1.188 +    /** Return the next pseudo random number as an unsigned 16bit value.
   1.189 +     */
   1.190 +    U16CPU nextU16() { return this->nextU() >> 16; }
   1.191 +
   1.192 +    /** Return the next pseudo random number as a signed 16bit value.
   1.193 +     */
   1.194 +    S16CPU nextS16() { return this->nextS() >> 16; }
   1.195 +
   1.196 +    /**
   1.197 +     *  Returns value [0...1) as an IEEE float
   1.198 +     */
   1.199 +    float nextF() {
   1.200 +        unsigned int floatint = 0x3f800000 | (this->nextU() >> 9);
   1.201 +        float f = SkBits2Float(floatint) - 1.0f;
   1.202 +        return f;
   1.203 +    }
   1.204 +
   1.205 +    /**
   1.206 +     *  Returns value [min...max) as a float
   1.207 +     */
   1.208 +    float nextRangeF(float min, float max) {
   1.209 +        return min + this->nextF() * (max - min);
   1.210 +    }
   1.211 +
   1.212 +    /** Return the next pseudo random number, as an unsigned value of
   1.213 +     at most bitCount bits.
   1.214 +     @param bitCount The maximum number of bits to be returned
   1.215 +     */
   1.216 +    uint32_t nextBits(unsigned bitCount) {
   1.217 +        SkASSERT(bitCount > 0 && bitCount <= 32);
   1.218 +        return this->nextU() >> (32 - bitCount);
   1.219 +    }
   1.220 +
   1.221 +    /** Return the next pseudo random unsigned number, mapped to lie within
   1.222 +     [min, max] inclusive.
   1.223 +     */
   1.224 +    uint32_t nextRangeU(uint32_t min, uint32_t max) {
   1.225 +        SkASSERT(min <= max);
   1.226 +        uint32_t range = max - min + 1;
   1.227 +        if (0 == range) {
   1.228 +            return this->nextU();
   1.229 +        } else {
   1.230 +            return min + this->nextU() % range;
   1.231 +        }
   1.232 +    }
   1.233 +
   1.234 +    /** Return the next pseudo random unsigned number, mapped to lie within
   1.235 +     [0, count).
   1.236 +     */
   1.237 +    uint32_t nextULessThan(uint32_t count) {
   1.238 +        SkASSERT(count > 0);
   1.239 +        return this->nextRangeU(0, count - 1);
   1.240 +    }
   1.241 +
   1.242 +    /** Return the next pseudo random number expressed as an unsigned SkFixed
   1.243 +     in the range [0..SK_Fixed1).
   1.244 +     */
   1.245 +    SkFixed nextUFixed1() { return this->nextU() >> 16; }
   1.246 +
   1.247 +    /** Return the next pseudo random number expressed as a signed SkFixed
   1.248 +     in the range (-SK_Fixed1..SK_Fixed1).
   1.249 +     */
   1.250 +    SkFixed nextSFixed1() { return this->nextS() >> 15; }
   1.251 +
   1.252 +    /** Return the next pseudo random number expressed as a SkScalar
   1.253 +     in the range [0..SK_Scalar1).
   1.254 +     */
   1.255 +    SkScalar nextUScalar1() { return SkFixedToScalar(this->nextUFixed1()); }
   1.256 +
   1.257 +    /** Return the next pseudo random number expressed as a SkScalar
   1.258 +     in the range [min..max).
   1.259 +     */
   1.260 +    SkScalar nextRangeScalar(SkScalar min, SkScalar max) {
   1.261 +        return this->nextUScalar1() * (max - min) + min;
   1.262 +    }
   1.263 +
   1.264 +    /** Return the next pseudo random number expressed as a SkScalar
   1.265 +     in the range (-SK_Scalar1..SK_Scalar1).
   1.266 +     */
   1.267 +    SkScalar nextSScalar1() { return SkFixedToScalar(this->nextSFixed1()); }
   1.268 +
   1.269 +    /** Return the next pseudo random number as a bool.
   1.270 +     */
   1.271 +    bool nextBool() { return this->nextU() >= 0x80000000; }
   1.272 +
   1.273 +    /** A biased version of nextBool().
   1.274 +     */
   1.275 +    bool nextBiasedBool(SkScalar fractionTrue) {
   1.276 +        SkASSERT(fractionTrue >= 0 && fractionTrue <= SK_Scalar1);
   1.277 +        return this->nextUScalar1() <= fractionTrue;
   1.278 +    }
   1.279 +
   1.280 +    /**
   1.281 +     *  Return the next pseudo random number as a signed 64bit value.
   1.282 +     */
   1.283 +    int64_t next64() {
   1.284 +        int64_t hi = this->nextS();
   1.285 +        return (hi << 32) | this->nextU();
   1.286 +    }
   1.287 +
   1.288 +    /** Reset the random object.
   1.289 +     */
   1.290 +    void setSeed(uint32_t seed) { init(seed); }
   1.291 +
   1.292 +private:
   1.293 +    // Initialize state variables with LCG.
   1.294 +    // We must ensure that both J and K are non-zero, otherwise the
   1.295 +    // multiply-with-carry step will forevermore return zero.
   1.296 +    void init(uint32_t seed) {
   1.297 +        fK = NextLCG(seed);
   1.298 +        if (0 == fK) {
   1.299 +            fK = NextLCG(fK);
   1.300 +        }
   1.301 +        fJ = NextLCG(fK);
   1.302 +        if (0 == fJ) {
   1.303 +            fJ = NextLCG(fJ);
   1.304 +        }
   1.305 +        SkASSERT(0 != fK && 0 != fJ);
   1.306 +    }
   1.307 +    static uint32_t NextLCG(uint32_t seed) { return kMul*seed + kAdd; }
   1.308 +
   1.309 +    //  See "Numerical Recipes in C", 1992 page 284 for these constants
   1.310 +    //  For the LCG that sets the initial state from a seed
   1.311 +    enum {
   1.312 +        kMul = 1664525,
   1.313 +        kAdd = 1013904223
   1.314 +    };
   1.315 +    // Constants for the multiply-with-carry steps
   1.316 +    enum {
   1.317 +        kKMul = 30345,
   1.318 +        kJMul = 18000,
   1.319 +    };
   1.320 +
   1.321 +    uint32_t fK;
   1.322 +    uint32_t fJ;
   1.323 +};
   1.324 +
   1.325 +#endif

mercurial