| #include "filter_test_op.h" | |
| #ifdef _MSC_VER | |
| #include <errno.h> | |
| #include <malloc.h> | |
| #endif | |
| // Allocate aligned memory, per recent requirement by the | |
| // Halide tests updated upstream. | |
| int allocate_aligned(void **mem, size_t alignment, size_t size) { | |
| #ifdef _MSC_VER | |
| *p = _aligned_malloc(size, alignment); | |
| return (*p) ? 0 : errno; | |
| #else | |
| return posix_memalign(mem, alignment, size); | |
| #endif | |
| } | |
| #if defined(__aarch64__) || defined(__arm__) | |
| #define FACTOR 5 | |
| #else | |
| #define FACTOR 1 | |
| #endif | |
| template<typename T> | |
| T rand_value() { | |
| return (T)((T)rand() / 8) - 100; | |
| } | |
| // Even on android, we want errors to stdout | |
| extern "C" void halide_print(void *, const char *msg) { | |
| printf("%s\n", msg); | |
| } | |
| template<typename T> | |
| buffer_t make_buffer(int w, int h) { | |
| T *mem; | |
| int err = allocate_aligned((void **)&mem, 128, w * h * sizeof(T)); | |
| buffer_t buf = {0}; | |
| buf.host = (uint8_t *)mem; | |
| buf.extent[0] = w; | |
| buf.extent[1] = h; | |
| buf.elem_size = sizeof(T); | |
| buf.stride[0] = 1; | |
| buf.stride[1] = w; | |
| for (int i = 0; i < w*h; i++) { | |
| mem[i] = rand_value<T>(); | |
| } | |
| return buf; | |
| } | |
| int main(int argc, char **argv) { | |
| unsigned int err_code = 0; | |
| #if (!__has_builtin(__builtin_cpu_supports) && (defined(__i386__) || defined(__x86_64__))) | |
| return err_code; | |
| #endif | |
| #if defined(__i386__) || defined(__x86_64__) | |
| if (!__builtin_cpu_supports("avx") || | |
| !__builtin_cpu_supports("avx2")) { | |
| return err_code; | |
| } | |
| #endif | |
| time_t seed; | |
| if (argc > 1) { | |
| seed = atoi(argv[1]); | |
| } | |
| else { | |
| seed = time(NULL); | |
| srand (seed); | |
| } | |
| int W = 256*FACTOR, H = 100; | |
| // Make some input buffers | |
| buffer_t bufs[] = { | |
| make_buffer<float>(W, H), | |
| make_buffer<double>(W, H), | |
| make_buffer<int8_t>(W, H), | |
| make_buffer<uint8_t>(W, H), | |
| make_buffer<int16_t>(W, H), | |
| make_buffer<uint16_t>(W, H), | |
| make_buffer<int32_t>(W, H), | |
| make_buffer<uint32_t>(W, H), | |
| make_buffer<int64_t>(W, H), | |
| make_buffer<uint64_t>(W, H) | |
| }; | |
| W/=FACTOR; | |
| int NO = 2; | |
| buffer_t out[] = { | |
| make_buffer<double>(W, H), | |
| make_buffer<double>(W, H) | |
| }; | |
| double *out_value[NO]; | |
| for (int i = 0; i < NO; i++) { | |
| filter f = filters[i]; | |
| f.fn(bufs + 0, | |
| bufs + 1, | |
| bufs + 2, | |
| bufs + 3, | |
| bufs + 4, | |
| bufs + 5, | |
| bufs + 6, | |
| bufs + 7, | |
| bufs + 8, | |
| bufs + 9, | |
| &(out[i])); | |
| out_value[i] = (double *)(out[i].host); | |
| } | |
| int err; | |
| for (int i = 0; i < W*H; i++) { | |
| if ((err = out_value[0][i] - out_value[1][i]) > 0.0001) { | |
| fprintf(stderr, "Code generation error (%d): %d. Seer used %ld\n", i, err, seed); | |
| err_code = 1; | |
| break; | |
| } | |
| } | |
| for (int i = 0; i < sizeof(bufs)/sizeof(buffer_t); i++) { | |
| delete[] bufs[i].host; | |
| } | |
| for (int i = 0; i < NO; i++) { | |
| delete[] out[i].host; | |
| } | |
| return err_code; | |
| } | |