[PATCH] test: ipa: rkisp1: utils: Fix floating and fixed point conversion test
Stefan Klug
stefan.klug at ideasonboard.com
Wed Jun 5 12:14:30 CEST 2024
Hi Paul,
thanks for the patch.
On Mon, Jun 03, 2024 at 09:53:24PM +0900, Paul Elder wrote:
> There was an issue where using map to store the test cases meant that
> the test for ignoring unused bits was skipped because of clashing keys.
> Fix this by changing the test to an array of tuples.
>
> While at it, reorganize the tests so that it's possible to test only
> reverse conversion, which was the case here to test that multiple fixed
> point numbers (due to unused bits) would result in the same floating
> point number.
>
> While at it, also change the arbitrary floating comparison precision to
> be more precise.
>
> Also fix a missing documentation brief.
>
> Fixes: 9d152e9c6 ipa: rkisp1: Add a helper to convert floating-point to
> fixed-point
> Signed-off-by: Paul Elder <paul.elder at ideasonboard.com>
> ---
> src/ipa/rkisp1/utils.cpp | 1 +
> test/ipa/rkisp1/rkisp1-utils.cpp | 97 +++++++++++++++++++++++---------
> 2 files changed, 70 insertions(+), 28 deletions(-)
>
> diff --git a/src/ipa/rkisp1/utils.cpp b/src/ipa/rkisp1/utils.cpp
> index 960ec64e9..8edcf5bf7 100644
> --- a/src/ipa/rkisp1/utils.cpp
> +++ b/src/ipa/rkisp1/utils.cpp
> @@ -9,6 +9,7 @@
>
> /**
> * \file utils.h
> + * \brief Utility functions for rkisp1
> */
>
> namespace libcamera {
> diff --git a/test/ipa/rkisp1/rkisp1-utils.cpp b/test/ipa/rkisp1/rkisp1-utils.cpp
> index e48f8d362..4757ca069 100644
> --- a/test/ipa/rkisp1/rkisp1-utils.cpp
> +++ b/test/ipa/rkisp1/rkisp1-utils.cpp
> @@ -7,8 +7,8 @@
>
> #include <cmath>
> #include <iostream>
> -#include <map>
> #include <stdint.h>
> +#include <tuple>
>
> #include "../src/ipa/rkisp1/utils.h"
>
> @@ -21,53 +21,94 @@ using namespace ipa::rkisp1;
> class RkISP1UtilsTest : public Test
> {
> protected:
> - template<unsigned int IntPrec, unsigned FracPrec, typename T>
> - int testSingleFixedPoint(double input, T expected)
> + /* R for real, I for integer */
> + template<unsigned int IntPrec, unsigned FracPrec, typename I, typename R>
> + int testFixedToFloat(I input, R expected, R *output = nullptr)
> {
> - T ret = utils::floatingToFixedPoint<IntPrec, FracPrec, T>(input);
> - if (ret != expected) {
> - cerr << "Expected " << input << " to convert to "
> - << expected << ", got " << ret << std::endl;
> + R out = utils::fixedToFloatingPoint<IntPrec, FracPrec, R>(input);
> + if (output)
> + *output = out;
> + R prec = 1.0 / (1 << FracPrec);
> + if (std::abs(out - expected) > prec) {
> + cerr << "Reverse conversion expected " << input
> + << " to convert to " << expected
> + << ", got " << out << std::endl;
> return TestFail;
> }
>
> - /*
> - * The precision check is fairly arbitrary but is based on what
> - * the rkisp1 is capable of in the crosstalk module.
> - */
> - double f = utils::fixedToFloatingPoint<IntPrec, FracPrec, double>(ret);
> - if (std::abs(f - input) > 0.005) {
> - cerr << "Reverse conversion expected " << ret
> - << " to convert to " << input
> - << ", got " << f << std::endl;
> + return TestPass;
> + }
> +
> + /* R for real, I for integer */
> + template<unsigned int IntPrec, unsigned FracPrec, typename R, typename I>
> + int testFloatToFixed(R input, I expected, I *output = nullptr)
> + {
> + I out = utils::floatingToFixedPoint<IntPrec, FracPrec, I>(input);
> + if (output)
> + *output = out;
> + if (out != expected) {
> + cerr << "Expected " << input << " to convert to "
> + << expected << ", got " << out << std::endl;
> return TestFail;
> }
>
> return TestPass;
> }
>
> + /* R for real, I for integer */
> + template<unsigned int IntPrec, unsigned FracPrec, typename R, typename I>
> + int testFullConversion(R input, I expected)
> + {
> + I outInt;
> + R outReal;
> + int status;
> +
> + status = testFloatToFixed<IntPrec, FracPrec, R, I>(input, expected, &outInt);
> + if (status != TestPass)
> + return status;
> +
> + status = testFixedToFloat<IntPrec, FracPrec, I, R>(outInt, input, &outReal);
> + if (status != TestPass)
> + return status;
> +
> + return TestPass;
> + }
> +
> +
> int testFixedPoint()
> {
> /*
> * The second 7.992 test is to test that unused bits don't
> * affect the result.
> + *
> + * Third parameter is for testing forward, fourth parameter is
> + * for testing reverse.
> */
> - std::map<double, uint16_t> testCases = {
> - { 7.992, 0x3ff },
> - { 7.992, 0xbff },
> - { 0.2, 0x01a },
> - { -0.2, 0x7e6 },
> - { -0.8, 0x79a },
> - { -0.4, 0x7cd },
> - { -1.4, 0x74d },
> - { -8, 0x400 },
> - { 0, 0 },
> + static const std::tuple<double, uint16_t, bool, bool> testCases[] = {
> + { 7.992, 0x3ff, true, true },
> + { 7.992, 0xbff, false, true },
> + { 0.2, 0x01a, true, true },
> + { -0.2, 0x7e6, true, true },
> + { -0.8, 0x79a, true, true },
> + { -0.4, 0x7cd, true, true },
> + { -1.4, 0x74d, true, true },
> + { -8, 0x400, true, true },
> + { 0, 0, true, true },
> };
>
> int ret;
> for (const auto &testCase : testCases) {
> - ret = testSingleFixedPoint<4, 7, uint16_t>(testCase.first,
> - testCase.second);
> + double floating;
> + uint16_t fixed;
> + bool forward, backward;
> + std::tie(floating, fixed, forward, backward) = testCase;
> + if (forward && backward)
> + ret = testFullConversion<4, 7, double, uint16_t>(floating, fixed);
> + else if (forward)
> + ret = testFloatToFixed<4, 7, double, uint16_t>(floating, fixed);
> + else if (backward)
> + ret = testFixedToFloat<4, 7, uint16_t, double>(fixed, floating);
> +
This is quite involved for only one single exception. What about keeping
the old loop for all "standard" cases and adding a
/* special case with a superfluous one in the unused bits */
ret = testFixedToFloat<4, 7, uint16_t, double>(0xbff, 7.992);
if (ret != TestPass)
return ret;
below the loop?
Do as you like.
Reviewed-by: Stefan Klug <stefan.klug at ideasonboard.com>
Cheers,
Stefan
> if (ret != TestPass)
> return ret;
> }
> --
> 2.39.2
>
More information about the libcamera-devel
mailing list