/work/svt-av1/Source/Lib/Codec/random.h
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2017, Alliance for Open Media. All rights reserved |
3 | | * |
4 | | * This source code is subject to the terms of the BSD 2 Clause License and |
5 | | * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License |
6 | | * was not distributed with this source code in the LICENSE file, you can |
7 | | * obtain it at https://www.aomedia.org/license/software-license. If the Alliance for Open |
8 | | * Media Patent License 1.0 was not distributed with this source code in the |
9 | | * PATENTS file, you can obtain it at https://www.aomedia.org/license/patent-license. |
10 | | */ |
11 | | |
12 | | #ifndef AOM_AV1_ENCODER_RANDOM_H_ |
13 | | #define AOM_AV1_ENCODER_RANDOM_H_ |
14 | | |
15 | | #ifdef __cplusplus |
16 | | extern "C" { |
17 | | #endif |
18 | | |
19 | | // Advance the generator to its next state, and generate the next 32-bit output. |
20 | | // Note that the low bits of this output are comparatively low-quality, so users |
21 | | // of this function should ensure that the high bits factor through to their |
22 | | // outputs. |
23 | 0 | static INLINE uint32_t lcg_next(uint32_t* state) { |
24 | 0 | *state = (uint32_t)(*state * 1103515245ULL + 12345); |
25 | 0 | return *state; |
26 | 0 | } Unexecuted instantiation: palette.c:lcg_next Unexecuted instantiation: resize.c:lcg_next Unexecuted instantiation: ransac.c:lcg_next |
27 | | |
28 | | // Generate a random number in the range [0, 32768). |
29 | 0 | static INLINE uint32_t lcg_rand16(uint32_t* state) { |
30 | 0 | return (lcg_next(state) / 65536) % 32768; |
31 | 0 | } |
32 | | |
33 | | // Generate a random number in the range [0, n) |
34 | | // This is implemented as (rand() * n) / <range of RNG> rather than |
35 | | // rand() % n, for a few reasons: This implementation is faster and less biased, |
36 | | // and if is a power of 2, this uses the higher-quality top bits from the RNG |
37 | | // output rather than the lower-quality bottom bits. |
38 | 0 | static INLINE uint32_t lcg_randint(uint32_t* state, uint32_t n) { |
39 | 0 | uint64_t v = ((uint64_t)lcg_next(state) * n) >> 32; |
40 | 0 | return (uint32_t)v; |
41 | 0 | } Unexecuted instantiation: palette.c:lcg_randint Unexecuted instantiation: resize.c:lcg_randint Unexecuted instantiation: ransac.c:lcg_randint |
42 | | |
43 | | // Generate a random number in the range [lo, hi) |
44 | 0 | static INLINE uint32_t lcg_randrange(uint32_t* state, uint32_t lo, uint32_t hi) { |
45 | 0 | assert(lo < hi); |
46 | 0 | return lo + lcg_randint(state, hi - lo); |
47 | 0 | } Unexecuted instantiation: palette.c:lcg_randrange Unexecuted instantiation: resize.c:lcg_randrange Unexecuted instantiation: ransac.c:lcg_randrange |
48 | | |
49 | | // Pick k distinct numbers from the set {0, ..., n-1} |
50 | | // All possible sets of k numbers, and all possible orderings of those numbers, |
51 | | // are equally likely. |
52 | | // |
53 | | // Note: The algorithm used here uses resampling to avoid choosing repeated |
54 | | // values. This works well as long as n >> k, but can potentially lead to many |
55 | | // resampling attempts if n is equal to or only slightly larger than k. |
56 | 0 | static INLINE void lcg_pick(int n, int k, int* out, unsigned int* seed) { |
57 | 0 | assert(0 <= k && k <= n); |
58 | 0 | for (int i = 0; i < k; i++) { |
59 | 0 | int v; |
60 | | |
61 | | // Inner resampling loop |
62 | | // We have to use a goto here because C does not have a multi-level continue |
63 | | // statement |
64 | 0 | resample: |
65 | 0 | v = (int)lcg_randint(seed, n); |
66 | 0 | for (int j = 0; j < i; j++) { |
67 | 0 | if (v == out[j]) { |
68 | | // Repeated v, resample |
69 | 0 | goto resample; |
70 | 0 | } |
71 | 0 | } |
72 | | |
73 | | // New v, accept |
74 | 0 | out[i] = v; |
75 | 0 | } |
76 | 0 | } Unexecuted instantiation: palette.c:lcg_pick Unexecuted instantiation: resize.c:lcg_pick Unexecuted instantiation: ransac.c:lcg_pick |
77 | | |
78 | | #ifdef __cplusplus |
79 | | } // extern "C" |
80 | | #endif |
81 | | |
82 | | #endif // AOM_AV1_ENCODER_RANDOM_H_ |