diff options
author | Paul Elder <paul.elder@ideasonboard.com> | 2024-03-27 17:54:49 +0900 |
---|---|---|
committer | Paul Elder <paul.elder@ideasonboard.com> | 2024-05-31 17:12:48 +0900 |
commit | 9d152e9c66c1094a482e704d95965078a0fe2cf3 (patch) | |
tree | b2fb40ead282da27a96586ef318a2482225282dc /src/ipa/rkisp1/utils.h | |
parent | c79fa47aac9b38865dab5e9f29030903bf460c46 (diff) |
ipa: rkisp1: Add a helper to convert floating-point to fixed-point
Add helper functions for converting between floating point and fixed
point numbers. Also add tests for them.
Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>
Reviewed-by: Stefan Klug <stefan.klug@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Diffstat (limited to 'src/ipa/rkisp1/utils.h')
-rw-r--r-- | src/ipa/rkisp1/utils.h | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/src/ipa/rkisp1/utils.h b/src/ipa/rkisp1/utils.h new file mode 100644 index 00000000..450f2244 --- /dev/null +++ b/src/ipa/rkisp1/utils.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Paul Elder <paul.elder@ideasonboard.com> + * + * Miscellaneous utility functions specific to rkisp1 + */ + +#pragma once + +#include <cmath> +#include <limits> +#include <type_traits> + +namespace libcamera { + +namespace ipa::rkisp1::utils { + +#ifndef __DOXYGEN__ +template<unsigned int I, unsigned int F, typename R, typename T, + std::enable_if_t<std::is_integral_v<R> && + std::is_floating_point_v<T>> * = nullptr> +#else +template<unsigned int I, unsigned int F, typename R, typename T> +#endif +constexpr R floatingToFixedPoint(T number) +{ + static_assert(sizeof(int) >= sizeof(R)); + static_assert(I + F <= sizeof(R) * 8); + + /* + * The intermediate cast to int is needed on arm platforms to properly + * cast negative values. See + * https://embeddeduse.com/2013/08/25/casting-a-negative-float-to-an-unsigned-int/ + */ + R mask = (1 << (F + I)) - 1; + R frac = static_cast<R>(static_cast<int>(std::round(number * (1 << F)))) & mask; + + return frac; +} + +#ifndef __DOXYGEN__ +template<unsigned int I, unsigned int F, typename R, typename T, + std::enable_if_t<std::is_floating_point_v<R> && + std::is_integral_v<T>> * = nullptr> +#else +template<unsigned int I, unsigned int F, typename R, typename T> +#endif +constexpr R fixedToFloatingPoint(T number) +{ + static_assert(sizeof(int) >= sizeof(T)); + static_assert(I + F <= sizeof(T) * 8); + + /* + * Recreate the upper bits in case of a negative number by shifting the sign + * bit from the fixed point to the first bit of the unsigned and then right shifting + * by the same amount which keeps the sign bit in place. + * This can be optimized by the compiler quite well. + */ + int remaining_bits = sizeof(int) * 8 - (I + F); + int t = static_cast<int>(static_cast<unsigned>(number) << remaining_bits) >> remaining_bits; + return static_cast<R>(t) / static_cast<R>(1 << F); +} + +} /* namespace ipa::rkisp1::utils */ + +} /* namespace libcamera */ |