This source file includes following definitions.
- expect_eq
- schedule_test
- check_constant_exterior
- check_repeat_edge
- check_repeat_image
- check_mirror_image
- check_mirror_interior
- test_all
- main
#include <algorithm>
#include <future>
#include <stdio.h>
#include "Halide.h"
using namespace Halide;
using namespace Halide::BoundaryConditions;
Var x("x"), y("y"), xo("xo"), yo("yo"), xi("xi"), yi("yi");
template <typename T>
bool expect_eq(T actual, T expected) {
if (expected != actual) {
fprintf(stderr, "Failed: expected %d, actual %d\n", (int) expected, (int) actual);
return false;
}
return true;
}
void schedule_test(Func f, int vector_width, const Target &t) {
if (vector_width != 1) {
f.vectorize(x, vector_width);
}
if (t.has_gpu_feature() && vector_width <= 16) {
f.gpu_tile(x, y, xo, yo, xi, yi, 2, 2);
} else if (t.features_any_of({Target::HVX_64, Target::HVX_128})) {
}
}
template <typename T>
bool check_constant_exterior(const Buffer<T> &input, T exterior, Func f,
int test_min_x, int test_extent_x, int test_min_y, int test_extent_y,
int vector_width,
Target t) {
bool success = true;
Buffer<T> result(test_extent_x, test_extent_y);
result.set_min(test_min_x, test_min_y);
f = lambda(x, y, f(x, y));
schedule_test(f, vector_width, t);
f.realize(result, t);
result.copy_to_host();
for (int32_t y = test_min_y; y < test_min_y + test_extent_y; y++) {
for (int32_t x = test_min_x; x < test_min_x + test_extent_x; x++) {
if (x < 0 || y < 0 || x >= input.width() || y >= input.height()) {
success &= expect_eq(result(x, y), exterior);
} else {
success &= expect_eq(result(x, y), input(x, y));
}
}
}
return success;
}
template <typename T>
bool check_repeat_edge(const Buffer<T> &input, Func f,
int test_min_x, int test_extent_x, int test_min_y, int test_extent_y,
int vector_width,
Target t) {
bool success = true;
Buffer<T> result(test_extent_x, test_extent_y);
result.set_min(test_min_x, test_min_y);
f = lambda(x, y, f(x, y));
schedule_test(f, vector_width, t);
f.realize(result, t);
result.copy_to_host();
for (int32_t y = test_min_y; y < test_min_y + test_extent_y; y++) {
for (int32_t x = test_min_x; x < test_min_x + test_extent_x; x++) {
int32_t clamped_y = std::min(input.height() - 1, std::max(0, y));
int32_t clamped_x = std::min(input.width() - 1, std::max(0, x));
success &= expect_eq(result(x, y), input(clamped_x, clamped_y));
}
}
return success;
}
template <typename T>
bool check_repeat_image(const Buffer<T> &input, Func f,
int test_min_x, int test_extent_x, int test_min_y, int test_extent_y,
int vector_width,
Target t) {
bool success = true;
Buffer<T> result(test_extent_x, test_extent_y);
result.set_min(test_min_x, test_min_y);
f = lambda(x, y, f(x, y));
schedule_test(f, vector_width, t);
f.realize(result, t);
result.copy_to_host();
for (int32_t y = test_min_y; y < test_min_y + test_extent_y; y++) {
for (int32_t x = test_min_x; x < test_min_x + test_extent_x; x++) {
int32_t mapped_x = x;
int32_t mapped_y = y;
while (mapped_x < 0) mapped_x += input.width();
while (mapped_x > input.width() - 1) mapped_x -= input.width();
while (mapped_y < 0) mapped_y += input.height();
while (mapped_y > input.height() - 1) mapped_y -= input.height();
success &= expect_eq(result(x, y), input(mapped_x, mapped_y));
}
}
return success;
}
template <typename T>
bool check_mirror_image(const Buffer<T> &input, Func f,
int test_min_x, int test_extent_x, int test_min_y, int test_extent_y,
int vector_width,
Target t) {
bool success = true;
Buffer<T> result(test_extent_x, test_extent_y);
result.set_min(test_min_x, test_min_y);
f = lambda(x, y, f(x, y));
schedule_test(f, vector_width, t);
f.realize(result, t);
result.copy_to_host();
for (int32_t y = test_min_y; y < test_min_y + test_extent_y; y++) {
for (int32_t x = test_min_x; x < test_min_x + test_extent_x; x++) {
int32_t mapped_x = (x < 0) ? -(x + 1) : x;
mapped_x = mapped_x % (2 * input.width());
if (mapped_x > (input.width() - 1)) {
mapped_x = (2 * input.width() - 1) - mapped_x;
}
int32_t mapped_y = (y < 0) ? -(y + 1) : y;
mapped_y = mapped_y % (2 * input.height());
if (mapped_y > (input.height() - 1)) {
mapped_y = (2 * input.height() - 1) - mapped_y;
}
success &= expect_eq(result(x, y), input(mapped_x, mapped_y));
}
}
return success;
}
template <typename T>
bool check_mirror_interior(const Buffer<T> &input, Func f,
int test_min_x, int test_extent_x, int test_min_y, int test_extent_y,
int vector_width,
Target t) {
bool success = true;
Buffer<T> result(test_extent_x, test_extent_y);
result.set_min(test_min_x, test_min_y);
f = lambda(x, y, f(x, y));
schedule_test(f, vector_width, t);
f.realize(result, t);
result.copy_to_host();
for (int32_t y = test_min_y; y < test_min_y + test_extent_y; y++) {
for (int32_t x = test_min_x; x < test_min_x + test_extent_x; x++) {
int32_t mapped_x = abs(x) % (input.width() * 2 - 2);
if (mapped_x > input.width() - 1) {
mapped_x = input.width() * 2 - 2 - mapped_x;
}
int32_t mapped_y = abs(y) % (input.height() * 2 - 2);
if (mapped_y > input.height() - 1) {
mapped_y = input.height() * 2 - 2 - mapped_y;
}
success &= expect_eq(result(x, y), input(mapped_x, mapped_y));
}
}
return success;
}
bool test_all(int vector_width, Target t) {
bool success = true;
const int W = 32;
const int H = 32;
Buffer<uint8_t> input(W, H);
for (int32_t y = 0; y < H; y++) {
for (int32_t x = 0; x < W; x++) {
input(x, y) = x + y * W;
}
}
Func input_f("input_f");
input_f(x, y) = input(x, y);
{
const int32_t test_min = -25;
const int32_t test_extent = 100;
success &= check_repeat_edge(
input,
repeat_edge(input_f, 0, W, 0, H),
test_min, test_extent, test_min, test_extent,
vector_width, t);
success &= check_repeat_edge(
input,
repeat_edge(input, 0, W, 0, H),
test_min, test_extent, test_min, test_extent,
vector_width, t);
success &= check_repeat_edge(
input,
repeat_edge(input, Expr(), Expr(), 0, H),
0, W, test_min, test_extent,
vector_width, t);
success &= check_repeat_edge(
input,
repeat_edge(input, 0, W, Expr(), Expr()),
test_min, test_extent, 0, H,
vector_width, t);
success &= check_repeat_edge(
input,
repeat_edge(input),
test_min, test_extent, test_min, test_extent,
vector_width, t);
}
{
const int32_t test_min = -25;
const int32_t test_extent = 100;
const uint8_t exterior = 42;
success &= check_constant_exterior(
input, exterior,
constant_exterior(input_f, exterior, 0, W, 0, H),
test_min, test_extent, test_min, test_extent,
vector_width, t);
success &= check_constant_exterior(
input, exterior,
constant_exterior(input, exterior, 0, W, 0, H),
test_min, test_extent, test_min, test_extent,
vector_width, t);
success &= check_constant_exterior(
input, exterior,
constant_exterior(input, exterior, Expr(), Expr(), 0, H),
0, W, test_min, test_extent,
vector_width, t);
success &= check_constant_exterior(
input, exterior,
constant_exterior(input, exterior, 0, W, Expr(), Expr()),
test_min, test_extent, 0, H,
vector_width, t);
success &= check_constant_exterior(
input, exterior,
constant_exterior(input, exterior),
test_min, test_extent, test_min, test_extent,
vector_width, t);
}
{
const int32_t test_min = -25;
const int32_t test_extent = 100;
success &= check_repeat_image(
input,
repeat_image(input_f, 0, W, 0, H),
test_min, test_extent, test_min, test_extent,
vector_width, t);
success &= check_repeat_image(
input,
repeat_image(input, 0, W, 0, H),
test_min, test_extent, test_min, test_extent,
vector_width, t);
success &= check_repeat_image(
input,
repeat_image(input, Expr(), Expr(), 0, H),
0, W, test_min, test_extent,
vector_width, t);
success &= check_repeat_image(
input,
repeat_image(input, 0, W, Expr(), Expr()),
test_min, test_extent, 0, H,
vector_width, t);
success &= check_repeat_image(
input,
repeat_image(input),
test_min, test_extent, test_min, test_extent,
vector_width, t);
}
{
const int32_t test_min = -25;
const int32_t test_extent = 100;
success &= check_mirror_image(
input,
mirror_image(input_f, 0, W, 0, H),
test_min, test_extent, test_min, test_extent,
vector_width, t);
success &= check_mirror_image(
input,
mirror_image(input, 0, W, 0, H),
test_min, test_extent, test_min, test_extent,
vector_width, t);
success &= check_mirror_image(
input,
mirror_image(input, Expr(), Expr(), 0, H),
0, W, test_min, test_extent,
vector_width, t);
success &= check_mirror_image(
input,
mirror_image(input, 0, W, Expr(), Expr()),
test_min, test_extent, 0, H,
vector_width, t);
success &= check_mirror_image(
input,
mirror_image(input),
test_min, test_extent, test_min, test_extent,
vector_width, t);
}
{
const int32_t test_min = -25;
const int32_t test_extent = 100;
success &= check_mirror_interior(
input,
mirror_interior(input_f, 0, W, 0, H),
test_min, test_extent, test_min, test_extent,
vector_width, t);
success &= check_mirror_interior(
input,
mirror_interior(input, 0, W, 0, H),
test_min, test_extent, test_min, test_extent,
vector_width, t);
success &= check_mirror_interior(
input,
mirror_interior(input, Expr(), Expr(), 0, H),
0, W, test_min, test_extent,
vector_width, t);
success &= check_mirror_interior(
input,
mirror_interior(input, 0, W, Expr(), Expr()),
test_min, test_extent, 0, H,
vector_width, t);
success &= check_mirror_interior(
input,
mirror_interior(input),
test_min, test_extent, test_min, test_extent,
vector_width, t);
}
return success;
}
int main(int argc, char **argv) {
Target target = get_jit_target_from_environment();
Halide::Internal::ThreadPool<bool> pool;
std::vector<std::future<bool>> futures;
for (int vector_width = 1; vector_width <= 32; vector_width *= 2) {
std::cout << "Testing vector_width: " << vector_width << "\n";
futures.push_back(pool.async(test_all, vector_width, target));
}
bool success = true;
for (auto &f : futures) {
success &= f.get();
}
if (!success) {
fprintf(stderr, "Failed!\n");
return -1;
}
printf("Success!\n");
return 0;
}