2009/11/29

Book review: Transition, Iain Banks

Transition is a hard book to categorise, apparently. In the UK, it is credited to Iain Banks, the writer's chosen title for his non-Space-Opera, more literary works. In the USA, it is credited to his SFnal sobriquet, Iain M Banks.

This confusion is perhaps expected - whilst Transition's setting lacks the "space" of most of Banksie's SF settings, it replaces it seamlessly with "choices" (in the form of the multiple, possibly infinite, parallel worlds of the conventional SF glossing of the Many Worlds Interpretation of QM).
Instead of Special Circumstances, possibly, we have the active arm of The Concern - a millennia-old organisation based in something like the setting's Amber, and staffed by the only individuals in the reality who can Transition between worlds. The Concern sees itself, the narrator tells us, as engaged in the process of spreading good across as many realities as it can - gardening the Shadows, as it were* - sending its agents to (say) distract the future Nobel prize winner so he doesn't step out in front of that speeding car, or (in the regrettable few cases where it is necessary) killing future despots before they attain their power.

Of course, the narrator also tells us that he is Unreliable, in the very first sentence of the novel.

I have also misrepresented the truth just now: there is not one narrative stand, but several: along with the mostly-dominant strand of Temudjin Oh, Transitionary of the Concern, we also flit between Patient 8287, possibly mad, possibly an ex-transitionary in hiding as a madman, the resolutely self-centred bastard Adrian Cubbish (who appears initially to have no connection to the Concern at all), the torturer (who claims to have principles) known as The Philosopher, and make brief one-off excursions to others every so often.
This multithreaded narrative is an intentional mirror of one of the concerns of the novel itself - solipsism, and how the unconscious belief in such affects our society. Indeed, Banksie seems quite concerned with trying to make his point about the significance of belief in the reality of the Other (and the importance in empathy with it) in as many ways as possible - several realities are apparently very similar to ours, except in that Religious Terrorism is associated with the sick, martyrdom-obsessed Christians, for example. Of course, one does get the feeling that Banks is preaching to the converted here somewhat - the point that the Christian Terrorists are supposed to make seems to have merely whooshed over the head of the reviewer at the Telegraph, for example.
That is not to say that Transitions works entirely. The ending (sans-epilogue, which does fix things up a little) is disappointingly close to Deus-Ex-Machina (with a touch of Herbertian "stress causes you to evolve ability"), with only just enough foreshadowing and development to veer it off that course. In general, there's just a smidgeon too much self-indulgence, ironically; another reviewer noted that Transition reads like Banks took all of his Culture novels, extracted the 10% of scenes he most enjoyed writing, and smooshed them all together into one volume with no filler. This is not precisely a negative point against Transitions, depending on how closely you agree with Banks' taste in cool scenes, however it is slightly exhausting and overseasoned in result.

Short pitch: It's Amber meets the Culture's Special Circumstances, with a side-order of Miles Teg.

Comparative ranking: Better than "Inversions", not as good as "Excession"

*One of the most powerful individuals in The Concern, Madame Theodora d'Ortolan, appears to have a deliberately significant name, for people with a little French.

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);
}