2026-04-21 15:14:50 +02:00
.
2026-04-21 15:14:44 +02:00
2026-04-20 23:38:49 +02:00
2026-04-20 23:38:49 +02:00
2026-04-21 15:14:50 +02:00

zig_units

Compile-time dimensional analysis and physical quantities for Zig.

zig_units lets you attach physical units to numeric values so that dimension mismatches (like adding distance to time) become compile errors rather than silent bugs.

At runtime, a Quantity is just its underlying numeric value — zero memory overhead.

const velocity = distance.divBy(time);  // Result type: L¹T⁻¹  ✓
const error    = mass.add(velocity);    // COMPILE ERROR: M¹ != L¹T⁻¹

Requirements: Zig 0.16.0


Installation

1. Add as a Zig dependency

zig fetch --save https://github.com/YOUR_USERNAME/zig_units/archive/refs/heads/main.tar.gz

2. Configure build.zig

const zig_units = b.dependency("zig_units", .{
    .target = target,
    .optimize = optimize,
});
// Add to your module or executable
exe.root_module.addImport("units", zig_units.module("zig_units"));

Quick Start: Using Predefined Quantities

units.Base provides a clean way to instantiate common physical types without manually defining dimensions.

const std = @import("std");
const units = @import("units");

pub fn main() !void {
    // Instantiate types for f32 backing
    const Meter  = units.Base.Meter.Of(f32);
    const Second = units.Base.Second.Of(f32);
    
    const dist = Meter{ .value = 10.0 };
    const time = Second{ .value = 2.0 };

    // Arithmetic is type-safe and creates the correct resulting dimension
    const vel = dist.divBy(time); // Type is Velocity (L/T)
    
    std.debug.print("Speed: {f}\n", .{vel}); // Output: 5m.s⁻¹
}

Defining Custom Quantities

You aren't limited to the built-in library. You can define any physical quantity by specifying its Dimensions (powers of base units) and its Scale (SI prefixes).

1. Create a custom dimension

Dimensions are defined by 7 base SI units: L (Length), M (Mass), T (Time), I (Current), Tp (Temp), N (Substance), J (Intensity).

const Dims = units.Dimensions;
const Scales = units.Scales;

// Frequency is T⁻¹
const FreqDims = Dims.init(.{ .T = -1 });

// Force is M¹ L¹ T⁻²
const ForceDims = Dims.init(.{ .M = 1, .L = 1, .T = -2 });

2. Create a custom Type

Combine a numeric type, the dimensions, and a scale.

const Hertz = units.Quantity(f32, FreqDims, Scales.init(.{}));

// A specialized scale: Millimeters per Second Squared
const MmPerSecSq = units.Quantity(f32, 
    Dims.init(.{ .L = 1, .T = -2 }), 
    Scales.init(.{ .L = .m }) // .m = milli
);

Unit Conversions

The library handles SI prefixes (k, m, u, n, etc.) and time aliases (.min, .hour) automatically. When performing arithmetic between different scales, the finer (smaller) scale wins to preserve precision.

const KM = units.Base.Meter.Scaled(f32, Scales.init(.{ .L = .k })); // Kilometers
const M  = units.Base.Meter.Of(f32);                               // Meters

const d1 = KM{ .value = 1.2 };  // 1.2 km
const d2 = M{ .value = 300.0 }; // 300 m

const total = d1.add(d2);      // Result is 1500.0 (Meters)
const final = total.to(KM);    // Explicitly convert back to KM -> 1.5

Physical Vectors (Vec3)

Physical quantities often come in 3D vectors (Position, Velocity, Force). Every Quantity type has a .Vec3 alias built-in.

const Vec3M = units.Base.Meter.Of(f32).Vec3;

const gravity = Vec3M{ .data = .{ 0, -9.81, 0 } };
const pos     = Vec3M.initDefault(0); // [0, 0, 0]

// Vectors support standard operations
const length = gravity.length(); // Returns f32: 9.81
const double = gravity.scale(2.0);

You can also create a Vector of any length. Vec3 found in a Quantity is just a convenience.

const M  = units.Base.Meter.Of(f32);
const Vec10M = units.QuantityVec(10, Meter);

const gravity = Vec10M.initDefault(1);
const length = gravity.length(); // Returns f32: 1.0

SI Scales Reference

Prefix Enum Factor
Kilo .k 10³
Mega .M 10⁶
Giga .G 10⁹
Milli .m 10⁻³
Micro .u 10⁻⁶
Minute .min 60
Hour .hour 3,600

API Summary

Quantity(T, dims, scales)

  • .add(rhs) / .sub(rhs): Automatic scaling, requires same dimensions.
  • .mulBy(rhs) / .divBy(rhs): Composes dimensions (e.g., L \times L = L^2).
  • .scale(scalar): Multiply by a raw number (preserves dimensions).
  • .to(OtherType): Safely convert between scales of the same dimension.
  • .vec3(): Create a 3D vector from a scalar.

Dimensions

  • L: Length (m)
  • M: Mass (g)
  • T: Time (s)
  • I: Current (A)
  • Tp: Temperature (K)
  • N: Amount (mol)
  • J: Intensity (cd)
Description
Zero-overhead, compile-time dimensional analysis and unit conversion for Zig.
Readme GPL-3.0 529 KiB
First version Latest
2026-04-21 23:20:09 +00:00
Languages
Zig 100%