c++11快速constexpr整数幂
c++11 fast constexpr integer powers
在这里击败死马。在C中进行整数幂运算的一种典型(快速)方法是:
int64_t ipow(int64_t base, int exp){
int64_t result = 1;
while(exp){
if(exp & 1)
result *= base;
exp >>= 1;
base *= base;
}
return result;
}
然而,我需要一个编译时的整数幂,所以我继续使用constexpr:进行递归实现
constexpr int64_t ipow_(int base, int exp){
return exp > 1 ? ipow_(base, (exp>>1) + (exp&1)) * ipow_(base, exp>>1) : base;
}
constexpr int64_t ipow(int base, int exp){
return exp < 1 ? 1 : ipow_(base, exp);
}
第二个函数只是以可预测的方式处理小于1的指数。在这种情况下,传递exp<0
是一个错误。
递归版本慢4倍
我生成了一个10E6随机值基数和指数的向量,范围为[0,15],并在向量上对两种算法进行计时(在进行非定时运行以尝试消除任何缓存影响之后)。如果不进行优化,递归方法的速度是循环的两倍。但使用-O3(GCC),循环速度是递归方法的4倍。
我想问你们的问题是:有人能想出一个更快的ipow()函数来处理0的指数和基数,并且可以用作constexpr
吗?
(免责声明:我不需要更快的ipow,我只是想看看这里的聪明人能想出什么)。
一个好的优化编译器会将尾部递归函数转换为与命令式代码一样快的运行速度。您可以通过泵浦将此函数转换为尾部递归。GCC 4.8.1编译此测试程序:
#include <cstdint>
constexpr int64_t ipow(int64_t base, int exp, int64_t result = 1) {
return exp < 1 ? result : ipow(base*base, exp/2, (exp % 2) ? result*base : result);
}
int64_t foo(int64_t base, int exp) {
return ipow(base, exp);
}
进入一个循环(见gcc.godbolt.org):
foo(long, int):
testl %esi, %esi
movl $1, %eax
jle .L4
.L3:
movq %rax, %rdx
imulq %rdi, %rdx
testb $1, %sil
cmovne %rdx, %rax
imulq %rdi, %rdi
sarl %esi
jne .L3
rep; ret
.L4:
rep; ret
与。while循环实现:
ipow(long, int):
testl %esi, %esi
movl $1, %eax
je .L4
.L3:
movq %rax, %rdx
imulq %rdi, %rdx
testb $1, %sil
cmovne %rdx, %rax
imulq %rdi, %rdi
sarl %esi
jne .L3
rep; ret
.L4:
rep; ret
一个指令接一个指令对我来说已经足够了。
这似乎是C++中constexpr和模板编程的标准问题。由于编译时的限制,如果在运行时执行,constexpr版本的速度会比正常版本慢。但是重载不允许选择正确的版本。标准化委员会正在研究这个问题。例如,请参阅以下工作文件http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3583.pdf
相关文章:
- 如何反转整数参数包
- enum是C++中的宏变量还是整数变量
- 努力将整数转换为链表。不知道我在这里做错了什么
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 整数不会重复超过随机数
- 在C++中手动调整数组大小
- 检查输入是否不是整数或数字
- C++使用整数的压缩数组初始化对象
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 多成员Constexpr结构初始化
- 将"打开的CV图像"中的"颜色"转换为整数格式
- 条件constexpr函数
- constexpr log10 整数函数
- Constexpr 可变参数模板,用于对无符号整数进行重新排序
- 这个constexpr整数不是空指针常量吗
- 如何编写constexpr交换函数来更改整数的尾数
- c++11快速constexpr整数幂
- c++ constexpr vs宏,字符串字面值vs整数
- Constexpr函数用于向数组中添加整数
- 如何从三个整数生成constexpr版本的字符串(或者可能是git/SVNcommit/rev.string)