Skip to content

Built-in Reference

This page lists all dimensions, units, constants, and functions provided by the Graphcal prelude. These are available in every .gcl file without any import declarations.

The set of bare-callable functions is closed: user code cannot add to it. Externally-provided functions are declared with import plugin blocks and called qualified through their alias — see Extern Functions (Plugins).

Built-in Constants

Name Type Value
PI Dimensionless 3.14159265358979...
E Dimensionless 2.71828182845904...
TAU Dimensionless 6.28318530717958... (2*PI)
SQRT2 Dimensionless 1.41421356237309...
LN2 Dimensionless 0.69314718055994...
LN10 Dimensionless 2.30258509299404...

Built-in Functions

Math Functions

Function Signature Description
sqrt(x) D -> D^(1/2) Square root (dimension halved)
cbrt(x) D -> D^(1/3) Cube root (dimension divided by 3)
abs(x) D -> D or Complex<D> -> D Absolute value or complex magnitude
sign(x) D -> Dimensionless Sign of value (-1.0, 0.0, or 1.0)
round(x) Dimensionless -> Dimensionless Round to nearest integer
trunc(x) Dimensionless -> Dimensionless Truncate toward zero
floor(x) Dimensionless -> Dimensionless Round toward negative infinity
ceil(x) Dimensionless -> Dimensionless Round toward positive infinity
clamp(x, min, max) (D, D, D) -> D Clamp value to range
hypot(a, b) (D, D) -> D Hypotenuse (sqrt(a^2 + b^2))
exp(x) Dimensionless -> Dimensionless or Complex<Dimensionless> -> Complex<Dimensionless> Real or complex exponential
expm1(x) Dimensionless -> Dimensionless exp(x) - 1 (numerically stable for small x)
ln(x) Dimensionless -> Dimensionless Natural logarithm
log1p(x) Dimensionless -> Dimensionless ln(1 + x) (numerically stable for small x)
log(x, base) (Dimensionless, Dimensionless) -> Dimensionless Logarithm with arbitrary base
log2(x) Dimensionless -> Dimensionless Base-2 logarithm
log10(x) Dimensionless -> Dimensionless Base-10 logarithm

The rounding functions (round, trunc, floor, ceil) reject dimensioned arguments: "round to an integer" has no unit-independent meaning for a physical quantity -- an integer number of meters is not an integer number of centimeters. To round a quantity, divide by an explicit granularity, round the dimensionless ratio, and scale back:

// Round down to whole centimeters.
node whole_cm: Length = floor(@x / 1.0 cm) * 1.0 cm;

Complex Functions

Complex<D> is the built-in complex type over dimension D. Both components are stored in SI base units and must have the same dimension. Construction is explicit; there is no a + bi literal syntax.

Function Signature Description
complex(re, im) (D, D) -> Complex<D> Construct from rectangular components
polar(magnitude, phase) (D, Angle) -> Complex<D> Construct from a non-negative magnitude and phase
to_complex(x) D -> Complex<D> Promote a real quantity with zero imaginary component
re(z) Complex<D> -> D Extract the real component
im(z) Complex<D> -> D Extract the imaginary component
abs(z) Complex<D> -> D Return the Euclidean magnitude
phase(z) Complex<D> -> Angle Return the principal phase from atan2(im, re)
conj(z) Complex<D> -> Complex<D> Return the complex conjugate
exp(z) Complex<Dimensionless> -> Complex<Dimensionless> Return e^z; dimensioned input is rejected
node displacement: Complex<Length> = complex(3.0 m, 4.0 m);
node same_polar: Complex<Length> = polar(5.0 m, 53.130102 deg);
node magnitude: Length = abs(@displacement); // 5 m
node direction: Angle = phase(@displacement);
node shifted: Complex<Length> = @displacement + to_complex(1.0 m);

polar rejects a negative magnitude instead of silently rotating the phase by π. Arithmetic and complex function results must remain finite. Complex division by zero is an evaluation error. See Complex Arithmetic for the mixed real/complex operation matrix.

Trigonometric Functions

