Skip to content

Instantly share code, notes, and snippets.

@fedelebron
Created June 28, 2011 11:21
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 fedelebron/1050931 to your computer and use it in GitHub Desktop.
Save fedelebron/1050931 to your computer and use it in GitHub Desktop.
Parallel Mandelbrot in Go
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)
}
@fedelebron
Copy link
Author

Rewrote for Go 1 :)

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