The Mandelbrot-Set with Google Go (Part I)

>> Part II: The Mandelbrot-Set with Google Go (Part II)

Time to learn a new programming language. This time my decision fell on a quite young member of the programming language family, namely Google Go.

The various promised features really made me a bit excited about this language, so I decided to make a simple implementation of the Mandelbrot-Set (with the option to also calculate Julia-Sets).

To keep it short – here’s the code:

package main

import (
 "fmt"
 "os"
 "math"
 "image"
 "image/png"
 "bufio"
 "time"
 "flag"
)

var pointX = flag.Float64("x", -2.0, "X coordinate of starting point of Mandelbrot or fix point for Julia (range: 2.0 to 2.0)")
var pointY = flag.Float64("y", -2.0, "Y coordinate of starting point of Mandelbrot or fix point for Julia (range: 2.0 to 2.0)")
var zoom = flag.Float64("z", 1.0, "Zoom level (only working properly for Mandelbrot)")
var julia = flag.Bool("julia", false, "Turn on Julia calculation")
var maxIter = flag.Int("maxIter", 51, "Max number of point iterations")
var imgSize = flag.Int("imgSize", 1000, "Size of the image")

func main() {
 flag.Parse()

 fmt.Printf("X: %f\n", *pointX)
 fmt.Printf("Y: %f\n", *pointY)
 fmt.Printf("Zoom: %f\n", *zoom)
 fmt.Printf("Julia: %t\n", *julia)
 fmt.Printf("MaxIter: %d\n", *maxIter)
 fmt.Printf("ImgSize: %d\n", *imgSize)

 start := time.Nanoseconds()
 img := CalculateImage(*imgSize, *imgSize)
 end := time.Nanoseconds()
 fmt.Printf("Time: %d ms\n", (end - start) / 1000 / 1000) // ms
 WriteImage(img)
}

func CalculateImage(imgWidth int, imgHeight int) *image.NRGBA {
 img := image.NewNRGBA(imgWidth, imgHeight)
 minCx := -2.0
 minCy := -2.0
 if !*julia {
 minCx = *pointX
 minCy = *pointY
 }
 maxSquAbs := 4.0 // maximum square of the absolute value
 // calculate step widths
 stepX := math.Fabs(minCx - 2.0) / float64(imgWidth) / *zoom
 stepY := math.Fabs(minCy - 2.0) / float64(imgHeight) / *zoom
 cx := 0.0
 cy := 0.0
 for px := 0; px < imgWidth; px++ {
 cx = minCx + float64(px) * stepX

 for py := 0; py < imgHeight; py++ {
 cy = minCy + float64(py) * stepY

 iterValue := PointIteration(cx, cy, maxSquAbs, *maxIter)

 color := ChooseColor(iterValue, *maxIter)
 img.Set(px, py, color)
 }
 }
 return img
}

func PointIteration(cx float64, cy float64, maxSquAbs float64, maxIter int) int {
 squAbs := 0.0
 iter := 0
 x := 0.0
 y := 0.0
 if *julia {
 x = cx
 y = cy
 cx = *pointX
 cy = *pointY
 }

 for squAbs <= maxSquAbs && iter < maxIter {
 xt := (x * x) - (y * y) + cx // z^2
 yt := (2.0 * x * y) + cy // z^2
 //xt := x * (x*x - 3*y*y) + cx // z^3
 //yt := y * (3*x*x - y*y) + cy // z^3
 //xt := x * (x*x*x*x - 10*x*x*y*y + 5*y*y*y*y) + cx // z^5
 //yt := y * (5*x*x*x*x - 10*x*x*y*y + y*y*y*y) + cy // z^5
 x = xt
 y = yt
 iter++
 squAbs = (x * x) + (y * y)
 }
 return iter;
}

func ChooseColor(iterValue int, maxIter int) *image.NRGBAColor {
 val := uint8(iterValue)
 if iterValue == maxIter {
 return &image.NRGBAColor {0, 0, 0, 255}
 }
 multi := uint8(255 / maxIter)
 return &image.NRGBAColor {0, val*multi, 0, 255}
 //return &image.NRGBAColor{^(val*multi), ^(val*multi), ^(val*multi), 255} // grey
}

func WriteImage(img *image.NRGBA) {
 file, err := os.Create("mandelbrot.png")
 if err != nil {
 fmt.Printf("Could not create file %s", file.Name())
 }
 writer := bufio.NewWriter(file)
 png.Encode(writer, img)
 writer.Flush()
 file.Close()
}

I have to admit i did not take much effort in cleaning up or optimizing the code. Mea culpa. The needed time for calculating the Mandelbrot-Set (1000×1000 px; 51 iterations) was about 600 ms on a Kubuntu VM with 2 cores@2,4GHz and 2GB RAM.

So this approach was pretty much straightforward and did a good job in getting my feet wet with Go. The next step now is to utilize some of the main features of Go: channels and goroutines for parallelization.

Finally here some pics:

>> Part II: The Mandelbrot-Set with Google Go (Part II)

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: