これを読んだらついムラムラと。

とっても車輪の再発明の気がするのですが、適当なのが見つからなかったので。

Demo

こんな感じ。基本的なものはそろっています。

var cplx = Math.Complex, cplxe = Math.Complex.polar;
var c1 = cplx(1,2), c2 = cplx(3,4);
p(c1);
p(c1.neg());
p(c1.con());
p(c1.add(c2));
p(c1.add(2));
p(c1.sub(c2));
p(c1.sub(2));
p(c1.mul(c2));
p(c1.mul(2));
p(c1.div(c2));
p(c1.div(2));
p(c1.arg());
p(c1.abs());
p(cplxe(c1.abs(),c1.arg()));
p(c1.exp());
p(c1.log());
p(c1.pow(c2));
p(c1.pow(2));
p(cplx(-2.5).pow(-2.5));


Riemann ζを計算できる程度には。

var cplx = Math.Complex, cplxe = Math.Complex.polar;
var pi = Math.PI;
p('ζ(2)              = ' + zeta(cplx(2)));
p('π^2/6             = ' + pi*pi/6);
p('ζ(1)              = ' + zeta(cplx(1)));
p('ζ(0)              = ' + zeta(cplx(0)));
p('ζ(-1)             = ' + zeta(cplx(-1)));
p('-1/12             = ' + -1/12);
p('ζ(-2)             = ' + zeta(cplx(-2)));
p('ζ(-4)             = ' + zeta(cplx(-4)));
p('ζ(i)              = ' + zeta(cplx(0,1)));
p('ζ(0.5)            = ' + zeta(cplx(0.5,0)));
p('ζ(0.5+14.134725i) = ' + zeta(cplx(0.5,14.134725)));
p('ζ(0.5+21.022040i) = ' + zeta(cplx(0.5,21.022040)));
p('ζ(0.5+25.010858i) = ' + zeta(cplx(0.5,25.010858)));
p('ζ(0.5+30.424876i) = ' + zeta(cplx(0.5,30.424876)));
p('ζ(0.5+32.935062i) = ' + zeta(cplx(0.5,32.935062)));
p('ζ(0.5+37.586178i) = ' + zeta(cplx(0.5,37.586178)));


ζはこうして計算しています。

var cplx = Math.Complex, cplxe = Math.Complex.polar;
combination = function(n, k){
    if (n < k)   return arguments.callee(k, n);
    if (k === 0) return 1;
    var r = 1;
    while (k >= 1){ r *= n-- / k--; }
    return r;
};

var MAXITER = 64;
var EPSILON = 1e-12;

zeta = function(z){
  var s = cplx(0,0);
  for (var i = 0; i < MAXITER; i++){
    var ss = cplx(0);
    for (var j = 0; j <= i; j++){
      var tt = cplx(combination(i,j)).div(cplx(j+1).pow(z));
      ss = j & 1 ? ss.sub(tt) : ss.add(tt);
    }
    if (ss.eq(0)) break;
    var t = ss.div(Math.pow(2,i+1));
    s = s.add(t);
    if (t.div(s).abs() < EPSILON) break;
  }
  /* p('iter=' + i); */
  return s.div(cplx(2).pow(cplx(1).sub(z)).sub(1).neg());
};

使ったのは、こちらの公式。

複素数でも問題なく使える優れものです。

あと、マンデルブロー集合も描いてみました。

Original: http://instantsolve.net/mandelbrot.htm

FirefoxだとSlow Script警告が出ます。SafariかChromeかOperaで

Open as PNG

calc_pixel = function(x, y) {
  var iteration = 0;
  var c = Math.Complex(x, y);
  var z = Math.Complex(0, 0);
  var i;
  for (i = 0; i < max_iteration; i++){
    z = z.mul(z).add(c);
    if (z.abs() >= 2) break;
  };
  return i;
}

複素数使わなくても描けるし、その方が高速でもあるのですが、ここではMath.Complexが使い物になるかどうかのテストなので。

Enjoy!

Dan the Complex Blogger