如何用最少的指令将两个四元数相乘?

2023-11-21

经过一番思考,我想出了以下使用 SSE 乘以两个四元数的代码:

#include <pmmintrin.h> /* SSE3 intrinsics */

/* multiplication of two quaternions (x, y, z, w) x (a, b, c, d) */

__m128 _mm_cross4_ps(__m128 xyzw, __m128 abcd)
{
    /* The product of two quaternions is:                                 */
    /* (X,Y,Z,W) = (xd+yc-zb+wa, -xc+yd+za+wb, xb-ya+zd+wc, -xa-yb-zc+wd) */

    __m128 wzyx = _mm_shuffle_ps(xyzw, xyzw, _MM_SHUFFLE(0,1,2,3));
    __m128 baba = _mm_shuffle_ps(abcd, abcd, _MM_SHUFFLE(0,1,0,1));
    __m128 dcdc = _mm_shuffle_ps(abcd, abcd, _MM_SHUFFLE(2,3,2,3));

    /* variable names below are for parts of componens of result (X,Y,Z,W) */
    /* nX stands for -X and similarly for the other components             */

    /* znxwy  = (xb - ya, zb - wa, wd - zc, yd - xc) */
    __m128 ZnXWY = _mm_hsub_ps(_mm_mul_ps(xyzw, baba), _mm_mul_ps(wzyx, dcdc));

    /* xzynw  = (xd + yc, zd + wc, wb + za, yb + xa) */
    __m128 XZYnW = _mm_hadd_ps(_mm_mul_ps(xyzw, dcdc), _mm_mul_ps(wzyx, baba));

    /* _mm_shuffle_ps(XZYnW, ZnXWY, _MM_SHUFFLE(3,2,1,0)) */
    /*      = (xd + yc, zd + wc, wd - zc, yd - xc)        */
    /* _mm_shuffle_ps(ZnXWY, XZYnW, _MM_SHUFFLE(2,3,0,1)) */
    /*      = (zb - wa, xb - ya, yb + xa, wb + za)        */

    /* _mm_addsub_ps adds elements 1 and 3 and subtracts elements 0 and 2, so we get: */
    /* _mm_addsub_ps(*, *) = (xd+yc-zb+wa, xb-ya+zd+wc, wd-zc+yb+xa, yd-xc+wb+za)     */

    __m128 XZWY = _mm_addsub_ps(_mm_shuffle_ps(XZYnW, ZnXWY, _MM_SHUFFLE(3,2,1,0)),
                                _mm_shuffle_ps(ZnXWY, XZYnW, _MM_SHUFFLE(2,3,0,1)));

    /* now we only need to shuffle the components in place and return the result      */
    return _mm_shuffle_ps(XZWY, XZWY, _MM_SHUFFLE(2,1,3,0));

    /* operations: 6 shuffles, 4 multiplications, 3 compound additions/subtractions   */
}

我预计大会将有最少量的说明。但是,当我将其编译为汇编时gcc -msse3 -S,生成的函数有 67 条指令:

    .text   
    .globl __Z13_mm_cross4_psU8__vectorfS_
__Z13_mm_cross4_psU8__vectorfS_:
LFB594:
    pushq   %rbp
LCFI0:
    movq    %rsp, %rbp
