pub struct Scratch<'a> { /* private fields */ }Expand description
A bump arena of f64 components for expansion arithmetic. See the
module documentation for the model.
Implementations§
Source§impl Scratch<'static>
impl Scratch<'static>
Sourcepub fn growable(initial: usize) -> Scratch<'static>
pub fn growable(initial: usize) -> Scratch<'static>
Creates an empty arena that owns its memory, with room for initial
components (at most u32::MAX, the most an arena uses).
When an operation needs more room the arena grows on the heap to at
least double its capacity, or to what the operation needs if that is
more, keeping its contents. Spans are indices, so they stay valid
after the buffer moves. The arena fails with
ScratchExhausted only when an operation
needs more than u32::MAX components, and then it is unchanged.
Running out of memory aborts, as for any alloc collection;
ScratchExhausted is returned only when the arena would exceed
u32::MAX components.
Available only with the alloc cargo feature.
§Examples
use implicit_predicates_core::Scratch;
let mut scratch = Scratch::growable(1);
let a = scratch.push(&[1e-20, 1.0])?; // grows
assert!(scratch.capacity() >= 2);
assert_eq!(scratch.get(a), &[1e-20, 1.0]);Source§impl Scratch<'_>
impl Scratch<'_>
Sourcepub fn product(&mut self, a: Span, b: Span) -> Result<Span, ScratchExhausted>
pub fn product(&mut self, a: Span, b: Span) -> Result<Span, ScratchExhausted>
Writes the expansion of a * b and returns its span.
The product is the sum, over the components c of the shorter
operand, of the longer operand scaled by c (expansion::scale),
accumulated with expansion::sum. It is exact, and the result is a
valid expansion of at most 2 * a.len() * b.len() components.
Requirement, as for scale: every component of a
and of b lies in the product domain (see
eft::in_product_domain), since
every product of a component of a by one of b is computed exactly
with eft::two_product; debug builds
panic if one does not. The components of the result can lie outside
that domain, so a product of products needs the caller to bound the
magnitudes involved.
Needs 4 * a.len() * b.len() + 2 * max(a.len(), b.len()) free
components while it works, or none if either operand is empty. The
result ends up just above the previous top, like that of every other
operation, and the working space beyond it is released.
§Errors
ScratchExhausted if that space is not free; the arena is
unchanged.
§Examples
use implicit_predicates_core::Scratch;
let tiny = 2f64.powi(-60);
let mut buf = [0.0; 32];
let mut scratch = Scratch::borrowed(&mut buf);
let a = scratch.push(&[tiny, 1.0])?; // 1 + 2^-60
let b = scratch.push(&[-tiny, 1.0])?; // 1 - 2^-60
let p = scratch.product(a, b)?;
assert_eq!(scratch.get(p), &[-tiny * tiny, 1.0]); // 1 - 2^-120
assert_eq!(scratch.used(), 4 + p.len());
assert_eq!(scratch.high_water(), 4 + 4 * 2 * 2 + 2 * 2);Source§impl<'a> Scratch<'a>
impl<'a> Scratch<'a>
Sourcepub fn borrowed(buf: &'a mut [f64]) -> Scratch<'a>
pub fn borrowed(buf: &'a mut [f64]) -> Scratch<'a>
Creates an empty arena over buf, of which it uses at most
u32::MAX components. The initial contents of buf do not matter.
§Examples
use implicit_predicates_core::Scratch;
let mut buf = [0.0; 64];
let scratch = Scratch::borrowed(&mut buf);
assert_eq!(scratch.capacity(), 64);
assert_eq!(scratch.used(), 0);Sourcepub fn mark(&self) -> Mark
pub fn mark(&self) -> Mark
Returns a mark of the current top, to return to with
reset.
§Examples
use implicit_predicates_core::Scratch;
let mut buf = [0.0; 4];
let mut scratch = Scratch::borrowed(&mut buf);
scratch.push(&[1.0])?;
let mark = scratch.mark();
scratch.push(&[2.0])?;
scratch.reset(mark);
assert_eq!(scratch.used(), 1);Sourcepub fn reset(&mut self, m: Mark)
pub fn reset(&mut self, m: Mark)
Lowers the top to the mark m, releasing every span created since
m was taken. high_water is unchanged.
m must not be above the current top, which happens when a reset
to an earlier mark came in between. That is a logic error: debug
builds panic, release builds leave the top unchanged.
§Examples
use implicit_predicates_core::Scratch;
let mut buf = [0.0; 4];
let mut scratch = Scratch::borrowed(&mut buf);
let mark = scratch.mark();
scratch.push(&[1e-20, 1.0])?;
scratch.reset(mark);
assert_eq!(scratch.used(), 0);
assert_eq!(scratch.high_water(), 2);Sourcepub fn get(&self, s: Span) -> &[f64]
pub fn get(&self, s: Span) -> &[f64]
Returns the components of the expansion at s.
Debug builds panic if s reaches past the top; see the
module documentation for spans that are no longer valid.
§Examples
use implicit_predicates_core::Scratch;
let mut buf = [0.0; 4];
let mut scratch = Scratch::borrowed(&mut buf);
let s = scratch.push(&[1e-20, 1.0])?;
assert_eq!(scratch.get(s), &[1e-20, 1.0]);Sourcepub fn used(&self) -> usize
pub fn used(&self) -> usize
Returns the number of components in use, below the top.
§Examples
use implicit_predicates_core::Scratch;
let mut buf = [0.0; 4];
let mut scratch = Scratch::borrowed(&mut buf);
scratch.push(&[1e-20, 1.0])?;
assert_eq!(scratch.used(), 2);Sourcepub fn capacity(&self) -> usize
pub fn capacity(&self) -> usize
Returns the number of components the arena can hold: the length of
its buffer, or u32::MAX if the buffer is longer.
§Examples
use implicit_predicates_core::Scratch;
let mut buf = [0.0; 8];
assert_eq!(Scratch::borrowed(&mut buf).capacity(), 8);Sourcepub fn high_water(&self) -> usize
pub fn high_water(&self) -> usize
Returns the highest used ever reached, counting the
space each successful operation reserves while it works, even when
its result turns out shorter. A buffer this long is enough
to repeat the same computation. Failed operations reserve nothing.
§Examples
use implicit_predicates_core::Scratch;
let mut buf = [0.0; 8];
let mut scratch = Scratch::borrowed(&mut buf);
let a = scratch.push(&[1e-20, 1.0])?;
let zero = scratch.diff(a, a)?; // reserves 4 components, keeps none
assert!(zero.is_empty());
assert_eq!(scratch.used(), 2);
assert_eq!(scratch.high_water(), 6);Sourcepub fn push(&mut self, e: &[f64]) -> Result<Span, ScratchExhausted>
pub fn push(&mut self, e: &[f64]) -> Result<Span, ScratchExhausted>
Copies the expansion e into the arena and returns its span.
Needs e.len() free components; an empty e always succeeds, giving
an empty span. Requirement: e is a valid expansion (see
expansion); it is copied as is, and debug builds panic if it is
not valid.
§Errors
ScratchExhausted if e does not fit; the arena is unchanged.
§Examples
use implicit_predicates_core::Scratch;
let mut buf = [0.0; 2];
let mut scratch = Scratch::borrowed(&mut buf);
let s = scratch.push(&[1e-20, 1.0])?;
assert_eq!(scratch.get(s), &[1e-20, 1.0]);Sourcepub fn sum(&mut self, a: Span, b: Span) -> Result<Span, ScratchExhausted>
pub fn sum(&mut self, a: Span, b: Span) -> Result<Span, ScratchExhausted>
Writes the expansion of a + b and returns its span, as
expansion::sum does.
Needs a.len() + b.len() free components while it works.
§Errors
ScratchExhausted if that space is not free; the arena is
unchanged.
§Examples
use implicit_predicates_core::Scratch;
let mut buf = [0.0; 8];
let mut scratch = Scratch::borrowed(&mut buf);
let a = scratch.push(&[1e-20, 1.0])?;
let b = scratch.push(&[-1e-20, 2.0])?;
let s = scratch.sum(a, b)?;
assert_eq!(scratch.get(s), &[3.0]);Sourcepub fn diff(&mut self, a: Span, b: Span) -> Result<Span, ScratchExhausted>
pub fn diff(&mut self, a: Span, b: Span) -> Result<Span, ScratchExhausted>
Writes the expansion of a - b and returns its span, as
expansion::diff does.
Needs a.len() + b.len() free components while it works.
§Errors
ScratchExhausted if that space is not free; the arena is
unchanged.
§Examples
use implicit_predicates_core::Scratch;
let mut buf = [0.0; 8];
let mut scratch = Scratch::borrowed(&mut buf);
let a = scratch.push(&[1e-20, 1.0])?;
let b = scratch.push(&[1e-20, 2.0])?;
let d = scratch.diff(a, b)?;
assert_eq!(scratch.get(d), &[-1.0]);Sourcepub fn scale(&mut self, a: Span, b: f64) -> Result<Span, ScratchExhausted>
pub fn scale(&mut self, a: Span, b: f64) -> Result<Span, ScratchExhausted>
Writes the expansion of a * b and returns its span, as
expansion::scale does, with the same requirements on the
magnitudes.
Needs 2 * a.len() free components while it works.
§Errors
ScratchExhausted if that space is not free; the arena is
unchanged.
§Examples
use implicit_predicates_core::Scratch;
let mut buf = [0.0; 8];
let mut scratch = Scratch::borrowed(&mut buf);
let a = scratch.push(&[0.25, 4.0])?;
let s = scratch.scale(a, 3.0)?;
assert_eq!(scratch.get(s), &[12.75]);Sourcepub fn sign(&self, a: Span) -> Sign
pub fn sign(&self, a: Span) -> Sign
Returns the exact sign of the expansion at a, as
expansion::sign does.
§Examples
use implicit_predicates_core::{Scratch, Sign};
let mut buf = [0.0; 2];
let mut scratch = Scratch::borrowed(&mut buf);
let a = scratch.push(&[1e-20, -1.0])?;
assert_eq!(scratch.sign(a), Sign::Negative);