Skip to content

Units and Quantities Principles

kwikius edited this page Sep 7, 2025 · 13 revisions

Units and Quantities – Design Principles (Draft)

This page outlines the draft design rules for quantities and units in gzScript. The aim is to provide a strongly typed, SI-first system that prevents errors while staying expressive enough for simulation scripting.

  1. Dimensions

    A dimension is represented as a mapping from base dimensions → rational exponents. Each base dimension is unique. If a base dimension is not present, its exponent is 0. Tuples need not be ordered; lookup is by base dimension.

Examples

Length = { L:1 } Velocity = { L:1, T:-1 } Square root L = { L:1/2 }

  1. Units

    A unit = (dimension, scaling factor). SI base units always have scale = 1. Non-SI units are defined by a rational scale factor relative to SI.

Examples

unit m = ( {L:1}, scale=1 ) unit s = ( {T:1}, scale=1 ) unit in = ( {L:1}, scale=254/10000 ) // 0.0254 m unit mph = :mi/h: // alias expands to scale factor × SI

  1. Quantities

    A quantity = (numeric value × unit). Numeric type and unit type are both part of the type system.

Examples

v = 5:m/s:; d = 25.4:mm:;

  1. Refinements

    Refinements are semantic subtypes of a dimension. A refinement adds meaning (e.g. height vs width) without changing the underlying dimension.

Rules

A height can be initialised from an anonymous Length.
A width can be initialised from an anonymous Length or another width.
A height cannot be initialised directly from a width.
Multiplication/division that changes the dimension always produces an anonymous result.
  1. Numeric Literals

    An integer literal is assigned the smallest integer type that can exactly hold it.

Examples

1 → int8 256 → int16 70000 → int32

This avoids unnecessary narrowing conversions.
Floating point literals follow similar principles, but details require care.
  1. Operations

    Addition, subtraction, comparison Only allowed between quantities of the same refinement or within the same refinement tree. Result keeps the refinement type. Adding mismatched refinements (e.g. height + width) is a compile error.

    Multiplication, division Produces an anonymous quantity with derived dimension. Example: 2:m: * 3:m: → 6:m^2:

    Mixed-unit operations If units differ, operands are converted to SI before operation. Example: 2:ft: + 1:m: → 1.6096:m:

  2. Angles

Angles are a special case, treated as refinements of dimensionless:

Radian family (rad, sr, …)
    Interchangeable with dimensionless.
    May be implicitly promoted/demoted.

Fraction-of-revolution family (deg, turn, …)
    Not interchangeable with dimensionless.
    Convertible to radians by explicit scaling.
  1. SI Preference

    SI is the canonical system.

    Operations collapse to SI unless: Both operands share the exact same non-SI unit, and the operation preserves that unit (e.g. addition). The result is explicitly assigned to a non-SI unit.

Examples

2:ft: + 3:ft: → 5:ft: 2:ft: * 3:ft: → 0.092903:m^2: // SI 2:ft: + 1:m: → 1.6096:m: // SI

  1. Examples

v = 5:m/s:; t = 2:s:;

// anonymous result d = v * t; // = 10:m: (anonymous length)

// refined quantities h:height: = 1.75:m:; w:width: = 0.30:m:;

// error: height cannot be initialised from width w = h; // compile error

// angles theta = 180:deg:; phi = 3.14:rad:; x = sin(phi); // ok, rad ↔ dimensionless y = sin(theta); // requires conversion deg → rad

Status

This page is a living draft. The rules here will evolve as gzScript matures.

Clone this wiki locally