2009/11/22

Golang - post 1

A "multibrot" generator in the Google Go programming language.
Should be called with [program name] [number]
where number is a mandatory value corresponding to the exponent of Z in the generalised Mandelbrot formula (and can be a float).
Outputs a file named mandel#.png, where # is the number given, which is a 1000x1000 png of the Complex plane from (-2-1.5i) to (2+1.5i).

Comments will come in an edit to this post etc.


package main
/* Fractal generator written in Go */

import "math"
import "fmt"
import "image"
import "image/png"
//import "io"
import "os"
import "strconv"

type Complex struct {
re,im float64;
}

func Mul (a, b Complex) (c Complex) {
c.re = a.re*b.re - a.im*b.im;
c.im = a.re*b.im + a.im*b.re;
return c
}

func Plus (a, b Complex) (c Complex) {
c.re = a.re + b.re;
c.im = a.im + b.im;
return c
}

func Conj (a Complex) (c Complex) {
c.re = a.re;
c.im = -a.re;
return c
}

func Mag (a Complex) (b float64) {
return math.Sqrt(a.re*a.re + a.im*a.im);
}

func Arg (a Complex) (b float64) {
if (a.im != 0) || (a.re > 0) {
return float64(2.0)*math.Atan(a.im / (Mag(a) + a.re));
}
else {
return float64(3.141592653589793);
}
return float64(0.0)
}


func Pow (a Complex, p float64) (b Complex) {
var x, y float64 = Mag(a), Arg(a);
x = math.Pow(x, p);
y = y*p;
b.re = x*math.Cos(y);
b.im = x*math.Sin(y);
return b;
}

func Mandel_mapping (z, c Complex) (zprime Complex) {
zprime = Plus(Mul(z,z), c);
return zprime
}


func Multibrot_mapping (z, c Complex, p float64) (zprime Complex) {
zprime = Plus(Pow(z, p), c);
return zprime;
}

const MAXITER int = 500;

func Mandel_membership_test (c Complex, p float64, colour bool) (t bool, its int, val float64) {
z := Complex{0.0, 0.0};
i,j := int(1), int(0);
t = true;
for i = 0; i < z =" Mandel_mapping(z," z =" Multibrot_mapping(z,"> float64(2.0) {
if colour == false { //return a simple escape count - the point at which we escape
return false, i, 0;
}
else {
t = false;
if j == 0 {
j = i;
}
else if i - j == 2 { //two iterations after escape, so Z gets biggish, use the exterior escape function for value
return false, i, Mag(z);
}
}
}
}
if t == false {
return t, i, Mag(z);
}
return true, 0, 0;

}

const XMAX int = 1000;
const YMAX int = 1000;
const REMIN float64 = -2.0;
const REMAX float64 = 2.0;
const IMMIN float64 = -1.5;
const IMMAX float64 = 1.5;
const RERNG float64 = REMAX - REMIN;
const IMRNG float64 = IMMAX - IMMIN;
//const POWER float64 = 2.0
func main () {
var x, y int;
var c Complex;
var t bool;
var its int;
var val float64;
var normal float64 = math.Log(float64(MAXITER));
var img *image.NRGBA = image.NewNRGBA(int(XMAX),int(YMAX));
var col image.NRGBAColor;
var POWER float64;
var testbit os.Error;
POWER, testbit = strconv.Atof64(os.Args[1]);
if testbit != nil {
fmt.Printf("Enter a number! %v %v", POWER, testbit);
return
}
for x = 0; x < XMAX; x++ {
c.im = IMRNG*float64(x)/float64(XMAX) + IMMIN;
for y = 0; y < YMAX; y++ {
c.re = RERNG*float64(y)/float64(YMAX) + REMIN;
//fmt.Printf("%v,%v", x, y);
t, its, val = Mandel_membership_test(c, POWER, true);
if t == true {
fmt.Printf("*");
col.R, col.G, col.B, col.A = 0,0,0,255;
img.Set(x,y,col);
}
else {
fmt.Printf(" ");
col.R, col.G, col.B, col.A = uint8(math.Sin(math.Log(val))*128+255) , uint8(math.Cos(math.Log(val*float64(its)))*128+255), uint8((normal - math.Log(float64(its)))*255), 255;
img.Set(x,y,col);
}
}
fmt.Printf("\n");
}
//Write the image out as a png
var outputfile, _ = os.Open("mandel" + strconv.Ftoa64(POWER, 'f', -1) + ".png", os.O_WRONLY | os.O_CREAT, 0666);
png.Encode(outputfile, img);
outputfile.Close();
//fmt.Printf("%v", os.Args)
//fmt.Printf("%v", arr);
}

No comments: