Skip to main content

Vector

Trait Vector 

Source
pub trait Vector:
    VectorOpsByValue<Self>
    + for<'b> VectorOpsByValue<&'b Self>
    + for<'a> VectorOpsByValue<Self::View<'a>>
    + for<'a, 'b> VectorOpsByValue<&'b Self::View<'a>>
    + Mul<Scale<Self::T>, Output = Self>
    + Div<Scale<Self::T>, Output = Self>
    + VectorMutOpsByValue<Self>
    + for<'a> VectorMutOpsByValue<Self::View<'a>>
    + for<'b> VectorMutOpsByValue<&'b Self>
    + for<'a, 'b> VectorMutOpsByValue<&'b Self::View<'a>>
    + MulAssign<Scale<Self::T>>
    + Clone
    + Send {
    type View<'a>: VectorView<'a, T = Self::T, Owned = Self>
       where Self: 'a;
    type ViewMut<'a>: VectorViewMut<'a, T = Self::T, Owned = Self, View = Self::View<'a>>
       where Self: 'a;
    type Index: VectorIndex;

Show 49 methods // Required methods fn context(&self) -> &Self::C; fn inner_mut(&mut self) -> &mut Self::Inner; fn set_index(&mut self, index: IndexType, value: Self::T); fn fill_index(&mut self, index: IndexType, value: Self::T); fn get_index(&self, index: IndexType) -> Self::T; fn norm(&self, k: i32) -> Self::T; fn squared_norm(&self, y: &Self, atol: &Self, rtol: Self::T) -> Self::T; fn len(&self) -> IndexType; fn from_element(nstates: usize, value: Self::T, ctx: Self::C) -> Self; fn fill(&mut self, value: Self::T); fn as_view(&self) -> Self::View<'_>; fn as_view_mut(&mut self) -> Self::ViewMut<'_>; fn get_batch(&self, batch: usize) -> Self::View<'_>; fn get_batch_mut(&mut self, batch: usize) -> Self::ViewMut<'_>; fn for_each_batch_mut_host<const M: usize, const N: usize>( mut_args: [&mut Self; M], args: [&Self; N], f: impl FnMut([&mut [Self::T]; M], [&[Self::T]; N], usize), ); fn copy_from(&mut self, other: &Self); fn copy_from_view(&mut self, other: &Self::View<'_>); fn from_vec(vec: Vec<Self::T>, ctx: Self::C) -> Self; fn from_slice(slice: &[Self::T], ctx: Self::C) -> Self; fn clone_as_vec(&self) -> Vec<Self::T>; fn axpy(&mut self, alpha: Self::T, x: &Self, beta: Self::T); fn axpy_v(&mut self, alpha: Self::T, x: &Self::View<'_>, beta: Self::T); fn batched_axpy(&mut self, alpha: &Self, x: &Self, beta: Self::T); fn component_mul_assign(&mut self, other: &Self); fn component_div_assign(&mut self, other: &Self); fn root_finding(&self, g1: &Self) -> (bool, Self::T, i32); fn assign_at_indices(&mut self, indices: &Self::Index, value: Self::T); fn copy_from_indices(&mut self, other: &Self, indices: &Self::Index); fn gather(&mut self, other: &Self, indices: &Self::Index); fn scatter(&self, indices: &Self::Index, other: &mut Self); // Provided methods fn total_len(&self) -> IndexType { ... } fn is_empty(&self) -> bool { ... } fn zeros(nstates: usize, ctx: Self::C) -> Self { ... } fn for_each_batch_host<const N: usize>( &mut self, args: [&Self; N], f: impl FnMut(&mut [Self::T], [&[Self::T]; N], usize), ) { ... } fn for_each_batch_mut<const M: usize, const N: usize>( mut_args: [&mut Self; M], args: [&Self; N], f: impl Fn([&mut [Self::T]; M], [&[Self::T]; N], usize) + Copy + Send, ) { ... } fn for_each_batch<const N: usize>( &mut self, args: [&Self; N], f: impl Fn(&mut [Self::T], [&[Self::T]; N], usize) + Copy + Send, ) { ... } fn for_each_elem_mut<const M: usize, const N: usize>( mut_args: [&mut Self; M], args: [&Self; N], f: impl Fn([&mut Self::T; M], [&[Self::T]; N], usize, usize) + Copy + Send, ) { ... } fn for_each_elem<const N: usize>( &mut self, args: [&Self; N], f: impl Fn(&mut Self::T, [&[Self::T]; N], usize, usize) + Copy + Send, ) { ... } fn reduce_batch_host<const N: usize>( dest: &mut Self, args: [&Self; N], init: Self::T, map: impl FnMut([&[Self::T]; N], usize, usize) -> Self::T, combine: impl FnMut(Self::T, Self::T) -> Self::T, ) { ... } fn reduce_batch<const N: usize>( dest: &mut Self, args: [&Self; N], init: Self::T, map: impl Fn([&[Self::T]; N], usize, usize) -> Self::T + Copy + Send, combine: impl Fn(Self::T, Self::T) -> Self::T + Copy + Send, ) { ... } fn reduce_elem_host<const N: usize>( dest: &mut Self, args: [&Self; N], init: Self::T, map: impl FnMut([&[Self::T]; N], usize, usize) -> Self::T, combine: impl FnMut(Self::T, Self::T) -> Self::T, ) { ... } fn reduce_elem<const N: usize>( dest: &mut Self, args: [&Self; N], init: Self::T, map: impl Fn([&[Self::T]; N], usize, usize) -> Self::T + Copy + Send, combine: impl Fn(Self::T, Self::T) -> Self::T + Copy + Send, ) { ... } fn dot(&self, other: &Self) -> Self::T { ... } fn rand(nstates: usize, seed: f64, ctx: Self::C) -> Self { ... } fn assert_eq_st(&self, other: &Self, tol: Self::T) { ... } fn assert_eq_eps(&self, other: &Self, factor: f64) { ... } fn assert_eq_norm( &self, other: &Self, atol: &Self, rtol: Self::T, factor: Self::T, ) { ... } fn assert_eq(&self, other: &Self, tol: &Self) { ... } fn assert_eq_vec(s: Vec<Self::T>, other: Vec<Self::T>, tol: Vec<Self::T>) { ... }
}
Expand description

