/******************************************************* * Copyright (c) 2014, ArrayFire * All rights reserved. * * This file is distributed under 3-clause BSD license. * The complete license agreement can be obtained at: * http://arrayfire.com/licenses/BSD-3-Clause ********************************************************/ #include #include #include #include #include #include #include #include #include #include using std::vector; using std::string; using std::cout; using std::endl; using std::abs; using af::cfloat; using af::cdouble; template class Approx2 : public ::testing::Test { public: virtual void SetUp() { subMat0.push_back(af_make_seq(0, 4, 1)); subMat0.push_back(af_make_seq(2, 6, 1)); subMat0.push_back(af_make_seq(0, 2, 1)); } vector subMat0; }; // create a list of types to be tested typedef ::testing::Types TestTypes; // register the type list TYPED_TEST_CASE(Approx2, TestTypes); template void approx2Test(string pTestFile, const unsigned resultIdx, const af_interp_type method, bool isSubRef = false, const vector * seqv = NULL) { if (noDoubleTests()) return; typedef typename af::dtype_traits::base_type BT; vector numDims; vector > in; vector > tests; readTests(pTestFile,numDims,in,tests); af::dim4 idims = numDims[0]; af::dim4 pdims = numDims[1]; af::dim4 qdims = numDims[2]; af_array inArray = 0; af_array pos0Array = 0; af_array pos1Array = 0; af_array outArray = 0; af_array tempArray = 0; vector input(in[0].begin(), in[0].end()); if (isSubRef) { ASSERT_EQ(AF_SUCCESS, af_create_array(&tempArray, &(input.front()), idims.ndims(), idims.get(), (af_dtype) af::dtype_traits::af_type)); ASSERT_EQ(AF_SUCCESS, af_index(&inArray, tempArray, seqv->size(), &seqv->front())); } else { ASSERT_EQ(AF_SUCCESS, af_create_array(&inArray, &(input.front()), idims.ndims(), idims.get(), (af_dtype) af::dtype_traits::af_type)); } ASSERT_EQ(AF_SUCCESS, af_create_array(&pos0Array, &(in[1].front()), pdims.ndims(), pdims.get(), (af_dtype) af::dtype_traits::af_type)); ASSERT_EQ(AF_SUCCESS, af_create_array(&pos1Array, &(in[2].front()), qdims.ndims(), qdims.get(), (af_dtype) af::dtype_traits::af_type)); ASSERT_EQ(AF_SUCCESS, af_approx2(&outArray, inArray, pos0Array, pos1Array, method, 0)); // Get result T* outData = new T[tests[resultIdx].size()]; ASSERT_EQ(AF_SUCCESS, af_get_data_ptr((void*)outData, outArray)); // Compare result size_t nElems = tests[resultIdx].size(); bool ret = true; for (size_t elIter = 0; elIter < nElems; ++elIter) { ret = (abs(tests[resultIdx][elIter] - outData[elIter]) < 0.001); ASSERT_EQ(true, ret) << tests[resultIdx][elIter] << "\t" << outData[elIter] << "at: " << elIter << std::endl; } // Delete delete[] outData; if(inArray != 0) af_release_array(inArray); if(pos0Array != 0) af_release_array(pos0Array); if(pos1Array != 0) af_release_array(pos1Array); if(outArray != 0) af_release_array(outArray); if(tempArray != 0) af_release_array(tempArray); } #define APPROX2_INIT(desc, file, resultIdx, method) \ TYPED_TEST(Approx2, desc) \ { \ approx2Test(string(TEST_DIR"/approx/"#file".test"), resultIdx, method);\ } APPROX2_INIT(Approx2Nearest, approx2, 0, AF_INTERP_NEAREST); APPROX2_INIT(Approx2Linear, approx2, 1, AF_INTERP_LINEAR); APPROX2_INIT(Approx2NearestBatch, approx2_batch, 0, AF_INTERP_NEAREST); APPROX2_INIT(Approx2LinearBatch, approx2_batch, 1, AF_INTERP_LINEAR); /////////////////////////////////////////////////////////////////////////////// // Test Argument Failure Cases /////////////////////////////////////////////////////////////////////////////// template void approx2ArgsTest(string pTestFile, const unsigned resultIdx, const af_interp_type method, const af_err err) { if (noDoubleTests()) return; typedef typename af::dtype_traits::base_type BT; vector numDims; vector > in; vector > tests; readTests(pTestFile,numDims,in,tests); af::dim4 idims = numDims[0]; af::dim4 pdims = numDims[1]; af::dim4 qdims = numDims[2]; af_array inArray = 0; af_array pos0Array = 0; af_array pos1Array = 0; af_array outArray = 0; vector input(in[0].begin(), in[0].end()); ASSERT_EQ(AF_SUCCESS, af_create_array(&inArray, &(input.front()), idims.ndims(), idims.get(), (af_dtype) af::dtype_traits::af_type)); ASSERT_EQ(AF_SUCCESS, af_create_array(&pos0Array, &(in[1].front()), pdims.ndims(), pdims.get(), (af_dtype) af::dtype_traits::af_type)); ASSERT_EQ(AF_SUCCESS, af_create_array(&pos1Array, &(in[2].front()), qdims.ndims(), qdims.get(), (af_dtype) af::dtype_traits::af_type)); ASSERT_EQ(err, af_approx2(&outArray, inArray, pos0Array, pos1Array, method, 0)); if(inArray != 0) af_release_array(inArray); if(pos0Array != 0) af_release_array(pos0Array); if(pos1Array != 0) af_release_array(pos1Array); if(outArray != 0) af_release_array(outArray); } #define APPROX2_ARGS(desc, file, resultIdx, method, err) \ TYPED_TEST(Approx2, desc) \ { \ approx2ArgsTest(string(TEST_DIR"/approx/"#file".test"), resultIdx, method, err); \ } APPROX2_ARGS(Approx2NearestArgsPos3D, approx2_pos3d, 0, AF_INTERP_NEAREST, AF_ERR_SIZE); APPROX2_ARGS(Approx2LinearArgsPos3D, approx2_pos3d, 1, AF_INTERP_LINEAR, AF_ERR_SIZE); APPROX2_ARGS(Approx2NearestArgsPosUnequal, approx2_unequal, 0, AF_INTERP_NEAREST, AF_ERR_SIZE); APPROX2_ARGS(Approx2ArgsInterpBilinear, approx2, 0, AF_INTERP_BILINEAR, AF_ERR_ARG); APPROX2_ARGS(Approx2ArgsInterpCubic, approx2, 0, AF_INTERP_CUBIC, AF_ERR_ARG); template void approx2ArgsTestPrecision(string pTestFile, const unsigned resultIdx, const af_interp_type method) { if (noDoubleTests()) return; vector numDims; vector > in; vector > tests; readTests(pTestFile,numDims,in,tests); af::dim4 idims = numDims[0]; af::dim4 pdims = numDims[1]; af::dim4 qdims = numDims[2]; af_array inArray = 0; af_array pos0Array = 0; af_array pos1Array = 0; af_array outArray = 0; vector input(in[0].begin(), in[0].end()); ASSERT_EQ(AF_SUCCESS, af_create_array(&inArray, &(input.front()), idims.ndims(), idims.get(), (af_dtype) af::dtype_traits::af_type)); ASSERT_EQ(AF_SUCCESS, af_create_array(&pos0Array, &(in[1].front()), pdims.ndims(), pdims.get(), (af_dtype) af::dtype_traits::af_type)); ASSERT_EQ(AF_SUCCESS, af_create_array(&pos1Array, &(in[2].front()), qdims.ndims(), qdims.get(), (af_dtype) af::dtype_traits::af_type)); if((af_dtype) af::dtype_traits::af_type == c32 || (af_dtype) af::dtype_traits::af_type == c64) { ASSERT_EQ(AF_ERR_ARG, af_approx2(&outArray, inArray, pos0Array, pos1Array, method, 0)); } else { ASSERT_EQ(AF_SUCCESS, af_approx2(&outArray, inArray, pos0Array, pos1Array, method, 0)); } if(inArray != 0) af_release_array(inArray); if(pos0Array != 0) af_release_array(pos0Array); if(pos1Array != 0) af_release_array(pos1Array); if(outArray != 0) af_release_array(outArray); } #define APPROX2_ARGSP(desc, file, resultIdx, method) \ TYPED_TEST(Approx2, desc) \ { \ approx2ArgsTestPrecision(string(TEST_DIR"/approx/"#file".test"), \ resultIdx, method); \ } APPROX2_ARGSP(Approx2NearestArgsPrecision, approx2, 0, AF_INTERP_NEAREST); APPROX2_ARGSP(Approx2LinearArgsPrecision, approx2, 1, AF_INTERP_LINEAR); //////////////////////////////////// CPP //////////////////////////////////// // TEST(Approx2, CPP) { if (noDoubleTests()) return; const unsigned resultIdx = 1; #define BT af::dtype_traits::base_type vector numDims; vector > in; vector > tests; readTests(string(TEST_DIR"/approx/approx2.test"),numDims,in,tests); af::dim4 idims = numDims[0]; af::dim4 pdims = numDims[1]; af::dim4 qdims = numDims[2]; af::array input(idims,&(in[0].front())); af::array pos0(pdims,&(in[1].front())); af::array pos1(qdims,&(in[2].front())); af::array output = af::approx2(input, pos0, pos1, AF_INTERP_LINEAR, 0); // Get result float* outData = new float[tests[resultIdx].size()]; output.host((void*)outData); // Compare result size_t nElems = tests[resultIdx].size(); bool ret = true; for (size_t elIter = 0; elIter < nElems; ++elIter) { ret = (std::abs(tests[resultIdx][elIter] - outData[elIter]) < 0.001); ASSERT_EQ(true, ret) << tests[resultIdx][elIter] << "\t" << outData[elIter] << "at: " << elIter << std::endl; } // Delete delete[] outData; #undef BT } TEST(Approx2, CPPNearestBatch) { if (noDoubleTests()) return; af::array input = af::randu(200, 100, 10); af::array pos = input.dims(0) * af::randu(100, 100, 10); af::array qos = input.dims(1) * af::randu(100, 100, 10); af::array outBatch = af::approx2(input, pos, qos, AF_INTERP_NEAREST); af::array outSerial(pos.dims()); for(int i = 0; i < pos.dims(2); i++) { outSerial(af::span, af::span, i) = af::approx2(input(af::span, af::span, i), pos(af::span, af::span, i), qos(af::span, af::span, i), AF_INTERP_NEAREST); } af::array outGFOR(pos.dims()); gfor(af::seq i, pos.dims(2)) { outGFOR(af::span, af::span, i) = af::approx2(input(af::span, af::span, i), pos(af::span, af::span, i), qos(af::span, af::span, i), AF_INTERP_NEAREST); } ASSERT_NEAR(0, af::sum(af::abs(outBatch - outSerial)), 1e-3); ASSERT_NEAR(0, af::sum(af::abs(outBatch - outGFOR)), 1e-3); } TEST(Approx2, CPPLinearBatch) { if (noDoubleTests()) return; af::array input = af::randu(200, 100, 10); af::array pos = input.dims(0) * af::randu(100, 100, 10); af::array qos = input.dims(1) * af::randu(100, 100, 10); af::array outBatch = af::approx2(input, pos, qos, AF_INTERP_LINEAR); af::array outSerial(pos.dims()); for(int i = 0; i < pos.dims(2); i++) { outSerial(af::span, af::span, i) = af::approx2(input(af::span, af::span, i), pos(af::span, af::span, i), qos(af::span, af::span, i), AF_INTERP_LINEAR); } af::array outGFOR(pos.dims()); gfor(af::seq i, pos.dims(2)) { outGFOR(af::span, af::span, i) = af::approx2(input(af::span, af::span, i), pos(af::span, af::span, i), qos(af::span, af::span, i), AF_INTERP_LINEAR); } ASSERT_NEAR(0, af::sum(af::abs(outBatch - outSerial)), 1e-3); ASSERT_NEAR(0, af::sum(af::abs(outBatch - outGFOR)), 1e-3); }