Function Signature Description
sin(x) Angle -> Dimensionless Sine
cos(x) Angle -> Dimensionless Cosine
tan(x) Angle -> Dimensionless Tangent
asin(x) Dimensionless -> Angle Inverse sine
acos(x) Dimensionless -> Angle Inverse cosine
atan(x) Dimensionless -> Angle Inverse tangent
atan2(y, x) (D, D) -> Angle Two-argument inverse tangent

Hyperbolic Functions

Function Signature Description
sinh(x) Dimensionless -> Dimensionless Hyperbolic sine
cosh(x) Dimensionless -> Dimensionless Hyperbolic cosine
tanh(x) Dimensionless -> Dimensionless Hyperbolic tangent
asinh(x) Dimensionless -> Dimensionless Inverse hyperbolic sine
acosh(x) Dimensionless -> Dimensionless Inverse hyperbolic cosine
atanh(x) Dimensionless -> Dimensionless Inverse hyperbolic tangent

Selection Functions

Function Signature Description
least(a, b) (D, D) -> D Lesser of two values
greatest(a, b) (D, D) -> D Greater of two values

These selectors always take exactly two values. To reduce an indexed value, use minimum(values) or maximum(values) instead.

Type Conversion Functions

Function Signature Description
to_float(x) Int -> Dimensionless Convert an integer to a binary64 Dimensionless quantity
to_int(x) Dimensionless -> Int Convert an integer-valued Dimensionless quantity exactly; reject fractional, non-finite, or out-of-range values
to_int(k) Key<Fin(N)> -> Int Extract the integer position of a Fin index key; named and coordinate keys are rejected

to_int never chooses a rounding policy implicitly. Apply trunc, floor, ceil, or round before converting when that is the intended policy:

node exact: Int = to_int(3.0);
node toward_zero: Int = to_int(trunc(3.7));
node nearest: Int = to_int(round(3.7));

Integrality is checked on the represented binary64 value. A conversion cannot detect precision that was already lost while computing that value.

Index Key Functions

These functions construct and consume index keys of type Key<I>. C is a coordinate axis over dimension D; c is a static Nat constant; e is a runtime Int; q is a quantity of dimension D.

Function Signature Description
key(Fin(N), c) (Fin(N), static Nat) -> Key<Fin(N)> Static Fin key; the position is range-checked while the program is compiled
fin_key(Fin(N), e) (Fin(N), Int) -> Key<Fin(N)> Runtime Fin key; an out-of-range position is a per-node evaluation error
floor_key(C, q) (C, D) -> Key<C> Greatest grid point <= q; fails when q is below the axis range
ceil_key(C, q) (C, D) -> Key<C> Least grid point >= q; fails when q is above the axis range
nearest_key(C, q) (C, D) -> Key<C> Closest grid point; total — a midpoint tie resolves toward the axis start
coord(k) Key<C> -> D Extract the quantity coordinate of a coordinate-axis key
to_int(k) Key<Fin(N)> -> Int Extract the integer position of a Fin key

Named axes need no former — a qualified label such as Maneuver.Departure is itself a constant of type Key<Maneuver> — and have no extraction: a named key is opaque apart from equality and match. There is no exact quantity-to-key cast for coordinate axes; select a grid point with an explicit search policy instead.

index TimeStep = range(0.0 s, 10.0 s, step: 0.1 s);

param event_time: Time = 3.47 s;
node before_event: Key<TimeStep> = floor_key(TimeStep, @event_time);
node event_coord: Time = coord(@before_event);

param readings: Pressure[Fin(8)] = for i: Fin(8) { 100.0 Pa };
param requested: Int = 5;
node channel: Key<Fin(8)> = fin_key(Fin(8), @requested);
node selected: Pressure = @readings[@channel];

Datetime Functions

Constructors

Function Signature Description
datetime("...") OffsetDateTimeLiteral -> Datetime Parse RFC 3339 with an explicit Z or numeric offset
datetime("...", "tz") (CivilDateTimeLiteral, TimezoneLiteral) -> Datetime Interpret local civil time in an IANA timezone
epoch<S>("...") CivilDateTimeLiteral -> Datetime<S> Interpret scale-free calendar coordinates in static time scale S
from_jd(x) Dimensionless -> Datetime Construct from Julian Date (UTC)
from_mjd(x) Dimensionless -> Datetime Construct from Modified Julian Date (UTC)
from_unix(x) Dimensionless -> Datetime Construct from Unix timestamp in seconds

