[libcamera-devel,1/2] libcamera: base: utils: Add abs_diff() utility function
diff mbox series

Message ID 20211206152644.4863-2-laurent.pinchart@ideasonboard.com
State Accepted
Commit f413f944d789911c9ded831ac45a7674c129ceba
Delegated to: Laurent Pinchart
Headers show
Series
  • libcamera: Introduce utils::abs_diff()
Related show

Commit Message

Laurent Pinchart Dec. 6, 2021, 3:26 p.m. UTC
The abs_diff() function computes the absolute difference of two
elements. This may seem trivial at first, but can lead to unexpected
results when operating on unsigned operands. A common implementation
of the absolute difference of two unsigned int (used through the
libcamera code base) is

	std::abs(static_cast<int>(a - b))

but doesn't return the expected result when either a or b is larger than
UINT_MAX / 2 due to overflows. The abs_diff() function offers a safe
alternative.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 include/libcamera/base/utils.h |  9 +++++++++
 src/libcamera/base/utils.cpp   | 17 +++++++++++++++++
 2 files changed, 26 insertions(+)

Comments

Kieran Bingham Dec. 6, 2021, 3:47 p.m. UTC | #1
Quoting Laurent Pinchart (2021-12-06 15:26:43)
> The abs_diff() function computes the absolute difference of two
> elements. This may seem trivial at first, but can lead to unexpected
> results when operating on unsigned operands. A common implementation
> of the absolute difference of two unsigned int (used through the
> libcamera code base) is
> 
>         std::abs(static_cast<int>(a - b))
> 
> but doesn't return the expected result when either a or b is larger than
> UINT_MAX / 2 due to overflows. The abs_diff() function offers a safe
> alternative.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  include/libcamera/base/utils.h |  9 +++++++++
>  src/libcamera/base/utils.cpp   | 17 +++++++++++++++++
>  2 files changed, 26 insertions(+)
> 
> diff --git a/include/libcamera/base/utils.h b/include/libcamera/base/utils.h
> index 3a803176693d..9ab18101cf27 100644
> --- a/include/libcamera/base/utils.h
> +++ b/include/libcamera/base/utils.h
> @@ -346,6 +346,15 @@ public:
>         }
>  };
>  
> +template<typename T>
> +decltype(auto) abs_diff(const T &a, const T &b)
> +{
> +       if (a < b)
> +               return b - a;
> +       else
> +               return a - b;
> +}
> +
>  } /* namespace utils */
>  
>  #ifndef __DOXYGEN__
> diff --git a/src/libcamera/base/utils.cpp b/src/libcamera/base/utils.cpp
> index 45b92b670837..8cf8a5b2c104 100644
> --- a/src/libcamera/base/utils.cpp
> +++ b/src/libcamera/base/utils.cpp
> @@ -437,6 +437,23 @@ std::string toAscii(const std::string &str)
>   * \return True if \a Duration is a non-zero time value, False otherwise
>   */
>  
> +/**
> + * \fn abs_diff(const T& a, const T& b)
> + * \brief Calculates the absolute value of the difference between two elements
> + * \param[in] a The first element
> + * \param[in] b The second element
> + *
> + * This function calculates the absolute value of the difference between two
> + * elements of the same type, in such a way that a negative value will never
> + * occur during the calculation.
> + *
> + * This is inspired by the std::abs_diff() candidate proposed in N4318
> + * (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4318.pdf).

It's unfortunate that this proposal hasn't progressed.
I'm happy to see an implementation in our utils though.

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

> + *
> + * \return The absolute value of the difference of the two parameters \a a and
> + * \a b
> + */
> +
>  } /* namespace utils */
>  
>  #ifndef __DOXYGEN__
> -- 
> Regards,
> 
> Laurent Pinchart
>
Umang Jain Dec. 7, 2021, 4:08 p.m. UTC | #2
Hi Laurent,

Thanks for the patch

