首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >弹物理四元数sse实现疑点

弹物理四元数sse实现疑点
EN

Stack Overflow用户
提问于 2013-10-03 12:14:58
回答 2查看 473关注 0票数 3

我当时正在研究四元数SSE实现,以了解它们是如何工作的(因为我正在实现自己的实现),我遇到了四元数乘法的这个项目实现:

代码语言:javascript
复制
VECTORMATH_FORCE_INLINE const Quat Quat::operator *( const Quat &quat ) const
{
    __m128 ldata, rdata, qv, tmp0, tmp1, tmp2, tmp3;
    __m128 product, l_wxyz, r_wxyz, xy, qw;
    ldata = mVec128;
    rdata = quat.mVec128;
    tmp0 = _mm_shuffle_ps( ldata, ldata, _MM_SHUFFLE(3,0,2,1) );
    tmp1 = _mm_shuffle_ps( rdata, rdata, _MM_SHUFFLE(3,1,0,2) );
    tmp2 = _mm_shuffle_ps( ldata, ldata, _MM_SHUFFLE(3,1,0,2) );
    tmp3 = _mm_shuffle_ps( rdata, rdata, _MM_SHUFFLE(3,0,2,1) );
    qv = vec_mul( vec_splat( ldata, 3 ), rdata );
    qv = vec_madd( vec_splat( rdata, 3 ), ldata, qv );
    qv = vec_madd( tmp0, tmp1, qv );
    qv = vec_nmsub( tmp2, tmp3, qv );
    product = vec_mul( ldata, rdata );
    l_wxyz = vec_sld( ldata, ldata, 12 );
    r_wxyz = vec_sld( rdata, rdata, 12 );
    qw = vec_nmsub( l_wxyz, r_wxyz, product );
    xy = vec_madd( l_wxyz, r_wxyz, product );
    qw = vec_sub( qw, vec_sld( xy, xy, 8 ) );
        VM_ATTRIBUTE_ALIGN16 unsigned int sw[4] = {0, 0, 0, 0xffffffff};
    return Quat( vec_sel( qv, qw, sw ) );
}

我关心的是这两条线:

代码语言:javascript
复制
l_wxyz = vec_sld( ldata, ldata, 12 );
r_wxyz = vec_sld( rdata, rdata, 12 );

宏实现:

代码语言:javascript
复制
#define _mm_ror_ps(vec,i)       \
    (((i)%4) ? (_mm_shuffle_ps(vec,vec, _MM_SHUFFLE((unsigned char)(i+3)%4,(unsigned char)(i+2)%4,(unsigned char)(i+1)%4,(unsigned char)(i+0)%4))) : (vec))

#define vec_sld(vec,vec2,x) _mm_ror_ps(vec, ((x)/4))

如果我正确理解,对于一个不能被4整除的数字(3不是12/4 = 3),vec_sld宏将缩减为:

代码语言:javascript
复制
l_wxyz = ldata;//vec_sld( ldata, ldata, 12 );
r_wxyz = rdata;//vec_sld( rdata, rdata, 12 );

实际上什么都没做。

如果该值可被4整除:

代码语言:javascript
复制
q = vec_sld( x, x, 16 );

宏将缩小为:

代码语言:javascript
复制
q = _mm_shuffle_ps( x, x, _MM_SHUFFLE(3,2,1,0) );

因为_MM_SHUFFLE(3,2,1,0)将x、y、z和w留在它们当前的位置。

如果vec_sld没有做任何事情,它的目的是什么?

我有遗漏什么吗?

编辑:这里是源代码来自的两个文件

  • aos.h (运算符*())
  • aos.h ( vec_sld和_mm_ror_ps的定义)
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-10-03 12:41:31

我想您在这里感到困惑的地方是,当((i)%4)不是4的倍数时,i计算为真,所以得到非倍数为4的_mm_shuffle_ps,否则只得到原始向量(因为按4的倍数旋转就是不操作)。

一些可能有用的背景:

vec_XXX宏表明该代码最初是从PowerPC/AltiVec移植的。vec_sld是一个AltiVec内禀,它将一对向量移动给定的字节数。在这种情况下,似乎使用vec_sld来旋转单个向量,因为两个输入向量是相同的,并且看起来12是作为字节移位传递的(即由3个浮点数旋转)。

因此,vec_sld(v, v, 12)被转换为_mm_ror_ps(v, 12/4) = _mm_ror_ps(v, 3),然后扩展为:

代码语言:javascript
复制
_mm_shuffle_ps(v, v, _MM_SHUFFLE(2, 1, 0, 3);

因此,看起来这段代码做的是对的。

票数 3
EN

Stack Overflow用户

发布于 2015-07-31 14:12:24

您还可以查看本征实现,以供参考:

SSE.h?at=default

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19158976

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档