Each constructor has exactly one interpretation source:

  • one-argument datetime requires Z or a numeric offset;
  • timezone-based datetime requires local civil coordinates with no embedded offset, timezone, or time-scale suffix;
  • epoch<S> requires local calendar coordinates with no embedded offset, timezone, or time-scale suffix, and S must be one supported bare time scale.

Datetime literals are parsed during checking. Invalid calendar dates and missing or contradictory interpretation sources are compile errors, not runtime failures. Local civil times are also resolved against Graphcal's bundled tzdb during checking: nonexistent times in DST gaps and repeated times in DST folds are rejected rather than shifted or selected silently. To choose a specific instant, use one-argument datetime with an explicit numeric offset. The obsolete positional form epoch("...", TT) is rejected; write epoch<TT>("...").

Time Scale Conversions

Function Signature Description
to_utc(x) Datetime(any) -> Datetime<UTC> Convert to UTC
to_tai(x) Datetime(any) -> Datetime<TAI> Convert to TAI
to_tt(x) Datetime(any) -> Datetime<TT> Convert to Terrestrial Time
to_tdb(x) Datetime(any) -> Datetime<TDB> Convert to Barycentric Dynamical Time
to_et(x) Datetime(any) -> Datetime<ET> Convert to Ephemeris Time
to_gpst(x) Datetime(any) -> Datetime<GPST> Convert to GPS Time
to_gst(x) Datetime(any) -> Datetime<GST> Convert to Galileo System Time
to_bdt(x) Datetime(any) -> Datetime<BDT> Convert to BeiDou Time
to_qzsst(x) Datetime(any) -> Datetime<QZSST> Convert to QZSS Time

Numeric Conversions

Function Signature Description
to_jd(x) Datetime -> Dimensionless Convert to Julian Date (UTC days)
to_mjd(x) Datetime -> Dimensionless Convert to Modified Julian Date (UTC days)
to_unix(x) Datetime -> Dimensionless Convert to Unix timestamp (seconds since 1970-01-01)

Extraction Functions

Function Signature Description
year(x) Datetime<S> -> Int Extract year
month(x) Datetime<S> -> Int Extract month (1-12)
day(x) Datetime<S> -> Int Extract day of month (1-31)
hour(x) Datetime<S> -> Int Extract hour (0-23)
minute(x) Datetime<S> -> Int Extract minute (0-59)
second(x) Datetime<S> -> Int Extract second (0-59)
weekday(x) Datetime<S> -> Int ISO weekday (1=Monday, 7=Sunday)
day_of_year(x) Datetime<S> -> Int Day of year (1-366)

All calendar extractors use the input's declared time scale. For example, hour(epoch<TT>("2024-11-05T12:00:00")) is 12, even though the same instant has a different UTC coordinate. A display timezone applied with -> remains formatting metadata and does not change extractor results.

Datetime Domain Constraints

Datetime<S> supports inclusive min: and max: constraints. Bounds are compile-time constants and must have exactly the constrained time scale:

param event: Datetime<TT>(
    min: epoch<TT>("2025-01-01T00:00:00"),
    max: epoch<TT>("2025-12-31T23:59:59"),
) = epoch<TT>("2025-06-01T12:00:00");

Cross-scale bounds require an explicit conversion such as to_tt(datetime("...Z")). Constraints apply element-wise to indexed datetime values and to constrained algebraic payload fields. See Type System — Domain Constraints.

Timezone Display

The -> operator can display a datetime in a specific timezone without changing the underlying value:

node meeting_ny: Datetime = @meeting -> "America/New_York";

Quoted timezone spellings are contextual TimezoneLiterals, not first-class String values. They are validated and canonicalized while the program is checked, then carried through compilation and evaluation as opaque IANA identifiers.

Timezone construction, validation, and display all use the same IANA timezone database bundled with the Graphcal toolchain. Graphcal never consults the host's zoneinfo installation, so a given Graphcal release resolves timezone rules identically across supported platforms. Invalid-timezone diagnostics report the bundled IANA tzdb release; updating those rules is an explicit Graphcal dependency update.

