ead*_*ead 4 c++ optimization gcc complex-numbers
我天真地假设,编译器将内联复数乘法,例如对于此函数:
#include <complex>
void mult(std::complex<double> &a, std::complex<double> &b){
a*=b;
}
Run Code Online (Sandbox Code Playgroud)
但是,当用gcc(带有-O2)编译时,生成的汇编器令人惊讶(至少对我而言):
mult(std::complex<double>&, std::complex<double>&):
pushq %rbx
movsd 8(%rdi), %xmm3
movsd (%rdi), %xmm2
movq %rdi, %rbx
movsd 8(%rsi), %xmm1
movsd (%rsi), %xmm0
call __muldc3
movsd %xmm0, (%rbx)
movsd %xmm1, 8(%rbx)
popq %rbx
ret
Run Code Online (Sandbox Code Playgroud)
有一个对此函数的调用,该函数__multdc3以某种方式替换了对的调用operator*=(其错误名称将是,_ZNSt7complexIdEmLIdEERS0_RKS_IT_E并且每个引用都将传递复数)。
然而,似乎是在没有什么特别实施的operator*=这可以解释的神奇:
// 26.2.5/13
// XXX: This is a grammar school implementation.
template<typename _Tp>
template<typename _Up>
complex<_Tp>&
complex<_Tp>::operator*=(const complex<_Up>& __z)
{
const _Tp __r = _M_real * __z.real() - _M_imag * __z.imag();
_M_imag = _M_real * __z.imag() + _M_imag * __z.real();
_M_real = __r;
return *this;
}
Run Code Online (Sandbox Code Playgroud)
我必须丢失一些东西,因此我的问题是:产生最终汇编程序的原因是什么?
您应注意,严格来说,用公式实现复杂的浮点乘法是“错误的”
(a+i*b)*(c + i*d) = a*c - b*d + i*(b*c + a*d)
Run Code Online (Sandbox Code Playgroud)
我在引号中写错了,因为C ++标准实际上并不需要正确的实现。C确实在某些附录中指定了它。
简单的实现无法在输入中Inf和/或NaN输入中给出正确的结果。
考虑(Inf + 0*i)*(Inf + 0*i):显然,对于一致的行为,结果应与真实浮点的结果分别相同,即Inf或(Inf + 0*i)。但是,上面的公式给出Inf + i*NaN。
因此,我可以想象这__muldc3是一个较长的函数,可以正确处理这些情况。
当呼叫消失时,-ffast-math这很可能是解释。
| 归档时间: |
|
| 查看次数: |
492 次 |
| 最近记录: |