Created
June 28, 2011 11:21
-
-
Save fedelebron/1050931 to your computer and use it in GitHub Desktop.
Parallel Mandelbrot in Go
This file contains 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
package main | |
import ( | |
"flag" | |
"image" | |
"image/color" | |
"image/png" | |
"math" | |
"os" | |
) | |
func modulus(z complex128) float64 { | |
a := real(z) | |
b := imag(z) | |
return math.Sqrt(a*a + b*b) | |
} | |
func escapeTime(a float64, b float64) (int, float64) { | |
c := complex(a, b) | |
iters := 0 | |
z := c | |
m := modulus(c) | |
for m < 10 { | |
z = z*z + c | |
m = modulus(z) | |
iters++ | |
if iters == 100 { | |
return -1, m | |
} | |
} | |
return iters, m | |
} | |
func getColor(time int) color.Color { | |
if time == -1 { | |
return image.Black | |
} | |
return image.White | |
} | |
type mandelbrotWriter struct { | |
f *os.File | |
offset int64 | |
} | |
func newMandelbrotWriter(file string) mandelbrotWriter { | |
var w mandelbrotWriter | |
w.f, _ = os.Create(file) | |
w.offset = 0 | |
return w | |
} | |
func (m *mandelbrotWriter) Write(p []uint8) (n int, err error) { | |
n, _ = m.f.WriteAt(p, m.offset) | |
m.offset += int64(n) | |
return n, nil | |
} | |
type Painter func(iterations int, value float64) color.RGBA | |
func makePainter(pallete_size int, starting_color color.RGBA, ending_color color.RGBA) Painter { | |
startR := int(starting_color.R) | |
startG := int(starting_color.G) | |
startB := int(starting_color.B) | |
increases := [3]float64{(float64(ending_color.R) - float64(startR)) / float64(pallete_size), | |
(float64(ending_color.G) - float64(startG)) / float64(pallete_size), | |
(float64(ending_color.B) - float64(startB)) / float64(pallete_size)} | |
table := make([]color.RGBA, pallete_size) | |
for i := 0; i < pallete_size; i++ { | |
table[i] = color.RGBA{uint8(math.Floor(float64(startR) + float64(i)*increases[0])), | |
uint8(math.Floor(float64(startG) + float64(i)*increases[1])), | |
uint8(math.Floor(float64(startB) + float64(i)*increases[2])), | |
0xFF} | |
} | |
lnP := math.Log(2) | |
tlnB := 2 * math.Log(20) | |
getColorId := func(iterations int, value float64) int { | |
return iterations + int(math.Log(tlnB-math.Log(math.Log(value)))/lnP) | |
} | |
return func(iterations int, value float64) color.RGBA { | |
if iterations == -1 { | |
return color.RGBA{0, 0, 0, 0xFF} | |
} | |
index := (getColorId(iterations, value)) * (pallete_size / 100) | |
if index < 0 { | |
index = 0 | |
} | |
if index >= pallete_size { | |
return color.RGBA{0, 0, 0, 0xFF} | |
} | |
return table[index] | |
} | |
} | |
func main() { | |
imageWidth := 800 | |
imageHeight := 600 | |
halfHeight := imageHeight / 2 | |
halfWidth := imageWidth / 2 | |
var scale float64 | |
flag.Float64Var(&scale, "scale", 1, "The scale of the image") | |
var offsetx float64 | |
flag.Float64Var(&offsetx, "x", 0, "The x-offset of the image") | |
var offsety float64 | |
flag.Float64Var(&offsety, "y", 0, "The y-offset of the image") | |
flag.Parse() | |
var w mandelbrotWriter = newMandelbrotWriter("mandelbrot.png") | |
var mandelbrot *image.RGBA = image.NewRGBA(image.Rect(0, 0, imageWidth, imageHeight)) | |
var painter Painter = makePainter(2<<8, color.RGBA{8, 192, 68, 0xFF}, color.RGBA{157, 21, 21, 0xFF}) | |
const ncores = 2 | |
scale *= 100 | |
k := 0 | |
step := imageWidth / ncores | |
c := make(chan int, ncores) | |
for k < imageWidth { | |
go func(m int) { | |
i := m | |
for i < m+step { | |
j := 0 | |
for j < imageHeight { | |
x := float64(i-halfWidth)/scale + float64(offsetx) | |
y := float64(j-halfHeight)/scale + float64(offsety) | |
mandelbrot.Set(i, j, painter(escapeTime(x, y))) | |
j++ | |
} | |
i++ | |
} | |
c <- 1 | |
}(k) | |
k += step | |
} | |
for i := 0; i < ncores; i++ { | |
<-c | |
} | |
png.Encode(&w, mandelbrot) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Rewrote for Go 1 :)