[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/arrayfire/arrayfire/feature/optional-graphics/test/meanvar.cpp [Back]  [Original]

/*******************************************************
 * Copyright (c) 2018, 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 

using af::array;
using af::cdouble;
using af::cfloat;
using af::dim4;
using af::dtype_traits;
using std::back_inserter;
using std::move;
using std::string;
using std::vector;

af_err init_err = af_init();

template
struct elseType {
    typedef typename cond_type::type type;
};

template
struct varOutType {
    typedef typename cond_type<
        is_same_type::value || is_same_type::value ||
            is_same_type::value || is_same_type::value ||
            is_same_type::value || is_same_type::value ||
            is_same_type::value || is_same_type::value,
        float, typename elseType::type>::type type;
};

template
using outType = typename varOutType::type;

template
struct meanvar_test {
    static af_dtype af_type;
    string test_description_;
    af_array in_;
    af_array weights_;
    af_var_bias bias_;
    int dim_;
    vector mean_;
    vector variance_;

    meanvar_test(string description, af_array in, af_array weights,
                 af_var_bias bias, int dim,
                 vector &&mean,
                 vector &&variance)
        : test_description_(description)
        , in_(0)
        , weights_(0)
        , bias_(bias)
        , dim_(dim) {
        af_retain_array(&in_, in);
        if (weights) { af_retain_array(&weights_, weights); }
        mean_.reserve(mean.size());
        variance_.reserve(variance.size());
        for (auto &v : mean) mean_.push_back((outType)v);
        for (auto &v : variance) variance_.push_back((outType)v);
    }

    meanvar_test(std::string name)
        : test_description_(name), in_(0), weights_(0) {}

    meanvar_test(meanvar_test &&other)
        : test_description_(other.test_description_)
        , in_(other.in_)
        , weights_(other.weights_)
        , bias_(other.bias_)
        , dim_(other.dim_)
        , mean_(other.mean_)
        , variance_(other.variance_) {
        other.in_      = 0;
        other.weights_ = 0;
    }
    meanvar_test &operator=(meanvar_test &&other) = default;
    meanvar_test &operator=(meanvar_test &other)  = delete;

    meanvar_test(const meanvar_test &other)
        : test_description_(other.test_description_)
        , in_(0)
        , weights_(0)
        , bias_(other.bias_)
        , dim_(other.dim_)
        , mean_(other.mean_)
        , variance_(other.variance_) {
        if (other.in_) af_retain_array(&in_, other.in_);
        if (other.weights_) { af_retain_array(&weights_, other.weights_); }
    }

    ~meanvar_test() {
#ifndef _WIN32
        if (in_) af_release_array(in_);
        if (weights_) {
            af_release_array(weights_);
            weights_ = 0;
        }
#endif
    }
};

template
af_dtype meanvar_test::af_type = dtype_traits::af_type;

template
class MeanVarTyped : public ::testing::TestWithParam {
   public:
    void meanvar_test_function(const meanvar_test &test) {
        SUPPORTED_TYPE_CHECK(T);
        SUPPORTED_TYPE_CHECK(outType);
        af_array mean, var;

        // Cast to the expected type
        af_array in = 0;
        ASSERT_SUCCESS(
            af_cast(&in, test.in_, (af_dtype)dtype_traits::af_type));

        EXPECT_EQ(AF_SUCCESS, af_meanvar(&mean, &var, in, test.weights_,
                                         test.bias_, test.dim_));

        vector h_mean(test.mean_.size()),
            h_var(test.variance_.size());

        dim4 outDim(1);
        af_get_dims(&outDim[0], &outDim[1], &outDim[2], &outDim[3], in);
        outDim[test.dim_] = 1;

        if (is_same_type::value) {
            ASSERT_VEC_ARRAY_NEAR(test.mean_, outDim, mean, 1.f);
            ASSERT_VEC_ARRAY_NEAR(test.variance_, outDim, var, 0.5f);
        } else if (is_same_type::value ||
                   is_same_type::value) {
            ASSERT_VEC_ARRAY_NEAR(test.mean_, outDim, mean, 0.0016f);
            ASSERT_VEC_ARRAY_NEAR(test.variance_, outDim, var, 0.2f);
        } else {
            ASSERT_VEC_ARRAY_NEAR(test.mean_, outDim, mean, 0.00001f);
            ASSERT_VEC_ARRAY_NEAR(test.variance_, outDim, var, 0.0001f);
        }

        ASSERT_SUCCESS(af_release_array(in));
        ASSERT_SUCCESS(af_release_array(mean));
        ASSERT_SUCCESS(af_release_array(var));
    }

    void meanvar_cpp_test_function(const meanvar_test &test) {
        SUPPORTED_TYPE_CHECK(T);
        SUPPORTED_TYPE_CHECK(outType);
        array mean, var;

        // Cast to the expected type
        af_array in_tmp = 0;
        ASSERT_SUCCESS(af_retain_array(&in_tmp, test.in_));
        array in(in_tmp);
        in = in.as((af_dtype)dtype_traits::af_type);

        af_array weights_tmp = test.weights_;
        if (weights_tmp) {
            ASSERT_SUCCESS(af_retain_array(&weights_tmp, weights_tmp));
        }
        array weights(weights_tmp);
        meanvar(mean, var, in, weights, test.bias_, test.dim_);

        vector h_mean(test.mean_.size()),
            h_var(test.variance_.size());

        dim4 outDim       = in.dims();
        outDim[test.dim_] = 1;

        if (is_same_type::value) {
            ASSERT_VEC_ARRAY_NEAR(test.mean_, outDim, mean, 1.f);
            ASSERT_VEC_ARRAY_NEAR(test.variance_, outDim, var, 0.5f);
        } else if (is_same_type::value ||
                   is_same_type::value) {
            ASSERT_VEC_ARRAY_NEAR(test.mean_, outDim, mean, 0.0016f);
            ASSERT_VEC_ARRAY_NEAR(test.variance_, outDim, var, 0.2f);
        } else {
            ASSERT_VEC_ARRAY_NEAR(test.mean_, outDim, mean, 0.00001f);
            ASSERT_VEC_ARRAY_NEAR(test.variance_, outDim, var, 0.0001f);
        }
    }
};

af_array empty = 0;

enum test_size { MEANVAR_SMALL, MEANVAR_LARGE };

template
meanvar_test meanvar_test_gen(string name, int in_index, int weight_index,
                                 af_var_bias bias, int dim, int mean_index,
                                 int var_index, test_size size) {
    if (noDoubleTests((af_dtype)af::dtype_traits::af_type) ||
        noDoubleTests((
            af_dtype)af::dtype_traits::af_type) ||
        noHalfTests((af_dtype)af::dtype_traits::af_type)) {
        meanvar_test out(name);
        return out;
    }

    vector inputs;
    vector outputs;
    if (size == MEANVAR_SMALL) {
        vector numDims_;
        vector in_;
        vector tests_;
        readTests(
            TEST_DIR "/meanvar/meanvar.data", numDims_, in_, tests_);

        inputs.resize(in_.size());
        for (size_t i = 0; i < in_.size(); i++) {
            af_create_array(&inputs[i], &in_[i].front(), numDims_[i].ndims(),
                            numDims_[i].get(),
                            (af_dtype)af::dtype_traits::af_type);
        }

        outputs.resize(tests_.size());
        for (size_t i = 0; i < tests_.size(); i++) {
            copy(tests_[i].begin(), tests_[i].end(), back_inserter(outputs[i]));
        }
    } else {
        dim_t full_array_size            = 2000;
        vector dimensions = {
            {2000, 1, 1, 1},  // 0
            {1, 2000, 1, 1},  // 1
            {1, 1, 2000, 1},  // 2

            {500, 4, 1, 1},  // 3
            {4, 500, 1, 1},  // 4
            {50, 40, 1, 1}   // 5
        };

        vector large_(full_array_size);
        for (size_t i = 0; i < large_.size(); i++) {
            large_[i] = static_cast(i);
        }

        inputs.resize(dimensions.size());
        for (size_t i = 0; i < dimensions.size(); i++) {
            af_create_array(&inputs[i], &large_.front(), 4,
                            dimensions[i].data(),
                            (af_dtype)af::dtype_traits::af_type);
        }

        outputs.push_back(
            vector(1, outType(999.5)));
        outputs.push_back(
            vector(1, outType(333500)));
        outputs.push_back({outType(249.50), outType(749.50),
                           outType(1249.50), outType(1749.50)});
        outputs.push_back(
            vector(4, outType(20875)));
    }
    meanvar_test out(name, inputs[in_index],
                        (weight_index == -1) ? empty : inputs[weight_index],
                        bias, dim, move(outputs[mean_index]),
                        move(outputs[var_index]));

    for (auto input : inputs) { af_release_array(input); }
    return out;
}

template
vector small_test_values() {
    // clang-format off
    return {
        //                  |           Name |   in_index | weight_index |                  bias |  dim | mean_index | var_index |
        meanvar_test_gen(   "Sample1Ddim0",           0,            -1,     AF_VARIANCE_SAMPLE,     0,           0,          1, MEANVAR_SMALL),
        meanvar_test_gen(   "Sample1Ddim1",           1,            -1,     AF_VARIANCE_SAMPLE,     1,           0,          1, MEANVAR_SMALL),
        meanvar_test_gen(   "Sample2Ddim0",           2,            -1,     AF_VARIANCE_SAMPLE,     0,           3,          4, MEANVAR_SMALL),
        meanvar_test_gen(   "Sample2Ddim1",           2,            -1,     AF_VARIANCE_SAMPLE,     1,           6,          7, MEANVAR_SMALL),

        meanvar_test_gen("Population1Ddim0",          0,            -1, AF_VARIANCE_POPULATION,     0,           0,          2, MEANVAR_SMALL),
        meanvar_test_gen("Population1Ddim1",          1,            -1, AF_VARIANCE_POPULATION,     1,           0,          2, MEANVAR_SMALL),
        meanvar_test_gen("Population2Ddim0",          2,            -1, AF_VARIANCE_POPULATION,     0,           3,          5, MEANVAR_SMALL),
        meanvar_test_gen("Population2Ddim1",          2,            -1, AF_VARIANCE_POPULATION,     1,           6,          8, MEANVAR_SMALL)};
    // clang-format on
}

template
vector large_test_values() {
    return {
        // clang-format off
        //                  |       Name |      in_index | weight_index |                  bias |  dim | mean_index | var_index |
        meanvar_test_gen("Sample1Ddim0",             0,            -1,     AF_VARIANCE_SAMPLE,     0,           0,          1, MEANVAR_LARGE),
        meanvar_test_gen("Sample1Ddim1",             1,            -1,     AF_VARIANCE_SAMPLE,     1,           0,          1, MEANVAR_LARGE),
        meanvar_test_gen("Sample1Ddim2",             2,            -1,     AF_VARIANCE_SAMPLE,     2,           0,          1, MEANVAR_LARGE),
        meanvar_test_gen("Sample2Ddim0",             3,            -1,     AF_VARIANCE_SAMPLE,     0,           2,          3, MEANVAR_LARGE),
        // TODO(umar) Add additional large tests
        // meanvar_test_gen(    "Sample2Ddim1",           3,            -1, AF_VARIANCE_SAMPLE,     1,           2,          3, MEANVAR_LARGE),
        // meanvar_test_gen(    "Sample2Ddim1",           2,            -1, AF_VARIANCE_SAMPLE,     1,           6,          7, MEANVAR_LARGE),
        // clang-format on
    };
}

#define MEANVAR_TEST(NAME, TYPE)                                              \
    using MeanVar##NAME = MeanVarTyped;                                 \
    INSTANTIATE_TEST_SUITE_P(                                                 \
        Small, MeanVar##NAME, ::testing::ValuesIn(small_test_values()), \
        [](const ::testing::TestParamInfo info) {   \
            return info.param.test_description_;                              \
        });                                                                   \
    INSTANTIATE_TEST_SUITE_P(                                                 \
        Large, MeanVar##NAME, ::testing::ValuesIn(large_test_values()), \
        [](const ::testing::TestParamInfo info) {   \
            return info.param.test_description_;                              \
        });                                                                   \
                                                                              \
    TEST_P(MeanVar##NAME, Testing) {                                          \
        const meanvar_test &test = GetParam();                          \
        meanvar_test_function(test);                                          \
    }                                                                         \
    TEST_P(MeanVar##NAME, TestingCPP) {                                       \
        const meanvar_test &test = GetParam();                          \
        meanvar_cpp_test_function(test);                                      \
    }

MEANVAR_TEST(Float, float)
MEANVAR_TEST(Double, double)
MEANVAR_TEST(Int, int)
MEANVAR_TEST(UnsignedInt, unsigned int)
MEANVAR_TEST(Short, short)
MEANVAR_TEST(UnsignedShort, unsigned short)
MEANVAR_TEST(Long, long long)
MEANVAR_TEST(UnsignedLong, unsigned long long)
MEANVAR_TEST(ComplexFloat, af::af_cfloat)
MEANVAR_TEST(ComplexDouble, af::af_cdouble)

#undef MEANVAR_TEST

using MeanVarHalf = MeanVarTyped;
INSTANTIATE_TEST_SUITE_P(
    Small, MeanVarHalf,
    ::testing::ValuesIn(small_test_values()),
    [](const ::testing::TestParamInfo info) {
        return info.param.test_description_;
    });
TEST_P(MeanVarHalf, Testing) {
    const meanvar_test &test = GetParam();
    meanvar_test_function(test);
}
TEST_P(MeanVarHalf, TestingCPP) {
    const meanvar_test &test = GetParam();
    meanvar_cpp_test_function(test);
}

#define MEANVAR_TEST(NAME, TYPE)                                              \
    using MeanVar##NAME = MeanVarTyped;                                 \
    INSTANTIATE_TEST_SUITE_P(                                                 \
        Small, MeanVar##NAME, ::testing::ValuesIn(small_test_values()), \
        [](const ::testing::TestParamInfo &info) {  \
            return info.param.test_description_;                              \
        });                                                                   \
                                                                              \
    TEST_P(MeanVar##NAME, Testing) {                                          \
        const meanvar_test &test = GetParam();                          \
        meanvar_test_function(test);                                          \
    }                                                                         \
    TEST_P(MeanVar##NAME, TestingCPP) {                                       \
        const meanvar_test &test = GetParam();                          \
        meanvar_cpp_test_function(test);                                      \
    }

// Only test small sizes because the range of the large arrays go out of bounds
MEANVAR_TEST(SignedChar, signed char)
MEANVAR_TEST(UnsignedChar, unsigned char)
// MEANVAR_TEST(Bool, unsigned char) // TODO(umar): test this type

Web Proxy Viewer  |  New URL  |  Original Page