问题描述
例如:
int64x2_t a{1,-1};
auto abs_val = vabsq_s64(a);//But this intrinsic is only or A64 architecture.
谢谢!
解决方法
如果您要执行很多64位操作,则应该对硬件进行三思。在ARMv7上,有很多功能缺少64位版本,因此,如果可以升级到AArch64,则确实应该。假设您没有该选择...
基本上,vabsq_s64
的每个泳道都是这样的:
res[i] = a[i] < 0 ? -a[i] : a[i];
您只需要使用其他内在函数即可。
让我们先处理一下否定。 NEON有一个vnegq_s64
函数可以解决这个问题,但是它仅适用于AArch64。但是,我们可以只从0中减去a:vsubq_s64(vdupq_n_s64(0),a)
。
现在,我们必须在取反值和原始值(这是vbslq_s64
的域)之间进行选择。 vbslq_s64
的第一个参数是一个掩码,用于确定要获取每个位的值的其他哪个参数。基本上,vbslq_s64(a,b,c)
在逻辑上类似于(a & b) | (~a & c)
。
要使用vbslq_s64
,我们首先需要一个掩码,当我们要使用一个值时,该通道中的全零,而当我们要使用另一个值时,则全为零。如果您使用的是AArch64,我会说要使用vcltzq_s64
,但不是。甚至vcltq_s64()
都仅适用于AArch64,但这没关系,因为总有更好的方法……只使用右移算术移位,它将以符号位移位(负数为1,正数为0)。您希望将符号位广播到每个通道的每个位,因此对于一个64位的值应为vshrq_n_s64(a,63)
。
当然,vbslq_s64
的第一个参数为uint64x2_t
,但是您拥有的是int64x2_t
,因此您需要使用vreinterpretq_u64_s64
进行转换。
将它们放在一起:
int64x2_t my_vabsq_s64(int64x2_t a) {
return vbslq_s64(
vreinterpretq_u64_s64(vshrq_n_s64(a,63)),vsubq_s64(vdupq_n_s64(0),a),a);
}