A complete vector abstraction supporting arithmetic operations, norms, and index operations.

This is the main vector trait used throughout diffsol. Implementing vectors can be hosted on CPU or GPU. Users typically do not need to implement this trait; use provided implementations like NalgebraVec or FaerVec.

Required Associated Types§

Source

type View<'a>: VectorView<'a, T = Self::T, Owned = Self> where Self: 'a

Source

type ViewMut<'a>: VectorViewMut<'a, T = Self::T, Owned = Self, View = Self::View<'a>> where Self: 'a

Source

type Index: VectorIndex

Required Methods§

Source

fn context(&self) -> &Self::C

Get the context associated with this vector (for device placement, threading, etc.).

Source

fn inner_mut(&mut self) -> &mut Self::Inner

Get a mutable reference to the inner representation of the vector.

Source

fn set_index(&mut self, index: IndexType, value: Self::T)

Set the value at the specified index to value. Panics unless nbatch == 1; to write the same value into every batch use Self::fill_index.

Source

fn fill_index(&mut self, index: IndexType, value: Self::T)

Set the value at the specified index to value in every batch.

This is what a basis or probe vector wants — the same scalar in every lane — and is the only way to write a single index of a batched vector; Self::set_index panics on one.

Source

fn get_index(&self, index: IndexType) -> Self::T

Get the value at the specified index. Panics unless nbatch == 1; for a batched vector read one lane with Self::get_batch.

Source

fn norm(&self, k: i32) -> Self::T

Compute the $\ell_k$ norm: $(\sum_i |x_i|^k)^{1/k}$

Source

fn squared_norm(&self, y: &Self, atol: &Self, rtol: Self::T) -> Self::T

Compute the squared weighted norm for error control: $\sum_i (x_i / (|y_i| \cdot \text{rtol} + \text{atol}_i))^2$

This norm is used by ODE solvers for adaptive error control.

Source

fn len(&self) -> IndexType

Get the per-batch length (number of states) in this vector. For batched vectors, this returns nstates, not nstates * nbatch.

Source

