Skip to documentation
SLOP

tiny.accy.choir.einsum

Reference tiny.accy choir einsum

Defined in choir.

API (36)

Actions

Public operations.

Types and contracts

Public types and contracts.

Values and defaults

Public values and defaults.

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

Source

Source: lib/accy/src/choir/einsum/lowering.zig:39

zig
/// Four figures for one call of `lowerPlan`: bytes of local scratch, structural/// visits, operations requested from the IR sink, and tensor types requested/// from it, so a compiler pass can charge one lowering against its work budget/// before it runs it. The figures assume an equation from `parse` and a plan/// from `createPlan`, so at most 62 labels, at most 63 inputs, and exactly one/// step fewer than inputs. Growth of the caller's arena, the internals of the/// context and of the sink, rewriter queues, parsing and planning are left out,/// and their owners add their own charges, as the einsum pass does.pub const LoweringBounds = struct {    scratch_bytes: u64,    structural_visits: u64,    operation_requests: u64,    tensor_type_requests: u64,    /// Bytes charged for one list of `T`: four times its grown capacity for 62    /// items, alignment slack for each allocation, and one more slice for a    /// final owned copy, so the bound functions can charge one list of at most    /// 62 items.    fn listBytes(comptime T: type) u64 {        return 4 * std.ArrayList(T).growCapacity(62) * @sizeOf(T) +            4 * @alignOf(T) + sliceBytes(T);    }    fn sliceBytes(comptime T: type) u64 {        return 62 * @sizeOf(T) + @alignOf(T) - 1;    }    /// Scratch charged for one contraction step: the reduction of each operand,    /// the batch and contracted axis lists, the broadcast-and-reduce path, and    /// the final transpose, so `loweringBounds` can multiply it by the step    /// count to charge the scratch of a whole plan. The charge is 11 byte    /// lists, 6 axis lists, 14 slices of dimensions or permutations, and 1 kept    /// order.    fn stepScratch() u64 {        return 11 * listBytes(u8) + 6 * listBytes(i64) +            14 * sliceBytes(i64) + sliceBytes(u8);    }};

Source: lib/accy/src/choir/einsum/planner.zig:25

