Created
May 14, 2012 17:34
-
-
Save foota/2695238 to your computer and use it in GitHub Desktop.
Mandelbrot sets (parallel processing)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
http://handasse.blogspot.com/2011/07/scala.html