diff --git a/src/backend/cpu/transform.cpp b/src/backend/cpu/transform.cpp index bbcf689f25..0fbe10ea5c 100644 --- a/src/backend/cpu/transform.cpp +++ b/src/backend/cpu/transform.cpp @@ -8,6 +8,7 @@ ********************************************************/ #include +#include #include #include #include @@ -22,23 +23,27 @@ void transform(Array &out, const Array &in, const Array &tf, const bool perspective) { out.eval(); in.eval(); + + // TODO: Temporary Fix, must fix handling subarrays upstream + // tf has to be linear, although offset is allowed + const Array tf_Lin = tf.isLinear() ? tf : copyArray(tf); tf.eval(); switch (method) { case AF_INTERP_NEAREST: case AF_INTERP_LOWER: - getQueue().enqueue(kernel::transform, out, in, tf, inverse, - perspective, method); + getQueue().enqueue(kernel::transform, out, in, tf_Lin, + inverse, perspective, method); break; case AF_INTERP_BILINEAR: case AF_INTERP_BILINEAR_COSINE: - getQueue().enqueue(kernel::transform, out, in, tf, inverse, - perspective, method); + getQueue().enqueue(kernel::transform, out, in, tf_Lin, + inverse, perspective, method); break; case AF_INTERP_BICUBIC: case AF_INTERP_BICUBIC_SPLINE: - getQueue().enqueue(kernel::transform, out, in, tf, inverse, - perspective, method); + getQueue().enqueue(kernel::transform, out, in, tf_Lin, + inverse, perspective, method); break; default: AF_ERROR("Unsupported interpolation type", AF_ERR_ARG); break; } diff --git a/src/backend/cuda/transform.cpp b/src/backend/cuda/transform.cpp index e0d0509c8d..af8b561191 100644 --- a/src/backend/cuda/transform.cpp +++ b/src/backend/cuda/transform.cpp @@ -9,6 +9,7 @@ #include +#include #include #include @@ -19,7 +20,11 @@ template void transform(Array &out, const Array &in, const Array &tf, const af::interpType method, const bool inverse, const bool perspective) { - kernel::transform(out, in, tf, inverse, perspective, method, + // TODO: Temporary Fix, must fix handling subarrays upstream + // tf has to be linear, although offset is allowed. + const Array tf_Lin = tf.isLinear() ? tf : copyArray(tf); + + kernel::transform(out, in, tf_Lin, inverse, perspective, method, interpOrder(method)); } diff --git a/src/backend/oneapi/kernel/transform.hpp b/src/backend/oneapi/kernel/transform.hpp index 07f70a3a62..874e9638c7 100644 --- a/src/backend/oneapi/kernel/transform.hpp +++ b/src/backend/oneapi/kernel/transform.hpp @@ -178,7 +178,8 @@ class transformCreateKernel { using TMatTy = typename std::conditional::type; TMatTy tmat; - const float *tmat_ptr = c_tmat_.get_pointer() + t_idx * transf_len; + const float *tmat_ptr = + c_tmat_.get_pointer() + tf_.offset + t_idx * transf_len; // We expect a inverse transform matrix by default // If it is an forward transform, then we need its inverse diff --git a/src/backend/oneapi/transform.cpp b/src/backend/oneapi/transform.cpp index a277df9661..00edc15817 100644 --- a/src/backend/oneapi/transform.cpp +++ b/src/backend/oneapi/transform.cpp @@ -9,6 +9,7 @@ #include +#include #include #include @@ -19,18 +20,25 @@ template void transform(Array &out, const Array &in, const Array &tf, const af_interp_type method, const bool inverse, const bool perspective) { + // TODO: Temporary Fix, must fix handling subarrays upstream + // tf has to be linear, although offset is allowed. + const Array tf_Lin = tf.isLinear() ? tf : copyArray(tf); + switch (method) { case AF_INTERP_NEAREST: case AF_INTERP_LOWER: - kernel::transform(out, in, tf, inverse, perspective, method, 1); + kernel::transform(out, in, tf_Lin, inverse, perspective, method, + 1); break; case AF_INTERP_BILINEAR: case AF_INTERP_BILINEAR_COSINE: - kernel::transform(out, in, tf, inverse, perspective, method, 2); + kernel::transform(out, in, tf_Lin, inverse, perspective, method, + 2); break; case AF_INTERP_BICUBIC: case AF_INTERP_BICUBIC_SPLINE: - kernel::transform(out, in, tf, inverse, perspective, method, 3); + kernel::transform(out, in, tf_Lin, inverse, perspective, method, + 3); break; default: AF_ERROR("Unsupported interpolation type", AF_ERR_ARG); } diff --git a/src/backend/opencl/kernel/transform.cl b/src/backend/opencl/kernel/transform.cl index 85c6a293ab..4fae1c05f8 100644 --- a/src/backend/opencl/kernel/transform.cl +++ b/src/backend/opencl/kernel/transform.cl @@ -133,7 +133,7 @@ kernel void transformKernel(global T *d_out, const KParam out, const int transf_len = 6; float tmat[6]; #endif - global const float *tmat_ptr = c_tmat + t_idx * transf_len; + global const float *tmat_ptr = c_tmat + tf.offset + t_idx * transf_len; // We expect a inverse transform matrix by default // If it is an forward transform, then we need its inverse diff --git a/src/backend/opencl/transform.cpp b/src/backend/opencl/transform.cpp index 78428ed3a7..de99f48a60 100644 --- a/src/backend/opencl/transform.cpp +++ b/src/backend/opencl/transform.cpp @@ -9,6 +9,7 @@ #include +#include #include namespace arrayfire { @@ -18,18 +19,25 @@ template void transform(Array &out, const Array &in, const Array &tf, const af_interp_type method, const bool inverse, const bool perspective) { + // TODO: Temporary Fix, must fix handling subarrays upstream + // tf has to be linear, although offset is allowed. + const Array tf_Lin = tf.isLinear() ? tf : copyArray(tf); + switch (method) { case AF_INTERP_NEAREST: case AF_INTERP_LOWER: - kernel::transform(out, in, tf, inverse, perspective, method, 1); + kernel::transform(out, in, tf_Lin, inverse, perspective, method, + 1); break; case AF_INTERP_BILINEAR: case AF_INTERP_BILINEAR_COSINE: - kernel::transform(out, in, tf, inverse, perspective, method, 2); + kernel::transform(out, in, tf_Lin, inverse, perspective, method, + 2); break; case AF_INTERP_BICUBIC: case AF_INTERP_BICUBIC_SPLINE: - kernel::transform(out, in, tf, inverse, perspective, method, 3); + kernel::transform(out, in, tf_Lin, inverse, perspective, method, + 3); break; default: AF_ERROR("Unsupported interpolation type", AF_ERR_ARG); } diff --git a/test/arrayfire_test.cpp b/test/arrayfire_test.cpp index 6803cc586d..eab07f5b41 100644 --- a/test/arrayfire_test.cpp +++ b/test/arrayfire_test.cpp @@ -229,9 +229,9 @@ ::testing::AssertionResult imageEq(std::string aName, std::string bName, af::saveImage(result_path.c_str(), b.as(f32)); af::saveImage(diff_path.c_str(), abs(a.as(f32) - b.as(f32))); - std::cout - << "" - << valid_path << "\n"; + std::cout << "" + << valid_path << "\n"; std::cout << "" << result_path << "\n"; @@ -526,7 +526,8 @@ dim_t ravelIdx(af::dim4 coords, af::dim4 strides) { 0LL); } -// Calculate a linearized index's multi-dimensonal coordinates in an af::array, +// Calculate a linearized index's multi-dimensonal coordinates in an +// af::array, // given its dimension sizes and strides af::dim4 unravelIdx(dim_t idx, af::dim4 dims, af::dim4 strides) { af::dim4 coords; @@ -567,8 +568,9 @@ std::string minimalDim4(af::dim4 coords, af::dim4 dims) { return os.str(); } -// Generates a random array. testWriteToOutputArray expects that it will receive -// the same af_array that this generates after the af_* function is called +// Generates a random array. testWriteToOutputArray expects that it will +// receive the same af_array that this generates after the af_* function is +// called void genRegularArray(TestOutputArrayInfo *metadata, const unsigned ndims, const dim_t *const dims, const af_dtype ty) { metadata->init(ndims, dims, ty); @@ -581,9 +583,9 @@ void genRegularArray(TestOutputArrayInfo *metadata, double val, } // Generates a large, random array, and extracts a subarray for the af_* -// function to use. testWriteToOutputArray expects that the large array that it -// receives is equal to the same large array with the gold array injected on the -// same subarray location +// function to use. testWriteToOutputArray expects that the large array that +// it receives is equal to the same large array with the gold array injected +// on the same subarray location void genSubArray(TestOutputArrayInfo *metadata, const unsigned ndims, const dim_t *const dims, const af_dtype ty) { const dim_t pad_size = 2; @@ -596,8 +598,9 @@ void genSubArray(TestOutputArrayInfo *metadata, const unsigned ndims, } // Calculate index of sub-array. These will be used also by - // testWriteToOutputArray so that the gold sub array will be placed in the - // same location. Currently, this location is the center of the large array + // testWriteToOutputArray so that the gold sub array will be placed in + // the same location. Currently, this location is the center of the + // large array af_seq subarr_idxs[4] = {af_span, af_span, af_span, af_span}; for (uint i = 0; i < ndims; ++i) { af_seq idx = {pad_size, pad_size + dims[i] - 1.0, 1.0}; @@ -620,8 +623,9 @@ void genSubArray(TestOutputArrayInfo *metadata, double val, } // Calculate index of sub-array. These will be used also by - // testWriteToOutputArray so that the gold sub array will be placed in the - // same location. Currently, this location is the center of the large array + // testWriteToOutputArray so that the gold sub array will be placed in + // the same location. Currently, this location is the center of the + // large array af_seq subarr_idxs[4] = {af_span, af_span, af_span, af_span}; for (uint i = 0; i < ndims; ++i) { af_seq idx = {pad_size, pad_size + dims[i] - 1.0, 1.0}; @@ -631,13 +635,14 @@ void genSubArray(TestOutputArrayInfo *metadata, double val, metadata->init(val, ndims, full_arr_dims, ty, &subarr_idxs[0]); } -// Generates a reordered array. testWriteToOutputArray expects that this array -// will still have the correct output values from the af_* function, even though -// the array was initially reordered. +// Generates a reordered array. testWriteToOutputArray expects that this +// array will still have the correct output values from the af_* function, +// even though the array was initially reordered. void genReorderedArray(TestOutputArrayInfo *metadata, const unsigned ndims, const dim_t *const dims, const af_dtype ty) { - // The rest of this function assumes that dims has 4 elements. Just in case - // dims has < 4 elements, use another dims array that is filled with 1s + // The rest of this function assumes that dims has 4 elements. Just in + // case dims has < 4 elements, use another dims array that is filled + // with 1s dim_t all_dims[4] = {1, 1, 1, 1}; for (uint i = 0; i < ndims; ++i) { all_dims[i] = dims[i]; } @@ -648,7 +653,8 @@ void genReorderedArray(TestOutputArrayInfo *metadata, const unsigned ndims, uint reorder_idxs[4] = {0, 2, 1, 3}; // Shape the output array such that the reordered output array will have - // the correct dimensions that the test asks for (i.e. must match dims arg) + // the correct dimensions that the test asks for (i.e. must match dims + // arg) dim_t init_dims[4] = {all_dims[0], all_dims[1], all_dims[2], all_dims[3]}; for (uint i = 0; i < 4; ++i) { init_dims[i] = all_dims[reorder_idxs[i]]; } metadata->init(4, init_dims, ty); @@ -663,8 +669,9 @@ void genReorderedArray(TestOutputArrayInfo *metadata, const unsigned ndims, void genReorderedArray(TestOutputArrayInfo *metadata, double val, const unsigned ndims, const dim_t *const dims, const af_dtype ty) { - // The rest of this function assumes that dims has 4 elements. Just in case - // dims has < 4 elements, use another dims array that is filled with 1s + // The rest of this function assumes that dims has 4 elements. Just in + // case dims has < 4 elements, use another dims array that is filled + // with 1s dim_t all_dims[4] = {1, 1, 1, 1}; for (uint i = 0; i < ndims; ++i) { all_dims[i] = dims[i]; } @@ -675,7 +682,8 @@ void genReorderedArray(TestOutputArrayInfo *metadata, double val, uint reorder_idxs[4] = {0, 2, 1, 3}; // Shape the output array such that the reordered output array will have - // the correct dimensions that the test asks for (i.e. must match dims arg) + // the correct dimensions that the test asks for (i.e. must match dims + // arg) dim_t init_dims[4] = {all_dims[0], all_dims[1], all_dims[2], all_dims[3]}; for (uint i = 0; i < 4; ++i) { init_dims[i] = all_dims[reorder_idxs[i]]; } metadata->init(val, 4, init_dims, ty); @@ -745,8 +753,8 @@ ::testing::AssertionResult testWriteToOutputArray( if (metadata->getOutputArrayType() == SUB_ARRAY) { // There are two full arrays. One will be injected with the gold - // subarray, the other should have already been injected with the af_* - // function's output. Then we compare the two full arrays + // subarray, the other should have already been injected with the + // af_* function's output. Then we compare the two full arrays af_array gold_full_array = metadata->getFullOutputCopy(); af_assign_seq(&gold_full_array, gold_full_array, metadata->getSubArrayNumDims(), @@ -1293,9 +1301,11 @@ ::testing::AssertionResult mtxReadSparseMatrix(af::array &out, return ::testing::AssertionFailure() << "\nEnd of file reached, expected more data, " << "following are some reasons this happens.\n" - << "\t - use of template type that doesn't match data " + << "\t - use of template type that doesn't match " + "data " "type\n" - << "\t - the mtx file itself doesn't have enough data\n"; + << "\t - the mtx file itself doesn't have enough " + "data\n"; } I[i] = r - 1; J[i] = c - 1; @@ -1319,9 +1329,11 @@ ::testing::AssertionResult mtxReadSparseMatrix(af::array &out, return ::testing::AssertionFailure() << "\nEnd of file reached, expected more data, " << "following are some reasons this happens.\n" - << "\t - use of template type that doesn't match data " + << "\t - use of template type that doesn't match " + "data " "type\n" - << "\t - the mtx file itself doesn't have enough data\n"; + << "\t - the mtx file itself doesn't have enough " + "data\n"; } I[i] = r - 1; J[i] = c - 1; @@ -1531,8 +1543,8 @@ vector> toCooVector(const af::array &arr) { } } - // Remove zero elements from result to ensure that only non-zero elements - // are compared + // Remove zero elements from result to ensure that only non-zero + // elements are compared out.erase(std::remove_if(out.begin(), out.end(), isZero), out.end()); std::sort(begin(out), end(out)); return out; @@ -1584,8 +1596,8 @@ std::string printContext(const std::vector &hGold, std::string goldName, // Get dim0 positions and out/reference values for the context window // - // Also get the max string length between the position and out/ref values - // per item so that it can be used later as the field width for + // Also get the max string length between the position and out/ref + // values per item so that it can be used later as the field width for // displaying each item in the context window for (dim_t i = 0; i < ctxElems; ++i) { std::ostringstream tmpOs; @@ -2063,31 +2075,35 @@ af::array toTempFormat(tempFormat form, const af::array &in) { break; case SUB_FORMAT_dim0: { af::dim4 pdims(dims); - pdims[0] += 2; - af::array parent = af::randu(pdims, in.type()); - parent(af::seq(1, dims[0]), af::span, af::span, af::span) = in; - ret = parent(af::seq(1, dims[0]), af::span, af::span, af::span); + pdims[0] *= 2; + af::array parent = af::randu(pdims, in.type()); + const af::seq dim = af::seq(dims[0]) + static_cast(dims[0]); + parent(dim, af::span, af::span, af::span) = in; + ret = parent(dim, af::span, af::span, af::span); }; break; case SUB_FORMAT_dim1: { af::dim4 pdims(dims); - pdims[1] += 2; - af::array parent = af::randu(pdims, in.type()); - parent(af::span, af::seq(1, dims[1]), af::span, af::span) = in; - ret = parent(af::span, af::seq(1, dims[1]), af::span, af::span); + pdims[1] *= 2; + const af::seq dim = af::seq(dims[1]) + static_cast(dims[1]); + af::array parent = af::randu(pdims, in.type()); + parent(af::span, dim, af::span, af::span) = in; + ret = parent(af::span, dim, af::span, af::span); }; break; case SUB_FORMAT_dim2: { af::dim4 pdims(dims); - pdims[2] += 2; - af::array parent = af::randu(pdims, in.type()); - parent(af::span, af::span, af::seq(1, dims[2]), af::span) = in; - ret = parent(af::span, af::span, af::seq(1, dims[2]), af::span); + pdims[2] *= 2; + const af::seq dim = af::seq(dims[2]) + static_cast(dims[2]); + af::array parent = af::randu(pdims, in.type()); + parent(af::span, af::span, dim, af::span) = in; + ret = parent(af::span, af::span, dim, af::span); }; break; case SUB_FORMAT_dim3: { af::dim4 pdims(dims); - pdims[3] += 2; - af::array parent = af::randu(pdims, in.type()); - parent(af::span, af::span, af::span, af::seq(1, dims[3])) = in; - ret = parent(af::span, af::span, af::span, af::seq(1, dims[3])); + pdims[3] *= 2; + const af::seq dim = af::seq(dims[3]) + static_cast(dims[3]); + af::array parent = af::randu(pdims, in.type()); + parent(af::span, af::span, af::span, dim) = in; + ret = parent(af::span, af::span, af::span, dim); }; break; case REORDERED_FORMAT: { const dim_t idxs[4] = {0, 3, 1, 2}; @@ -2138,21 +2154,22 @@ void toTempFormat(tempFormat form, af_array *out, const af_array &in) { res = nullptr; }; break; case SUB_FORMAT_dim0: { - const dim_t pdims[4] = {dims[0] + 2, dims[1], dims[2], dims[3]}; + const dim_t pdims[4] = {dims[0] * 2, dims[1], dims[2], dims[3]}; af_array parent = nullptr; - ASSERT_SUCCESS(af_randu(&parent, std::max(1u, numdims), pdims, ty)); - const af_seq idxs[4] = {af_make_seq(1, dims[0], 1), af_span, - af_span, af_span}; - + ASSERT_SUCCESS(af_randu(&parent, 4, pdims, ty)); + const af_seq idxs[4] = {af_make_seq(dims[0], 2. * dims[0] - 1., 1.), + af_span, af_span, af_span}; ASSERT_SUCCESS(af_assign_seq(out, parent, numdims, idxs, in)); ASSERT_SUCCESS(af_index(out, parent, numdims, idxs)); ASSERT_SUCCESS(af_release_array(parent)); + parent = nullptr; }; break; case SUB_FORMAT_dim1: { - const dim_t pdims[4] = {dims[0], dims[1] + 2, dims[2], dims[3]}; + const dim_t pdims[4] = {dims[0], dims[1] * 2, dims[2], dims[3]}; af_array parent = nullptr; - ASSERT_SUCCESS(af_randu(&parent, std::max(2u, numdims), pdims, ty)); - const af_seq idxs[4] = {af_span, af_make_seq(1, dims[1], 1), + ASSERT_SUCCESS(af_randu(&parent, 4, pdims, ty)); + const af_seq idxs[4] = {af_span, + af_make_seq(dims[1], 2. * dims[1] - 1., 1.), af_span, af_span}; ASSERT_SUCCESS(af_assign_seq(out, parent, numdims, idxs, in)); ASSERT_SUCCESS(af_index(out, parent, numdims, idxs)); @@ -2160,22 +2177,24 @@ void toTempFormat(tempFormat form, af_array *out, const af_array &in) { parent = nullptr; }; break; case SUB_FORMAT_dim2: { - const dim_t pdims[4] = {dims[0], dims[1], dims[2] + 2, dims[3]}; + const dim_t pdims[4] = {dims[0], dims[1], dims[2] * 2, dims[3]}; af_array parent = nullptr; - ASSERT_SUCCESS(af_randu(&parent, std::max(3u, numdims), pdims, ty)); + ASSERT_SUCCESS(af_randu(&parent, 4, pdims, ty)); const af_seq idxs[4] = {af_span, af_span, - af_make_seq(1, dims[2], 1), af_span}; + af_make_seq(dims[2], 2. * dims[2] - 1., 1.), + af_span}; ASSERT_SUCCESS(af_assign_seq(out, parent, numdims, idxs, in)); ASSERT_SUCCESS(af_index(out, parent, numdims, idxs)); ASSERT_SUCCESS(af_release_array(parent)); parent = nullptr; }; break; case SUB_FORMAT_dim3: { - const dim_t pdims[4] = {dims[0], dims[1], dims[2], dims[3] + 2}; + const dim_t pdims[4] = {dims[0], dims[1], dims[2], dims[3] * 2}; af_array parent = nullptr; - ASSERT_SUCCESS(af_randu(&parent, std::max(4u, numdims), pdims, ty)); - const af_seq idxs[4] = {af_span, af_span, af_span, - af_make_seq(1, dims[3], 1)}; + ASSERT_SUCCESS(af_randu(&parent, 4, pdims, ty)); + const af_seq idxs[4] = { + af_span, af_span, af_span, + af_make_seq(dims[3], 2. * dims[3] - 1., 1.)}; ASSERT_SUCCESS(af_assign_seq(out, parent, numdims, idxs, in)); ASSERT_SUCCESS(af_index(out, parent, numdims, idxs)); ASSERT_SUCCESS(af_release_array(parent)); diff --git a/test/transform.cpp b/test/transform.cpp index ef3b0dd4f9..e6026576ba 100644 --- a/test/transform.cpp +++ b/test/transform.cpp @@ -620,3 +620,43 @@ TEST(TransformBatching, CPP) { } } } + +#define TEST_TEMP_FORMAT(form, interp) \ + TEST(TEMP_FORMAT, form##_##interp) { \ + IMAGEIO_ENABLED_CHECK(); \ + \ + vector inDims; \ + vector inFiles; \ + vector goldDim; \ + vector goldFiles; \ + \ + vector HDims; \ + vector> HIn; \ + vector> HTests; \ + readTests(TEST_DIR "/transform/tux_tmat.test", \ + HDims, HIn, HTests); \ + \ + readImageTests(string(TEST_DIR "/transform/tux_nearest.test"), inDims, \ + inFiles, goldDim, goldFiles); \ + inFiles[1].insert(0, string(TEST_DIR "/transform/")); \ + const array IH = array(HDims[0][0], HDims[0][1], &(HIn[0].front())); \ + const array scene_img = loadImage(inFiles[1].c_str(), false); \ + \ + const array out = \ + transform(toTempFormat(form, scene_img), toTempFormat(form, IH), \ + inDims[0][0], inDims[0][1], interp, false); \ + const array gold = transform(scene_img, IH, inDims[0][0], \ + inDims[0][1], interp, false); \ + \ + EXPECT_ARRAYS_EQ(out, gold); \ + } + +#define TESTS_TEMP_FORMAT(form) \ + TEST_TEMP_FORMAT(form, AF_INTERP_NEAREST) \ + TEST_TEMP_FORMAT(form, AF_INTERP_BILINEAR) \ + TEST_TEMP_FORMAT(form, AF_INTERP_BILINEAR_COSINE) \ + TEST_TEMP_FORMAT(form, AF_INTERP_BICUBIC) \ + TEST_TEMP_FORMAT(form, AF_INTERP_BICUBIC_SPLINE) \ + TEST_TEMP_FORMAT(form, AF_INTERP_LOWER) + +FOREACH_TEMP_FORMAT(TESTS_TEMP_FORMAT) \ No newline at end of file diff --git a/test/transform_coordinates.cpp b/test/transform_coordinates.cpp index 2875f18c1a..bc5dbed4e9 100644 --- a/test/transform_coordinates.cpp +++ b/test/transform_coordinates.cpp @@ -61,7 +61,7 @@ void transformCoordinatesTest(string pTestFile) { dim_t outEl = 0; ASSERT_SUCCESS(af_get_elements(&outEl, outArray)); vector outData(outEl); - ASSERT_SUCCESS(af_get_data_ptr((void*)&outData.front(), outArray)); + ASSERT_SUCCESS(af_get_data_ptr((void *)&outData.front(), outArray)); ASSERT_SUCCESS(af_release_array(outArray)); const float thr = 1.f; @@ -114,3 +114,26 @@ TEST(TransformCoordinates, CPP) { << "at: " << elIter << endl; } } + +#define TESTS_TEMP_FORMAT(form) \ + TEST(TEMP_FORMAT, form) { \ + vector inDims; \ + vector> in; \ + vector> gold; \ + \ + readTests(TEST_DIR \ + "/transformCoordinates/3d_matrix.test", \ + inDims, in, gold); \ + \ + const array tf(inDims[0][0], inDims[0][1], &(in[0].front())); \ + const float d0 = in[1][0]; \ + const float d1 = in[1][1]; \ + \ + const array out = \ + transformCoordinates(toTempFormat(form, tf), d0, d1); \ + const array gout = transformCoordinates(tf, d0, d1); \ + \ + EXPECT_ARRAYS_EQ(out, gout); \ + } + +FOREACH_TEMP_FORMAT(TESTS_TEMP_FORMAT) \ No newline at end of file