Skip to main content

Module scratch

Module scratch 

Source
Expand description

A bump arena for expansion arithmetic.

A Scratch arena hands out the memory for the expansions that a computation builds step by step. Its memory is a buffer the caller lends it (Scratch::borrowed), so nothing allocates. With the alloc feature an arena can instead own its memory and grow on the heap (Scratch::growable).

§Model

  • Bump allocation. The arena keeps a top: the buffer below it is in use, the rest is free. Each operation writes its result just above the top and raises the top by the length of that result.
  • Spans are indices. Operations take and return Spans, positions in the arena rather than references to it, so a computation can hold many results while it keeps calling &mut self operations. Read the components of a span with Scratch::get.
  • Marks and reset. Scratch::mark records the current top and Scratch::reset lowers the top back to a mark, releasing at once every result built since. Spans created before the mark stay valid.
  • Exhaustion. Before it writes, an operation reserves all the space it may need above the top: the longest result it can produce (the capacity documented by the slice primitive in expansion), plus, for Scratch::product, room for its intermediate expansions. If that does not fit, the operation returns ScratchExhausted and leaves the arena unchanged. Scratch::high_water tells how much of the buffer a computation needed, which is how to size the buffer.

An arena uses at most u32::MAX components of its buffer. An arena that grows fails with ScratchExhausted only when an operation needs more than that.

A span means something only to the arena that created it, and only while the top stays above it. Using a span after a reset past its start, or with another arena, is a logic error: debug builds detect it when the span reaches past the top, and the result is otherwise unspecified (a panic or unrelated components), but never undefined behavior.

§Examples

use implicit_predicates_core::{Scratch, Sign};

let mut buf = [0.0; 16];
let mut scratch = Scratch::borrowed(&mut buf);
let a = scratch.push(&[1e-20, 1.0])?;
let b = scratch.push(&[3.0])?;

let mark = scratch.mark();
let sum = scratch.sum(a, b)?; // 1 + 3 + 1e-20
let scaled = scratch.scale(sum, -2.0)?;
assert_eq!(scratch.get(scaled), &[-2e-20, -8.0]);
assert_eq!(scratch.sign(scaled), Sign::Negative);

// Release `sum` and `scaled`; `a` and `b` stay valid.
scratch.reset(mark);
assert_eq!(scratch.used(), 3);
assert_eq!(scratch.get(a), &[1e-20, 1.0]);

Structs§

Mark
A saved top of a Scratch arena, to return to with Scratch::reset. Marks compare equal when they save the same top.
Scratch
A bump arena of f64 components for expansion arithmetic. See the module documentation for the model.
ScratchExhausted
The error of a Scratch operation whose worst-case result does not fit in the free part of the arena.
Span
The position of an expansion in a Scratch arena.