fn from_element(nstates: usize, value: Self::T, ctx: Self::C) -> Self

Create a vector of length nstates with all elements initialized to value.

Source

fn fill(&mut self, value: Self::T)

Fill all elements of this vector with value.

Source

fn as_view(&self) -> Self::View<'_>

Create an immutable view of this vector.

Source

fn as_view_mut(&mut self) -> Self::ViewMut<'_>

Create a mutable view of this vector.

Source

fn get_batch(&self, batch: usize) -> Self::View<'_>

Get an immutable view of a single batch (with nbatch=1 context).

Source

fn get_batch_mut(&mut self, batch: usize) -> Self::ViewMut<'_>

Get a mutable view of a single batch (with nbatch=1 context).

Source

fn for_each_batch_mut_host<const M: usize, const N: usize>( mut_args: [&mut Self; M], args: [&Self; N], f: impl FnMut([&mut [Self::T]; M], [&[Self::T]; N], usize), )

Run f once per batch lane on the host.

The lane count (i.e. number of batches) is governed by mut_args[0], the primary output. Every other operand, mutable or not, broadcasts. Panics if an operand’s batch count is not broadcastable into the output’s, or if mut_args is empty.

The closure’s last argument is the lane of the output being written, in 0..mut_args[0].context().nbatch().

A device-backed vector stages every operand through host memory to run f, so prefer Self::for_each_batch_mut when f is device-compilable.

ⓘ
// y = A^T v, via a scratch buffer the backend requires to be mutable
V::for_each_batch_mut_host([y, &mut scratch], [x, v], |[y, scratch], [x, v], _lane| {
    scratch.copy_from_slice(v);
    op.transpose_mul(x, scratch, y);
});
Source

fn copy_from(&mut self, other: &Self)

Copy all values from other into this vector.

Source