On 12/6/21 8:56 PM, Laurent Pinchart wrote:
> The abs_diff() function computes the absolute difference of two
> elements. This may seem trivial at first, but can lead to unexpected
> results when operating on unsigned operands. A common implementation
> of the absolute difference of two unsigned int (used through the
> libcamera code base) is
>
> 	std::abs(static_cast<int>(a - b))
>
> but doesn't return the expected result when either a or b is larger than
> UINT_MAX / 2 due to overflows. The abs_diff() function offers a safe
> alternative.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>


Reviewed-by: Umang Jain <umang.jain@ideasonboard.com>

> ---
>   include/libcamera/base/utils.h |  9 +++++++++
>   src/libcamera/base/utils.cpp   | 17 +++++++++++++++++
>   2 files changed, 26 insertions(+)
>
> diff --git a/include/libcamera/base/utils.h b/include/libcamera/base/utils.h
> index 3a803176693d..9ab18101cf27 100644
> --- a/include/libcamera/base/utils.h
> +++ b/include/libcamera/base/utils.h
> @@ -346,6 +346,15 @@ public:
>   	}
>   };
>   
> +template<typename T>
> +decltype(auto) abs_diff(const T &a, const T &b)
> +{
> +	if (a < b)
> +		return b - a;
> +	else
> +		return a - b;
> +}
> +
>   } /* namespace utils */
>   
>   #ifndef __DOXYGEN__
> diff --git a/src/libcamera/base/utils.cpp b/src/libcamera/base/utils.cpp
> index 45b92b670837..8cf8a5b2c104 100644
> --- a/src/libcamera/base/utils.cpp
> +++ b/src/libcamera/base/utils.cpp
> @@ -437,6 +437,23 @@ std::string toAscii(const std::string &str)
>    * \return True if \a Duration is a non-zero time value, False otherwise
>    */
>   
> +/**
> + * \fn abs_diff(const T& a, const T& b)
> + * \brief Calculates the absolute value of the difference between two elements
> + * \param[in] a The first element
> + * \param[in] b The second element
> + *
> + * This function calculates the absolute value of the difference between two
> + * elements of the same type, in such a way that a negative value will never
> + * occur during the calculation.
> + *
> + * This is inspired by the std::abs_diff() candidate proposed in N4318
> + * (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4318.pdf).
> + *
> + * \return The absolute value of the difference of the two parameters \a a and
> + * \a b
> + */
> +
>   } /* namespace utils */
>   
>   #ifndef __DOXYGEN__

Patch
diff mbox series

diff --git a/include/libcamera/base/utils.h b/include/libcamera/base/utils.h
index 3a803176693d..9ab18101cf27 100644
--- a/include/libcamera/base/utils.h
+++ b/include/libcamera/base/utils.h
@@ -346,6 +346,15 @@  public:
 	}
 };
 
+template<typename T>
+decltype(auto) abs_diff(const T &a, const T &b)
+{
+	if (a < b)
+		return b - a;
+	else
+		return a - b;
+}
+
 } /* namespace utils */
 
 #ifndef __DOXYGEN__
diff --git a/src/libcamera/base/utils.cpp b/src/libcamera/base/utils.cpp
index 45b92b670837..8cf8a5b2c104 100644
--- a/src/libcamera/base/utils.cpp
+++ b/src/libcamera/base/utils.cpp
@@ -437,6 +437,23 @@  std::string toAscii(const std::string &str)
  * \return True if \a Duration is a non-zero time value, False otherwise
  */
 
+/**
+ * \fn abs_diff(const T& a, const T& b)
+ * \brief Calculates the absolute value of the difference between two elements
+ * \param[in] a The first element
+ * \param[in] b The second element
+ *
+ * This function calculates the absolute value of the difference between two
+ * elements of the same type, in such a way that a negative value will never
+ * occur during the calculation.
+ *
+ * This is inspired by the std::abs_diff() candidate proposed in N4318
+ * (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4318.pdf).
+ *
+ * \return The absolute value of the difference of the two parameters \a a and
+ * \a b
+ */
+
 } /* namespace utils */
 
 #ifndef __DOXYGEN__