Skip to content

Instantly share code, notes, and snippets.

@foota
Created May 14, 2012 17:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save foota/2695238 to your computer and use it in GitHub Desktop.
Save foota/2695238 to your computer and use it in GitHub Desktop.
Mandelbrot sets (parallel processing)
// mandelbrot.scala with actor by nox, 2011.07.09
import scala.actors._, Actor._
import scala.annotation.tailrec
import java.io.FileOutputStream
import java.awt.image.BufferedImage
import java.awt.Color
import javax.imageio.ImageIO
import scala.testing.Benchmark
/**
* マンデルブロ集合.
* SW : 画像の幅.
* SH : 画像の高さ.
* T : 集合の上の位置.
* L : 集合の左の位置.
* W : 集合の幅.
* H : 集合の高さ.
* MAX_LOOP : イテレーションの最大回数.
* TH : 閾値.
*/
final class Mandelbrot(SW: Int, SH: Int, T: Double, L: Double, W: Double, H: Double, MAX_LOOP: Int, TH: Double) {
/**
* イテレーションの回数から色を決定して任意のピクセルにセットする.
*/
def setPixel(x: Int, y: Int, a: Any, image: BufferedImage) =
a match {
case -1 => image setRGB(x, y, 0)
case i: Int => image setRGB(x, y, Color HSBtoRGB(i / 100.0f, 1.0f, 1.0f))
}
/**
* マンデルブロ集合の計算部分.
*/
@tailrec
def calcLoop(i: Int, cr: Double, ci: Double, zr: Double, zi: Double): Int = {
val zr2 = zr * zr
val zi2 = zi * zi
i match {
case MAX_LOOP => -1
case _ if zr2 + zi2 >= TH => i
case _ => {
val zrzi = zr * zi
calcLoop(i + 1, cr, ci, zr2 - zi2 + cr, zrzi + zrzi + ci)
}
}
}
/**
* アクター.
* ある幅に存在するピクセルの計算を受け持つ.
*/
def calc = actor {
react {
case (ix: Int, image: BufferedImage) => {
for (iy <- 0 until SH)
setPixel(ix, iy, calcLoop(0, L + (ix.toDouble / SW) * W, T + (iy.toDouble / SH) * H, 0.0, 0.0), image)
reply(ix)
}
}
}
/**
* 幅のピクセル数分だけアクターにメッセージを送る.
*/
@tailrec
def runLoop(ix: Int, results: Array[Future[Any]], image: BufferedImage): Unit =
ix match {
case SW => results foreach(_ apply)
case _ => {
results(ix) = calc !! ((ix, image))
runLoop(ix + 1, results, image)
}
}
/**
* 実行.
* 計算部分の処理時間計測および画像ファイルの書き出し.
*/
def run = {
val results = new Array[Future[Any]](SW)
val image = new BufferedImage(SW, SH, BufferedImage TYPE_3BYTE_BGR)
val t = (new Benchmark { def run = runLoop(0, results, image) } runBenchmark 1)(0) / 1000.0
println("Time: " + t + " s")
val out = new FileOutputStream("mandelbrot.png")
ImageIO write(image, "png", out)
out close
}
}
object MandelbrotMain {
def main(args: Array[String]) =
new Mandelbrot(4800, 4800, -0.005, -0.005, 0.01, 0.01, 10000, 10.0) run
//new Mandelbrot(640, 480, -1.0, -2.0, 2.6666667, 2.0, 1000, 10.0) run
//new Mandelbrot(800, 800, 0.025185, -1.401565, 0.0005, 0.0005, 10000, 10.0) run
}
@foota
Copy link
Author

foota commented May 14, 2012

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment