複素数計算モジュール

2007-12-30 - はてなダイアリー - debedebeの日記を見て。
フィボナッチ数列の螺旋を見てみたいなと思った。

負数の実数乗に対応しているソフトが見つけられなかったので、自分でちょっとしたプログラムを書いてみた。
数値計算複素数領域まで一般化するライブラリ。
asinとかacosとかも一般化したかったけど、ちょっと無理でした。

module cmath;
public import std.math;

real arg(real x)  { return atan2(0, x); }
real arg(ireal x) { return atan2(x.im, 0); }
real arg(creal x) { return atan2(x.im, x.re); }

alias std.math.exp exp;
creal exp(ireal x) { return cos(x.im) + 1i * sin(x.im); }
creal exp(creal x) { return exp(x.re) * (cos(x.im) + 1i * sin(x.im)); }


creal ln(real x)  { return log(abs(x)) + 1i * arg(x); }
creal ln(ireal x) { return log(abs(x)) + 1i * arg(x); }
creal ln(creal x) { return log(abs(x)) + 1i * arg(x); }

alias std.math.cos cos;
real  cos(ireal x) { return cosh(x.im); }
creal cos(creal x) { return cos(x.re) * cosh(x.im) - 1i * sin(x.re) * sinh(x.im); }

alias std.math.sin sin;
ireal sin(ireal x) { return 1i * sinh(x.im); }
creal sin(creal x) { return sin(x.re) * cosh(x.im) + 1i * cos(x.re) * sinh(x.im); }

alias std.math.tan tan;
ireal tan(ireal x) { return sin(x) / cos(x); }
creal tan(creal x) { return sin(x) / cos(x); }

creal pow2(real x, real y) { return exp(y * ln(x)); }
creal pow2(creal x, real y) { return exp(y * ln(x)); }
creal pow2(creal x, ireal y) { return exp(y * ln(x)); }
creal pow2(creal x, creal y) { return exp(y * ln(x)); }

Googleの電卓でデバッグしたから多分大丈夫なはず?

最後のpow2はテンプレート使ってもうちょっと簡単に書きたかったけど、やり方がわからなかった。

creal pow2(T, S)(T x, S, y){...}

で、TとSはrealかirealかcrealっていうのはどうやって設定すればいんだろうか。