複素数(9)

虚数の場合

引数が純虚数だと速くなる可能性があるので、
それ用にも書いてみる。

 e^{iy} = \cos{iy} + i\sin{iy}
 \cos{(iy)} = \frac{e^{-y} + e^y}{2}
 \sin{(iy)} = \frac{e^{-y} - e^y}{2i}
 \tan{(iy)} = \frac{1}{i}\frac{e^{-y} - e^y}{e^{-y} + e^y} = i\frac{e^{2y} - 1}{e^{2y} + 1}

ここまでは一価だからやさしい。

log

 \log{iy} = \log{y} + \log{i}

虚部は[-π, π]だから、

 \log{iy} = \log{y} + \frac{\pi}{2}i

sqrt

 \sqrt{iy} = \sqrt{(\pm{i})(\pm{y})} = \sqrt{\pm y}e^{\pm\frac{\pi}{4}i} = (1 \pm i)\sqrt{\frac{\pm y}{2}}

符号はyの正負による。

acos

 \mbox{acos}{(iy)} = \mp i(\log(iy + i\sqrt{y^2 + 1})) = \mp i(\log(y + \sqrt{y^2 + 1}) + \frac{\pi}{2}i)

実部が[0, π]だから、-を取る。

 \mbox{acos}{(iy)} = \frac{\pi}{2} - i\log{(y + \sqrt{y^2 + 1})}

asin

 \mbox{asin}{(iy)} = -i\log{(-y + \pm\sqrt{y^2 + 1})}

実部が[-π/2, π/2]だから、
-を取ると、logの中が負で、(2n + 1)πiの項が出てきて、
範囲に収まらない。
+を取ると、logの中が正となり、実部は常に0。

 \mbox{asin}{(iy)} = -i\log{(-y + sqrt{y^2 + 1})}

atan

 \mbox{atan}{(iy)} = \frac{1}{2}\log{\frac{1 + y}{1 - y}}


powはメリットなさそうなので、パス。



import std.cstream;
import std.math;

void main(char[][] args) {
dout.writefln(exp(0.1i));
dout.writefln(cos(0.1i));
dout.writefln(sin(0.1i));
dout.writefln(tan(0.1i));
dout.writefln(log(1.1i));
dout.writefln(sqrt(-1i));
dout.writefln(acos(0.1i));
dout.writefln(asin(0.1i));
dout.writefln(atan(0.1i));
}

cdouble exp(idouble z) {
auto y = z.im;
return std.math.cos(y) + 1i * std.math.sin(y);
}

cdouble cos(idouble z) {
auto e = std.math.exp(z.im);
return (e + 1 / e) / 2 + 0i;
}

cdouble sin(idouble z) {
auto e = std.math.exp(z.im);
return 0.5i * (e - 1 / e) + 0;
}

cdouble tan(idouble z) {
auto e2 = std.math.exp(z.im * 2);
return 1i * (e2 - 1) / (e2 + 1) + 0;
}

cdouble log(idouble z) {
return std.math.log(z.im) + std.math.PI * 0.5i;
}

cdouble sqrt(idouble z) {
auto y = z.im;
if(y >= 0)
return (1 + 1i) * std.math.sqrt(y / 2);
else
return (1 - 1i) * std.math.sqrt(-y / 2);
}

cdouble acos(idouble z) {
auto y = z.im;
return std.math.PI / 2
- 1i * std.math.log(y + std.math.sqrt(y * y + 1));
}

cdouble asin(idouble z) {
auto y = z.im;
return 1i * std.math.log(y
+ std.math.sqrt(y * y + 1)) + 0;
}

cdouble atan(idouble z) {
auto y = z.im;
return 0.5 * log((1 + y) / (1 - y) + 0i);
}

cdouble log(cdouble z) {
double x = z.re;
double y = z.im;
return std.math.log(x * x + y * y) / 2
+ 1i * atan2(y, x);
}

cdouble sqrt(cdouble z) {
double x = z.re;
double y = z.im;
double theta = atan2(y, x) / 2;
return std.math.sqrt(abs(z))
* (std.math.cos(theta) + 1i * std.math.sin(theta));
}