Skip to documentation
SLOP

tiny.zen.diagram.domain

Reference tiny.zen diagram domain

Defined in diagram.

API (7)

Actions

Public operations.

Types and contracts

Public types and contracts.

Values and defaults

Public values and defaults.

No direct callersNo direct callsdiagramdomain
Static calls · unresolved targets: unknown · external targets: unknown.

Source

Called byCallsNo direct callsprivate sourcelib.zen.src.diagram.boundscomputePrepareddiagram.domainexpand
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsdiagram.spacexNumberCoordinatediagram.spaceyCoordinateprivate sourcelib.zen.src.diagram.domainscaleddiagram.domainratio
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallstest sourcelib.zen.src.diagram.domaintest: linear ticks split the range ev...test sourcelib.zen.src.diagram.domaintest: log ticks cover fractional deca...test sourcelib.zen.src.diagram.domaintest: log ticks fall back to even pla...test sourcelib.zen.src.diagram.domaintest: log ticks honor the configured ...test sourcelib.zen.src.diagram.domaintest: log ticks land on decadestest sourcelib.zen.src.diagram.domaintest: log ticks thin wide ranges by w...private sourcelib.zen.src.diagram.domainevenTicksprivate sourcelib.zen.src.diagram.domainlogTicksdiagram.domainticks
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callsprivate sourcelib.zen.src.diagram.boundscomputePrepareddiagram.domainvalidate
Static calls · unresolved targets: 1 · external targets: 0.

Source: lib/zen/src/diagram/domain.zig

zig
const std = @import("std");const model = @import("model.zig");const root = @import("root.zig");const spec = root.spec;const Bounds = model.Bounds;pub fn expand(min: *f64, max: *f64, kind: spec.ScaleKind, base: f64) void {    if (min.* != max.*) return;    switch (kind) {        .linear => {            min.* -= 0.5;            max.* += 0.5;        },        .log => {            const factor = @sqrt(base);            min.* /= factor;            max.* *= factor;        },    }}pub fn ratio(value: f64, min: f64, max: f64, kind: spec.ScaleKind, base: f64) !f64 {    const scaled_value = try scaled(value, kind, base);    const scaled_min = try scaled(min, kind, base);    const scaled_max = try scaled(max, kind, base);    return (scaled_value - scaled_min) / (scaled_max - scaled_min);}fn scaled(value: f64, kind: spec.ScaleKind, base: f64) !f64 {    return switch (kind) {        .linear => value,        .log => if (value > 0) std.math.log(f64, base, value) else error.InvalidScale,    };}pub const max_ticks = 6;const even_tick_count = 5;pub const Ticks = struct {    values: [max_ticks]f64,    count: usize,    pub fn slice(self: *const Ticks) []const f64 {        std.debug.assert(self.count <= max_ticks);        return self.values[0..self.count];    }};pub fn ticks(min: f64, max: f64, kind: spec.ScaleKind, base: f64) !Ticks {    std.debug.assert(min < max);    return switch (kind) {        .linear => evenTicks(min, max, kind, base),        .log => logTicks(min, max, base),    };}fn evenTicks(min: f64, max: f64, kind: spec.ScaleKind, base: f64) !Ticks {    var result = Ticks{ .values = undefined, .count = even_tick_count };    const scaled_min = try scaled(min, kind, base);    const scaled_max = try scaled(max, kind, base);    for (result.values[0..even_tick_count], 0..) |*value, index| {        const tick_ratio = @as(f64, @floatFromInt(index)) / (even_tick_count - 1);        const placed = scaled_min + (scaled_max - scaled_min) * tick_ratio;        value.* = switch (kind) {            .linear => placed,            .log => std.math.pow(f64, base, placed),        };    }    return result;}fn logTicks(min: f64, max: f64, base: f64) !Ticks {    std.debug.assert(min > 0);    std.debug.assert(base > 1);    const epsilon = 1e-9;    const power_min: i64 = @intFromFloat(@ceil(std.math.log(f64, base, min) - epsilon));    const power_max: i64 = @intFromFloat(@floor(std.math.log(f64, base, max) + epsilon));    if (power_max < power_min + 1) return evenTicks(min, max, .log, base);    const decade_count: usize = @intCast(power_max - power_min + 1);    const stride = (decade_count + max_ticks - 1) / max_ticks;    std.debug.assert(stride >= 1);    var result = Ticks{ .values = undefined, .count = 0 };    for (0..max_ticks) |index| {        const power = power_min + @as(i64, @intCast(index * stride));        if (power > power_max) break;        result.values[result.count] = std.math.pow(f64, base, @as(f64, @floatFromInt(power)));        result.count += 1;    }    std.debug.assert(result.count >= 2);    return result;}pub fn validate(bounds: Bounds) !void {    if (bounds.x_kind == .log) {        if (bounds.categorical) return error.InvalidScale;        if (bounds.x_min <= 0 or bounds.x_max <= 0) return error.InvalidScale;    }    if (bounds.y_kind == .log and (bounds.y_min <= 0 or bounds.y_max <= 0)) return error.InvalidScale;}test "linear ticks split the range evenly" {    const result = try ticks(0, 100, .linear, 10);    try std.testing.expectEqual(@as(usize, 5), result.count);    try std.testing.expectEqual(@as(f64, 0), result.values[0]);    try std.testing.expectEqual(@as(f64, 25), result.values[1]);    try std.testing.expectEqual(@as(f64, 100), result.values[4]);}test "log ticks land on decades" {    const result = try ticks(1, 1000, .log, 10);    try std.testing.expectEqual(@as(usize, 4), result.count);    for ([_]f64{ 1, 10, 100, 1000 }, result.slice()) |expected, actual| {        try std.testing.expectApproxEqRel(expected, actual, 1e-9);    }}test "log ticks cover fractional decades" {    const result = try ticks(0.001, 10, .log, 10);    try std.testing.expectEqual(@as(usize, 5), result.count);    for ([_]f64{ 0.001, 0.01, 0.1, 1, 10 }, result.slice()) |expected, actual| {        try std.testing.expectApproxEqRel(expected, actual, 1e-9);    }}test "log ticks thin wide ranges by whole decades" {    const result = try ticks(1, 1e9, .log, 10);    try std.testing.expectEqual(@as(usize, 5), result.count);    for ([_]f64{ 1, 100, 1e4, 1e6, 1e8 }, result.slice()) |expected, actual| {        try std.testing.expectApproxEqRel(expected, actual, 1e-9);    }}test "log ticks fall back to even placement inside one decade" {    const result = try ticks(2, 8, .log, 10);    try std.testing.expectEqual(@as(usize, 5), result.count);    try std.testing.expectApproxEqRel(@as(f64, 2), result.values[0], 1e-9);    try std.testing.expectApproxEqRel(@as(f64, 4), result.values[2], 1e-9);    try std.testing.expectApproxEqRel(@as(f64, 8), result.values[4], 1e-9);}test "log ticks honor the configured base" {    const result = try ticks(1, 32, .log, 2);    try std.testing.expectEqual(@as(usize, 6), result.count);    for ([_]f64{ 1, 2, 4, 8, 16, 32 }, result.slice()) |expected, actual| {        try std.testing.expectApproxEqRel(expected, actual, 1e-9);    }}

Source: lib/zen/src/diagram/root.zig:5

zig
pub const domain = @import("domain.zig");

Audit

Definitions8
Public names8
Members2
Version26.7.0
Revisiondaab053ee433