LCFI1:
    subq    $232, %rsp
    movaps  %xmm0, -336(%rbp)
    movaps  %xmm1, -352(%rbp)
    movaps  -336(%rbp), %xmm0
    movaps  -336(%rbp), %xmm1
    shufps  $27, %xmm1, %xmm0
    movaps  %xmm0, -16(%rbp)
    movaps  -352(%rbp), %xmm0
    movaps  -352(%rbp), %xmm1
    shufps  $17, %xmm1, %xmm0
    movaps  %xmm0, -32(%rbp)
    movaps  -352(%rbp), %xmm0
    movaps  -352(%rbp), %xmm1
    shufps  $187, %xmm1, %xmm0
    movaps  %xmm0, -48(%rbp)
    movaps  -16(%rbp), %xmm0
    movaps  %xmm0, -112(%rbp)
    movaps  -48(%rbp), %xmm0
    movaps  %xmm0, -128(%rbp)
    movaps  -128(%rbp), %xmm0
    movaps  -112(%rbp), %xmm1
    mulps   %xmm1, %xmm0
    movaps  -336(%rbp), %xmm1
    movaps  %xmm1, -144(%rbp)
    movaps  -32(%rbp), %xmm1
    movaps  %xmm1, -160(%rbp)
    movaps  -160(%rbp), %xmm1
    movaps  -144(%rbp), %xmm2
    mulps   %xmm2, %xmm1
    movaps  %xmm1, -176(%rbp)
    movaps  %xmm0, -192(%rbp)
    movaps  -176(%rbp), %xmm0
    hsubps  -192(%rbp), %xmm0
    movaps  %xmm0, -64(%rbp)
    movaps  -16(%rbp), %xmm0
    movaps  %xmm0, -208(%rbp)
    movaps  -32(%rbp), %xmm0
    movaps  %xmm0, -224(%rbp)
    movaps  -224(%rbp), %xmm0
    movaps  -208(%rbp), %xmm1
    mulps   %xmm1, %xmm0
    movaps  -336(%rbp), %xmm1
    movaps  %xmm1, -240(%rbp)
    movaps  -48(%rbp), %xmm1
    movaps  %xmm1, -256(%rbp)
    movaps  -256(%rbp), %xmm1
    movaps  -240(%rbp), %xmm2
    mulps   %xmm2, %xmm1
    movaps  %xmm1, -272(%rbp)
    movaps  %xmm0, -288(%rbp)
    movaps  -272(%rbp), %xmm0
    haddps  -288(%rbp), %xmm0
    movaps  %xmm0, -80(%rbp)
    movaps  -64(%rbp), %xmm0
    movaps  -80(%rbp), %xmm1
    shufps  $177, %xmm1, %xmm0
    movaps  -80(%rbp), %xmm1
    movaps  -64(%rbp), %xmm2
    shufps  $228, %xmm2, %xmm1
    movaps  %xmm1, -304(%rbp)
    movaps  %xmm0, -320(%rbp)
    movaps  -304(%rbp), %xmm0
    addsubps        -320(%rbp), %xmm0
    movaps  %xmm0, -96(%rbp)
    movaps  -96(%rbp), %xmm0
    movaps  -96(%rbp), %xmm1
    shufps  $156, %xmm1, %xmm0
    leave
LCFI2:
    ret

我究竟做错了什么?必须有一种更好的方法来打乱元素而不使用这么多movaps指示。


没关系。如果我用以下命令编译代码gcc-msse3-O1 -S相反,我得到以下信息:

    .text
    .align 4,0x90
    .globl __Z13_mm_cross4_psU8__vectorfS_
__Z13_mm_cross4_psU8__vectorfS_:
LFB644:
    movaps  %xmm0, %xmm5
    movaps  %xmm1, %xmm3
    movaps  %xmm0, %xmm2
    shufps  $27, %xmm0, %xmm5
    movaps  %xmm5, %xmm4
    shufps  $17, %xmm1, %xmm3
    shufps  $187, %xmm1, %xmm1
    mulps   %xmm3, %xmm2
    mulps   %xmm1, %xmm4
    mulps   %xmm5, %xmm3
    mulps   %xmm1, %xmm0
    hsubps  %xmm4, %xmm2
    haddps  %xmm3, %xmm0
    movaps  %xmm2, %xmm1
    shufps  $177, %xmm0, %xmm1
    shufps  $228, %xmm2, %xmm0
    addsubps        %xmm1, %xmm0
    shufps  $156, %xmm0, %xmm0
    ret

现在只有 18 条指令。这正是我一开始所期望的。哎呀。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何用最少的指令将两个四元数相乘? 的相关文章

随机推荐

  • 用于取消引用函数结果的 PHP 语法

    背景 在我经常使用的所有其他编程语言中 对函数的返回值进行操作很简单 而无需声明新变量来保存函数结果 然而 在 PHP 中 这似乎并不那么简单 示例1 函数结果是一个数组
  • 从外部解决方案使用 Windows 服务中托管的 WCF 服务

    我使用以下演练设置了一个托管在 Windows 服务中的 WCF 库 http msdn microsoft com en us library ff649818 aspx 消费者 winforms 位于相同的解决方案中 该解决方案位于我的
  • 如何引用不同工作表上同名的图表?

    我有两个包含图表的工作表 并使用宏来运行所有包含图表的工作表并更新绘制的值 但是 当我尝试在第一个图表之后引用工作表中的图表时 我遇到了问题 尽管工作表的引用发生了变化 但对图表的引用却没有变化 循环看起来像这样 For Each ws I
  • Flutter:检测键盘打开和关闭[重复]

    这个问题在这里已经有答案了 我有一个BottomNavigationBar在我的应用程序的最上层 我想检测应用程序 子树中基本上任何位置的键盘打开和关闭 这样我就可以显示和隐藏BottomNavigationBar每当键盘可见时 这是一个普
  • 如何从 Rust 写入特定的原始文件描述符?

    我需要写入文件描述符 3 我一直在寻找它 但文档很差 我唯一发现的是使用libc图书馆和fdopen方法 但我还没有找到任何关于如何使用它或在其上编写的示例 谁能给我提供一个在 Rust 中写入文件描述符的示例 您可以使用FromRawFd
  • 使用 OCaml 解析语法

    我有一个任务是使用 OCaml 为 玩具 语法编写一个 玩具 解析器 但不确定如何开始 并继续 这个问题 下面是一个 Awk 语法示例 type nonterm term symbol N of nonterm T of term type
  • Microsoft Teams 来电事件

    我想创建一个应用程序 当用户在 MS Teams 中接到电话时会收到通知 我的意思是我想在来电事件中订阅一些内容 然后根据来电信息执行某些操作 这可能吗 到目前为止 我在 SDK 中没有看到任何事件 现在似乎有一个功能可能适合这个 通话记录
  • 当输出分配给变量时获取管道的退出代码(命令替换)[重复]

    这个问题在这里已经有答案了 获取管道命令的退出代码工作正常 echo ABC false true echo PIPESTATUS 0 PIPESTATUS 1 PIPESTATUS 2 Output is 0 1 0 但是当我将输出分配给
  • 可以在套接字上使用 SO_LINGER 设置的“逗留时间”究竟是多少?

    手册页对这个选项几乎没有任何解释 虽然网络上和 StackOverflow 上的答案中有大量可用信息 但我发现那里提供的许多信息甚至是自相矛盾的 那么该设置的真正用途是什么 为什么我需要设置或更改它 当 TCP 套接字断开连接时 系统必须考
  • 为什么在 -[_PFManagedObjectReferenceQueue _queueForDealloc:] 中释放托管对象可能会崩溃?

    我偶尔会看到像这样的堆栈跟踪崩溃 0 libobjc A dylib 0x97dc0edb objc msgSend 27 1 com apple CoreData 0x97edcdc2 PFManagedObjectReferenceQu
  • Azure 权限:无权执行此操作

    所以我有一个数据工厂 它调用一个读取 blob 存储的 Azure 函数 我不明白为什么我会收到此错误 此请求无权执行此操作 是数据工厂 azure 存储还是azure 功能的问题吗 我还向 Storage Blob Data Contri
  • iPhone SDK NSString 转 NSDate

    我通过解析 XML 文件得到了一个字符串 如下所示 Fri 09 Apr 2010 00 00 45 0200 相应的模式应该是 EEE dd MMM yyyy HH mm ss ZZ 但我得到 空 这是我的代码 NSString date
  • 为什么可以将 nullptr 分配给 std::string?

    所以今天我写了一个相当难发现的错误 我将 std string 初始化为 nullptr 不是指向 std string 的指针 而是值本身 我发现显然只能在 C 11 或更高版本中使用 clang 来完成 include
  • 将 ID 添加到 GridView 行

    如何向 GridView 行添加 ID 应该呈现 ID 我正在使用 NET C 我有 GridView 控件 我有一些操作表行的 javascript 函数 但必须有这些行的 ID table tr tr id should come fr
  • 如何在 Android 中对图像应用缩放、拖动和旋转 [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 目前不接受答案 有人可以告诉我在 Android 应用程序中对图像应用缩放 拖动和旋转的教程吗 尝试使用下面的代码它对我有用 float lastEvent nul
  • 使用 Oauth 通过 Gmail 进行身份验证后,有没有办法获取您的电子邮件地址?

    在 Python Web 应用程序中 我可以使用 OAuth 和 IMAP 连接到 Gmail OAuth 只需使用您当前登录的任何 Google 帐户 并要求您授予对网络应用程序的访问权限 但是 它不提供 API 来实际检索该帐户的电子邮
  • HttpRequestMessage 和摘要式身份验证

    winrt 中是否有任何内置函数可以将摘要身份验证与 HttpRequestMessage 相关联 或者我是否必须使用其他类才能执行此任务 Thanks 我正在使用HttpClient对于 HttpRequest 消息 这HttpClien
  • 在android编程中使用实用程序类

    我对实用程序类有一点了解 但对需求略有疑问 如果我在我的应用程序中使用实用程序类而不是在我的主活动中使用该类 我是否必须创建该类的对象 或者我可以直接在我的主活动中导入该类吗 如果我没有表达清楚的话 我很抱歉 简而言之 我想清楚的是 基本上
  • 从 XML 中获取具有特定名称的所有节点的值

    我无法以最有效的方式从 XML 获取具有特定名称的节点的所有值 例如 h1 h1
  • 如何用最少的指令将两个四元数相乘?

    经过一番思考 我想出了以下使用 SSE 乘以两个四元数的代码 include