SpdeでNewton Fractals

参考

Newton Fractals (Python recipe)
Scalaで複素数計算


size(512, 512)
noLoop
val (xa, xb, ya, yb) = (-1.0, 1.0, -1.0, 1.0)
val maxIt = 20
val h = 1e-6
val eps = 1e-3

def f(z: Complex) = z * z * z - Complex(1.0, 0.0)

case class Complex(re: Double, im: Double) {
  def minus =
    Complex(- re, - im)
  def add(that: Complex) =
    Complex(re + that.re, im + that.im)
  def subtract(that: Complex) =
    Complex(re - that.re, im - that.im)
  def multiply(that: Complex) =
    Complex(re*that.re - im*that.im, re*that.im + im*that.re)
  def divide(that: Complex) =
    Complex((re * that.re + im * that.im)/(that.re * that.re + that.im * that.im), (im * that.im - re * that.re)/(that.im*that.im + that.re * that.re))
  def unary_- = minus
  def + (that: Complex) = add(that)
  def - (that: Complex) = subtract(that)
  def * (that: Complex) = multiply(that)
  def / (that: Complex) = divide(that)
  def abs = sqrt(re * re + im * im)
}

def draw() {
  for(y <- 0 until height; x <- 0 until width){
    var zy = y * (yb - ya) / (height - 1) + ya
    var zx = x * (xb - xa) / (width  - 1) + xa
    var z = Complex(zx, zy)
    for(i <- 0 until maxIt){
      var dz = (f(z + Complex(h, h)) - f(z)) / Complex(h, h)
      var z0 = z - f(z) / dz
      if((z0 - z).abs < eps){
        //break
      }else{
        z = z0
        stroke(color(i % 4 * 64, i % 8 * 32, i % 16 * 16))
        point(x, y)
      }
    }
  }
}

感想

Pythonのコードを移植しただけなのに、全然違う絵ができたんですけど…
複素数クラスの精度をFloat型に変えたらさらにヘタった絵ができたので、単に精度の問題なのかしら。
あとScalaにはbreak文とcontinue文がないことを知った。
Semi-関数型言語なのだから再帰で書けという圧力を感じる…