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 selfoperations. Read the components of a span withScratch::get. - Marks and reset.
Scratch::markrecords the current top andScratch::resetlowers 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, forScratch::product, room for its intermediate expansions. If that does not fit, the operation returnsScratchExhaustedand leaves the arena unchanged.Scratch::high_watertells 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
Scratcharena, to return to withScratch::reset. Marks compare equal when they save the same top. - Scratch
- A bump arena of
f64components for expansion arithmetic. See the module documentation for the model. - Scratch
Exhausted - The error of a
Scratchoperation whose worst-case result does not fit in the free part of the arena. - Span
- The position of an expansion in a
Scratcharena.