[RFC,v2,05/22] libcamera: base: cxx20: Add `has_single_bit()`
diff mbox series

Message ID 20250721104622.1550908-6-barnabas.pocze@ideasonboard.com
State New
Headers show
Series
  • libcamera: Add `MetadataList`
Related show

Commit Message

Barnabás Pőcze July 21, 2025, 10:46 a.m. UTC
`has_single_bit()` checks if the given unsigned integer has a single
bit set, that is, whether the number is a power of two or not.

Not all requirements of the C++20 standard are implemented.

See https://en.cppreference.com/w/cpp/numeric/has_single_bit

Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
---
 include/libcamera/base/details/cxx20.h | 10 ++++++++++
 1 file changed, 10 insertions(+)

Comments

Jacopo Mondi July 25, 2025, 1:04 p.m. UTC | #1
Hi Barnabás

On Mon, Jul 21, 2025 at 12:46:05PM +0200, Barnabás Pőcze wrote:
> `has_single_bit()` checks if the given unsigned integer has a single
> bit set, that is, whether the number is a power of two or not.
>
> Not all requirements of the C++20 standard are implemented.
>
> See https://en.cppreference.com/w/cpp/numeric/has_single_bit
>
> Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
> ---
>  include/libcamera/base/details/cxx20.h | 10 ++++++++++
>  1 file changed, 10 insertions(+)
>
> diff --git a/include/libcamera/base/details/cxx20.h b/include/libcamera/base/details/cxx20.h
> index 2d26db53e..8bf45ff11 100644
> --- a/include/libcamera/base/details/cxx20.h
> +++ b/include/libcamera/base/details/cxx20.h
> @@ -7,9 +7,19 @@
>
>  #pragma once
>
> +#include <type_traits>
> +
>  namespace libcamera::details::cxx20 {
>
>  template<typename T> struct type_identity { using type = T; };
>  template<typename T> using type_identity_t = typename type_identity<T>::type;
>
> +template<typename T>
> +constexpr bool has_single_bit(T x) noexcept
> +{
> +	static_assert(std::is_unsigned_v<T>);

I was wondering if a compile time assertion is better than restricting
the template substitution to unsigned int with std::enable_if<> but in
the end the result is the same...

> +
> +	return x != 0 && (x & (x - 1)) == 0;

cppreference.com has a more "compact"

        return x && !(x & (x - 1));

Up to you!

Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>

> +}
> +
>  } /* namespace libcamera::details::cxx20 */
> --
> 2.50.1
>
Laurent Pinchart July 27, 2025, 1:36 p.m. UTC | #2
On Fri, Jul 25, 2025 at 03:04:46PM +0200, Jacopo Mondi wrote:
> Hi Barnabás
> 
> On Mon, Jul 21, 2025 at 12:46:05PM +0200, Barnabás Pőcze wrote:
> > `has_single_bit()` checks if the given unsigned integer has a single
> > bit set, that is, whether the number is a power of two or not.
> >
> > Not all requirements of the C++20 standard are implemented.
> >
> > See https://en.cppreference.com/w/cpp/numeric/has_single_bit
> >
> > Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
> > ---
> >  include/libcamera/base/details/cxx20.h | 10 ++++++++++
> >  1 file changed, 10 insertions(+)
> >
> > diff --git a/include/libcamera/base/details/cxx20.h b/include/libcamera/base/details/cxx20.h
> > index 2d26db53e..8bf45ff11 100644
> > --- a/include/libcamera/base/details/cxx20.h
> > +++ b/include/libcamera/base/details/cxx20.h
> > @@ -7,9 +7,19 @@
> >
> >  #pragma once
> >
> > +#include <type_traits>
> > +
> >  namespace libcamera::details::cxx20 {
> >
> >  template<typename T> struct type_identity { using type = T; };
> >  template<typename T> using type_identity_t = typename type_identity<T>::type;
> >
> > +template<typename T>
> > +constexpr bool has_single_bit(T x) noexcept
> > +{
> > +	static_assert(std::is_unsigned_v<T>);
> 
> I was wondering if a compile time assertion is better than restricting
> the template substitution to unsigned int with std::enable_if<> but in
> the end the result is the same...

When there are no other template candidates they need to be considered,
a static assertion will give better error messages.

Can we add a std::is_integral check here to get closer to the C++20
requirements ?

> > +
> > +	return x != 0 && (x & (x - 1)) == 0;
> 
> cppreference.com has a more "compact"
> 
>         return x && !(x & (x - 1));
> 
> Up to you!
> 
> Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> 
> > +}
> > +
> >  } /* namespace libcamera::details::cxx20 */
Barnabás Pőcze July 27, 2025, 5:19 p.m. UTC | #3
Hi

