AIFS Language Reference
AIFS is the program format used by IFStile
and the ifslib rendering library. It describes iterated function systems
ranging from simple 2D contractions to high-dimensional algebraic IFS projected onto
the plane. The language is documented formally in
Mekhontsev (2019), Appendix E
.
File Structure
@@import other.aifs # optional: include another .aifs file
@ID:ParentID # start of a block; ID and ParentID are optional
# comment
$dim=2 # dimension of the rational space (required per block)
...
A file contains any number of blocks separated by @ID:ParentID lines.
Each block is a GIFS that may define multiple attractor sets.
Each block inherits all definitions from its parent and can override them.
ID may be empty (@); ParentID may be empty (no parent).
Rendering selection
-
ifslib(used in this site) renders the first visible block and within it the first visible attractor set, unless$rootoverrides this. - IFStile lets you browse all blocks and all sets within a block via its IFS List UI.
Variable Types
| Prefix | Meaning |
|---|---|
| (none) | Ordinary variable — computed once |
$name | Built-in special variable (e.g. $dim, $subspace) |
&name | Substitution macro — re-evaluated at every use site |
Operators
| Syntax | Meaning |
|---|---|
f1*f2 | Composition: x → f1(f2(x)) |
S1|S2 | Union of sets (or operators): S1 ∪ S2 |
f^n | n-fold composition f ∘ f ∘ … ∘ f |
f^-1 | Inverse map f⁻¹ |
+ - * / ^ | Arithmetic on scalars and matrices |
a%b | Modulo — result has sign of b (Python-style); b=0 returns a |
$i | Identity map |
$e | Empty set ∅ |
Precedence note: 2*[1,0] = 2(x+[1,0]) = 2x+[2,0],
but [1,0]*2 = 2x+[1,0]. The general rule is
[t]*M gives f(x) = M·x + t (standard affine form).
Vectors and Matrices
[a1, a2, ..., an] defines a vector of n elements, automatically
converted to a translation or matrix by context:
- For
$dim=2: a 2-vector is a translation, a 4-vector is a 2×2 matrix (row-major). - For
$dim=n: an n-vector is a translation, n²-vector is an n×n matrix. - Element access: if
v=[a1,..,an]thenv[0]=a1,v[n-1]=an.
Affine Maps
The standard 2D affine map form is:
f=[tx,ty]*[a,b,c,d] # f(x) = [[a,b],[c,d]]·x + [tx,ty]
[tx,ty] # pure translation by [tx,ty]
[0.5,0,0,0.5] # pure scaling by 0.5 (no translation) Special Matrix Constructors
| Syntax | Meaning |
|---|---|
$companion([a0,...,an-1]) | Companion matrix for the monic polynomial a₀ + a₁x + … + aₙ₋₁xⁿ⁻¹ + xⁿ |
$exchange() | Anti-diagonal identity matrix (exchange matrix χₙ) |
$charpoly(M) | Characteristic polynomial coefficients of matrix M as a vector [a0,...,an-1] (monic, ascending) |
$numden(val, eps?) | Rational approximation of val — returns [numerator, denominator], or [0,0] if none found within tolerance |
$pi | The constant π |
Example: s=$companion([1,-1,1,-1]) builds the companion
matrix for x⁴−x³+x²−x+1 (the 10th cyclotomic polynomial), whose eigenvalues are
primitive 10th roots of unity — two complex conjugate pairs.
Index 0 selects the first complex pair (a 2D real Jordan cell), so
$subspace=[s,0] alone projects to a 2D plane where the action of s
is a rotation by π/5 = 36°.
Special Variables
| Variable | Meaning |
|---|---|
$dim=n | Dimension of the rational space. All affine maps must have this dimension. Required in every block. |
$n=name | Human-readable name for the block, displayed in IFStile's block list. No effect on rendering. |
$subspace=[M, i1, i2, …] |
Projects from the n-dimensional rational space to a rendering subspace.
M is a matrix identifier (typically defined via $companion);
each index selects one real Jordan cell of M.
A real eigenvalue → 1D cell (contributes 1 rendering dimension);
a complex conjugate pair → 2D cell (contributes 2 rendering dimensions).
The total rendering dimension is the sum of the selected cells' dimensions.
Indices are 0-based positions in the sequence of eigenvalues with Im(λ) ≥ 0,
ordered by decreasing modulus (ties broken by decreasing real part).
|
$root=name |
Selects which attractor set is shown first in this block.
ifslib always renders this set; IFStile uses it as the
initial selection when the user first switches to the block.
Not needed if the desired set is already the first one defined in the block.
|
$camera=… |
Sets the view for a block. Two formats: 2D: $camera=[cx, cy, r, angle] — center (cx,cy),
screen radius r, rotation angle in degrees.3D: $camera=[[loc],[target],[up],fov] — camera position,
look-at point, up vector, field of view in degrees.Example 3D: $camera=[[-0.1,0.55,-3],[0.5,-0.5,0.62],[0.17,0.74,0.15],30].Supported by both ifslib and IFStile.
|
$a=c | Marks the block as checked in IFStile's UI. UI-only — has no effect on ifslib. |
$a=h |
Marks the block as hidden. Both ifslib and IFStile skip hidden blocks;
ifslib searches for the first non-hidden block to render.
Hidden blocks can still be used as parent blocks.
|
When $dim=2 no $subspace is needed — the rational and
rendering spaces coincide. For higher-dimensional rational forms use
$subspace to select the 2D eigenplane where the attractor lives.
Mathematical Functions
Available for scalar expressions:
sin, cos, tan,
asin, acos, atan,
exp, log, floor, ceil, arg,
if — conditional (three forms):
if(cond)→ 1 ifcond > 0, else 0if(cond, val1, val2)→val1ifcond > 0, elseval2if(cond1, val1, cond2, val2, default)→ multi-branch: first positive condition wins
Array Operations
| Syntax | Meaning |
|---|---|
a[-1] | Negative index: last element (a[-2] = second-to-last, etc.) |
a() | Array size (number of elements) |
a[start:end:step] | Python-style slicing; step optional (default 1); negative step reverses |
a[] | Flatten one nesting level |
a[idxArr] | Fancy indexing: select multiple elements by index array |
[e0,e1,...](idx) | Lazy indexing: evaluates only element at idx, others are not computed |
Auto-generation syntax — a single array can contain any number of generator segments interleaved with static elements:
[static..., $, termCond, genExpr, static..., $, termCond, genExpr, static...] - Static elements before, between, and after generator segments are appended as-is.
$— marks start of a generator segment;$is shorthand for$(0)— a reference to the current array being built$()=$(0)()= current length of the array being built (equals current index during generation)$[-1]=$(0)[-1]= last element of the current array (i.e. the previously appended element)$(1),$(2), … — references to enclosing (parent, grandparent, …) arrays; useful when building nested arraystermCond— generate whiletermCond > 0;N-$()generates until total count reaches NgenExpr— expression for each generated elementtail...— zero or more static elements appended after generation stops
Examples:
-
[0, 1, $, 7-$(), $[-1]+$[-2]]→ 7 Fibonacci values[0,1,1,2,3,5,8]
Stops by count:7-$()becomes 0 once 7 elements have been appended. -
[1, $, 1000-$[-1], $[-1]*2]→ powers of 2 while last element < 1000:[1,2,4,8,...,512]
Stops by value:1000-$[-1]goes non-positive once the last element reaches 1000.
Block Functions
Any block (@name) can be used as a reusable function:
@funcName
param1 = defaultVal # parameter with default value
param2 = defaultVal
ret = expr # return value
@
result = funcName(arg1, arg2) # call by position
result = funcName() # call with all defaults
result = $new(funcName, param2, val) # named override
field = result.param1 # field access on block instance - The last variable defined in the block is the return value. Naming it
retis a readable convention — the name has no special meaning. - Block inheritance:
@child:parent— child overrides parent variables; any block can be a parent. @:ParentID— anonymous child block, inherits from parent.
JavaScript Interop
AIFS files can embed ES module JavaScript before the first @@ separator:
export function funcName(arg) { return arg + 1; }
export const constArr = [11, 12];
@@
@
$init = funcName # call JS function once at init
result = funcName(3) # call JS function from AIFS
val = constArr[1] # access JS constant - JS functions callable from AIFS must be
exported. console.log(...)is available inside JS functions.$init = jsFunccallsjsFunconce during block initialization; the function can setthis.varName = valueto inject AIFS variables.
Attractor Equations
Ordinary IFS
S=(f1|f2|f3)*S # S is the unique compact attractor of {f1,f2,f3} The attractor equation is mandatory.
Without it ifslib_init returns 0 and nothing renders.
GIFS — Generalized IFS (multiple attractors)
When a self-similar system defines two or more interleaved attractors, each gets its own equation. Attractor variables appear on both sides:
A1=g^-1*(h1*A1|h2*A1|h3*A2)
A2=g^-1*(h4*A1|h5*A2)
Here h*A denotes the image of attractor set A under map h.
g must be an expansion (spectral radius > 1 after projection) to guarantee
that the attractor exists; if g is a contraction, existence depends on the GIFS dependency graph.
See the Robinson Triangles entry for a worked example.
Templates (Finder / Search)
Templates describe families of maps for use with the IFStile Finder module.
They are not required for rendering with ifslib:
| Syntax | Meaning |
|---|---|
$real(a,b) / $integer(a,b) | Distribution T: uniform on [a, b] (real or integer) |
$number(T) | Distribution T for a scalar — passed as argument to $semigroup, $vector, etc. |
$semigroup([g1,...,gm], T) | Random element of the semigroup generated by g1…gm, with element distribution T |
$vector(L, T) | Random vector of length L with component distribution T |
T can be a $real(a,b) or $integer(a,b) uniform distribution,
or a number (log-variance of a normal distribution on ℝ, i.e. σ = e^(T/2)),
or omitted (IFStile uses its Finder “log variance” search parameter as default).
Complete Examples
Sierpiński Triangle — simple 2D IFS
@
$dim=2
f1=[0.5,0,0,0.5]
f2=[0.5,0]*[0.5,0,0,0.5]
f3=[0.25,0.5]*[0.5,0,0,0.5]
S=(f1|f2|f3)*S See: Sierpiński Triangle
Rauzy Fractal — 3D rational form with companion matrix
@
$dim=3
$subspace=[g,0]
g=$companion([-1,1,1]) # companion for x³+x²+x-1 (tribonacci)
A=(g^-1|g^-2*[0,1,0]|g^-3*[0,1,1])*A See: Rauzy Fractal
Robinson Triangles — GIFS with 4D rational form
@
$dim=4
$subspace=[s,0]
s=$companion([1,-1,1,-1]) # 10th cyclotomic polynomial
r=$exchange()
g=s-s^4
h1=s^4*[-1,0,-1,0]
h2=s^2*r*[-1,0,0,0]
h3=s^9
h4=s^6*r*[0,-1,0,-1]
h5=s^3*[1,-1,0,-1]
A1=g^-1*(h1*A1|h2*A1|h3*A2)
A2=g^-1*(h4*A1|h5*A2) See: Robinson Triangles
Reference
- Mekhontsev, D. (2019). An algebraic framework for finding and analyzing self-affine tiles and fractals . Doctoral thesis, Ernst-Moritz-Arndt-Universität Greifswald. Appendix E contains the full language specification.
- IFStile — the software package that implements the AIFS language.