## 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)