ARM NEON我的计算结果有负数时是不正确的

时间:2014-07-27 01:12:43

标签: assembly arm neon alphablending

我正在尝试使用装配中的氖((200 *(53-255))/ 255)+ 255计算以下结果,其结果应该等于大约97

我在这里测试http://szeged.github.io/nevada/以及双核Cortex-A7 ARM CPU平板电脑。结果是243,这是不正确的 我应该如何实现这一点以获得97的正确结果?

d2包含200,200,200,200,200,200,200,200
d4包含255,255,255,255,255,255,255,255
d6包含53,53,53,53,53,53,53,53

vsub.s8 d8, d6, d4  (53 - 255 results in d8 = 54,54,54,54,54,54,54,54)
vmull.s8 q5,d8,d2  (54 * 200 results in q5 = 244,48,244,48,244,48,244,48,244,48,244,48,244,48,244,48)
vshrn.s16 d12, q5, #8 (divide by 255 results in d12 = 244,244,244,244,244,244,244,244) 
vadd.s8 d5, d4, d12  (final result d5 = 243,243,243,243,243,243,243,243) 

1 个答案:

答案 0 :(得分:1)

243绝对正确。

Alpha通道是无符号8位值,您应使用u8u16代替s8s16

虽然对于比特宽度保持不变的标准算术而言,符号并不重要,但对于乘法长而言,这是一个完全不同的故事。

这就是为什么ARM UMULLSMULL有两个单独的指令用于长乘法,而单MUL指令用于32位有符号和无符号乘法的原因。

54 * 200根本不可能,因为200在有符号的乘法中被解释为-56。

=>
54*-56 = -3024
-3024/256 = -12
-12 + -1 = -13    // 255 = -1
-13 = 243

您实际上必须将vmull.s8更改为vmull.u8

=>
54*200 = 4800
2800/256 = 18
18 + -1 = 17

老实说,我不知道你对上面的操作有什么期望97的结果:它应该是某种alpha混合,因为其中一个标签暗示了?

此外,>>8不是/255。这只是一个糟糕的近似值。你可能认为你可以使用低精度的精度,但是在alpha混合时它的FAR就足够了。

你一定做错了。