On Wed, Mar 3, 2021 at 9:05 AM Bell, Ian H. (Fed) via Std-Discussion <std-discussion@lists.isocpp.org> wrote:

std::cout << pow(std::complex<double>(-0.1, 1e-100), 2.0) << std::endl;

gives

(0.01,-2.44929e-18)

Here are the calculations being carried out:

log(a + bi) = log(a*a + b*b) / 2 + i * atan2(b, a)

exp(a + bi) = exp(a) * cos(b) + i * exp(a) * sin(b)

In your case, you have x = -.1 + 1e-100i,

so l = log(x) = log(.1) + i * atan2(1e-100, -.1) = log(.1) + i * numbers::pi

log(a + bi) = log(a*a + b*b) / 2 + i * atan2(b, a)

exp(a + bi) = exp(a) * cos(b) + i * exp(a) * sin(b)

In your case, you have x = -.1 + 1e-100i,

so l = log(x) = log(.1) + i * atan2(1e-100, -.1) = log(.1) + i * numbers::pi

Then exp(2*l) = exp(2*log(.1) + i * 2 * numbers::pi)

= .01 * (cos(2 * numbers::pi) + i * sin(2 * numbers::pi))

= .01 - i * 2.4492935982947064e-18

Basically, atan2(1e-100, -.1) just gives you numbers::pi, and then

sin(2 * numbers::pi) isn't 0 because numbers::pi isn't exactly π.

Doubles don't have enough precision to be able to deal with complex

logarithms and trigonometry at this scale.