Skip to documentation
SLOP

tiny.reducer.bytes.capacity

Reference tiny.reducer bytes capacity

Defined in bytes.

The layout and the memory bound of the workspace (the one byte allocation Storage makes up front and reuses for every run) are derived for byte reduction.

API (3)

Types and contracts

Public types and contracts.

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

Source

Source: lib/reducer/src/bytes/capacity.zig

zig
//! The layout and the memory bound of the *workspace* (the one byte allocation//! `Storage` makes up front and reuses for every run) are derived for byte//! reduction.//!//! The caller supplies one sizing number, the longest input it will submit, as//! its *limits*, which the formulas write $N$. Shortening a sequence of length//! $N$ needs two regions of memory at the same time://! 1. The *witness lane* holds the *current sequence* (the shortest sequence//!    the oracle has accepted so far, which the search deletes from next) and//!    needs $N$ bytes.//! 2. The *scratch lane* is where each *candidate* (one shorter byte sequence//!    built by deleting a run of bytes from the current sequence and handed to//!    the oracle) is assembled and needs $N - 1$ bytes.//!//! Every candidate is strictly shorter than the current sequence, so the//! scratch lane needs at most $\max(N - 1, 0)$ bytes. The total is://!//! $$\text{storage\_bytes} = N + \max(N - 1, 0)$$//!//! At $N = 0$ both lanes need 0 bytes, so the total is 0 bytes. A workspace of//! zero length asks the allocator for a zero-byte slice while initializing, and//! that request need not reach the heap.//!//! `Capacity.derive()` works out this layout in arithmetic and allocates//! nothing. The arithmetic overflows when//! $N + \max(N - 1, 0) > \text{maxInt}(\text{usize})$. For example, on a 64-bit//! target the largest input limit that can be represented is//! $\lfloor \text{maxInt}(\text{usize}) / 2 \rfloor + 1 = 2^{63}$, and the//! storage it derives is $\text{maxInt}(\text{usize}) = 2^{64} - 1$ bytes. A//! limit above that returns `DeriveError.CapacityOverflow`, which reports that//! the bound exceeds what `usize` can hold and stands apart from an allocator//! failure.const std = @import("std");/// Sizing constraint the caller supplies for the byte reduction workspace.pub const Limits = struct {    /// Ceiling on the length in bytes of any initial input handed to    /// `reduce()`. An input longer than this is refused at acquisition with    /// `Exhaustion.InputCapacityExceeded`.    max_input_bytes: usize,};/// Errors raised while computing the storage requirement from `Limits`.pub const DeriveError = error{    /// The requested `max_input_bytes` cannot be represented in `usize` once    /// the scratch lane is added to it, which is the condition    /// $N + \max(N - 1, 0) > \text{maxInt}(\text{usize})$. The bound exceeds    /// what the arithmetic can represent, so it stands apart from the    /// allocator's own `OutOfMemory`.    CapacityOverflow,};/// Workspace layout derived from the caller's limits, sized so that a run in/// steady state needs no further allocation.pub const Capacity = struct {    /// Caller's limits that this capacity was derived from.    limits: Limits,    /// Byte offset in the backing allocation where the scratch lane starts. It    /// equals `limits.max_input_bytes` exactly.    candidate_offset: usize,    /// Greatest length in bytes any candidate takes, which is $\max(N - 1, 0)$.    candidate_bytes: usize,    /// Total the combined allocation needs, which is    /// $\text{candidate\_offset} + \text{candidate\_bytes}$.    storage_bytes: usize,    /// Works out the memory a workspace needs to reduce inputs up to    /// `limits.max_input_bytes`. It computes $N + \max(N - 1, 0)$, taking the    /// scratch lane's length with saturating subtraction and the total with    /// checked addition. It produces the arithmetic layout alone and calls no    /// allocator.    ///    /// ## Errors    /// It returns `DeriveError.CapacityOverflow` when the combined requirement    /// exceeds `std.math.maxInt(usize)`.    pub fn derive(limits: Limits) DeriveError!Capacity {        const candidate_bytes = limits.max_input_bytes -| 1;        const capacity = Capacity{            .limits = limits,            .candidate_offset = limits.max_input_bytes,            .candidate_bytes = candidate_bytes,            .storage_bytes = std.math.add(                usize,                limits.max_input_bytes,                candidate_bytes,            ) catch return error.CapacityOverflow,        };        std.debug.assert(capacity.candidate_offset == limits.max_input_bytes);        std.debug.assert(capacity.candidate_bytes <= limits.max_input_bytes);        std.debug.assert(capacity.storage_bytes >= limits.max_input_bytes);        std.debug.assert(            capacity.candidate_offset + capacity.candidate_bytes == capacity.storage_bytes,        );        return capacity;    }};fn modelCapacity(limits: Limits) DeriveError!Capacity {    const input_bytes: u128 = limits.max_input_bytes;    const candidate_bytes = if (input_bytes == 0) 0 else input_bytes - 1;    const storage_bytes = input_bytes + candidate_bytes;    if (storage_bytes > std.math.maxInt(usize)) return error.CapacityOverflow;    return .{        .limits = limits,        .candidate_offset = limits.max_input_bytes,        .candidate_bytes = @intCast(candidate_bytes),        .storage_bytes = @intCast(storage_bytes),    };}test "byte storage capacity matches an independent byte model" {    comptime {        @stardustClaim(            @import("alloc_phase").capacity.witness(@import("./root.zig").Storage, "reducer_byte_capacity"),            null,            null,            null,            null,            null,            null,        );    }    const limits = Limits{ .max_input_bytes = 9 };    try std.testing.expectEqual(try modelCapacity(limits), try Capacity.derive(limits));    try std.testing.expectEqual(@as(usize, 17), (try Capacity.derive(limits)).storage_bytes);    try std.testing.expectEqual(        @as(usize, 0),        (try Capacity.derive(.{ .max_input_bytes = 0 })).storage_bytes,    );}test "byte storage capacity accepts its largest representable input limit" {    const max_input_bytes = std.math.maxInt(usize) / 2 + 1;    const capacity = try Capacity.derive(.{ .max_input_bytes = max_input_bytes });    try std.testing.expectEqual(std.math.maxInt(usize), capacity.storage_bytes);    try std.testing.expectError(        error.CapacityOverflow,        Capacity.derive(.{ .max_input_bytes = max_input_bytes + 1 }),    );}

Source: lib/reducer/src/bytes/root.zig:44

zig
/// Module holding the capacity derivation and the limits type.pub const capacity = @import("capacity.zig");

Audit

Definitions2
Public names2
Members1
Version26.7.0
Revisiondaab053ee433