2025. 07. 27. 15:36 keltezéssel, Laurent Pinchart írta:
> On Fri, Jul 25, 2025 at 03:04:46PM +0200, Jacopo Mondi wrote:
>> Hi Barnabás
>>
>> On Mon, Jul 21, 2025 at 12:46:05PM +0200, Barnabás Pőcze wrote:
>>> `has_single_bit()` checks if the given unsigned integer has a single
>>> bit set, that is, whether the number is a power of two or not.
>>>
>>> Not all requirements of the C++20 standard are implemented.
>>>
>>> See https://en.cppreference.com/w/cpp/numeric/has_single_bit
>>>
>>> Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
>>> ---
>>>   include/libcamera/base/details/cxx20.h | 10 ++++++++++
>>>   1 file changed, 10 insertions(+)
>>>
>>> diff --git a/include/libcamera/base/details/cxx20.h b/include/libcamera/base/details/cxx20.h
>>> index 2d26db53e..8bf45ff11 100644
>>> --- a/include/libcamera/base/details/cxx20.h
>>> +++ b/include/libcamera/base/details/cxx20.h
>>> @@ -7,9 +7,19 @@
>>>
>>>   #pragma once
>>>
>>> +#include <type_traits>
>>> +
>>>   namespace libcamera::details::cxx20 {
>>>
>>>   template<typename T> struct type_identity { using type = T; };
>>>   template<typename T> using type_identity_t = typename type_identity<T>::type;
>>>
>>> +template<typename T>
>>> +constexpr bool has_single_bit(T x) noexcept
>>> +{
>>> +	static_assert(std::is_unsigned_v<T>);
>>
>> I was wondering if a compile time assertion is better than restricting
>> the template substitution to unsigned int with std::enable_if<> but in
>> the end the result is the same...
> 
> When there are no other template candidates they need to be considered,
> a static assertion will give better error messages.
> 
> Can we add a std::is_integral check here to get closer to the C++20
> requirements ?

C++20 defines it only for some unsigned types. Could you clarify why
`std::is_integral` would be needed?


Regards,
Barnabás Pőcze


> 
>>> +
>>> +	return x != 0 && (x & (x - 1)) == 0;
>>
>> cppreference.com has a more "compact"
>>
>>          return x && !(x & (x - 1));
>>
>> Up to you!
>>
>> Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
>>
>>> +}
>>> +
>>>   } /* namespace libcamera::details::cxx20 */
>
Laurent Pinchart July 27, 2025, 6:38 p.m. UTC | #4
On Sun, Jul 27, 2025 at 07:19:22PM +0200, Barnabás Pőcze wrote:
> 2025. 07. 27. 15:36 keltezéssel, Laurent Pinchart írta:
> > On Fri, Jul 25, 2025 at 03:04:46PM +0200, Jacopo Mondi wrote:
> >> On Mon, Jul 21, 2025 at 12:46:05PM +0200, Barnabás Pőcze wrote:
> >>> `has_single_bit()` checks if the given unsigned integer has a single
> >>> bit set, that is, whether the number is a power of two or not.
> >>>
> >>> Not all requirements of the C++20 standard are implemented.
> >>>
> >>> See https://en.cppreference.com/w/cpp/numeric/has_single_bit
> >>>
> >>> Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
> >>> ---
> >>>   include/libcamera/base/details/cxx20.h | 10 ++++++++++
> >>>   1 file changed, 10 insertions(+)
> >>>
> >>> diff --git a/include/libcamera/base/details/cxx20.h b/include/libcamera/base/details/cxx20.h
> >>> index 2d26db53e..8bf45ff11 100644
> >>> --- a/include/libcamera/base/details/cxx20.h
> >>> +++ b/include/libcamera/base/details/cxx20.h
> >>> @@ -7,9 +7,19 @@
> >>>
> >>>   #pragma once
> >>>
> >>> +#include <type_traits>
> >>> +
> >>>   namespace libcamera::details::cxx20 {
> >>>
> >>>   template<typename T> struct type_identity { using type = T; };
> >>>   template<typename T> using type_identity_t = typename type_identity<T>::type;
> >>>
> >>> +template<typename T>
> >>> +constexpr bool has_single_bit(T x) noexcept
> >>> +{
> >>> +	static_assert(std::is_unsigned_v<T>);
> >>
> >> I was wondering if a compile time assertion is better than restricting
> >> the template substitution to unsigned int with std::enable_if<> but in
> >> the end the result is the same...
> > 
> > When there are no other template candidates they need to be considered,
> > a static assertion will give better error messages.
> > 
> > Can we add a std::is_integral check here to get closer to the C++20
> > requirements ?
> 
> C++20 defines it only for some unsigned types. Could you clarify why
> `std::is_integral` would be needed?

Hmmm I suppose std::is_unsigned implies std::is_integral ?

Could we match the C++20 requirements to avoid accidental use of this
function that would not work with the C++20 version when we'll switch to
that standard ?

> >>> +
> >>> +	return x != 0 && (x & (x - 1)) == 0;
> >>
> >> cppreference.com has a more "compact"
> >>
> >>          return x && !(x & (x - 1));
> >>
> >> Up to you!
> >>
> >> Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> >>
> >>> +}
> >>> +
> >>>   } /* namespace libcamera::details::cxx20 */
Barnabás Pőcze July 27, 2025, 6:43 p.m. UTC | #5
2025. 07. 27. 20:38 keltezéssel, Laurent Pinchart írta:
> On Sun, Jul 27, 2025 at 07:19:22PM +0200, Barnabás Pőcze wrote:
>> 2025. 07. 27. 15:36 keltezéssel, Laurent Pinchart írta:
>>> On Fri, Jul 25, 2025 at 03:04:46PM +0200, Jacopo Mondi wrote:
>>>> On Mon, Jul 21, 2025 at 12:46:05PM +0200, Barnabás Pőcze wrote:
>>>>> `has_single_bit()` checks if the given unsigned integer has a single
>>>>> bit set, that is, whether the number is a power of two or not.
>>>>>
>>>>> Not all requirements of the C++20 standard are implemented.
>>>>>
>>>>> See https://en.cppreference.com/w/cpp/numeric/has_single_bit
>>>>>
>>>>> Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
>>>>> ---
>>>>>    include/libcamera/base/details/cxx20.h | 10 ++++++++++
>>>>>    1 file changed, 10 insertions(+)
>>>>>
>>>>> diff --git a/include/libcamera/base/details/cxx20.h b/include/libcamera/base/details/cxx20.h
>>>>> index 2d26db53e..8bf45ff11 100644
>>>>> --- a/include/libcamera/base/details/cxx20.h
>>>>> +++ b/include/libcamera/base/details/cxx20.h
>>>>> @@ -7,9 +7,19 @@
>>>>>
>>>>>    #pragma once
>>>>>
>>>>> +#include <type_traits>
>>>>> +
>>>>>    namespace libcamera::details::cxx20 {
>>>>>
>>>>>    template<typename T> struct type_identity { using type = T; };
>>>>>    template<typename T> using type_identity_t = typename type_identity<T>::type;
>>>>>
>>>>> +template<typename T>
>>>>> +constexpr bool has_single_bit(T x) noexcept
>>>>> +{
>>>>> +	static_assert(std::is_unsigned_v<T>);
>>>>
>>>> I was wondering if a compile time assertion is better than restricting
>>>> the template substitution to unsigned int with std::enable_if<> but in
>>>> the end the result is the same...
>>>
>>> When there are no other template candidates they need to be considered,
>>> a static assertion will give better error messages.
>>>
>>> Can we add a std::is_integral check here to get closer to the C++20
>>> requirements ?
>>
>> C++20 defines it only for some unsigned types. Could you clarify why
>> `std::is_integral` would be needed?
> 
> Hmmm I suppose std::is_unsigned implies std::is_integral ?

Technically it doesn't, it only checks if it's an arithmetic type.
But I haven't see unsigned floats yet.


> 
> Could we match the C++20 requirements to avoid accidental use of this
> function that would not work with the C++20 version when we'll switch to
> that standard ?

I think `is_unsigned` gets us pretty close. Otherwise you'd need to do
a series of `std::is_same_v<...>` to match the C++20 requirements.


> 
>>>>> +
>>>>> +	return x != 0 && (x & (x - 1)) == 0;
>>>>
>>>> cppreference.com has a more "compact"
>>>>
>>>>           return x && !(x & (x - 1));
>>>>
>>>> Up to you!
>>>>
>>>> Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
>>>>
>>>>> +}
>>>>> +
>>>>>    } /* namespace libcamera::details::cxx20 */
>

Patch
diff mbox series

diff --git a/include/libcamera/base/details/cxx20.h b/include/libcamera/base/details/cxx20.h
index 2d26db53e..8bf45ff11 100644
--- a/include/libcamera/base/details/cxx20.h
+++ b/include/libcamera/base/details/cxx20.h
@@ -7,9 +7,19 @@ 
 
 #pragma once
 
+#include <type_traits>
+
 namespace libcamera::details::cxx20 {
 
 template<typename T> struct type_identity { using type = T; };
 template<typename T> using type_identity_t = typename type_identity<T>::type;
 
+template<typename T>
+constexpr bool has_single_bit(T x) noexcept
+{
+	static_assert(std::is_unsigned_v<T>);
+
+	return x != 0 && (x & (x - 1)) == 0;
+}
+
 } /* namespace libcamera::details::cxx20 */