File: random.cpp

package info (click to toggle)
halide 21.0.0-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 55,752 kB
  • sloc: cpp: 289,334; ansic: 22,751; python: 7,486; makefile: 4,299; sh: 2,508; java: 1,549; javascript: 282; pascal: 207; xml: 127; asm: 9
file content (179 lines) | stat: -rw-r--r-- 5,252 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#include "Halide.h"
#include <stdio.h>

using namespace Halide;

int main(int argc, char **argv) {
    Var x, y;

    const double tol = 0.01;

    {
        // Make a random image and check its statistics.
        Func f;
        f(x, y) = random_float();
        f.vectorize(x, 4);
        f.parallel(y);
        Buffer<float> rand_image = f.realize({1024, 1024});

        // Do some tests for randomness.

        Func g;
        g(x, y) = cast<double>(rand_image(x, y));

        RDom r(rand_image);
        Expr val = g(r.x, r.y);

        double mean = evaluate<double>(sum(val)) / (1024 * 1024);
        double variance = evaluate<double>(sum(pow(val - (float)mean, 2))) / (1024 * 1024 - 1);

        // Also check the mean and variance of the gradient in x and y to check for pixel correlations.

        Expr dx = g(r.x, r.y) - g((r.x + 1) % 1024, r.y);
        Expr dy = g(r.x, r.y) - g(r.x, (r.y + 1) % 1024);

        double mean_dx = evaluate<double>(sum(dx)) / (1024 * 1024);
        double variance_dx = evaluate<double>(sum(pow(dx - (float)mean_dx, 2))) / (1024 * 1024 - 1);

        double mean_dy = evaluate<double>(sum(dy)) / (1024 * 1024);
        double variance_dy = evaluate<double>(sum(pow(dy - (float)mean_dy, 2))) / (1024 * 1024 - 1);

        if (fabs(mean - 0.5) > tol) {
            printf("Bad mean: %f\n", mean);
            return 1;
        }

        if (fabs(variance - 1.0 / 12) > tol) {
            printf("Bad variance: %f\n", variance);
            return 1;
        }

        if (fabs(mean_dx) > tol) {
            printf("Bad mean_dx: %f\n", mean_dx);
            return 1;
        }

        if (fabs(variance_dx - 1.0 / 6) > tol) {
            printf("Bad variance_dx: %f\n", variance_dx);
            return 1;
        }

        if (fabs(mean_dy) > tol) {
            printf("Bad mean_dy: %f\n", mean_dy);
            return 1;
        }

        if (fabs(variance_dy - 1.0 / 6) > tol) {
            printf("Bad variance_dy: %f\n", variance_dy);
            return 1;
        }
    }

    // The same random seed should produce the same image, and
    // different random seeds should produce statistically independent
    // images.
    {
        Param<int> seed;

        Func f;
        f(x, y) = cast<double>(random_float(seed));

        seed.set(0);

        Buffer<double> im1 = f.realize({1024, 1024});
        Buffer<double> im2 = f.realize({1024, 1024});

        Func g;
        g(x, y) = f(x, y);
        seed.set(1);

        Buffer<double> im3 = g.realize({1024, 1024});

        RDom r(im1);
        Expr v1 = im1(r.x, r.y);
        Expr v2 = im2(r.x, r.y);
        Expr v3 = im3(r.x, r.y);

        double e1 = evaluate<double>(sum(abs(v1 - v2))) / (1024 * 1024);
        double e2 = evaluate<double>(sum(abs(v1 - v3))) / (1024 * 1024);

        if (e1 != 0.0) {
            printf("The same random seed should produce the same image. "
                   "Instead the mean absolute difference was: %f\n",
                   e1);
            return 1;
        }

        if (fabs(e2 - 1.0 / 3) > 0.01) {
            printf("Different random seeds should produce different images. "
                   "The mean absolute difference should be 1/3 but was %f\n",
                   e2);
            return 1;
        }
    }

    // Test random ints as well.
    {
        Func f;
        f(x, y) = random_int();
        Buffer<int> im = f.realize({1024, 1024});

        // Count the number of set bits;
        RDom r(im);
        Expr val = f(r.x, r.y);

        int set_bits = evaluate<int>(sum(popcount(val)));

        // It should be that about half of them are set
        int correct = 512 * 1024 * 32;
        if (fabs(double(set_bits) / correct - 1) > tol) {
            printf("Set bits was %d instead of %d\n", set_bits, correct);
            return 1;
        }

        // Check to make sure adjacent bits are uncorrelated.
        Expr val2 = val ^ (val * 2);
        set_bits = evaluate<int>(sum(popcount(val2)));
        if (fabs(double(set_bits) / correct - 1) > tol) {
            printf("Set bits was %d instead of %d\n", set_bits, correct);
            return 1;
        }
    }

    // Check independence and dependence.
    {
        // Make two random variables
        Expr r1 = cast<double>(random_float());
        Expr r2 = cast<double>(random_float());

        Func f;
        f(x, y) = r1 + r1 - 1.0f;

        Func g;
        g(x, y) = r1 + r2 - 1.0f;

        // f is the sum of two dependent (equal) random variables, so should have variance 1/3
        // g is the sum of two independent random variables, so should have variance 1/6

        const int S = 1024;
        RDom r(0, S, 0, S);
        Expr f_val = f(r.x, r.y);
        Expr g_val = g(r.x, r.y);
        double f_var = evaluate<double>(sum(f_val * f_val)) / (S * S - 1);
        double g_var = evaluate<double>(sum(g_val * g_val)) / (S * S - 1);

        if (fabs(f_var - 1.0 / 3) > tol) {
            printf("Variance of f was supposed to be 1/3: %f\n", f_var);
            return 1;
        }

        if (fabs(g_var - 1.0 / 6) > tol) {
            printf("Variance of g was supposed to be 1/6 %f\n", g_var);
            return 1;
        }
    }

    printf("Success!\n");

    return 0;
}