pub struct Session<'session> { /* private fields */ }Expand description
One explicit concrete session over a caller-held CPU engine.
The session borrows an engine for the whole of its life. Inside
CpuExecutionContext::with_concrete_session that is the context’s engine,
borrowed for the closure; a caller that owns an engine (crate::CpuBackend)
builds the same session with Session::new and keeps it across as many
operations as it wants. Every route on it runs through that one engine, so a
stage does not pay an entry per operation.
§Examples
use tensor4all_tensorbackend::CpuExecutionContext;
use tenferro::Tensor;
use tensor4all_tensorbackend::CpuBackend;
let context = CpuExecutionContext::from_backend(CpuBackend::with_threads(1)?);
let a = Tensor::from_vec_col_major(vec![2, 2], vec![1.0_f64, 2.0, 3.0, 4.0])?;
let b = Tensor::from_vec_col_major(vec![2, 2], vec![0.0_f64, 1.0, 1.0, 0.0])?;
let (ab, a_again) = context.with_concrete_session(
|session| -> Result<_, Box<dyn std::error::Error + Send + Sync>> {
let ab = session.contraction(&a, &[1], &b, &[0])?;
// One session, two operations.
let a_again = session.permute(&a, &[1, 0])?;
Ok((ab, a_again))
},
)??;
// `a` is `[[1, 3], [2, 4]]` column-major and `b` swaps the axes, so `a * b`
// is `[[3, 1], [4, 2]]`.
assert_eq!(ab.as_slice::<f64>()?, &[3.0, 4.0, 1.0, 2.0]);
assert_eq!(a_again.as_slice::<f64>()?, &[1.0, 3.0, 2.0, 4.0]);Implementations§
Source§impl<'session> Session<'session>
impl<'session> Session<'session>
Sourcepub fn new(engine: &'session mut dyn Engine) -> Self
pub fn new(engine: &'session mut dyn Engine) -> Self
Wrap a borrowed engine as this frontend’s session.
A caller that owns an engine - a crate::CpuBackend, an engine it built
itself, or one borrowed for a stage - builds the same Session the
callback-scoped CpuExecutionContext::with_concrete_session hands out, so a
long stage can keep one session across many operations without entering a
context. The engine stays borrowed for the whole life of the returned session:
this constructor never enters, replaces or reroutes an engine.
§Examples
use tensor4all_tensorbackend::{explicit::Session, CpuBackend};
use tenferro::Tensor;
let mut backend = CpuBackend::with_threads(1)?;
let a = Tensor::from_vec_col_major(vec![2, 2], vec![1.0_f64, 2.0, 3.0, 4.0])?;
let mut session = Session::new(backend.engine_mut());
// One session, two operations.
let transposed = session.permute(&a, &[1, 0])?;
let total = session.sum(&transposed)?;
assert_eq!(total.as_slice::<f64>()?, &[10.0]);Sourcepub fn engine(&mut self) -> &mut dyn Engine
pub fn engine(&mut self) -> &mut dyn Engine
The engine behind this explicit session.
Exposed so a prepared plan can evaluate itself on the caller’s engine; it is not a second entry point, and it never consults another backend.
Sourcepub fn reshape(
&mut self,
tensor: &NativeTensor,
shape: &[usize],
) -> Result<NativeTensor>
pub fn reshape( &mut self, tensor: &NativeTensor, shape: &[usize], ) -> Result<NativeTensor>
Reshape a concrete tensor without changing its column-major linearization.
§Errors
Returns [tenferro_tensor::Error::Validation] when the element counts
differ or the requested layout is invalid,
[tenferro_tensor::Error::UnsupportedDType] for a dtype the backend cannot
reshape, and [tenferro_tensor::Error::BackendSource] when the operation
itself fails. It never retries on another route.
§Examples
use tensor4all_tensorbackend::CpuExecutionContext;
use tenferro::Tensor;
use tensor4all_tensorbackend::CpuBackend;
let context = CpuExecutionContext::from_backend(CpuBackend::with_threads(1)?);
let x = Tensor::from_vec_col_major(vec![4], vec![1.0_f64, 2.0, 3.0, 4.0])?;
let reshaped = context.with_concrete_session(|session| session.reshape(&x, &[2, 2]))??;
assert_eq!(reshaped.as_slice::<f64>()?, &[1.0, 2.0, 3.0, 4.0]);Sourcepub fn permute(
&mut self,
tensor: &NativeTensor,
perm: &[usize],
) -> Result<NativeTensor>
pub fn permute( &mut self, tensor: &NativeTensor, perm: &[usize], ) -> Result<NativeTensor>
Permute the axes of a concrete tensor.
§Errors
Returns [tenferro_tensor::Error::Validation] when perm is not a
permutation of the tensor’s axes, and
[tenferro_tensor::Error::BackendSource] when the operation itself fails.
§Examples
use tensor4all_tensorbackend::CpuExecutionContext;
use tenferro::Tensor;
use tensor4all_tensorbackend::CpuBackend;
let context = CpuExecutionContext::from_backend(CpuBackend::with_threads(1)?);
let x = Tensor::from_vec_col_major(vec![2, 2], vec![1.0_f64, 2.0, 3.0, 4.0])?;
let transposed = context.with_concrete_session(|session| session.permute(&x, &[1, 0]))??;
assert_eq!(transposed.as_slice::<f64>()?, &[1.0, 3.0, 2.0, 4.0]);Sourcepub fn contraction(
&mut self,
lhs: &NativeTensor,
lhs_axes: &[usize],
rhs: &NativeTensor,
rhs_axes: &[usize],
) -> Result<NativeTensor>
pub fn contraction( &mut self, lhs: &NativeTensor, lhs_axes: &[usize], rhs: &NativeTensor, rhs_axes: &[usize], ) -> Result<NativeTensor>
Binary contraction along the given axes, preserving the remaining axes in order.
The operand identity and axis building is the same code path the compatibility frontend uses, so both frontends contract identically; only the session differs.
§Errors
Returns [tenferro_einsum::Error::InvalidSubscripts] when the axis lists are
malformed or of different length, and [tenferro_einsum::Error::Tensor] when the
backend rejects the operands, when an operand cannot be promoted, or when the
contraction itself fails.
Operands are promoted to a common dtype exactly as the compatibility frontend promotes them: a heterogeneous set contracts in the promoted dtype, and a set that already shares one dtype is used as is.
§Examples
use tensor4all_tensorbackend::CpuExecutionContext;
use tenferro::Tensor;
use tensor4all_tensorbackend::CpuBackend;
let context = CpuExecutionContext::from_backend(CpuBackend::with_threads(1)?);
let a = Tensor::from_vec_col_major(vec![2, 2], vec![1.0_f64, 2.0, 3.0, 4.0])?;
let b = Tensor::from_vec_col_major(vec![2, 1], vec![5.0_f64, 6.0])?;
let product =
context.with_concrete_session(|session| session.contraction(&a, &[1], &b, &[0]))??;
assert_eq!(product.as_slice::<f64>()?, &[23.0, 34.0]);Sourcepub fn einsum(
&mut self,
operands: &[&NativeTensor],
input_ids: &[&[usize]],
output_ids: &[usize],
) -> Result<NativeTensor>
pub fn einsum( &mut self, operands: &[&NativeTensor], input_ids: &[&[usize]], output_ids: &[usize], ) -> Result<NativeTensor>
N-ary einsum from integer labels, evaluated on this session.
The labels are validated by the same helper the compatibility frontend uses; the evaluation is tenferro-einsum’s session-direct einsum, so it does not compile a semantic graph or start a runtime worker.
§Errors
Returns [tenferro_einsum::Error::InvalidSubscripts] for malformed labels, a
label list whose length does not match the operand’s rank, or a label-list
count that does not match the operand count, and
[tenferro_einsum::Error::Tensor] when the backend rejects the operands, when an
operand cannot be promoted, or when the contraction itself fails.
Operands are promoted to a common dtype exactly as the compatibility frontend promotes them: a heterogeneous set contracts in the promoted dtype, and a set that already shares one dtype is used as is.
§Examples
use tensor4all_tensorbackend::CpuExecutionContext;
use tenferro::Tensor;
use tensor4all_tensorbackend::CpuBackend;
let context = CpuExecutionContext::from_backend(CpuBackend::with_threads(1)?);
let a = Tensor::from_vec_col_major(vec![2, 2], vec![1.0_f64, 2.0, 3.0, 4.0])?;
let b = Tensor::from_vec_col_major(vec![2, 2], vec![1.0_f64, 0.0, 0.0, 1.0])?;
let product = context.with_concrete_session(|session| {
session.einsum(&[&a, &b], &[&[0, 1], &[1, 2]], &[0, 2])
})??;
assert_eq!(product.as_slice::<f64>()?, &[1.0, 2.0, 3.0, 4.0]);Sourcepub fn sum(&mut self, tensor: &NativeTensor) -> Result<NativeTensor>
pub fn sum(&mut self, tensor: &NativeTensor) -> Result<NativeTensor>
Sum every element of a concrete tensor, returning the rank-0 result.
The compatibility frontend wraps the same rank-0 tensor in a
BackendScalar; this route stays on the concrete value so it works without
the compatibility feature.
§Errors
Returns [tenferro_tensor::Error::Validation] for an unsupported reduction
shape and [tenferro_tensor::Error::BackendSource] when the reduction itself
fails.
§Examples
use tensor4all_tensorbackend::CpuExecutionContext;
use tenferro::Tensor;
use tensor4all_tensorbackend::CpuBackend;
let context = CpuExecutionContext::from_backend(CpuBackend::with_threads(1)?);
let x = Tensor::from_vec_col_major(vec![2, 2], vec![1.0_f64, 2.0, 3.0, 4.0])?;
let total = context.with_concrete_session(|session| session.sum(&x))??;
assert_eq!(total.shape(), &[] as &[usize]);
assert_eq!(total.as_slice::<f64>()?, &[10.0]);Sourcepub fn conj(&mut self, tensor: &NativeTensor) -> Result<NativeTensor>
pub fn conj(&mut self, tensor: &NativeTensor) -> Result<NativeTensor>
Conjugate a concrete tensor.
A real tensor is returned unchanged; a complex tensor is conjugated elementwise.
§Errors
Returns [tenferro_tensor::Error::Unsupported] for a dtype the backend cannot
conjugate and [tenferro_tensor::Error::BackendSource] when the operation
itself fails.
§Examples
use tensor4all_tensorbackend::CpuExecutionContext;
use tenferro::Tensor;
use tensor4all_tensorbackend::CpuBackend;
use num_complex::Complex64;
let context = CpuExecutionContext::from_backend(CpuBackend::with_threads(1)?);
let x = Tensor::from_vec_col_major(
vec![2],
vec![Complex64::new(1.0, 2.0), Complex64::new(3.0, -4.0)],
)?;
let conjugated = context.with_concrete_session(|session| session.conj(&x))??;
assert_eq!(
conjugated.as_slice::<Complex64>()?,
&[Complex64::new(1.0, -2.0), Complex64::new(3.0, 4.0)]
);Sourcepub fn einsum_reads(
&mut self,
operands: &[TensorRead<'_>],
input_ids: &[&[usize]],
output_ids: &[usize],
) -> Result<NativeTensor>
pub fn einsum_reads( &mut self, operands: &[TensorRead<'_>], input_ids: &[&[usize]], output_ids: &[usize], ) -> Result<NativeTensor>
N-ary einsum over borrowed read inputs, without materializing them.
Same contract as Session::einsum, except that the operands are
TensorRead views: a non-contiguous or lazily
represented operand stays borrowed until the contract evaluates it.
§Errors
Returns [tenferro_einsum::Error::InvalidSubscripts] for malformed labels or a
label list whose length does not match the operand’s rank, and
[tenferro_einsum::Error::Tensor] when the backend rejects the operands or the
contraction itself fails.
§Examples
use tensor4all_tensorbackend::CpuExecutionContext;
use tenferro::Tensor;
use tensor4all_tensorbackend::CpuBackend;
use tenferro_tensor::TensorRead;
let context = CpuExecutionContext::from_backend(CpuBackend::with_threads(1)?);
let a = Tensor::from_vec_col_major(vec![2, 2], vec![1.0_f64, 2.0, 3.0, 4.0])?;
let b = Tensor::from_vec_col_major(vec![2, 1], vec![5.0_f64, 6.0])?;
let reads = [TensorRead::from_tensor(&a), TensorRead::from_tensor(&b)];
let product = context
.with_concrete_session(|session| session.einsum_reads(&reads, &[&[0, 1], &[1, 2]], &[0, 2]))??;
assert_eq!(product.as_slice::<f64>()?, &[23.0, 34.0]);Sourcepub fn contraction_into(
&mut self,
lhs: &NativeTensor,
lhs_axes: &[usize],
rhs: &NativeTensor,
rhs_axes: &[usize],
out: TensorWrite<'_>,
) -> Result<()>
pub fn contraction_into( &mut self, lhs: &NativeTensor, lhs_axes: &[usize], rhs: &NativeTensor, rhs_axes: &[usize], out: TensorWrite<'_>, ) -> Result<()>
Binary contraction into a caller-provided destination.
The destination is fully written and is never zero-filled first. The operands and the destination must already share one dtype: this route does not convert into a caller-owned output, and a mismatch is rejected typed by the backend.
§Errors
Returns [tenferro_einsum::Error::InvalidSubscripts] when the axis lists are
malformed or of different length, and [tenferro_einsum::Error::Tensor] when the
backend rejects the operands, the destination or the contraction.
§Examples
use tensor4all_tensorbackend::CpuExecutionContext;
use tenferro::Tensor;
use tensor4all_tensorbackend::CpuBackend;
use tenferro_tensor::TensorWrite;
let context = CpuExecutionContext::from_backend(CpuBackend::with_threads(1)?);
let a = Tensor::from_vec_col_major(vec![2, 2], vec![1.0_f64, 2.0, 3.0, 4.0])?;
let b = Tensor::from_vec_col_major(vec![2, 1], vec![5.0_f64, 6.0])?;
let mut out = Tensor::from_vec_col_major(vec![2, 1], vec![0.0_f64, 0.0])?;
context.with_concrete_session(|session| {
session.contraction_into(&a, &[1], &b, &[0], TensorWrite::Tensor(&mut out))
})??;
assert_eq!(out.as_slice::<f64>()?, &[23.0, 34.0]);Sourcepub fn solve_matrix<T>(
&mut self,
a: &Matrix<T>,
b: &Matrix<T>,
) -> Result<Matrix<T>, BackendLinalgError>
pub fn solve_matrix<T>( &mut self, a: &Matrix<T>, b: &Matrix<T>, ) -> Result<Matrix<T>, BackendLinalgError>
Solve A X = B for column-major matrices on this session.
Same kernel, conversion and validation as
solve_matrix, entered through this session instead of
the process-global one.
§Errors
Returns BackendLinalgError under the same
conditions as solve_matrix.
§Examples
use tensor4all_tensorbackend::{CpuExecutionContext, Matrix};
use tensor4all_tensorbackend::CpuBackend;
let context = CpuExecutionContext::from_backend(CpuBackend::with_threads(1)?);
let a = Matrix::from_col_major_vec(2, 2, vec![2.0_f64, 0.0, 0.0, 4.0]);
let b = Matrix::from_col_major_vec(2, 1, vec![6.0_f64, 8.0]);
let x = context.with_concrete_session(|session| session.solve_matrix(&a, &b))??;
assert_eq!(x.as_col_major_slice(), &[3.0, 2.0]);Sourcepub fn triangular_solve_matrix<T>(
&mut self,
a: &Matrix<T>,
b: &Matrix<T>,
left_side: bool,
lower: bool,
transpose_a: bool,
unit_diagonal: bool,
) -> Result<Matrix<T>, BackendLinalgError>
pub fn triangular_solve_matrix<T>( &mut self, a: &Matrix<T>, b: &Matrix<T>, left_side: bool, lower: bool, transpose_a: bool, unit_diagonal: bool, ) -> Result<Matrix<T>, BackendLinalgError>
Solve a triangular system for column-major matrices on this session.
Same kernel, conversion and validation as
triangular_solve_matrix, entered through this
session instead of the process-global one. left_side, lower, transpose_a
and unit_diagonal have the same meaning as on that entry.
§Errors
Returns BackendLinalgError under the same
conditions as triangular_solve_matrix.
§Examples
use tensor4all_tensorbackend::{CpuExecutionContext, Matrix};
use tensor4all_tensorbackend::CpuBackend;
let context = CpuExecutionContext::from_backend(CpuBackend::with_threads(1)?);
let a = Matrix::from_col_major_vec(2, 2, vec![2.0_f64, 1.0, 0.0, 4.0]);
let b = Matrix::from_col_major_vec(2, 1, vec![4.0_f64, 4.0]);
let x = context.with_concrete_session(|session| {
session.triangular_solve_matrix(&a, &b, true, true, false, false)
})??;
assert_eq!(x.as_col_major_slice(), &[2.0, 0.5]);Sourcepub fn full_piv_lu_matrix<T>(
&mut self,
a: &Matrix<T>,
) -> Result<FullPivLuMatrixResult<T>, BackendLinalgError>where
T: BackendLinalgScalar + Copy,
pub fn full_piv_lu_matrix<T>(
&mut self,
a: &Matrix<T>,
) -> Result<FullPivLuMatrixResult<T>, BackendLinalgError>where
T: BackendLinalgScalar + Copy,
Complete-pivoting LU decomposition of a column-major matrix on this session.
Same kernel and conversion as
full_piv_lu_matrix, entered through this session
instead of the process-global one.
§Errors
Returns BackendLinalgError under the same
conditions as full_piv_lu_matrix.
§Examples
use tensor4all_tensorbackend::{CpuExecutionContext, Matrix};
use tensor4all_tensorbackend::CpuBackend;
let context = CpuExecutionContext::from_backend(CpuBackend::with_threads(1)?);
let a = Matrix::from_col_major_vec(2, 2, vec![0.0_f64, 1.0, 2.0, 3.0]);
let factors = context.with_concrete_session(|session| session.full_piv_lu_matrix(&a))??;
assert_eq!(factors.p.nrows(), 2);
assert_eq!(factors.q.ncols(), 2);Sourcepub fn qr_backend<T>(
&mut self,
a: TypedTensor<T>,
) -> Result<(TypedTensor<T>, TypedTensor<T>), BackendLinalgError>where
T: BackendLinalgScalar,
pub fn qr_backend<T>(
&mut self,
a: TypedTensor<T>,
) -> Result<(TypedTensor<T>, TypedTensor<T>), BackendLinalgError>where
T: BackendLinalgScalar,
Thin/economy QR of a typed tensor on this session.
Same kernel and conversion as qr_backend, entered through
this session instead of the process-global one.
§Errors
Returns BackendLinalgError under the same
conditions as qr_backend.
§Examples
use tensor4all_tensorbackend::CpuExecutionContext;
use tenferro::TypedTensor;
use tensor4all_tensorbackend::CpuBackend;
let context = CpuExecutionContext::from_backend(CpuBackend::with_threads(1)?);
let a = TypedTensor::<f64>::from_vec_col_major(vec![2, 2], vec![1.0, 2.0, 3.0, 4.0])?;
let (q, r) = context.with_concrete_session(|session| session.qr_backend(a))??;
assert_eq!(q.shape(), &[2, 2]);
assert_eq!(r.shape(), &[2, 2]);Sourcepub fn svd_backend<T>(
&mut self,
a: &TypedTensor<T>,
) -> Result<SvdResult<T>, BackendLinalgError>where
T: BackendLinalgScalar,
pub fn svd_backend<T>(
&mut self,
a: &TypedTensor<T>,
) -> Result<SvdResult<T>, BackendLinalgError>where
T: BackendLinalgScalar,
Thin/economy SVD of a typed tensor on this session.
Same kernel and conversion as svd_backend, entered through
this session instead of the process-global one.
§Errors
Returns BackendLinalgError under the same
conditions as svd_backend.
§Examples
use tensor4all_tensorbackend::CpuExecutionContext;
use tenferro::TypedTensor;
use tensor4all_tensorbackend::CpuBackend;
let context = CpuExecutionContext::from_backend(CpuBackend::with_threads(1)?);
let a = TypedTensor::<f64>::from_vec_col_major(vec![2, 2], vec![3.0, 0.0, 0.0, 2.0])?;
let factors = context.with_concrete_session(|session| session.svd_backend(&a))??;
assert_eq!(factors.s().as_slice()?, &[3.0, 2.0]);Sourcepub fn mat_mul<T: BlasMul>(
&mut self,
a: &Matrix<T>,
b: &Matrix<T>,
) -> Result<Matrix<T>, MatrixMulError>
pub fn mat_mul<T: BlasMul>( &mut self, a: &Matrix<T>, b: &Matrix<T>, ) -> Result<Matrix<T>, MatrixMulError>
Matrix multiplication A * B on this session.
The same kernel and shape validation as
mat_mul, entered through this session instead of the
process-global one, and returning the shared
Matrix container.
§Errors
Returns MatrixMulError when the shapes disagree or
the session operation fails.
§Examples
use tensor4all_tensorbackend::{CpuExecutionContext, Matrix};
use tensor4all_tensorbackend::CpuBackend;
let context = CpuExecutionContext::from_backend(CpuBackend::with_threads(1)?);
let a = Matrix::from_col_major_vec(2, 2, vec![1.0_f64, 2.0, 3.0, 4.0]);
let b = Matrix::from_col_major_vec(2, 2, vec![1.0_f64, 0.0, 0.0, 1.0]);
let c = context.with_concrete_session(|session| session.mat_mul(&a, &b))??;
assert_eq!(c.as_col_major_slice(), &[1.0, 2.0, 3.0, 4.0]);Sourcepub fn qr(
&mut self,
tensor: &NativeTensor,
) -> Result<(NativeTensor, NativeTensor)>
pub fn qr( &mut self, tensor: &NativeTensor, ) -> Result<(NativeTensor, NativeTensor)>
Thin/economy QR decomposition.
§Errors
Returns [tenferro_tensor::Error::Validation] for an unsupported dtype or
rank, and [tenferro_tensor::Error::BackendSource] when the factorization
itself fails.
§Examples
use tensor4all_tensorbackend::CpuExecutionContext;
use tenferro::Tensor;
use tensor4all_tensorbackend::CpuBackend;
let context = CpuExecutionContext::from_backend(CpuBackend::with_threads(1)?);
let a = Tensor::from_vec_col_major(vec![2, 2], vec![1.0_f64, 2.0, 3.0, 4.0])?;
let (q, r) = context.with_concrete_session(|session| session.qr(&a))??;
// `A = Q R` is reproduced to rounding, which is the correctness property
// of a factorization.
let reconstructed =
context.with_concrete_session(|session| session.contraction(&q, &[1], &r, &[0]))??;
for (got, want) in reconstructed.as_slice::<f64>()?.iter().zip([1.0, 2.0, 3.0, 4.0]) {
assert!((got - want).abs() < 1e-12, "got {got}, want {want}");
}Sourcepub fn svd(
&mut self,
tensor: &NativeTensor,
) -> Result<(NativeTensor, NativeTensor, NativeTensor)>
pub fn svd( &mut self, tensor: &NativeTensor, ) -> Result<(NativeTensor, NativeTensor, NativeTensor)>
Thin/economy SVD.
§Errors
Returns [tenferro_tensor::Error::Validation] for an unsupported dtype or
rank, and [tenferro_tensor::Error::BackendSource] when the factorization
itself fails.
§Examples
use tensor4all_tensorbackend::CpuExecutionContext;
use tenferro::Tensor;
use tensor4all_tensorbackend::CpuBackend;
let context = CpuExecutionContext::from_backend(CpuBackend::with_threads(1)?);
let a = Tensor::from_vec_col_major(vec![2, 2], vec![3.0_f64, 0.0, 0.0, 2.0])?;
let (u, s, vt) = context.with_concrete_session(|session| session.svd(&a))??;
// The singular values of diag(3, 2) are 3 and 2.
assert_eq!(s.as_slice::<f64>()?, &[3.0, 2.0]);
assert_eq!(u.shape(), &[2, 2]);
assert_eq!(vt.shape(), &[2, 2]);Sourcepub fn solve(
&mut self,
lhs: &NativeTensor,
rhs: &NativeTensor,
) -> Result<NativeTensor>
pub fn solve( &mut self, lhs: &NativeTensor, rhs: &NativeTensor, ) -> Result<NativeTensor>
Solve A X = B for a square A.
§Errors
Returns [tenferro_tensor::Error::Validation] when lhs is not square, when
the operands have mismatched shapes, or for an unsupported dtype, and
[tenferro_tensor::Error::BackendSource] when the solve itself fails.
§Examples
use tensor4all_tensorbackend::CpuExecutionContext;
use tenferro::Tensor;
use tensor4all_tensorbackend::CpuBackend;
let context = CpuExecutionContext::from_backend(CpuBackend::with_threads(1)?);
let a = Tensor::from_vec_col_major(vec![2, 2], vec![2.0_f64, 0.0, 0.0, 4.0])?;
let b = Tensor::from_vec_col_major(vec![2, 1], vec![6.0_f64, 8.0])?;
let x = context.with_concrete_session(|session| session.solve(&a, &b))??;
assert_eq!(x.as_slice::<f64>()?, &[3.0, 2.0]);Sourcepub fn triangular_solve(
&mut self,
lhs: &NativeTensor,
rhs: &NativeTensor,
left_side: bool,
lower: bool,
transpose_a: bool,
unit_diagonal: bool,
) -> Result<NativeTensor>
pub fn triangular_solve( &mut self, lhs: &NativeTensor, rhs: &NativeTensor, left_side: bool, lower: bool, transpose_a: bool, unit_diagonal: bool, ) -> Result<NativeTensor>
Solve A X = B where A is triangular.
left_side: solveA X = Bwhen true,X A = Bwhen false;lower:Ais lower triangular;transpose_a: solve withAtransposed;unit_diagonal: treat the diagonal ofAas one, ignoring the stored values.
§Errors
Returns [tenferro_tensor::Error::Validation] for a shape mismatch or an
unsupported dtype, and [tenferro_tensor::Error::BackendSource] when the solve
itself fails.
§Examples
use tensor4all_tensorbackend::CpuExecutionContext;
use tenferro::Tensor;
use tensor4all_tensorbackend::CpuBackend;
let context = CpuExecutionContext::from_backend(CpuBackend::with_threads(1)?);
// Lower triangular, column-major.
let a = Tensor::from_vec_col_major(vec![2, 2], vec![2.0_f64, 1.0, 0.0, 4.0])?;
let b = Tensor::from_vec_col_major(vec![2, 1], vec![4.0_f64, 4.0])?;
let x = context.with_concrete_session(|session| {
session.triangular_solve(&a, &b, true, true, false, false)
})??;
assert_eq!(x.as_slice::<f64>()?, &[2.0, 0.5]);Sourcepub fn full_piv_lu(
&mut self,
tensor: &NativeTensor,
) -> Result<(NativeTensor, NativeTensor, NativeTensor, NativeTensor, NativeTensor)>
pub fn full_piv_lu( &mut self, tensor: &NativeTensor, ) -> Result<(NativeTensor, NativeTensor, NativeTensor, NativeTensor, NativeTensor)>
Full-pivoting LU decomposition P A Q = L U, returning
(P, L, U, Q, parity).
§Errors
Returns [tenferro_tensor::Error::Validation] for a non-square A or an
unsupported dtype, and [tenferro_tensor::Error::BackendSource] when the
factorization itself fails.
§Examples
use tensor4all_tensorbackend::CpuExecutionContext;
use tenferro::Tensor;
use tensor4all_tensorbackend::CpuBackend;
let context = CpuExecutionContext::from_backend(CpuBackend::with_threads(1)?);
let a = Tensor::from_vec_col_major(vec![2, 2], vec![1.0_f64, 2.0, 3.0, 4.0])?;
let (p, l, u, q, _parity) = context
.with_concrete_session(|session| session.full_piv_lu(&a))?
.expect("full-pivoting LU");
for factor in [&p, &l, &u, &q] {
assert_eq!(factor.shape(), &[2, 2]);
}
// Column-major, so index 0 is (0, 0), index 1 is (1, 0) and index 2 is (0, 1).
let l = l.as_slice::<f64>()?;
let u = u.as_slice::<f64>()?;
assert_eq!(l[2], 0.0, "L is lower triangular");
assert_eq!(u[1], 0.0, "U is upper triangular");Trait Implementations§
Auto Trait Implementations§
impl<'session> !RefUnwindSafe for Session<'session>
impl<'session> !Send for Session<'session>
impl<'session> !Sync for Session<'session>
impl<'session> !UnwindSafe for Session<'session>
impl<'session> Freeze for Session<'session>
impl<'session> Unpin for Session<'session>
impl<'session> UnsafeUnpin for Session<'session>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
impl<T, U> Imply<T> for U
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more