diff options
Diffstat (limited to 'tests/validation/UNIT/FixedPoint.cpp')
-rw-r--r-- | tests/validation/UNIT/FixedPoint.cpp | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/tests/validation/UNIT/FixedPoint.cpp b/tests/validation/UNIT/FixedPoint.cpp new file mode 100644 index 0000000000..63d4150318 --- /dev/null +++ b/tests/validation/UNIT/FixedPoint.cpp @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2017 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include "validation/FixedPoint.h" + +#include "TypePrinter.h" +#include "Utils.h" +#include "validation/Validation.h" +#include "validation/ValidationUserConfiguration.h" + +#include "boost_wrapper.h" + +#include <fstream> +#include <vector> + +using namespace arm_compute; +using namespace arm_compute::test; +using namespace arm_compute::test::validation; + +namespace +{ +std::string func_names[] = +{ + "add", "sub", "mul", "exp", "log", "inv_sqrt" +}; +} // namespace + +#ifndef DOXYGEN_SKIP_THIS +BOOST_AUTO_TEST_SUITE(UNIT) +BOOST_AUTO_TEST_SUITE(FixedPoint) + +BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) +BOOST_DATA_TEST_CASE(FixedPointQS8Inputs, boost::unit_test::data::make(func_names) * boost::unit_test::data::xrange(1, 7), func_name, frac_bits) +{ + const std::string base_file_name = user_config.path.get() + "/dumps/" + func_name + "_Q8." + cpp11::to_string(frac_bits); + std::ifstream inputs_file{ base_file_name + ".in", std::ios::binary | std::ios::in }; + + BOOST_TEST_INFO(base_file_name + ".in"); + BOOST_TEST_REQUIRE(inputs_file.good()); + + float float_val = 0.f; + + // Read first value + inputs_file.read(reinterpret_cast<char *>(&float_val), sizeof(float_val)); + + while(inputs_file.good()) + { + // Convert to fixed point + fixed_point_arithmetic::fixed_point<int8_t> in_val(float_val, frac_bits); + + // Check that the value didn't change + BOOST_TEST(static_cast<float>(in_val) == float_val); + + // Read next value + inputs_file.read(reinterpret_cast<char *>(&float_val), sizeof(float_val)); + } +} + +BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly")) +//FIXME: Figure out how to handle expected failures properly +// The last input argument specifies the expected number of failures for a +// given combination of (function name, number of fractional bits) as defined +// by the first two arguments. +BOOST_DATA_TEST_CASE(FixedPointQS8Outputs, (boost::unit_test::data::make(func_names) * boost::unit_test::data::xrange(1, 7)) ^ (boost::unit_test::data::make({ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, 13, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 32, 67 })), + func_name, frac_bits, expected_failures) +{ + const std::string base_file_name = user_config.path.get() + "/dumps/" + func_name + "_Q8." + cpp11::to_string(frac_bits); + std::ifstream inputs_file{ base_file_name + ".in", std::ios::binary | std::ios::in }; + std::ifstream reference_file{ base_file_name + ".out", std::ios::binary | std::ios::in }; + + BOOST_TEST_INFO(base_file_name + ".in"); + BOOST_TEST_REQUIRE(inputs_file.good()); + BOOST_TEST_INFO(base_file_name + ".out"); + BOOST_TEST_REQUIRE(reference_file.good()); + + const float step_size = std::pow(2.f, -frac_bits); + + float float_val = 0.f; + float ref_val = 0.f; + int64_t num_mismatches = 0; + + // Read first values + inputs_file.read(reinterpret_cast<char *>(&float_val), sizeof(float_val)); + reference_file.read(reinterpret_cast<char *>(&ref_val), sizeof(ref_val)); + + while(inputs_file.good() && reference_file.good()) + { + fixed_point_arithmetic::fixed_point<int8_t> in_val(float_val, frac_bits); + fixed_point_arithmetic::fixed_point<int8_t> out_val(0.f, frac_bits); + + float tolerance = 0.f; + + if(func_name == "add") + { + out_val = in_val + in_val; + } + else if(func_name == "sub") + { + out_val = in_val - in_val; //NOLINT + } + else if(func_name == "mul") + { + tolerance = 1.f * step_size; + out_val = in_val * in_val; + } + else if(func_name == "exp") + { + tolerance = 2.f * step_size; + out_val = fixed_point_arithmetic::exp(in_val); + } + else if(func_name == "log") + { + tolerance = 4.f * step_size; + out_val = fixed_point_arithmetic::log(in_val); + } + else if(func_name == "inv_sqrt") + { + tolerance = 5.f * step_size; + out_val = fixed_point_arithmetic::inv_sqrt(in_val); + } + + BOOST_TEST_INFO("input = " << in_val); + BOOST_TEST_INFO("output = " << out_val); + BOOST_TEST_INFO("reference = " << ref_val); + BOOST_TEST_INFO("tolerance = " << tolerance); + BOOST_TEST_WARN((std::abs(static_cast<float>(out_val) - ref_val) <= tolerance)); + + if(std::abs(static_cast<float>(out_val) - ref_val) > tolerance) + { + ++num_mismatches; + } + + // Read next values + inputs_file.read(reinterpret_cast<char *>(&float_val), sizeof(float_val)); + reference_file.read(reinterpret_cast<char *>(&ref_val), sizeof(ref_val)); + } + + BOOST_TEST(num_mismatches == expected_failures); +} + +BOOST_AUTO_TEST_SUITE_END() +BOOST_AUTO_TEST_SUITE_END() +#endif |