ddemidov / vexcl
1
#define BOOST_TEST_MODULE StencilConvolution
2
#include <boost/test/unit_test.hpp>
3
#include <vexcl/vector.hpp>
4
#include <vexcl/multivector.hpp>
5
#include <vexcl/stencil.hpp>
6
#include "context_setup.hpp"
7

8
struct index {
9
    size_t n;
10 6
    index(size_t n) : n(n) {}
11

12
    size_t operator()(size_t i, long shift) const {
13 6
        return std::min<size_t>(n - 1, std::max<long>(0, static_cast<long>(i) + shift));
14
    }
15
};
16

17 6
BOOST_AUTO_TEST_CASE(stencil_convolution)
18
{
19
    const size_t n = 1024;
20

21 6
    std::vector<double> s = random_vector<double>(rand() % 64 + 1);
22

23 6
    int center = rand() % s.size();
24

25 6
    vex::stencil<double> S(ctx, s, center);
26

27 6
    std::vector<double> x = random_vector<double>(n);
28 6
    std::generate(x.begin(), x.end(), [](){ return (double)rand() / RAND_MAX; });
29

30 6
    vex::vector<double> X(ctx, x);
31 6
    vex::vector<double> Y(ctx, n);
32

33 6
    Y = 1;
34 6
    Y += X * S;
35

36 6
    index idx(n);
37

38 6
    check_sample(Y, [&](size_t i, double a) {
39 6
        double sum = 1;
40
        size_t j = 0;
41 6
        int k = -center;
42 6
        for(; j < s.size(); k++, j++)
43 6
            sum += s[j] * x[idx(i, k)];
44 6
        BOOST_CHECK_CLOSE(a, sum, 1e-8);
45 6
    });
46

47 6
    Y = 42 * (X * S);
48

49 6
    check_sample(Y, [&](size_t i, double a) {
50
        double sum = 0;
51
        size_t j = 0;
52 6
        int k = -center;
53 6
        for(; j < s.size(); k++, j++)
54 6
            sum += s[j] * x[idx(i, k)];
55 6
        BOOST_CHECK_CLOSE(a, 42 * sum, 1e-8);
56 6
    });
57
}
58

59
#if BOOST_VERSION >= 105000
60
// Boost upto v1.49 segfaults on this test
61 6
BOOST_AUTO_TEST_CASE(two_stencils)
62
{
63
    const size_t n = 32;
64 6
    std::vector<double> s(5, 1);
65 6
    vex::stencil<double> S(ctx, s, 3);
66 6
    vex::vector<double> X(ctx, n);
67 6
    vex::vector<double> Y(ctx, n);
68

69 6
    X = 0;
70 6
    Y = X * S + X * S;
71

72 6
    BOOST_CHECK(Y[ 0] == 0);
73 6
    BOOST_CHECK(Y[16] == 0);
74 6
    BOOST_CHECK(Y[31] == 0);
75
}
76
#endif
77

78 6
BOOST_AUTO_TEST_CASE(small_vector)
79
{
80
    const size_t n = 128;
81

82 6
    std::vector<double> s = random_vector<double>(rand() % 64 + 1);
83

84 6
    int center = rand() % s.size();
85

86 6
    vex::stencil<double> S(ctx, s, center);
87

88 6
    std::vector<double> x = random_vector<double>(n);
89

90 6
    vex::vector<double> X(ctx, x);
91 6
    vex::vector<double> Y(ctx, n);
92

93 6
    Y = 1;
94 6
    Y += X * S;
95

96 6
    index idx(n);
97

98 6
    check_sample(Y, [&](size_t i, double a) {
99 6
        double sum = 1;
100
        size_t j = 0;
101 6
        int k = -center;
102 6
        for(; j < s.size(); k++, j++)
103 6
            sum += s[j] * x[idx(i, k)];
104 6
        BOOST_CHECK_CLOSE(a, sum, 1e-8);
105 6
    });
106
}
107

