[v4,10/21] ipa: libipa: fixedpoint: Provide a ScaledFixedPoint type
diff mbox series

Message ID 20251114005428.90024-11-kieran.bingham@ideasonboard.com
State New
Headers show
Series
  • libipa: Introduce a Quantized type
Related show

Commit Message

Kieran Bingham Nov. 14, 2025, 12:54 a.m. UTC
Extend the new Quantized FixedPoint capabilities with a ScaledFixedPointQTraits
which takes an existing Quantized type and scales the conversion by the
given Scale template parameter.

This can be useful to represent fixed point values which represent
a linear range with a different scale to the underlying float
or integral type.

Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>

---

v3:
- Rename quantized_type to QuantizedType

v4:
- Fix copydoc for ScaledFixedPointQTraits::toFloat

 src/ipa/libipa/fixedpoint.cpp | 59 +++++++++++++++++++++++++++++++++++
 src/ipa/libipa/fixedpoint.h   | 24 ++++++++++++++
 2 files changed, 83 insertions(+)

Comments

Barnabás Pőcze Nov. 14, 2025, 6:08 p.m. UTC | #1
2025. 11. 14. 1:54 keltezéssel, Kieran Bingham írta:
> Extend the new Quantized FixedPoint capabilities with a ScaledFixedPointQTraits
> which takes an existing Quantized type and scales the conversion by the
> given Scale template parameter.
> 
> This can be useful to represent fixed point values which represent
> a linear range with a different scale to the underlying float
> or integral type.
> 
> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
> 
> ---
> 
> v3:
> - Rename quantized_type to QuantizedType
> 
> v4:
> - Fix copydoc for ScaledFixedPointQTraits::toFloat
> 
>   src/ipa/libipa/fixedpoint.cpp | 59 +++++++++++++++++++++++++++++++++++
>   src/ipa/libipa/fixedpoint.h   | 24 ++++++++++++++
>   2 files changed, 83 insertions(+)
> 
> diff --git a/src/ipa/libipa/fixedpoint.cpp b/src/ipa/libipa/fixedpoint.cpp
> index 03053668ed79..97cdd9b3f7aa 100644
> --- a/src/ipa/libipa/fixedpoint.cpp
> +++ b/src/ipa/libipa/fixedpoint.cpp
> @@ -185,6 +185,65 @@ namespace ipa {
>    * Represents values in the range [0.0, 4095.9375] with a resolution of 1/16.
>    */
>   
> +/**
> + * \struct ScaledFixedPointQTraits
> + * \brief Wrap a FixedPointQTraits with a linear scaling factor
> + *
> + * This trait extends an existing fixed-point quantisation policy
> + * by applying an additional multiplicative scale between the
> + * floating-point and quantised domains.
> + *
> + * \tparam Q The base fixed-point traits type
> + * \tparam Scale The scale factor applied to the floating-point domain
> + */
> +
> +/**
> + * \typedef ScaledFixedPointQTraits::QuantizedType
> + * \copydoc FixedPointQTraits::QuantizedType
> + */
> +
> +/**
> + * \var ScaledFixedPointQTraits::scale
> + * \brief The constant scaling factor applied to the floating-point domain
> + *
> + * Floating-point inputs are divided by this factor before quantisation,
> + * and multiplied by it after dequantisation.
> + */
> +
> +/**
> + * \var ScaledFixedPointQTraits::qmin
> + * \copydoc FixedPointQTraits::qmin
> + */
> +
> +/**
> + * \var ScaledFixedPointQTraits::qmax
> + * \copydoc FixedPointQTraits::qmax
> + */
> +
> +/**
> + * \var ScaledFixedPointQTraits::min
> + * \copydoc FixedPointQTraits::min
> + */
> +
> +/**
> + * \var ScaledFixedPointQTraits::max
> + * \copydoc FixedPointQTraits::max
> + */
> +
> +/**
> + * \fn ScaledFixedPointQTraits::fromFloat(float v)
> + * \copydoc FixedPointQTraits::fromFloat(float v)
> + *
> + * The input value \a v is divided by the scaling factor before conversion.
> + */
> +
> +/**
> + * \fn ScaledFixedPointQTraits::toFloat(QuantizedType q)
> + * \copydoc FixedPointQTraits::toFloat()
> + *
> + * The output value is multiplied by the scaling factor after conversion.
> + */
> +
>   } /* namespace ipa */
>   
>   } /* namespace libcamera */
> diff --git a/src/ipa/libipa/fixedpoint.h b/src/ipa/libipa/fixedpoint.h
> index 05dd97e64f40..1e984350111c 100644
> --- a/src/ipa/libipa/fixedpoint.h
> +++ b/src/ipa/libipa/fixedpoint.h
> @@ -113,6 +113,30 @@ using UQ5_8 = Quantized<FixedPointQTraits<5, 8, uint16_t>>;
>   using Q12_4 = Quantized<FixedPointQTraits<12, 4, int16_t>>;
>   using UQ12_4 = Quantized<FixedPointQTraits<12, 4, uint16_t>>;
>   
> +template<typename Q, int Scale>
> +struct ScaledFixedPointQTraits {

I believe we could name it just "ScaledQTraits" since there is nothing here
that inherently depends on `FixedQTraits`


> +	using QuantizedType = typename Q::QuantizedType;
> +
> +	static constexpr float scale = static_cast<float>(Scale);

I would add `static_assert(Scale > 0)`. But otherwise it looks good to me.
Having a float as a template parameter is sadly a C++20 feature.

Reviewed-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>


> +
> +	/* Re-expose base limits, adjusted by the scaling factor */
> +	static constexpr QuantizedType qmin = Q::qmin;
> +	static constexpr QuantizedType qmax = Q::qmax;
> +	static constexpr float min = Q::min * scale;
> +	static constexpr float max = Q::max * scale;
> +
> +	static QuantizedType fromFloat(float v)
> +	{
> +		v = std::clamp(v, min, max);
> +		return Q::fromFloat(v / scale);
> +	}
> +
> +	static float toFloat(QuantizedType q)
> +	{
> +		return Q::toFloat(q) * scale;
> +	}
> +};
> +
>   } /* namespace ipa */
>   
>   } /* namespace libcamera */
Kieran Bingham Nov. 14, 2025, 6:52 p.m. UTC | #2
Quoting Barnabás Pőcze (2025-11-14 18:08:53)
> 2025. 11. 14. 1:54 keltezéssel, Kieran Bingham írta:
> > Extend the new Quantized FixedPoint capabilities with a ScaledFixedPointQTraits
> > which takes an existing Quantized type and scales the conversion by the
> > given Scale template parameter.
> > 
> > This can be useful to represent fixed point values which represent
> > a linear range with a different scale to the underlying float
> > or integral type.
> > 
> > Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
> > 
> > ---
> > 
> > v3:
> > - Rename quantized_type to QuantizedType
> > 
> > v4:
> > - Fix copydoc for ScaledFixedPointQTraits::toFloat
> > 
> >   src/ipa/libipa/fixedpoint.cpp | 59 +++++++++++++++++++++++++++++++++++
> >   src/ipa/libipa/fixedpoint.h   | 24 ++++++++++++++
> >   2 files changed, 83 insertions(+)
> > 
> > diff --git a/src/ipa/libipa/fixedpoint.cpp b/src/ipa/libipa/fixedpoint.cpp
> > index 03053668ed79..97cdd9b3f7aa 100644
> > --- a/src/ipa/libipa/fixedpoint.cpp
> > +++ b/src/ipa/libipa/fixedpoint.cpp
> > @@ -185,6 +185,65 @@ namespace ipa {
> >    * Represents values in the range [0.0, 4095.9375] with a resolution of 1/16.
> >    */
> >   
> > +/**
> > + * \struct ScaledFixedPointQTraits
> > + * \brief Wrap a FixedPointQTraits with a linear scaling factor
> > + *
> > + * This trait extends an existing fixed-point quantisation policy
> > + * by applying an additional multiplicative scale between the
> > + * floating-point and quantised domains.
> > + *
> > + * \tparam Q The base fixed-point traits type
> > + * \tparam Scale The scale factor applied to the floating-point domain
> > + */
> > +
> > +/**
> > + * \typedef ScaledFixedPointQTraits::QuantizedType
> > + * \copydoc FixedPointQTraits::QuantizedType
> > + */
> > +
> > +/**
> > + * \var ScaledFixedPointQTraits::scale
> > + * \brief The constant scaling factor applied to the floating-point domain
> > + *
> > + * Floating-point inputs are divided by this factor before quantisation,
> > + * and multiplied by it after dequantisation.
> > + */
> > +
> > +/**
> > + * \var ScaledFixedPointQTraits::qmin
> > + * \copydoc FixedPointQTraits::qmin
> > + */
> > +
> > +/**
> > + * \var ScaledFixedPointQTraits::qmax
> > + * \copydoc FixedPointQTraits::qmax
> > + */
> > +
> > +/**
> > + * \var ScaledFixedPointQTraits::min
> > + * \copydoc FixedPointQTraits::min
> > + */
> > +
> > +/**
> > + * \var ScaledFixedPointQTraits::max
> > + * \copydoc FixedPointQTraits::max
> > + */
> > +
> > +/**
> > + * \fn ScaledFixedPointQTraits::fromFloat(float v)
> > + * \copydoc FixedPointQTraits::fromFloat(float v)
> > + *
> > + * The input value \a v is divided by the scaling factor before conversion.
> > + */
> > +
> > +/**
> > + * \fn ScaledFixedPointQTraits::toFloat(QuantizedType q)
> > + * \copydoc FixedPointQTraits::toFloat()
> > + *
> > + * The output value is multiplied by the scaling factor after conversion.
> > + */
> > +
> >   } /* namespace ipa */
> >   
> >   } /* namespace libcamera */
> > diff --git a/src/ipa/libipa/fixedpoint.h b/src/ipa/libipa/fixedpoint.h
> > index 05dd97e64f40..1e984350111c 100644
> > --- a/src/ipa/libipa/fixedpoint.h
> > +++ b/src/ipa/libipa/fixedpoint.h
> > @@ -113,6 +113,30 @@ using UQ5_8 = Quantized<FixedPointQTraits<5, 8, uint16_t>>;
> >   using Q12_4 = Quantized<FixedPointQTraits<12, 4, int16_t>>;
> >   using UQ12_4 = Quantized<FixedPointQTraits<12, 4, uint16_t>>;
> >   
> > +template<typename Q, int Scale>
> > +struct ScaledFixedPointQTraits {
> 
> I believe we could name it just "ScaledQTraits" since there is nothing here
> that inherently depends on `FixedQTraits`

Good point.

> > +     using QuantizedType = typename Q::QuantizedType;
> > +
> > +     static constexpr float scale = static_cast<float>(Scale);
> 
> I would add `static_assert(Scale > 0)`. But otherwise it looks good to me.
> Having a float as a template parameter is sadly a C++20 feature.

Indeed, I think I started as an int and hit the compile failures.

I wonder when we will move to C++20 then ;-)