fn copy_from_view(&mut self, other: &Self::View<'_>)

Copy all values from a vector view into this vector.

Source

fn from_vec(vec: Vec<Self::T>, ctx: Self::C) -> Self

Create a vector from a Rust Vec.

Source

fn from_slice(slice: &[Self::T], ctx: Self::C) -> Self

Create a vector from a slice.

Source

fn clone_as_vec(&self) -> Vec<Self::T>

Clone this vector as a Rust Vec.

Source

fn axpy(&mut self, alpha: Self::T, x: &Self, beta: Self::T)

Compute the AXPY operation: self = alpha * x + beta * self

Source

fn axpy_v(&mut self, alpha: Self::T, x: &Self::View<'_>, beta: Self::T)

Compute the AXPY operation with a vector view: self = alpha * x + beta * self

Source

fn batched_axpy(&mut self, alpha: &Self, x: &Self, beta: Self::T)

Per-batch AXPY: self[i]_b = alpha_b * x[i]_b + beta * self[i]_b

alpha is a batched scalar: one value per batch, so alpha.len() == 1 and its batch count equals self’s. A uniform multiplier is plain Self::axpy instead. The x operand may broadcast if its nbatch == 1.

Source

fn component_mul_assign(&mut self, other: &Self)

Element-wise multiplication: self_i *= other_i

Source

fn component_div_assign(&mut self, other: &Self)

Element-wise division: self_i /= other_i

Source

fn root_finding(&self, g1: &Self) -> (bool, Self::T, i32)

Detect roots (zero crossings) between this vector (as g0) and another vector (g1).

Returns a tuple of:

  • bool: true if a zero crossing is found (g1_i == 0 for some i)
  • T: the interpolation factor at the maximum crossing (0 if none found) (given by maxmimum |g0_i / (g1_i - g0_i)|)
  • i32: the index of the maximum crossing (-1 if none found)
Source

fn assign_at_indices(&mut self, indices: &Self::Index, value: Self::T)

Assign value to all elements at the specified indices.

Source

fn copy_from_indices(&mut self, other: &Self, indices: &Self::Index)

Copy values from other at the specified indices: self[indices[i]] = other[indices[i]]

Source

fn gather(&mut self, other: &Self, indices: &Self::Index)

Gather values from other at indices: self[i] = other[indices[i]]

Source

fn scatter(&self, indices: &Self::Index, other: &mut Self)

Scatter values to other at indices: other[indices[i]] = self[i]

Provided Methods§

Source

fn total_len(&self) -> IndexType

Get the total number of elements stored, including all batches. Returns self.len() * self.context().nbatch().

Source

fn is_empty(&self) -> bool

Check if the vector is empty.

Source

fn zeros(nstates: usize, ctx: Self::C) -> Self

Create a vector of length nstates with all elements set to zero.

Source

fn for_each_batch_host<const N: usize>( &mut self, args: [&Self; N], f: impl FnMut(&mut [Self::T], [&[Self::T]; N], usize), )

Run f once per batch lane of self on the host, passing that lane of self as a mutable slice and the corresponding lane of each operand in args as an immutable slice.

The single-output case of Self::for_each_batch_mut_host.

ⓘ
// y_0 = x_0 v_0 + x_1 v_1, y_1 = 0, for every batch of y
y.for_each_batch_host([x, v], |y, [x, v], _lane| {
    y[0] = x[0] * v[0] + x[1] * v[1];
    y[1] = T::zero();
});
Source

fn for_each_batch_mut<const M: usize, const N: usize>( mut_args: [&mut Self; M], args: [&Self; N], f: impl Fn([&mut [Self::T]; M], [&[Self::T]; N], usize) + Copy + Send, )

Run f once per batch lane on the device where the backend has one, falling back to Self::for_each_batch_mut_host otherwise.

Same lane, broadcast and panic semantics as Self::for_each_batch_mut_host; which side ran it is not observable beyond timing.

f must therefore be device-compilable Rust — arithmetic and control flow over the lane slices, no host function pointers, no allocation, no std .A closure that cannot meet this should use [Self::for_each_batch_mut_host`] instead.

Source

fn for_each_batch<const N: usize>( &mut self, args: [&Self; N], f: impl Fn(&mut [Self::T], [&[Self::T]; N], usize) + Copy + Send, )

Run f once per batch lane of self on the device where the backend has one.

The single-output case of Self::for_each_batch_mut, and subject to the same device-compilable requirement on f.

ⓘ
// y_0 = x_0 v_0 + x_1 v_1, y_1 = 0, for every batch of y
y.for_each_batch([x, v], |y, [x, v], _lane| {
    y[0] = x[0] * v[0] + x[1] * v[1];
    y[1] = T::zero();
});
Source

fn for_each_elem_mut<const M: usize, const N: usize>( mut_args: [&mut Self; M], args: [&Self; N], f: impl Fn([&mut Self::T; M], [&[Self::T]; N], usize, usize) + Copy + Send, )

Run f once per element of every batch lane on the device where the backend has one, falling back to a host loop otherwise.

The element-parallel counterpart of Self::for_each_batch_mut: f is handed one element of each output rather than the whole lane, so a backend with a device can run every (lane, element) pair concurrently.

The inputs are still full lane slices, so reads may go anywhere in the lane.

f must be device-compilable Rust — arithmetic and control flow over the slices, no host function pointers, no allocation, no std.

Source

fn for_each_elem<const N: usize>( &mut self, args: [&Self; N], f: impl Fn(&mut Self::T, [&[Self::T]; N], usize, usize) + Copy + Send, )

Run f once per element of every batch lane of self on the device where the backend has one.

The single-output case of Self::for_each_elem_mut, and subject to the same device-compilable requirement on f.

ⓘ
// y_i = x_i p_0 + x_{i+1}, wrapping, for every batch of y
y.for_each_elem([x, p], |y, [x, p], _lane, i| {
    *y = x[i] * p[0] + x[(i + 1) % x.len()];
});
Source

fn reduce_batch_host<const N: usize>( dest: &mut Self, args: [&Self; N], init: Self::T, map: impl FnMut([&[Self::T]; N], usize, usize) -> Self::T, combine: impl FnMut(Self::T, Self::T) -> Self::T, )

Reduce args over the batch dimension, elementwise, on the host.

dest[i] becomes map(.., b, i) folded over every lane b with combine, starting from init. dest is the one operand the batch dimension is removed from, so it must be unbatched (context().nbatch() == 1); its length is the element range. The lane count comes from args[0], and the other operands broadcast into it.

combine must be associative with init as its identity. This host path folds in lane order, but Self::reduce_batch folds on a device and needs commutativity too.

dest must not alias any of args.

ⓘ
// dest_i = max_b |x[b, i]|
V::reduce_batch_host(&mut dest, [x], T::zero(),
    |[x], _lane, i| x[i].abs(),
    |a, b| a.max(b));
Source

fn reduce_batch<const N: usize>( dest: &mut Self, args: [&Self; N], init: Self::T, map: impl Fn([&[Self::T]; N], usize, usize) -> Self::T + Copy + Send, combine: impl Fn(Self::T, Self::T) -> Self::T + Copy + Send, )

Reduce args over the batch dimension, elementwise, on the device where the backend has one, falling back to Self::reduce_batch_host otherwise.

Same shape and broadcast rules; map and combine must be device-compilable Rust, as for Self::for_each_batch_mut. combine must also be associative and commutative: the device folds with warp shuffles that pair a lane with lane ^ delta, so neither the order nor the grouping of the operands is the caller’s. Sum, max and min all qualify.

Source

fn reduce_elem_host<const N: usize>( dest: &mut Self, args: [&Self; N], init: Self::T, map: impl FnMut([&[Self::T]; N], usize, usize) -> Self::T, combine: impl FnMut(Self::T, Self::T) -> Self::T, )

Reduce each batch lane of args over its elements, on the host.

Lane b of dest becomes map(.., b, i) folded over every element i with combine, starting from init. dest is a batched scalar — len() == 1 with the operands’ lane count — the same shape Self::batched_axpy takes. The element range comes from args[0], and the other operands broadcast into the lanes.

combine must be associative with init as its identity. This host path folds in index order, but Self::reduce_elem folds on a device and needs commutativity too.

dest must not alias any of args.

ⓘ
// dest_b = sum_i x[b, i] * v[b, i]
V::reduce_elem_host(&mut dest, [x, v], T::zero(),
    |[x, v], _lane, i| x[i] * v[i],
    |a, b| a + b);
Source

fn reduce_elem<const N: usize>( dest: &mut Self, args: [&Self; N], init: Self::T, map: impl Fn([&[Self::T]; N], usize, usize) -> Self::T + Copy + Send, combine: impl Fn(Self::T, Self::T) -> Self::T + Copy + Send, )

Reduce each batch lane of args over its elements, on the device where the backend has one, falling back to Self::reduce_elem_host otherwise.

Same shape and broadcast rules; map and combine must be device-compilable Rust, as for Self::for_each_elem_mut. combine must also be associative and commutative: the device folds with warp shuffles that pair a lane with lane ^ delta, so neither the order nor the grouping of the operands is the caller’s. Sum, max and min all qualify.

Source

fn dot(&self, other: &Self) -> Self::T

The dot product with other, summed over every element of every batch lane. other broadcasts into this vector’s lanes, as in Self::reduce_elem. The per-lane sums are added on the host, which on a device backend means a copy back to the host each call: meant for tests and checks rather than inner loops.

Source

fn rand(nstates: usize, seed: f64, ctx: Self::C) -> Self

A deterministic pseudo-random vector of length nstates with the lanes of ctx, for tests: element i of lane b is sin((b * nstates + i + 1) * seed). The values are irregular, so a dot test can’t pass by symmetry, and different seeds give different vectors.

Source

fn assert_eq_st(&self, other: &Self, tol: Self::T)

Assert that this vector equals other within a scalar tolerance tol.

Source

fn assert_eq_eps(&self, other: &Self, factor: f64)

Assert that this vector equals other within factor machine epsilons of Self::T.

Source

fn assert_eq_norm( &self, other: &Self, atol: &Self, rtol: Self::T, factor: Self::T, )

Assert that this vector equals other using a weighted norm (same as used by ODE solvers).

Uses squared_norm internally with the scaling factors, and asserts that the resulting norm is less than factor.

Source

fn assert_eq(&self, other: &Self, tol: &Self)

Assert that this vector equals other using a vector of per-element tolerances.

Source

fn assert_eq_vec(s: Vec<Self::T>, other: Vec<Self::T>, tol: Vec<Self::T>)

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§