Skip to content

popcount uintN_t for N!=32 problem #8

@prlw1

Description

@prlw1

P2933R4 brings in overloads for <bit> functions.

Trying the following example (with g++ 16.0.0 20250827 -std=c++26 on NetBSD)

#include <bit>
#include <cstdint>
#include <print>
#include <simd>

int main() {
        using V = typename std::datapar::simd<std::uint8_t, 16>;
        V vec = std::datapar::iota<V>;
        for (std::size_t i{}; i != V::size; ++i) {
                std::println("{:4b}:{}", vec[i], std::popcount(vec[i]));
        }
/*
        auto pc = std::datapar::popcount(vec);
        for (std::size_t i{}; i != V::size; ++i) {
                std::println("{:4b}:{}", vec[i], pc[i]);
        }
*/
}

the above compiles and runs as is.

If the commented-out code is reinstated, compilation fails with

In file included from /usr/src/local/simd/simd:20,
                 from popcount.cc:4:
/usr/src/local/simd/bits/simd_bit.h: In instantiation of 'constexpr std::datapar::rebind_t<typename std::make_signed<typename _Vp::value_type>::type, _Vp> std::datapar::popcount(const _Vp&) [with _Vp = basic_simd<unsigned char, std::_VecAbi<16> >; rebind_t<typename std::make_signed<typename _Vp::value_type>::type, _Vp> = basic_simd<signed char, std::_VecAbi<16> >; typename std::make_signed<typename _Vp::value_type>::type = signed char; typename _Vp::value_type = unsigned char]':
required from here
popcount.cc:13:34:   
   13 |         auto pc = std::datapar::popcount(vec);
      |                   ~~~~~~~~~~~~~~~~~~~~~~^~~~~
/usr/src/local/simd/bits/simd_bit.h:106:14: error: use of deleted function 'constexpr std::datapar::basic_simd<_Tp, _Abi>::basic_simd(_Fp&&) [with _Fp = std::datapar::popcount<basic_simd<unsigned char, std::_VecAbi<16> > >(const basic_simd<unsigned char, std::_VecAbi<16> >&)::<lambda(int)>; _Tp = signed char; _Abi = std::_VecAbi<16>]': Invalid return type of the generator function: Requires value-preserving conversion or implicitly convertible user-defined type.
  106 |       return _Rp([&](int __i) { return std::popcount(__v[__i]); });
      |              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/src/local/simd/simd:12:
/usr/src/local/simd/bits/simd.h:166:9: note: declared here
  166 |         basic_simd(_Fp&& )
      |         ^~~~~~~~~~
/usr/src/local/simd/bits/simd_bit.h:106:14: note: use '-fdiagnostics-all-candidates' to display considered candidates
  106 |       return _Rp([&](int __i) { return std::popcount(__v[__i]); });
      |              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*** Error code 1

If uint8_t is replaced with uint32_t, then all is well again.

Apart from the principle of least surprise, I think

The type V::value_type is an unsigned integer type

should work for any uintN_t?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions