Skip to content

Examples

These are complete, compilable programs straight from the Maxon repository — the same files you can run with ./bin/maxon. Each one leans on a different part of the language.

Spectral norm

Computes the largest eigenvalue of an infinite matrix with the power method. Shows ranged type aliases, try … otherwise inside hot loops, and labeled nesting.

spectral-norm.maxon
// Spectral-norm benchmark from Computer Language Benchmarks Game
// Calculate eigenvalue using the power method
// For n = 5500, result should be approximately 1.274224153

typealias VectorIndex = int(0 to 5500)
typealias Iteration = int(0 to 10)
typealias VectorComponent = float(0.0 to f64.max)
typealias Vector = Array with VectorComponent

function evalA(row VectorIndex, col VectorIndex) returns VectorComponent
	let indexSum = row + col
	let denominator = ((indexSum * (indexSum + 1)) / 2) + row + 1
	return 1.0 / denominator
end 'evalA'

function multiplyByMatrix(resultVector Vector, inputVector Vector, dimension VectorIndex)
	for row in 0 upto dimension 'outer'
		var accumulator = 0.0
		for col in 0 upto dimension 'inner'
			let inputComponent = try inputVector.get(col) otherwise 0.0
			accumulator = accumulator + (inputComponent * evalA(VectorIndex{row}, col: VectorIndex{col}))
		end 'inner'
		resultVector.set(row, value: accumulator)
	end 'outer'
end 'multiplyByMatrix'

function multiplyByTranspose(resultVector Vector, inputVector Vector, dimension VectorIndex)
	for row in 0 upto dimension 'outer'
		var accumulator = 0.0
		for col in 0 upto dimension 'inner'
			let inputComponent = try inputVector.get(col) otherwise 0.0
			accumulator = accumulator + (inputComponent * evalA(VectorIndex{col}, col: VectorIndex{row}))
		end 'inner'
		resultVector.set(row, value: accumulator)
	end 'outer'
end 'multiplyByTranspose'

function applyAtA(resultVector Vector, inputVector Vector, workspace Vector, dimension VectorIndex)
	multiplyByMatrix(workspace, inputVector: inputVector, dimension: dimension)
	multiplyByTranspose(resultVector, inputVector: workspace, dimension: dimension)
end 'applyAtA'

function main() returns ExitCode
	let problemSize = VectorIndex{5500}

	var eigenvector = Vector.create()
	eigenvector.resize(5500)
	var previousVector = Vector.create()
	previousVector.resize(5500)
	var workspace = Vector.create()
	workspace.resize(5500)

	for index in 0 upto problemSize 'init'
		eigenvector.set(index, value: 1.0)
	end 'init'

	var iteration = Iteration{0}
	while iteration < 10 'iterate'
		applyAtA(previousVector, inputVector: eigenvector, workspace: workspace, dimension: problemSize)
		applyAtA(eigenvector, inputVector: previousVector, workspace: workspace, dimension: problemSize)
		iteration = Iteration{iteration + 1}
	end 'iterate'

	var numerator = 0.0
	var denominator = 0.0
	for index in 0 upto problemSize 'rayleigh'
		let uComponent = try eigenvector.get(index) otherwise 0.0
		let vComponent = try previousVector.get(index) otherwise 0.0
		numerator = numerator + (uComponent * vComponent)
		denominator = denominator + (vComponent * vComponent)
	end 'rayleigh'

	let spectralNorm = sqrt(numerator / denominator)

	return trunc(spectralNorm * 1000000000.0)
end 'main'

N-body simulation

A classic gravitational simulation of the outer solar system. Shows struct types with methods, static constructors, and named arguments.

nbody.maxon
// N-Body simulation from Computer Language Benchmarks Game
// https://benchmarksgame-team.pages.debian.net/benchmarksgame/program/nbody-rust-1.html
//
// Expected output (9 decimal places):
// -0.169075164
// -0.169059907

typealias Integer = int(i64.min to i64.max)
typealias Real = float(f64.min to f64.max)
typealias PlanetArray = Array with Planet

type Planet
	export var x as Real
	export var y as Real
	export var z as Real
	export var vx as Real
	export var vy as Real
	export var vz as Real
	export var mass as Real

	static function create(x Real, y Real, z Real, vx Real, vy Real, vz Real, mass Real) returns Planet
		return Planet{x: x, y: y, z: z, vx: vx, vy: vy, vz: vz, mass: mass}
	end 'create'
end 'Planet'

function initBodies(bodies PlanetArray)
	// Constants
	let SOLAR_MASS = 39.478417604357432  // 4.0 * PI * PI
	let DAYS_PER_YEAR = 365.24

	// Sun (at origin with zero velocity initially)
	bodies.set(0, value: Planet.create(0.0, y: 0.0, z: 0.0, vx: 0.0, vy: 0.0, vz: 0.0, mass: SOLAR_MASS))

	// Jupiter
	bodies.set(1, value: Planet.create(
	4.84143144246472090e+00,
	y: -1.16032004402742839e+00,
	z: -1.03622044471123109e-01,
	vx: 1.66007664274403694e-03 * DAYS_PER_YEAR,
	vy: 7.69901118419740425e-03 * DAYS_PER_YEAR,
	vz: -6.90460016972063023e-05 * DAYS_PER_YEAR,
	mass: 9.54791938424326609e-04 * SOLAR_MASS
	))

	// Saturn
	bodies.set(2, value: Planet.create(
	8.34336671824457987e+00,
	y: 4.12479856412430479e+00,
	z: -4.03523417114321381e-01,
	vx: -2.76742510726862411e-03 * DAYS_PER_YEAR,
	vy: 4.99852801234917238e-03 * DAYS_PER_YEAR,
	vz: 2.30417297573763929e-05 * DAYS_PER_YEAR,
	mass: 2.85885980666130812e-04 * SOLAR_MASS
	))

	// Uranus
	bodies.set(3, value: Planet.create(
	1.28943695621391310e+01,
	y: -1.51111514016986312e+01,
	z: -2.23307578892655734e-01,
	vx: 2.96460137564761618e-03 * DAYS_PER_YEAR,
	vy: 2.37847173959480950e-03 * DAYS_PER_YEAR,
	vz: -2.96589568540237556e-05 * DAYS_PER_YEAR,
	mass: 4.36624404335156298e-05 * SOLAR_MASS
	))

	// Neptune
	bodies.set(4, value: Planet.create(
	1.53796971148509165e+01,
	y: -2.59193146099879641e+01,
	z: 1.79258772950371181e-01,
	vx: 2.68067772490389322e-03 * DAYS_PER_YEAR,
	vy: 1.62824170038242295e-03 * DAYS_PER_YEAR,
	vz: -9.51592254519715870e-05 * DAYS_PER_YEAR,
	mass: 5.15138902046611451e-05 * SOLAR_MASS
	))
end 'initBodies'

function offsetMomentum(bodies PlanetArray, n Integer)
	let SOLAR_MASS = 39.478417604357432  // 4.0 * PI * PI

	var px = 0.0
	var py = 0.0
	var pz = 0.0

	for i in 0 upto n 'momentum_loop'
		var body = try bodies.get(i) otherwise Planet.create(0.0, y: 0.0, z: 0.0, vx: 0.0, vy: 0.0, vz: 0.0, mass: 0.0)
		px = px + body.vx * body.mass
		py = py + body.vy * body.mass
		pz = pz + body.vz * body.mass
	end 'momentum_loop'

	var sun = try bodies.get(0) otherwise Planet.create(0.0, y: 0.0, z: 0.0, vx: 0.0, vy: 0.0, vz: 0.0, mass: 0.0)
	sun.vx = -px / SOLAR_MASS
	sun.vy = -py / SOLAR_MASS
	sun.vz = -pz / SOLAR_MASS
	bodies.set(0, value: sun)
end 'offsetMomentum'

function energy(bodies PlanetArray, n Integer) returns Real
	var e = 0.0

	for i in 0 upto n 'outer_energy'
		var bi = try bodies.get(i) otherwise Planet.create(0.0, y: 0.0, z: 0.0, vx: 0.0, vy: 0.0, vz: 0.0, mass: 0.0)
		// Kinetic energy: 0.5 * m * v^2
		e = e + 0.5 * bi.mass * (bi.vx * bi.vx + bi.vy * bi.vy + bi.vz * bi.vz)

		// Potential energy with other bodies
		var j = i + 1
		while j < n 'inner_energy'
			var bj = try bodies.get(j) otherwise Planet.create(0.0, y: 0.0, z: 0.0, vx: 0.0, vy: 0.0, vz: 0.0, mass: 0.0)
			let dx = bi.x - bj.x
			let dy = bi.y - bj.y
			let dz = bi.z - bj.z

			let distance = sqrt(dx * dx + dy * dy + dz * dz)
			e = e - (bi.mass * bj.mass) / distance

			j = j + 1
		end 'inner_energy'
	end 'outer_energy'

	return e
end 'energy'

function advance(bodies PlanetArray, n Integer, dt Real)
	for i in 0 upto n 'outer_advance'
		var bi = try bodies.get(i) otherwise Planet.create(0.0, y: 0.0, z: 0.0, vx: 0.0, vy: 0.0, vz: 0.0, mass: 0.0)
		var j = i + 1
		while j < n 'inner_advance'
			var bj = try bodies.get(j) otherwise Planet.create(0.0, y: 0.0, z: 0.0, vx: 0.0, vy: 0.0, vz: 0.0, mass: 0.0)
			let dx = bi.x - bj.x
			let dy = bi.y - bj.y
			let dz = bi.z - bj.z

			let dist_sq = dx * dx + dy * dy + dz * dz
			let distance = sqrt(dist_sq)
			let mag = dt / (dist_sq * distance)

			let bj_mass_mag = bj.mass * mag
			let bi_mass_mag = bi.mass * mag

			bi.vx = bi.vx - dx * bj_mass_mag
			bi.vy = bi.vy - dy * bj_mass_mag
			bi.vz = bi.vz - dz * bj_mass_mag

			bj.vx = bj.vx + dx * bi_mass_mag
			bj.vy = bj.vy + dy * bi_mass_mag
			bj.vz = bj.vz + dz * bi_mass_mag

			bodies.set(j, value: bj)
			j = j + 1
		end 'inner_advance'
		bodies.set(i, value: bi)
	end 'outer_advance'

	// Update positions
	for k in 0 upto n 'update_positions'
		var body = try bodies.get(k) otherwise Planet.create(0.0, y: 0.0, z: 0.0, vx: 0.0, vy: 0.0, vz: 0.0, mass: 0.0)
		body.x = body.x + dt * body.vx
		body.y = body.y + dt * body.vy
		body.z = body.z + dt * body.vz
		bodies.set(k, value: body)
	end 'update_positions'
end 'advance'

function main() returns ExitCode
	let n = 5  // Number of bodies
	var bodies = PlanetArray.create()
	bodies.resize(5)

	initBodies(bodies)
	offsetMomentum(bodies, n: n)

	// Print initial energy
	let e1 = energy(bodies, n: n)
	print("{e1}")

	// Run simulation for 50,000,000 steps
	let steps = 50000000
	var step = 0
	while step < steps 'simulation'
		advance(bodies, n: n, dt: 0.01)
		step = step + 1
	end 'simulation'

	// Print final energy
	let e2 = energy(bodies, n: n)
	print("{e2}")

	return 0
end 'main'

Fannkuch-redux

Generates every permutation of an array and counts pancake flips. Shows array manipulation and integer-heavy control flow.

fannkuch-redux.maxon
// Fannkuch-redux benchmark from Computer Language Benchmarks Game
// https://benchmarksgame-team.pages.debian.net/benchmarksgame/description/fannkuchredux.html#fannkuchredux
//
// This implementation is a single-threaded version of the algorithm.
// The algorithm generates all permutations of [0..n-1] and counts the maximum
// number of "flips" (reversals from position 0 to position p[0]) needed
// to sort any permutation back to the identity permutation.
//
// Expected output for n=10:
// 73196
// Pfannkuchen(10) = 38
//
// Expected output for n=12:
// 3968050
// Pfannkuchen(12) = 65

typealias Integer = int(i64.min to i64.max)
typealias IntArray = Array with Integer

// Compute factorial
function factorial(n Integer) returns Integer
	var result = 1
	for i in 1 to n 'fact_loop'
		result = result * i
	end 'fact_loop'
	return result
end 'factorial'

// Copy array from src to dst
function copyArray(dst IntArray, src IntArray, n Integer)
	for i in 0 upto n 'copy_loop'
		dst.set(i, value: try src.get(i) otherwise 0)
	end 'copy_loop'
end 'copyArray'

// Generate the idx-th permutation of n elements
function getPermutation(p IntArray, count IntArray, fact IntArray, n Integer, idx Integer)
	// Initialize to identity permutation
	for i in 0 upto n 'init_loop'
		p.set(i, value: i)
	end 'init_loop'

	// Generate the idx-th permutation using factorial base
	var pp = IntArray.create()
	pp.resize(16)
	var remaining = idx
	var i = n - 1
	while i > 0 'perm_loop'
		var d = trunc(remaining / (try fact.get(i) otherwise 1))
		count.set(i, value: d)
		remaining = remaining mod (try fact.get(i) otherwise 1)

		// Copy current permutation to temporary
		copyArray(pp, src: p, n: n)

		// Rotate: p[j] = pp[j+d] (with wraparound)
		var j = 0
		while j <= i 'rotate_loop'
			if j + d <= i 'in_bounds'
				p.set(j, value: try pp.get(j + d) otherwise 0)
			end 'in_bounds' else 'out_of_bounds'
				p.set(j, value: try pp.get(j + d - i - 1) otherwise 0)
			end 'out_of_bounds'
			j = j + 1
		end 'rotate_loop'

		i = i - 1
	end 'perm_loop'
end 'getPermutation'

// Count the number of flips for a permutation
function countFlips(perm IntArray, n Integer) returns Integer
	var first = try perm.get(0) otherwise 0
	if first == 0 'check_sorted'
		return 0
	end 'check_sorted'

	// Copy permutation for flipping
	var pp = IntArray.create()
	pp.resize(16)
	copyArray(pp, src: perm, n: n)

	var flips = 1
	var firstValue = first

	while (try pp.get(firstValue) otherwise 0) != 0 'flip_loop'
		var newFirst = try pp.get(firstValue) otherwise 0
		pp.set(firstValue, value: firstValue)

		// Reverse middle elements if firstValue > 2
		if firstValue > 2 'reverse_middle'
			var i = 1
			var j = firstValue - 1
			while i < j 'reverse_loop'
				var temp = try pp.get(i) otherwise 0
				pp.set(i, value: try pp.get(j) otherwise 0)
				pp.set(j, value: temp)
				i = i + 1
				j = j - 1
			end 'reverse_loop'
		end 'reverse_middle'

		firstValue = newFirst
		flips = flips + 1
	end 'flip_loop'

	return flips
end 'countFlips'

// Advance to next permutation
function nextPermutation(p IntArray, count IntArray)
	// Swap p[0] and p[1]
	var firstValue = try p.get(1) otherwise 0
	p.set(1, value: try p.get(0) otherwise 0)
	p.set(0, value: firstValue)

	var i = 1
	while (try count.get(i) otherwise 0) >= i 'rotate_loop'
		count.set(i, value: 0)
		i = i + 1

		var newFirst = try p.get(1) otherwise 0
		p.set(0, value: newFirst)

		// Rotate left
		for j in 1 upto i 'shift_loop'
			p.set(j, value: try p.get(j + 1) otherwise 0)
		end 'shift_loop'

		p.set(i, value: firstValue)
		firstValue = newFirst
	end 'rotate_loop'

	count.set(i, value: (try count.get(i) otherwise 0) + 1)
end 'nextPermutation'

function main() returns ExitCode
	var n = 11

	// Compute factorials
	var fact = IntArray.create()
	fact.resize(17)
	for i in 0 to n 'fact_init'
		fact.set(i, value: factorial(i))
	end 'fact_init'

	var totalPerms = try fact.get(n) otherwise 0

	// Working arrays
	var p = IntArray.create()
	p.resize(16)
	var count = IntArray.create()
	count.resize(16)

	// Initialize to first permutation
	getPermutation(p, count: count, fact: fact, n: n, idx: 0)

	var maxFlips = 0
	var checkSum = 0
	var idx = 0

	while idx < totalPerms 'main_loop'
		// Count flips for current permutation
		if (try p.get(0) otherwise 0) != 0 'need_flips'
			var flips = countFlips(p, n: n)

			if flips > maxFlips 'update_max'
				maxFlips = flips
			end 'update_max'

			// Update checksum (alternating sign based on permutation index)
			if idx mod 2 == 0 'even_perm'
				checkSum = checkSum + flips
			end 'even_perm' else 'odd_perm'
				checkSum = checkSum - flips
			end 'odd_perm'
		end 'need_flips'

		// Advance to next permutation
		idx = idx + 1
		if idx < totalPerms 'continue_loop'
			nextPermutation(p, count: count)
		end 'continue_loop'
	end 'main_loop'

	// Results verified for n=10:
	// - checkSum: 73196
	// - maxFlips: 38
	// Returning maxFlips as exit code
	return maxFlips
end 'main'

Want to walk through the language step by step instead? Start with your first program →