Aggregation Functions (Indexed Values)

These functions operate on rank-one for comprehensions or indexed values. D is a quantity dimension; T may be any non-indexed value type.

Function Signature Description
sum(values) D[I] -> D Sum of all elements
product(values) D[I] -> D^\|I\| Product of all elements; cardinality determines the result dimension
maximum(values) D[I] -> D Maximum element
minimum(values) D[I] -> D Minimum element
argmax(values) D[I] -> Key<I> Key of the maximum element; ties resolve to the first extremum in index order
argmin(values) D[I] -> Key<I> Key of the minimum element; ties resolve to the first extremum in index order
mean(values) D[I] -> D Arithmetic mean
rss(values) D[I] -> D Root sum square, computed with scaled accumulation
count(values) T[I] -> Int Exact number of elements

argmax and argmin return the extremum's location as an index key rather than its value, so the result can re-index the source or any other value on the same axis. Because axes are never empty and ties are deterministic, the identity @x[argmax(@x)] == maximum(@x) always holds:

index Maneuver = { Departure, Correction, Insertion };
param delta_v: Velocity[Maneuver] = {
    Maneuver.Departure: 2.46 km/s,
    Maneuver.Correction: 0.12 km/s,
    Maneuver.Insertion: 1.83 km/s,
};
param fuel_margin: Dimensionless[Maneuver] = {
    Maneuver.Departure: 1.1,
    Maneuver.Correction: 1.2,
    Maneuver.Insertion: 1.3,
};

node critical: Key<Maneuver> = argmax(@delta_v);
node critical_dv: Velocity = @delta_v[@critical];        // 2.46 km/s
node critical_margin: Dimensionless = @fuel_margin[@critical];

product makes chained reductions explicit without deeply nested binary multiplication. A dimensioned product requires a concrete axis cardinality so its output exponent is known; a dimensionless product does not. rss is the unit-safe quadrature operation for uncertainty budgets and Euclidean component combinations, and avoids avoidable intermediate overflow/underflow. Keep a budget's deterministic means and statistical sigmas as separate values, then combine each according to its semantics:

index BudgetLine = { Structure, Payload };
param means: Mass[BudgetLine] = {
    BudgetLine.Structure: 100.0 kg,
    BudgetLine.Payload: 50.0 kg,
};
param sigmas: Mass[BudgetLine] = {
    BudgetLine.Structure: 3.0 kg,
    BudgetLine.Payload: 4.0 kg,
};
node budget_mean: Mass = sum(@means);   // 150 kg
node budget_sigma: Mass = rss(@sigmas); // 5 kg

Convert a count explicitly when quantity arithmetic needs a dimensionless scalar: sum(@values) / to_float(count(@values)). Direct multi-axis aggregation is rejected; reduce one selected axis at a time with an explicit for, such as product(for row: Row { product(for column: Column { @a[row, column] }) }).

Frame-Tagged Vectors and Attitudes

Reference frames are project-specific nominal types, so Graphcal does not provide global Eci, Body, or similarly named frame values. Define the frames and wrappers in project vocabulary, then use the array linear-algebra built-ins for their numeric kernels:

type Eci { Eci }
type Body { Body }
type Vec3<D: Dim, Frame: Type> { Vec3(x: D, y: D, z: D) }
type Rotation<From: Type, To: Type> {
    Rotation(elements: Dimensionless[Fin(3), Fin(3)])
}
type Quaternion<From: Type, To: Type> {
    Quaternion(w: Dimensionless, x: Dimensionless, y: Dimensionless, z: Dimensionless)
}

node r: Vec3<Length, Eci> = Vec3<Length, Eci>(x: 1.0 m, y: 2.0 m, z: 3.0 m);
node q: Quaternion<Eci, Body> =
    Quaternion<Eci, Body>(w: 1.0, x: 0.0, y: 0.0, z: 0.0);

The phantom Frame / From / To arguments prevent accidental frame reinterpretation at type-check time. The linear_algebra_ergonomics.gcl fixture demonstrates an explicit matrix-vector frame transition. Projects can package numeric component operations in reusable DAGs with required type-level inputs; see DAG Blocks.