> 
> Reviewed-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>

Thanks


> 
> 
> > +
> > +     /* Re-expose base limits, adjusted by the scaling factor */
> > +     static constexpr QuantizedType qmin = Q::qmin;
> > +     static constexpr QuantizedType qmax = Q::qmax;
> > +     static constexpr float min = Q::min * scale;
> > +     static constexpr float max = Q::max * scale;
> > +
> > +     static QuantizedType fromFloat(float v)
> > +     {
> > +             v = std::clamp(v, min, max);
> > +             return Q::fromFloat(v / scale);
> > +     }
> > +
> > +     static float toFloat(QuantizedType q)
> > +     {
> > +             return Q::toFloat(q) * scale;
> > +     }
> > +};
> > +
> >   } /* namespace ipa */
> >   
> >   } /* namespace libcamera */
>
Isaac Scott Nov. 18, 2025, 12:39 p.m. UTC | #3
Hi Kieran,

Thank you for the patch!

Reviewed-by: Isaac Scott <isaac.scott@ideasonboard.com>

Quoting Kieran Bingham (2025-11-14 00:54:14)
> Extend the new Quantized FixedPoint capabilities with a ScaledFixedPointQTraits
> which takes an existing Quantized type and scales the conversion by the
> given Scale template parameter.
> 
> This can be useful to represent fixed point values which represent
> a linear range with a different scale to the underlying float
> or integral type.
> 
> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
> 
> ---
> 
> v3:
> - Rename quantized_type to QuantizedType
> 
> v4:
> - Fix copydoc for ScaledFixedPointQTraits::toFloat
> 
>  src/ipa/libipa/fixedpoint.cpp | 59 +++++++++++++++++++++++++++++++++++
>  src/ipa/libipa/fixedpoint.h   | 24 ++++++++++++++
>  2 files changed, 83 insertions(+)
> 
> diff --git a/src/ipa/libipa/fixedpoint.cpp b/src/ipa/libipa/fixedpoint.cpp
> index 03053668ed79..97cdd9b3f7aa 100644
> --- a/src/ipa/libipa/fixedpoint.cpp
> +++ b/src/ipa/libipa/fixedpoint.cpp
> @@ -185,6 +185,65 @@ namespace ipa {
>   * Represents values in the range [0.0, 4095.9375] with a resolution of 1/16.
>   */
>  
> +/**
> + * \struct ScaledFixedPointQTraits
> + * \brief Wrap a FixedPointQTraits with a linear scaling factor
> + *
> + * This trait extends an existing fixed-point quantisation policy
> + * by applying an additional multiplicative scale between the
> + * floating-point and quantised domains.
> + *
> + * \tparam Q The base fixed-point traits type
> + * \tparam Scale The scale factor applied to the floating-point domain
> + */
> +
> +/**
> + * \typedef ScaledFixedPointQTraits::QuantizedType
> + * \copydoc FixedPointQTraits::QuantizedType
> + */
> +
> +/**
> + * \var ScaledFixedPointQTraits::scale
> + * \brief The constant scaling factor applied to the floating-point domain
> + *
> + * Floating-point inputs are divided by this factor before quantisation,
> + * and multiplied by it after dequantisation.
> + */
> +
> +/**
> + * \var ScaledFixedPointQTraits::qmin
> + * \copydoc FixedPointQTraits::qmin
> + */
> +
> +/**
> + * \var ScaledFixedPointQTraits::qmax
> + * \copydoc FixedPointQTraits::qmax
> + */
> +
> +/**
> + * \var ScaledFixedPointQTraits::min
> + * \copydoc FixedPointQTraits::min
> + */
> +
> +/**
> + * \var ScaledFixedPointQTraits::max
> + * \copydoc FixedPointQTraits::max
> + */
> +
> +/**
> + * \fn ScaledFixedPointQTraits::fromFloat(float v)
> + * \copydoc FixedPointQTraits::fromFloat(float v)
> + *
> + * The input value \a v is divided by the scaling factor before conversion.
> + */
> +
> +/**
> + * \fn ScaledFixedPointQTraits::toFloat(QuantizedType q)
> + * \copydoc FixedPointQTraits::toFloat()
> + *
> + * The output value is multiplied by the scaling factor after conversion.
> + */
> +
>  } /* namespace ipa */
>  
>  } /* namespace libcamera */
> diff --git a/src/ipa/libipa/fixedpoint.h b/src/ipa/libipa/fixedpoint.h
> index 05dd97e64f40..1e984350111c 100644
> --- a/src/ipa/libipa/fixedpoint.h
> +++ b/src/ipa/libipa/fixedpoint.h
> @@ -113,6 +113,30 @@ using UQ5_8 = Quantized<FixedPointQTraits<5, 8, uint16_t>>;
>  using Q12_4 = Quantized<FixedPointQTraits<12, 4, int16_t>>;
>  using UQ12_4 = Quantized<FixedPointQTraits<12, 4, uint16_t>>;
>  
> +template<typename Q, int Scale>
> +struct ScaledFixedPointQTraits {
> +       using QuantizedType = typename Q::QuantizedType;
> +
> +       static constexpr float scale = static_cast<float>(Scale);
> +
> +       /* Re-expose base limits, adjusted by the scaling factor */
> +       static constexpr QuantizedType qmin = Q::qmin;
> +       static constexpr QuantizedType qmax = Q::qmax;
> +       static constexpr float min = Q::min * scale;
> +       static constexpr float max = Q::max * scale;
> +
> +       static QuantizedType fromFloat(float v)
> +       {
> +               v = std::clamp(v, min, max);
> +               return Q::fromFloat(v / scale);
> +       }
> +
> +       static float toFloat(QuantizedType q)
> +       {
> +               return Q::toFloat(q) * scale;
> +       }
> +};
> +
>  } /* namespace ipa */
>  
>  } /* namespace libcamera */
> -- 
> 2.51.1
>

Patch
diff mbox series

diff --git a/src/ipa/libipa/fixedpoint.cpp b/src/ipa/libipa/fixedpoint.cpp
index 03053668ed79..97cdd9b3f7aa 100644
--- a/src/ipa/libipa/fixedpoint.cpp
+++ b/src/ipa/libipa/fixedpoint.cpp
@@ -185,6 +185,65 @@  namespace ipa {
  * Represents values in the range [0.0, 4095.9375] with a resolution of 1/16.
  */
 
+/**
+ * \struct ScaledFixedPointQTraits
+ * \brief Wrap a FixedPointQTraits with a linear scaling factor
+ *
+ * This trait extends an existing fixed-point quantisation policy
+ * by applying an additional multiplicative scale between the
+ * floating-point and quantised domains.
+ *
+ * \tparam Q The base fixed-point traits type
+ * \tparam Scale The scale factor applied to the floating-point domain
+ */
+
+/**
+ * \typedef ScaledFixedPointQTraits::QuantizedType
+ * \copydoc FixedPointQTraits::QuantizedType
+ */
+
+/**
+ * \var ScaledFixedPointQTraits::scale
+ * \brief The constant scaling factor applied to the floating-point domain
+ *
+ * Floating-point inputs are divided by this factor before quantisation,
+ * and multiplied by it after dequantisation.
+ */
+
+/**
+ * \var ScaledFixedPointQTraits::qmin
+ * \copydoc FixedPointQTraits::qmin
+ */
+
+/**
+ * \var ScaledFixedPointQTraits::qmax
+ * \copydoc FixedPointQTraits::qmax
+ */
+
+/**
+ * \var ScaledFixedPointQTraits::min
+ * \copydoc FixedPointQTraits::min
+ */
+
+/**
+ * \var ScaledFixedPointQTraits::max
+ * \copydoc FixedPointQTraits::max
+ */
+
+/**
+ * \fn ScaledFixedPointQTraits::fromFloat(float v)
+ * \copydoc FixedPointQTraits::fromFloat(float v)
+ *
+ * The input value \a v is divided by the scaling factor before conversion.
+ */
+
+/**
+ * \fn ScaledFixedPointQTraits::toFloat(QuantizedType q)
+ * \copydoc FixedPointQTraits::toFloat()
+ *
+ * The output value is multiplied by the scaling factor after conversion.
+ */
+
 } /* namespace ipa */
 
 } /* namespace libcamera */
