c - 限制真实(固定/浮点)值的最快方法?

标签 c numbers bit-manipulation clamp

是否有比使用 if 语句或三元运算符更有效的方法来限制实数? 我想对 double 和 32 位定点实现 (16.16) 都执行此操作。我要求可以处理这两种情况的代码;它们将在单独的函数中处理。

显然,我可以做这样的事情:

double clampedA;
double a = calculate();
clampedA = a > MY_MAX ? MY_MAX : a;
clampedA = a < MY_MIN ? MY_MIN : a;

double a = calculate();
double clampedA = a;
if(clampedA > MY_MAX)
    clampedA = MY_MAX;
else if(clampedA < MY_MIN)
    clampedA = MY_MIN;

定点版本将使用函数/宏进行比较。

这是在代码的性能关键部分完成的,因此我正在寻找一种尽可能有效的方法来完成它(我怀疑这会涉及位操作)

编辑:它必须是标准/可移植的 C,平台特定的功能在这里没有任何意义。此外,MY_MINMY_MAX 与我想要钳位的值的类型相同(上面示例中的 double )。

最佳答案

GCC 和 clang 都为以下简单、直接、可移植的代码生成漂亮的程序集:

double clamp(double d, double min, double max) {
  const double t = d < min ? min : d;
  return t > max ? max : t;
}

> gcc -O3 -march=native -Wall -Wextra -Wc++-compat -S -fverbose-asm lamp_ternary_operator.c

GCC 生成的程序集:

maxsd   %xmm0, %xmm1    # d, min
movapd  %xmm2, %xmm0    # max, max
minsd   %xmm1, %xmm0    # min, max
ret

> clang -O3 -march=native -Wall -Wextra -Wc++-compat -S -fverbose-asm lamp_ternary_operator.c

Clang 生成的程序集:

maxsd   %xmm0, %xmm1
minsd   %xmm1, %xmm2
movaps  %xmm2, %xmm0
ret

三个指令(不包括ret),没有分支。非常好。

这是在配备 Core i3 M 350 的 Ubuntu 13.04 上使用 GCC 4.7 和 clang 3.2 进行测试的。 附带说明一下,调用 std::min 和 std::max 的简单 C++ 代码生成了相同的程序集。

这是针对 double 的。对于 int,GCC 和 clang 都会生成具有 5 个指令(不包括 ret)并且没有分支的汇编。也很优秀。

我目前不使用定点,所以我不会对定点发表意见。

关于c - 限制真实(固定/浮点)值的最快方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23032492/

相关文章:

javascript - 一组随机数

sql - 尝试对 2 个字段相乘所得的值进行舍入

java - 如何使用 XOR 在 Java 中开发​OTPInputStream​

c - 如何使用按位运算符将位与 C 中的无符号整数隔离?

c - 如何将 Apache 模块(处理程序)限制为虚拟主机 (vhost)

c - 调用函数后指向 B 树根节点的指针开始指向子节点(应该继续指向根节点)

c - 使用c中的指针求二维数组中的总和

javascript - 是否有从字符串中提取数字的函数

c - 在位数组中找到第一个零

java - 为什么我的 native JNI 代码是顺序运行而不是并发运行?