Linear Algebra (Indexed Quantities)

Linear-algebra built-ins operate on rank-one vectors and rank-two matrices. Axes are part of the type and contractions require the same typed axis, not merely the same number of entries. Fin(N) axes match structurally; named axes match by their declaration identity.

Function Signature Description
dot(a, b) (D1[I], D2[I]) -> D1 * D2 Dot product
matmul(a, b) (D1[I, J], D2[J, K]) -> (D1 * D2)[I, K] Matrix product over J
transpose(a) D[I, J] -> D[J, I] Swap matrix axes
trace(a) D[I, I] -> D Sum the diagonal of a square typed-axis matrix
norm(v) D[I] -> D Euclidean vector norm
cross(a, b) (D1[I], D2[I]) -> (D1 * D2)[I] Three-component cross product; I must have exactly three entries
outer(a, b) (D1[I], D2[J]) -> (D1 * D2)[I, J] Outer product
solve(a, b) (D1[I, I], D2[I]) -> (D2 / D1)[I] Solve the square system a * x = b
inverse(a) D[I, I] -> D^-1[I, I] Matrix inverse
det(a) D[I, I] -> D^\|I\| Determinant; the axis cardinality becomes the dimension exponent
param A: Length[Fin(2), Fin(3)] = table[Fin(2), Fin(3)] {
    1.0 m, 2.0 m, 3.0 m;
    4.0 m, 5.0 m, 6.0 m;
};
param B: Dimensionless[Fin(3), Fin(2)] = table[Fin(3), Fin(2)] {
    7.0, 8.0;
    9.0, 10.0;
    11.0, 12.0;
};

node AB: Length[Fin(2), Fin(2)] = matmul(@A, @B);
node A_t: Length[Fin(3), Fin(2)] = transpose(@A);

There is no implicit axis selection or broadcasting. For example, matmul always contracts the second axis of its first argument with the first axis of its second argument. Distinct named axes with equal cardinality are rejected.

solve and inverse use scaled partial-pivoting LU, reject singular or numerically ill-conditioned matrices, and verify the residual before returning a result. These failures are explicit evaluation errors; they never return NaN or infinity. det remains defined for singular matrices and returns zero. Because a determinant's physical dimension is D raised to the matrix order, det requires a concrete axis cardinality.

Prelude Base Dimensions

Dimension Description
Length Spatial distance
Time Temporal duration
Mass Mass
Temperature Thermodynamic temperature
ElectricCurrent Electric current
Amount Amount of substance
LuminousIntensity Luminous intensity
Angle Plane angle
Dimensionless No physical dimension

Prelude Derived Dimensions

Dimension Definition
Velocity Length / Time
Acceleration Length / Time^2
Force Mass * Length / Time^2
Energy Mass * Length^2 / Time^2
Power Mass * Length^2 / Time^3
Pressure Mass / (Length * Time^2)
Frequency 1 / Time
Area Length^2
Volume Length^3

Prelude Units

Length

Unit Definition
m Base unit (meter)
km 1000 m
cm 0.01 m
mm 0.001 m

Time

Unit Definition
s Base unit (second)
min 60 s
h 3600 s

h is the only prelude spelling for the hour unit; hour(value) remains the datetime extractor.

Mass

Unit Definition
kg Base unit (kilogram)
g 0.001 kg

Temperature

Unit Definition
K Base unit (kelvin)

Electric Current

Unit Definition
A Base unit (ampere)

Amount of Substance

Unit Definition
mol Base unit (mole)

Luminous Intensity

Unit Definition
cd Base unit (candela)

Angle

Unit Definition
rad Base unit (radian)
deg pi/180 rad

Force

Unit Definition
N 1 kg*m/s^2
kN 1000 N

Energy

Unit Definition
J 1 N*m
kJ 1000 J

Power

Unit Definition
W 1 J/s
kW 1000 W

Pressure

Unit Definition
Pa 1 N/m^2
kPa 1000 Pa
MPa 1000000 Pa

Frequency

Unit Definition
Hz 1/s