diff --git a/src/ipa/libipa/fixedpoint.h b/src/ipa/libipa/fixedpoint.h
index 05dd97e64f40..1e984350111c 100644
--- a/src/ipa/libipa/fixedpoint.h
+++ b/src/ipa/libipa/fixedpoint.h
@@ -113,6 +113,30 @@  using UQ5_8 = Quantized<FixedPointQTraits<5, 8, uint16_t>>;
 using Q12_4 = Quantized<FixedPointQTraits<12, 4, int16_t>>;
 using UQ12_4 = Quantized<FixedPointQTraits<12, 4, uint16_t>>;
 
+template<typename Q, int Scale>
+struct ScaledFixedPointQTraits {
+	using QuantizedType = typename Q::QuantizedType;
+
+	static constexpr float scale = static_cast<float>(Scale);
+
+	/* Re-expose base limits, adjusted by the scaling factor */
+	static constexpr QuantizedType qmin = Q::qmin;
+	static constexpr QuantizedType qmax = Q::qmax;
+	static constexpr float min = Q::min * scale;
+	static constexpr float max = Q::max * scale;
+
+	static QuantizedType fromFloat(float v)
+	{
+		v = std::clamp(v, min, max);
+		return Q::fromFloat(v / scale);
+	}
+
+	static float toFloat(QuantizedType q)
+	{
+		return Q::toFloat(q) * scale;
+	}
+};
+
 } /* namespace ipa */
 
 } /* namespace libcamera */