acos
をzとおくと、eiZの2次方程式となり、
これを解くと、
より、
ただし、logが2π周期で、頭に±がついている。
主値は、C++では定義されていない?
C99ではあるらしい。
http://docs.hp.com/ja/B2355-60104-06/cacos.3M.html
値域は、実部が[0, π]だということである。
logは虚部が[-π, π]だから、適当に符号を選べばよい。
import std.cstream;
import std.math;void main(char[][] args) {
dout.writefln(acos(1+1i)); // 0.904557+-1.06128i
dout.writefln(acos(1-1i)); // 0.904557+1.06128i
}cdouble acos(cdouble z) {
cdouble c = 1i * log(z + sqrt(z * z - 1));
if(c.re >= 0)
return c;
else
return -c;
}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));
}
http://docs.hp.com/ja/B2355-60104-06/casin.3M.html
logの中の両方の積が-1であることから、
どちらかの実部が0以上となる。
そちらのlogを取ると、虚部の絶対値がπ/2以下になる。
(ややあいまいな部分があるが、ここでは気にしないことにする)
import std.cstream;
import std.math;void main(char[][] args) {
dout.writefln(asin(1+1i));
dout.writefln(asin(1-1i));
}cdouble asin(cdouble z) {
cdouble c = sqrt(1 - z * z);
cdouble s1 = 1i * z + c;
if(s1.re >= 0)
return -1i * log(s1);
else
return -1i * log(1i * z - c);
}// 以下のlogとsqrtの定義は略