108 6
BOOST_AUTO_TEST_CASE(multivector)
109
{
110
    typedef std::array<double, 2> elem_t;
111
    const size_t n = 1024;
112

113 6
    std::vector<double> s = random_vector<double>(rand() % 64 + 1);
114 6
    int center = rand() % s.size();
115

116 6
    vex::stencil<double> S(ctx, s.begin(), s.end(), center);
117

118 6
    std::vector<double> x = random_vector<double>(2 * n);
119

120 6
    vex::multivector<double,2> X(ctx, x);
121 6
    vex::multivector<double,2> Y(ctx, n);
122

123 6
    Y = 1;
124 6
    Y += X * S;
125

126 6
    index idx(n);
127

128 6
    check_sample(Y, [&](size_t i, elem_t a) {
129 6
        double sum[2] = {1, 1};
130
        size_t j = 0;
131 6
        int k = -center;
132 6
        for(; j < s.size(); k++, j++) {
133 6
            sum[0] += s[j] * x[0 + idx(i, k)];
134 6
            sum[1] += s[j] * x[n + idx(i, k)];
135
        }
136

137 6
        BOOST_CHECK_CLOSE(a[0], sum[0], 1e-8);
138 6
        BOOST_CHECK_CLOSE(a[1], sum[1], 1e-8);
139 6
    });
140

141 6
    Y = 42 * (X * S);
142

143 6
    check_sample(Y, [&](size_t i, elem_t a) {
144
        double sum[2] = {0, 0};
145
        size_t j = 0;
146 6
        int k = -center;
147 6
        for(; j < s.size(); k++, j++) {
148 6
            sum[0] += s[j] * x[0 + idx(i, k)];
149 6
            sum[1] += s[j] * x[n + idx(i, k)];
150
        }
151

152 6
        BOOST_CHECK_CLOSE(a[0], 42 * sum[0], 1e-8);
153 6
        BOOST_CHECK_CLOSE(a[1], 42 * sum[1], 1e-8);
154 6
    });
155
}
156

157 6
BOOST_AUTO_TEST_CASE(big_stencil)
158
{
159
    const size_t n = 1 << 16;
160

161 6
    std::vector<double> s = random_vector<double>(2048);
162 6
    int center = rand() % s.size();
163

164 6
    vex::stencil<double> S(ctx, s, center);
165

166 6
    std::vector<double> x = random_vector<double>(n);
167

168 6
    vex::vector<double> X(ctx, x);
169 6
    vex::vector<double> Y(ctx, n);
170

171 6
    index idx(n);
172

173 6
    Y = X * S;
174 6
    check_sample(Y, [&](size_t i, double a) {
175 6
        double sum = 0;
176
        size_t j = 0;
177 6
        int k = -center;
178 6
        for(; j < s.size(); k++, j++)
179 6
            sum += s[j] * x[idx(i, k)];
180 6
        BOOST_CHECK_CLOSE(a, sum, 1e-8);
181 6
    });
182
}
183

184 6
BOOST_AUTO_TEST_CASE(user_defined_stencil)
185
{
186
    const size_t n = 1024;
187

188 6
    VEX_STENCIL_OPERATOR(oscillate,
189
            double, 3, 1,  "return sin(X[1] - X[0]) + sin(X[0] - X[-1]);",
190
            ctx);
191

192 6
    std::vector<double> x = random_vector<double>(n);
193

194 6
    vex::vector<double> X(ctx, x);
195 6
    vex::vector<double> Y(ctx, n);
196

197 6
    Y = oscillate(X);
198

199 6
    index idx(n);
200

201 6
    check_sample(Y, [&](size_t i, double a) {
202 6
        size_t left  = idx(i, -1);
203 6
        size_t right = idx(i, +1);
204 6
        double s = sin(x[right] - x[i]) + sin(x[i] - x[left]);
205 6
        BOOST_CHECK_CLOSE(a, s, 1e-8);
206 6
    });
207

208
#if BOOST_VERSION >= 105000
209 6
    Y = 41 * oscillate(X) + oscillate(X);
210

211 6
    check_sample(Y, [&](size_t i, double a) {
212 6
        size_t left  = idx(i, -1);
213 6
        size_t right = idx(i, +1);
214 6
        double s = sin(x[right] - x[i]) + sin(x[i] - x[left]);
215 6
        BOOST_CHECK_CLOSE(a, 42 * s, 1e-8);
216 6
    });
217
#endif
218
}
219

220 6
BOOST_AUTO_TEST_SUITE_END()

Read our documentation on viewing source code .

Loading