从模板参数中提取用于局部类型的simd向量长度



我正在努力寻找正确的C++/clang语句来解决以下问题。首先请注意,由于在算术运算之前进行整数提升,以下内容不会使无符号short溢出。

unsigned short testme = 16320;
testme = testme * 257 / 64;

结果为65535。但当我使用simd在无符号空头向量上尝试类似的东西时,它不起作用:

#import <simd/simd.h>
template <typename T>
void muldiv( T* data, unsigned multiply, unsigned divide)
{
*data = (*data * multiply) / divide;
}
...
simd::ushort4 testme = 16320;
muldiv( &testme, 257, 64);

这给出了四个1023的矢量。没有发生整数提升,乘法被包装。在查阅了叮当作响的文档后,我能想到的最好的就是这个。请注意,调用方必须提供一个伪参数,以便作为模板类型参数提供工作精度。

#import <simd/simd.h>
template <typename T, typename W>
void muldiv( T* data, unsigned multiply, unsigned divide, W workingtype)
{
*data = __builtin_convertvector( (__builtin_convertvector(*data, W) * multiply) / divide, T);
}
...
simd::ushort4 testme = 16320;
muldiv( &testme, 257, 64, simd::uint4());

现在我得到一个4个65535的向量。T是模板参数的原因是有时我会传递ushort4、ushort8、ushort16等。但我发现将工作精度作为参数传递很难看,因为它总是无符号的int。我想不出从T中提取simd长度的方法,所以我可以在本地声明类型W。功能中有这样的东西会很好:

typedef unsigned int W __attribute__((__vector_size__( ?? )));

但我不知道该怎么做。我试过这样的东西:

bool hopeful = __is_convertible_to( simd::ushort4, simd::uint4);

但希望总是虚假的。

有人能告诉我我需要什么魔法吗?

注意,这是在苹果平台上提供的<simd/simd.h>。

因此clang允许您对属性进行模式匹配,并在模板中生成新的属性修改类型。

所以我们可以这样做。

simd宽度属性上的第一个模式匹配:

template<class T>
struct get_simd_width;
template<class T, std::size_t x>
struct get_simd_width< __attribute__((__ext_vector_type__(x))) T >:
std::integral_constant<std::size_t, x>
{};

此外,提取属性类型的基本类型:

template<class T>
struct get_simd_type;
template<class T, std::size_t x>
struct get_simd_type< __attribute__((__ext_vector_type__(x))) T >
{
using type = T;
};

然后我们做一些语法调整,使它们更容易使用:

template<class T>
constexpr std::size_t simd_width = get_simd_width<T>{};
template<class T>
using simd_type = typename get_simd_type<T>::type;

这是为了生成一个具有属性的新simd类型:

template<class T>
struct simd_helper;
template<class T, std::size_t N>
struct simd_helper<T[N]> {
using type = __attribute__((__ext_vector_type__(N))) T;
};
template<class T>
using simd = typename simd_helper<T>::type;

然后CCD_ 1生成宽度为4的simd类型。

这些应该能解决你的问题。活生生的例子。

template <class T>
void muldiv( T* data, unsigned multiply, unsigned divide)
{
using W = simd<int[simd_width<T>]>;
*data = __builtin_convertvector( (__builtin_convertvector(*data, W) * multiply) / divide, T);
}

相关内容

  • 没有找到相关文章

最新更新