[PATCH] libcamera: utils: Add a helper to convert floating-point to fixed-point
Stefan Klug
stefan.klug at ideasonboard.com
Mon Apr 15 12:03:38 CEST 2024
Hi Paul,
thank you for the patch.
On Mon, Apr 15, 2024 at 06:00:23PM +0900, Paul Elder wrote:
> On Wed, Mar 27, 2024 at 05:57:00PM +0900, Paul Elder wrote:
> > Add a helper function to convert floating-point numbers to fixed-point
> > numbers.
> >
> > Signed-off-by: Paul Elder <paul.elder at ideasonboard.com>
> > ---
> > I originally needed this for rkisp1 crosstalk but then I realized it's
> > more efficient to just have the tuning tool output fixed-point and have
> > the IPA simply copy those values instead of calculating them on-the-fly.
> > Still, I made this helper so if people think it's useful...
>
> Turns out we do need it now! So that we can have human-readable (or
> make-sensable) CCMs in the tuning file for rkisp1.
>
>
> Paul
>
> > ---
> > include/libcamera/base/utils.h | 27 +++++++++++++++++++++++++++
> > src/libcamera/base/utils.cpp | 10 ++++++++++
> > 2 files changed, 37 insertions(+)
> >
> > diff --git a/include/libcamera/base/utils.h b/include/libcamera/base/utils.h
> > index 37d9af60..ab421cc7 100644
> > --- a/include/libcamera/base/utils.h
> > +++ b/include/libcamera/base/utils.h
> > @@ -369,6 +369,33 @@ decltype(auto) abs_diff(const T &a, const T &b)
> >
> > double strtod(const char *__restrict nptr, char **__restrict endptr);
> >
> > +#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(I + F <= sizeof(R) * 8);
> > +
> > + R integer = static_cast<R>(number);
> > + T fractional = number - integer;
> > +
> > + R mask = (1 << I) - 1;
> > + R whole = (integer >= 0 ? integer : ~integer + 1) & mask;
> > +
> > + R frac = 0;
> > + for (unsigned int i = 0; i < F; i++) {
> > + fractional *= 2;
> > + frac <<= 1;
> > + frac |= (static_cast<R>(fractional) & 0x1);
> > + }
> > +
> > + return (whole << F) | frac;
> > +}
To be honest I don't really get it. Why is that complexity needed? I
didn't try it out, but my naive appoach would be:
return static_cast<R>(std::round( number * (1 << F)))
Maybe I'm missing something here.
As this ends up in the public includes, we should add a inverse function
to convert fixed point to floating.
e.g.
return (static_cast<double>input / static_cast<double>(1 << F));
I believe We should also add a simple testcase to ensure this doesn't
break and produces the correct values.
Are there commonly used fixed point formats? Maybe it would be helpful
to add typedefs for these formats. Something like
float2Fixed_11_5()
as retyping these template params over and over might be error prone.
(Maybe we could also leave that to the user of the function)
Best regards,
Stefan
> > +
> > } /* namespace utils */
> >
> > #ifndef __DOXYGEN__
> > diff --git a/src/libcamera/base/utils.cpp b/src/libcamera/base/utils.cpp
> > index 3b73b442..38bee317 100644
> > --- a/src/libcamera/base/utils.cpp
> > +++ b/src/libcamera/base/utils.cpp
> > @@ -521,6 +521,16 @@ double strtod(const char *__restrict nptr, char **__restrict endptr)
> > #endif
> > }
> >
> > +/**
> > + * \fn R floatingToFixedPoint(T number)
> > + * \brief Convert a floating point number to a fixed-point representation
> > + * \tparam I Bit width of the integer part of the fixed-point
> > + * \tparam F Bit width of the fractional part of the fixed-point
> > + * \tparam R Return type of the fixed-point representation
> > + * \tparam T Input type of the floating point representation
> > + * \return The converted value
> > + */
> > +
> > } /* namespace utils */
> >
> > #ifndef __DOXYGEN__
> > --
> > 2.39.2
> >
More information about the libcamera-devel
mailing list