zig
pub const Options = struct {    strategy: Strategy = .auto,    max_exact_inputs: u8 = 18,    exact_state_limit: usize = default_exact_state_limit,    beam_width: usize = 64,    auto_beam_width: usize = default_auto_beam_width,    /// Returns the structural visits charged for one `createPlan` run over    /// `input_count` inputs under these options, whatever pruning or cache hits    /// happen during the run. The einsum pass calls this with the operand count    /// to charge planning against its work budget. The charge covers the    /// dimensions the cost model reads, scans of the kept sets, completion    /// searches, ordering and the hash maps, and it leaves out parsing,    /// lowering, allocator internals and tensor execution. One cost evaluation    /// is charged as eight passes over 256 labels, plus scans of the inputs and    /// fixed metadata. Partition work is charged by the number of ways to    /// assign each input outside, left or right, and the greedy strategy adds    /// its lookahead. Map work is charged for four maps with lookups, inserts,    /// growth and collisions, with eight times as many buckets as entries. The    /// automatic strategy is charged for the path it will take: exact search    /// when the state count fits, widening plus beam above the exact input    /// limit, and beam otherwise. The errors are `error.EmptyEquation`,    /// `error.TooManyInputs` above 63, `error.ExactInputLimitExceeded` for    /// exact search past its limit, and `error.WorkOverflow`.    pub fn workBound(self: Options, input_count: usize) !u64 {        if (input_count == 0) return error.EmptyEquation;        if (input_count > 63) return error.TooManyInputs;        var work: PlannerWork = .{ .inputs = input_count };        if (precomputeStateCount(input_count)) |states| try work.add(16 * states);        switch (self.strategy) {            .left_to_right => try work.linear(false),            .greedy => try work.linear(true),            .optimal => try work.optimal(self.max_exact_inputs),            .beam => try work.beam(@max(self.beam_width, 1), false),            .anytime => try work.widening(@max(self.beam_width, 1)),            .auto => {                if (canUseExactPlan(input_count, self)) {                    try work.optimal(self.max_exact_inputs);                } else if (input_count > self.max_exact_inputs) {                    const width = @max(self.auto_beam_width, 1);                    try work.widening(width);                    try work.beam(width, true);                } else {                    try work.beam(@max(self.beam_width, 1), false);                }            },        }        return work.visits;    }    /// Returns the bytes of allocator storage one `createPlan` run may request,    /// counting list growth that is never reclaimed and the arenas of beam    /// search. The einsum pass calls this with the operand count to charge    /// planning's memory against its scratch budget. This bound leaves out    /// parsing, lowering, the overhead of the caller's arena and stack storage.    /// The figure follows the same strategy choice `createPlan` makes, and for    /// a widening search it adds up the storage of every width tried. A test    /// runs every strategy in a fixed buffer of this size that never frees.    pub fn storageBound(self: Options, input_count: usize) !u64 {        if (input_count == 0) return error.EmptyEquation;        if (input_count > 63) return error.TooManyInputs;        var storage: PlannerStorage = .{};        if (precomputeStateCount(input_count)) |states| {            try storage.slice(IndexSet, 2 * states);        }        switch (self.strategy) {            .left_to_right, .greedy => try storage.linear(input_count),            .optimal => try storage.optimal(input_count, self.max_exact_inputs),            .beam => try storage.beam(input_count, @max(self.beam_width, 1), false),            .anytime => try storage.widening(input_count, @max(self.beam_width, 1)),            .auto => {                if (canUseExactPlan(input_count, self)) {                    try storage.optimal(input_count, self.max_exact_inputs);                } else if (input_count > self.max_exact_inputs) {                    const width = @max(self.auto_beam_width, 1);                    try storage.widening(input_count, width);                    try storage.beam(input_count, width, true);                } else {                    try storage.beam(input_count, @max(self.beam_width, 1), false);                }            },        }        return storage.bytes;    }};

Source: lib/accy/src/choir/einsum/planner.zig:428

zig
pub const Plan = struct {    allocator: std.mem.Allocator,    strategy: Strategy,    steps: []Step,    total_scalar_cost: u128,    total_flop_cost: u128,    peak_intermediate_elements: u128,    peak_workspace_elements: u128,    output_elements: u128,    selected_beam_width: usize,    search: SearchStats,    pub fn deinit(self: *Plan) void {        self.allocator.free(self.steps);        self.* = undefined;    }};

Source: lib/accy/src/choir/einsum/planner.zig:403

zig
pub const Step = struct {    lhs: NodeId,    rhs: NodeId,    result: NodeId,    lhs_inputs: u64,    rhs_inputs: u64,    result_inputs: u64,    lhs_indices: IndexSet,    rhs_indices: IndexSet,    result_indices: IndexSet,    summed_indices: IndexSet,    scalar_cost: u128,    flop_cost: u128,    result_elements: u128,    work_elements: u128,};

Source: lib/accy/src/choir/einsum/planner.zig:13

zig
pub const Strategy = enum {    auto,    left_to_right,    greedy,    beam,    anytime,    optimal,};

Source: lib/accy/src/choir/einsum/spec.zig:70

zig
pub const Equation = struct {    allocator: std.mem.Allocator,    inputs: []Input,    output: []const u8,    output_set: IndexSet,    index_set: IndexSet,    dimensions: [256]u64,    pub fn deinit(self: *Equation) void {        for (self.inputs) |input| {            self.allocator.free(input.indices);            self.allocator.free(input.dims);        }        self.allocator.free(self.inputs);        self.allocator.free(self.output);        self.* = undefined;    }    pub fn dimension(self: *const Equation, index: u8) u64 {        std.debug.assert(self.index_set.contains(index));        return self.dimensions[index];    }    pub fn elementCount(self: *const Equation, indices: IndexSet) u128 {        var product: u128 = 1;        for (indices.words, 0..) |initial_word, word_index| {            var word = initial_word;            while (word != 0) {                const bit: usize = @intCast(@ctz(word));                const index: u8 = @intCast(word_index * 64 + bit);                product = saturatingMul(product, self.dimension(index));                word &= word - 1;            }        }        return product;    }    pub fn inputSet(self: *const Equation, input_mask: u64) IndexSet {        var set: IndexSet = .{};        for (self.inputs, 0..) |input, index| {            if ((input_mask & (@as(u64, 1) << @intCast(index))) == 0) continue;            set = set.unioned(input.index_set);        }        return set;    }};

Source: lib/accy/src/choir/einsum/spec.zig:4

zig
pub const IndexSet = struct {    words: [4]u64 = .{ 0, 0, 0, 0 },    pub fn add(self: *IndexSet, index: u8) void {        self.words[wordIndex(index)] |= bitMask(index);    }    pub fn contains(self: IndexSet, index: u8) bool {        return (self.words[wordIndex(index)] & bitMask(index)) != 0;    }    pub fn unioned(self: IndexSet, other: IndexSet) IndexSet {        return .{ .words = .{            self.words[0] | other.words[0],            self.words[1] | other.words[1],            self.words[2] | other.words[2],            self.words[3] | other.words[3],        } };    }    pub fn intersected(self: IndexSet, other: IndexSet) IndexSet {        return .{ .words = .{            self.words[0] & other.words[0],            self.words[1] & other.words[1],            self.words[2] & other.words[2],            self.words[3] & other.words[3],        } };    }    pub fn without(self: IndexSet, other: IndexSet) IndexSet {        return .{ .words = .{            self.words[0] & ~other.words[0],            self.words[1] & ~other.words[1],            self.words[2] & ~other.words[2],            self.words[3] & ~other.words[3],        } };    }    pub fn eql(self: IndexSet, other: IndexSet) bool {        return std.mem.eql(u64, &self.words, &other.words);    }    pub fn isEmpty(self: IndexSet) bool {        return self.words[0] == 0 and self.words[1] == 0 and self.words[2] == 0 and self.words[3] == 0;    }    pub fn count(self: IndexSet) u32 {        return @popCount(self.words[0]) + @popCount(self.words[1]) + @popCount(self.words[2]) + @popCount(self.words[3]);    }    fn wordIndex(index: u8) usize {        return @intCast(index >> 6);    }    fn bitMask(index: u8) u64 {        const shift: u6 = @intCast(index & 63);        return @as(u64, 1) << shift;    }};

Source: lib/accy/src/choir/einsum/spec.zig:64

zig
pub const Input = struct {    indices: []const u8,    index_set: IndexSet,    dims: []const u64,};

Source: lib/accy/src/choir/einsum/spec.zig:138

zig
/// Two figures for one parse: the bytes the parser asks its allocator for,/// counting list growth it cannot give back, and the structural visits. The/// einsum pass reads these two figures to charge a parse before it runs it. The/// figures leave out stack storage, the internals of the allocator or arena,/// and the borrowed equation text and shapes. The parser reads an input's/// dimensions only after that input's rank matches its labels, which are unique/// letters and digits.pub const ParseBounds = struct {    allocation_capacity: u64 = 0,    structural_visits: u64 = 0,    const Error = error{WorkOverflow};    fn add(a: u64, b: u64) Error!u64 {        return std.math.add(u64, a, b) catch return error.WorkOverflow;    }    fn multiply(a: u64, b: u64) Error!u64 {        return std.math.mul(u64, a, b) catch return error.WorkOverflow;    }    fn slice(comptime T: type, count: usize) Error!u64 {        if (count == 0) return 0;        return add(try multiply(@sizeOf(T), count), @alignOf(T) - 1);    }    /// Charges the bytes for one growing list of `count` items of `T` for the    /// parse bound: every capacity the list grows through, then one more slice    /// for the final `toOwnedSlice` copy that happens when shrinking cannot    /// resize or remap in place.    fn list(comptime T: type, count: usize) Error!u64 {        std.debug.assert(count <= 63);        var capacity: usize = 0;        var bytes: u64 = 0;        while (capacity < count) {            capacity = std.ArrayList(T).growCapacity(capacity + 1);            bytes = try add(bytes, try slice(T, capacity));        }        return add(bytes, try slice(T, count));    }};

Source: lib/accy/src/choir/einsum/lowering.zig:19

zig
pub const LowerError = error{    InputCountMismatch,    InvalidPlan,    InvalidDimension,} || std.mem.Allocator.Error;

Source: lib/accy/src/choir/einsum/lowering.zig:100

zig
pub fn lowerPlan(    allocator: std.mem.Allocator,    fb: *choir_root.semantic.FunctionBuilder,    equation: *const Equation,    plan: *const Plan,    inputs: []const *ir.Value,    dtype: DType,) !*ir.Value {    var sink = FunctionSink{ .fb = fb };    return try lowerPlanWithSink(allocator, &sink, equation, plan, inputs, dtype);}
Called byCallsprivate sourcelib.accy.src.choir.einsum.loweringboundLoweredImagetest sourcelib.accy.src.choir.einsum.loweringtest: einsum lowering emits planned d...test sourcelib.accy.src.choir.einsum.loweringtest: einsum lowering emits single in...test sourcelib.accy.src.choir.einsum.loweringtest: einsum lowering reduces operand...test sourcelib.accy.src.choir.einsum.loweringtest: einsum lowering transposes fina...private sourcelib.accy.src.choir.einsum.loweringlowerPlanWithSinkchoirlowerEinsumPlan
Static calls · unresolved targets: 0 · external targets: 0.

Source: lib/accy/src/choir/einsum/lowering.zig:112

zig
pub fn lowerPlanWithRewriter(    allocator: std.mem.Allocator,    rewriter: *rewrite.PatternRewriter,    equation: *const Equation,    plan: *const Plan,    inputs: []const *ir.Value,    dtype: DType,) !*ir.Value {    var sink = RewriterSink{ .rewriter = rewriter };    return try lowerPlanWithSink(allocator, &sink, equation, plan, inputs, dtype);}
Called byCallsprivate sourcelib.accy.src.choir.einsum.loweringboundLoweredImageprivate sourcelib.accy.src.choir.einsum.loweringlowerPlanWithSinkchoir.einsumlowerPlanWithRewriter
Static calls · unresolved targets: 0 · external targets: 0.

Source: lib/accy/src/choir/einsum/lowering.zig:82

zig
/// Returns the figures for an equation with `input_count` inputs, or/// `error.EmptyEquation` for none and `error.TooManyInputs` above 63, and that/// check keeps every product in range. The einsum pass calls this with the/// operand count to add the lowering's share to its work estimate. Each step is/// charged for both operand reductions and for the general broadcast-and-reduce/// path, even when the matrix-product path skips them. One reduction may/// transpose, make a zero, reshape, reduce, and reshape back. The operation/// figure is 19 per step and the tensor-type figure 17 per step, and a single/// input is charged 3 of each for its own reduction and the final transpose./// Visits count searches over labels and axes, which grow with the square of/// the rank, together with local copies and cleanup. Visits measure neither/// machine instructions nor tensor execution.pub fn loweringBounds(input_count: usize) !LoweringBounds {    if (input_count == 0) return error.EmptyEquation;    if (input_count > 63) return error.TooManyInputs;    const steps: u64 = input_count - 1;    const states: u64 = input_count + steps;    const scratch = states * @sizeOf(State) + @alignOf(State) - 1 + if (steps == 0)        LoweringBounds.listBytes(u8) + LoweringBounds.listBytes(i64) +            3 * LoweringBounds.sliceBytes(i64)    else        steps * LoweringBounds.stepScratch();    return .{        .scratch_bytes = scratch,        .structural_visits = 8 * scratch + 64 * 63 * 63 * @max(steps, 1) + 8 * states,        .operation_requests = if (steps == 0) 3 else 19 * steps,        .tensor_type_requests = if (steps == 0) 3 else 17 * steps,    };}
Called byCallsprivate sourcelib.accy.src.choir.einsum.loweringboundLoweredImageprivate sourcelib.accy.src.choir.einsum.loweringloweringStorageWitnesstest sourcelib.accy.src.choir.einsum.loweringtest: einsum lowering bounds reject i...private sourcelib.accy.src.choir.einsum.lowering.LoweringBo...listBytesprivate sourcelib.accy.src.choir.einsum.lowering.LoweringBo...sliceBytesprivate sourcelib.accy.src.choir.einsum.lowering.LoweringBo...stepScratchchoir.einsumloweringBounds
Static calls · unresolved targets: 0 · external targets: 0.

Source: lib/accy/src/choir/einsum/planner.zig:11

zig
pub const NodeId = u32;
Called byCallstest sourcelib.accy.src.choir.einsum.plannertest: einsum planner storage bound co...private sourcelib.accy.src.choir.einsum.planner.PlannerStoragebeamprivate sourcelib.accy.src.choir.einsum.planner.PlannerStoragelinearprivate sourcelib.accy.src.choir.einsum.planner.PlannerStorageoptimalprivate sourcelib.accy.src.choir.einsum.planner.PlannerStoragesliceprivate sourcelib.accy.src.choir.einsum.planner.PlannerStoragewidening+2 morechoir.einsum.OptionsstorageBound
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallstest sourcelib.accy.src.choir.einsum.plannertest: einsum planner work bound follo...test sourcelib.accy.src.choir.einsum.plannertest: einsum planner work bound handl...private sourcelib.accy.src.choir.einsum.planner.PlannerWorkaddprivate sourcelib.accy.src.choir.einsum.planner.PlannerWorkbeamprivate sourcelib.accy.src.choir.einsum.planner.PlannerWorklinearprivate sourcelib.accy.src.choir.einsum.planner.PlannerWorkoptimalprivate sourcelib.accy.src.choir.einsum.planner.PlannerWorkwidening+2 morechoir.einsum.OptionsworkBound
Static calls · unresolved targets: 0 · external targets: 0.

Source: lib/accy/src/choir/einsum/planner.zig:446

zig
pub const PlanError = error{    EmptyEquation,    TooManyInputs,    ExactInputLimitExceeded,    InvalidState,} || std.mem.Allocator.Error;

Source: lib/accy/src/choir/einsum/planner.zig:580

zig
pub fn createPlan(allocator: std.mem.Allocator, equation: *const Equation, options: Options) PlanError!Plan {    if (equation.inputs.len == 0) return error.EmptyEquation;    if (equation.inputs.len > 63) return error.TooManyInputs;    var context = try PlanningContext.init(allocator, equation);    defer context.deinit(allocator);    return switch (options.strategy) {        .auto => createAutoPlan(allocator, &context, options),        .left_to_right => createLinearPlan(allocator, &context, .left_to_right),        .greedy => createLinearPlan(allocator, &context, .greedy),        .beam => createBeamPlan(allocator, &context, options.beam_width),        .anytime => createAnytimePlan(allocator, &context, options.beam_width),        .optimal => createOptimalPlan(allocator, &context, options.max_exact_inputs),    };}
Called byCallsprivate sourcelib.accy.src.choir.einsum.loweringloweringAllocationWitnessprivate sourcelib.accy.src.choir.einsum.loweringloweringStorageWitnesstest sourcelib.accy.src.choir.einsum.loweringtest: einsum lowering bounds reject i...test sourcelib.accy.src.choir.einsum.loweringtest: einsum lowering emits planned d...test sourcelib.accy.src.choir.einsum.loweringtest: einsum lowering emits single in...+23 moreprivate sourcelib.accy.src.choir.einsum.planner.PlanningCon...deinitprivate sourcelib.accy.src.choir.einsum.planner.PlanningCon...initprivate sourcelib.accy.src.choir.einsum.plannercreateAnytimePlanprivate sourcelib.accy.src.choir.einsum.plannercreateAutoPlanprivate sourcelib.accy.src.choir.einsum.plannercreateBeamPlan+2 morechoircreateEinsumPlan
Static calls · unresolved targets: 0 · external targets: 0.

Source: lib/accy/src/choir/einsum/planner.zig:23

zig
pub const default_auto_beam_width: usize = 256;

Source: lib/accy/src/choir/einsum/planner.zig:22

zig
pub const default_exact_state_limit: usize = 262_144;
Called byCallschoir.EinsumEquationelementCountchoir.einsum.IndexSetcontainschoir.EinsumEquationdimension
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsprivate sourcelib.accy.src.choir.einsum.planner.PlanningCon...elementCountchoir.EinsumEquationdimensionprivate sourcelib.accy.src.choir.einsum.specsaturatingMulchoir.EinsumEquationelementCount
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callerschoir.einsum.IndexSetunionedchoir.EinsumEquationinputSet
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsprivate sourcelib.accy.src.choir.einsum.loweringsetFromOrderprivate sourcelib.accy.src.choir.einsum.specparseInputprivate sourcelib.accy.src.choir.einsum.specparseOutputprivate sourcelib.accy.src.choir.einsum.spec.IndexSetbitMaskprivate sourcelib.accy.src.choir.einsum.spec.IndexSetwordIndexchoir.einsum.IndexSetadd
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallschoir.EinsumEquationdimensionprivate sourcelib.accy.src.choir.einsum.specparseInputprivate sourcelib.accy.src.choir.einsum.specparseOutputprivate sourcelib.accy.src.choir.einsum.spec.IndexSetbitMaskprivate sourcelib.accy.src.choir.einsum.spec.IndexSetwordIndexchoir.einsum.IndexSetcontains
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callschoir.EinsumEquationinputSetchoir.einsum.IndexSetunioned
Static calls · unresolved targets: 0 · external targets: 0.

Source: lib/accy/src/choir/einsum/spec.zig:117

zig
pub const ParseError = error{    MissingArrow,    MultipleArrows,    EmptyInputList,    InvalidIndex,    RepeatedInputIndex,    RepeatedOutputIndex,    OutputIndexMissing,    ArityMismatch,    RankMismatch,    DimensionMismatch,    TooManyInputs,} || std.mem.Allocator.Error;

Source: lib/accy/src/choir/einsum/spec.zig:203

zig
pub fn parse(allocator: std.mem.Allocator, equation: []const u8, input_shapes: []const []const u64) ParseError!Equation {    const arrow = findArrow(equation) orelse return error.MissingArrow;    if (findArrow(equation[arrow + 2 ..]) != null) return error.MultipleArrows;    if (input_shapes.len > 63) return error.TooManyInputs;    const lhs = equation[0..arrow];    const rhs = equation[arrow + 2 ..];    var dimensions: [256]u64 = undefined;    var global_indices: IndexSet = .{};    var inputs = std.ArrayListUnmanaged(Input).empty;    errdefer inputs.deinit(allocator);    errdefer freeInputs(allocator, inputs.items);    var input_index: usize = 0;    var term_iter = std.mem.splitScalar(u8, lhs, ',');    while (term_iter.next()) |term| {        if (input_index >= input_shapes.len) return error.ArityMismatch;        const input = try parseInput(allocator, term, input_shapes[input_index], &dimensions, &global_indices);        var input_owned = true;        errdefer if (input_owned) freeInput(allocator, input);        try inputs.append(allocator, input);        input_owned = false;        input_index += 1;    }    if (input_index == 0) return error.EmptyInputList;    if (input_index != input_shapes.len) return error.ArityMismatch;    const output = try parseOutput(allocator, rhs, global_indices);    errdefer allocator.free(output.indices);    return .{        .allocator = allocator,        .inputs = try inputs.toOwnedSlice(allocator),        .output = output.indices,        .output_set = output.index_set,        .index_set = global_indices,        .dimensions = dimensions,    };}
Called byCallsprivate sourcelib.accy.src.choir.einsum.specparseAllocationWitnessprivate sourcelib.accy.src.choir.einsum.specparseStorageWitnesstest sourcelib.accy.src.choir.einsum.spectest: einsum parser accepts scalar op...test sourcelib.accy.src.choir.einsum.spectest: einsum parser bounds preserve e...test sourcelib.accy.src.choir.einsum.spectest: einsum parser rejects inconsist...+2 moreprivate sourcelib.accy.src.choir.einsum.specfindArrowprivate sourcelib.accy.src.choir.einsum.specfreeInputprivate sourcelib.accy.src.choir.einsum.specfreeInputsprivate sourcelib.accy.src.choir.einsum.specparseInputprivate sourcelib.accy.src.choir.einsum.specparseOutputchoirparseEinsumEquation
Static calls · unresolved targets: 1 · external targets: 4.

Source: lib/accy/src/choir/einsum/spec.zig:184

zig
/// Returns the figures for an equation of `equation_bytes` bytes and/// `input_count` inputs, computed from those two numbers alone with no parsing/// and no allocation, so the einsum pass can call this with the equation length/// and operand count before parsing. The figures cover a successful parse and/// every error the parse can stop at. The parser looks for the arrow and for a/// second arrow before it checks the input limit, so above 63 inputs the/// figures charge only the text scan and no storage. Label lists stop at 62/// distinct letters and digits, so extra whitespace lengthens the scan but adds/// no storage. Structural visits cover copies, checks of dimensions and label/// sets, transfers, and cleanup after a failed prefix. A test parses inside a/// fixed buffer of the charged size that never frees.pub fn parseBounds(equation_bytes: usize, input_count: usize) ParseBounds.Error!ParseBounds {    var bounds: ParseBounds = .{        .structural_visits = try ParseBounds.add(1, try ParseBounds.multiply(16, equation_bytes)),    };    if (input_count > 63) return bounds;    const labels = @min(equation_bytes, 62);    const label_storage = try ParseBounds.list(u8, labels);    const input_storage = try ParseBounds.add(label_storage, try ParseBounds.slice(u64, labels));    bounds.allocation_capacity = try ParseBounds.add(        try ParseBounds.list(Input, input_count),        try ParseBounds.add(try ParseBounds.multiply(input_count, input_storage), label_storage),    );    bounds.structural_visits = try ParseBounds.add(bounds.structural_visits, try ParseBounds.add(        try ParseBounds.multiply(4, bounds.allocation_capacity),        16 * (input_count + 1),    ));    return bounds;}
Called byCallsprivate sourcelib.accy.src.choir.einsum.specparseStorageWitnesstest sourcelib.accy.src.choir.einsum.spectest: einsum parser bounds include re...private sourcelib.accy.src.choir.einsum.spec.ParseBoundsaddprivate sourcelib.accy.src.choir.einsum.spec.ParseBoundslistprivate sourcelib.accy.src.choir.einsum.spec.ParseBoundsmultiplyprivate sourcelib.accy.src.choir.einsum.spec.ParseBoundsslicechoir.einsumparseBounds
Static calls · unresolved targets: 0 · external targets: 0.

Source: lib/accy/src/choir/einsum/root.zig

zig
const spec = @import("spec.zig");const planner = @import("planner.zig");const lowering = @import("lowering.zig");pub const Equation = spec.Equation;pub const Input = spec.Input;pub const IndexSet = spec.IndexSet;pub const ParseError = spec.ParseError;pub const ParseBounds = spec.ParseBounds;pub const NodeId = planner.NodeId;pub const Options = planner.Options;pub const Plan = planner.Plan;pub const PlanError = planner.PlanError;pub const Step = planner.Step;pub const Strategy = planner.Strategy;pub const default_exact_state_limit = planner.default_exact_state_limit;pub const default_auto_beam_width = planner.default_auto_beam_width;pub const LowerError = lowering.LowerError;pub const LoweringBounds = lowering.LoweringBounds;pub const parse = spec.parse;pub const parseBounds = spec.parseBounds;pub const createPlan = planner.createPlan;pub const loweringBounds = lowering.loweringBounds;pub const lowerPlan = lowering.lowerPlan;pub const lowerPlanWithRewriter = lowering.lowerPlanWithRewriter;

Source: lib/accy/src/choir/root.zig:11

zig
pub const einsum = @import("einsum/root.zig");

Complete call list for choir.einsum.Options.storageBound

7 direct calls.

Complete call list for choir.einsum.Options.workBound

7 direct calls.

Complete caller list for choir.createEinsumPlan

28 direct callers.

Complete call list for choir.createEinsumPlan

7 direct calls.

Complete caller list for choir.parseEinsumEquation

7 direct callers.

Audit

Definitions37
Public names47
Members51
Version26.7.0
Revisiondaab053ee433