[v3,01/11] ipa: helpers: Add Unsigned Q(m, n) helpers
diff mbox series

Message ID 20241107114819.57599-2-dan.scally@ideasonboard.com
State Superseded
Headers show
Series
  • Add Mali-C55 IPA Module and Algorithms
Related show

Commit Message

Dan Scally Nov. 7, 2024, 11:48 a.m. UTC
Add functions to convert a double to or from an unsigned Q(m,n)
format. As the format is unsigned this most resembles the UQ variant
of the TI implementation detailed on Wikipedia:

https://en.wikipedia.org/wiki/Q_(number_format)

Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com>
---
Changes in v3:

	- New patch

 src/ipa/libipa/helpers.cpp | 29 +++++++++++++++++++++++++++++
 src/ipa/libipa/helpers.h   |  2 ++
 2 files changed, 31 insertions(+)

Comments

Jacopo Mondi Nov. 11, 2024, 10:28 a.m. UTC | #1
Hi Dan

On Thu, Nov 07, 2024 at 11:48:09AM +0000, Daniel Scally wrote:
> Add functions to convert a double to or from an unsigned Q(m,n)
> format. As the format is unsigned this most resembles the UQ variant
> of the TI implementation detailed on Wikipedia:
>
> https://en.wikipedia.org/wiki/Q_(number_format)
>
> Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com>
> ---
> Changes in v3:
>
> 	- New patch
>
>  src/ipa/libipa/helpers.cpp | 29 +++++++++++++++++++++++++++++
>  src/ipa/libipa/helpers.h   |  2 ++
>  2 files changed, 31 insertions(+)
>
> diff --git a/src/ipa/libipa/helpers.cpp b/src/ipa/libipa/helpers.cpp
> index 6c038895..908c6e93 100644
> --- a/src/ipa/libipa/helpers.cpp
> +++ b/src/ipa/libipa/helpers.cpp
> @@ -72,6 +72,35 @@ uint32_t estimateCCT(double red, double green, double blue)
>  	return 449 * n * n * n + 3525 * n * n + 6823.3 * n + 5520.33;
>  }
>
> +/**
> + * \brief Convert double to Q(m.n) format
> + * \param[in] value The value to convert

I would mention you expect only positive values

> + * \param[in] m The number of bits used to represent the integer part
> + * \param[in] n The number of bits used to represent the fraction part
> + *
> + * This function converts a double into an unsigned fractional Q format,
> + * clamping at the largest possible value given m and n. As these formats are
> + * unsigned the m figure does not include a sign bit.
> + */
> +unsigned int toUnsignedQFormat(double value, unsigned int m, unsigned int n)

double can be negative, and if a negative is provided it gets
automatically converted to 0. Should this be catch ? If this function
does not support negative input values, I would rather catch this
earlier even by using FATAL as this is programming "error" and
shouldn't be triggered by user input ?

> +{
> +	double maxVal = (std::pow(2, m + n) - 1) / std::pow(2, n);
> +
> +	return std::clamp(value, 0.0, maxVal) * std::pow(2, n);
> +}
> +
> +/**
> + * \brief Convert Q(m.n) formatted number to double
> + * \param[in] value The value to convert
> + * \param[in] n The number of bits used to represent the fraction part
> + *
> + * This function converts an unsigned Q formatted value into a double.
> + */
> +double fromUnsignedQFormat(unsigned int value, unsigned int n)
> +{
> +	return value / std::pow(2, n);
> +}
> +
>  } /* namespace ipa */
>
>  } /* namespace libcamera */
> diff --git a/src/ipa/libipa/helpers.h b/src/ipa/libipa/helpers.h
> index 51c74a36..1f26e768 100644
> --- a/src/ipa/libipa/helpers.h
> +++ b/src/ipa/libipa/helpers.h
> @@ -15,6 +15,8 @@ namespace ipa {
>
>  double rec601LuminanceFromRGB(unsigned int r, unsigned int g, unsigned int b);
>  uint32_t estimateCCT(double red, double green, double blue);
> +unsigned int toUnsignedQFormat(double value, unsigned int m, unsigned int n);
> +double fromUnsignedQFormat(unsigned int value, unsigned int n);
>
>  } /* namespace ipa */
>
> --
> 2.30.2
>
Laurent Pinchart Nov. 12, 2024, 8 a.m. UTC | #2
Hi Dan,

Thank you for the patch.

On Thu, Nov 07, 2024 at 11:48:09AM +0000, Daniel Scally wrote:
> Add functions to convert a double to or from an unsigned Q(m,n)
> format. As the format is unsigned this most resembles the UQ variant
> of the TI implementation detailed on Wikipedia:
> 
> https://en.wikipedia.org/wiki/Q_(number_format)

Time to move src/ipa/rkisp1/utils.{h,cpp} to libipa ? I would then call
it math.h, fixedpoint.h or something similar.

> Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com>
> ---
> Changes in v3:
> 
> 	- New patch
> 
>  src/ipa/libipa/helpers.cpp | 29 +++++++++++++++++++++++++++++
>  src/ipa/libipa/helpers.h   |  2 ++
>  2 files changed, 31 insertions(+)
> 
> diff --git a/src/ipa/libipa/helpers.cpp b/src/ipa/libipa/helpers.cpp
> index 6c038895..908c6e93 100644
> --- a/src/ipa/libipa/helpers.cpp
> +++ b/src/ipa/libipa/helpers.cpp
> @@ -72,6 +72,35 @@ uint32_t estimateCCT(double red, double green, double blue)
>  	return 449 * n * n * n + 3525 * n * n + 6823.3 * n + 5520.33;
>  }
>  
> +/**
> + * \brief Convert double to Q(m.n) format
> + * \param[in] value The value to convert
> + * \param[in] m The number of bits used to represent the integer part
> + * \param[in] n The number of bits used to represent the fraction part
> + *
> + * This function converts a double into an unsigned fractional Q format,
> + * clamping at the largest possible value given m and n. As these formats are
> + * unsigned the m figure does not include a sign bit.
> + */
> +unsigned int toUnsignedQFormat(double value, unsigned int m, unsigned int n)
> +{
> +	double maxVal = (std::pow(2, m + n) - 1) / std::pow(2, n);
> +
> +	return std::clamp(value, 0.0, maxVal) * std::pow(2, n);
> +}
> +
> +/**
> + * \brief Convert Q(m.n) formatted number to double
> + * \param[in] value The value to convert
> + * \param[in] n The number of bits used to represent the fraction part
> + *
> + * This function converts an unsigned Q formatted value into a double.
> + */
> +double fromUnsignedQFormat(unsigned int value, unsigned int n)
> +{
> +	return value / std::pow(2, n);
> +}
> +
>  } /* namespace ipa */
>  
>  } /* namespace libcamera */
> diff --git a/src/ipa/libipa/helpers.h b/src/ipa/libipa/helpers.h
> index 51c74a36..1f26e768 100644
> --- a/src/ipa/libipa/helpers.h
> +++ b/src/ipa/libipa/helpers.h
> @@ -15,6 +15,8 @@ namespace ipa {
>  
>  double rec601LuminanceFromRGB(unsigned int r, unsigned int g, unsigned int b);
>  uint32_t estimateCCT(double red, double green, double blue);
> +unsigned int toUnsignedQFormat(double value, unsigned int m, unsigned int n);
> +double fromUnsignedQFormat(unsigned int value, unsigned int n);
>  
>  } /* namespace ipa */
>

Patch
diff mbox series

diff --git a/src/ipa/libipa/helpers.cpp b/src/ipa/libipa/helpers.cpp
index 6c038895..908c6e93 100644
--- a/src/ipa/libipa/helpers.cpp
+++ b/src/ipa/libipa/helpers.cpp
@@ -72,6 +72,35 @@  uint32_t estimateCCT(double red, double green, double blue)
 	return 449 * n * n * n + 3525 * n * n + 6823.3 * n + 5520.33;
 }
 
+/**
+ * \brief Convert double to Q(m.n) format
+ * \param[in] value The value to convert
+ * \param[in] m The number of bits used to represent the integer part
+ * \param[in] n The number of bits used to represent the fraction part
+ *
+ * This function converts a double into an unsigned fractional Q format,
+ * clamping at the largest possible value given m and n. As these formats are
+ * unsigned the m figure does not include a sign bit.
+ */
+unsigned int toUnsignedQFormat(double value, unsigned int m, unsigned int n)
+{
+	double maxVal = (std::pow(2, m + n) - 1) / std::pow(2, n);
+
+	return std::clamp(value, 0.0, maxVal) * std::pow(2, n);
+}
+
+/**
+ * \brief Convert Q(m.n) formatted number to double
+ * \param[in] value The value to convert
+ * \param[in] n The number of bits used to represent the fraction part
+ *
+ * This function converts an unsigned Q formatted value into a double.
+ */
+double fromUnsignedQFormat(unsigned int value, unsigned int n)
+{
+	return value / std::pow(2, n);
+}
+
 } /* namespace ipa */
 
 } /* namespace libcamera */
diff --git a/src/ipa/libipa/helpers.h b/src/ipa/libipa/helpers.h
index 51c74a36..1f26e768 100644
--- a/src/ipa/libipa/helpers.h
+++ b/src/ipa/libipa/helpers.h
@@ -15,6 +15,8 @@  namespace ipa {
 
 double rec601LuminanceFromRGB(unsigned int r, unsigned int g, unsigned int b);
 uint32_t estimateCCT(double red, double green, double blue);
+unsigned int toUnsignedQFormat(double value, unsigned int m, unsigned int n);
+double fromUnsignedQFormat(unsigned int value, unsigned int n);
 
 } /* namespace ipa */