pub struct Storage(/* private fields */);Expand description
Storage backend for tensor data.
Public callers interact with this opaque wrapper through constructors and high-level query/materialization methods.
§Examples
use tensor4all_tensorbackend::Storage;
// Dense 2x3 matrix stored column-major: [[1,2,3],[4,5,6]]
let data = vec![1.0_f64, 4.0, 2.0, 5.0, 3.0, 6.0];
let s = Storage::from_dense_col_major(data, &[2, 3]).unwrap();
assert!(s.is_f64());
assert!(!s.is_complex());
// Diagonal storage: 2x2 identity-like diagonal
let diag = Storage::new_diag(vec![1.0_f64, 2.0]).unwrap();
assert!(diag.is_f64());Implementations§
Source§impl Storage
impl Storage
Sourcepub fn from_dense_col_major<T: StorageScalar>(
data: Vec<T>,
logical_dims: &[usize],
) -> Result<Self>
pub fn from_dense_col_major<T: StorageScalar>( data: Vec<T>, logical_dims: &[usize], ) -> Result<Self>
Create dense storage from column-major logical values (generic over scalar type).
The scalar type is inferred from the data argument.
§Errors
Returns an error when the shape product would overflow usize or
data.len() does not match the expected shape.
§Examples
use tensor4all_tensorbackend::Storage;
// 2x2 matrix, column-major: [[1,3],[2,4]]
let s = Storage::from_dense_col_major(vec![1.0_f64, 2.0, 3.0, 4.0], &[2, 2]).unwrap();
assert!(s.is_f64());
assert!(s.is_dense());
assert_eq!(s.len(), 4);Sourcepub fn from_diag_col_major<T: StorageScalar>(
diag_data: Vec<T>,
logical_rank: usize,
) -> Result<Self>
pub fn from_diag_col_major<T: StorageScalar>( diag_data: Vec<T>, logical_rank: usize, ) -> Result<Self>
Create diagonal storage from column-major diagonal payload values (generic over scalar type).
Creates a rank-2 diagonal storage by default. The scalar type is
inferred from diag_data.
§Errors
Returns an error when the diagonal payload length does not match the
length required for logical_rank or a stride product would overflow
usize.
§Examples
use tensor4all_tensorbackend::Storage;
let s = Storage::from_diag_col_major(vec![1.0_f64, 2.0, 3.0], 2).unwrap();
assert!(s.is_diag());
assert!(s.is_f64());
assert_eq!(s.len(), 3);Sourcepub fn new_dense<T: StorageScalar + Default>(size: usize) -> StorageResult<Self>
pub fn new_dense<T: StorageScalar + Default>(size: usize) -> StorageResult<Self>
Create a new 1D zero-initialized dense storage (generic over scalar type).
§Examples
use tensor4all_tensorbackend::Storage;
let s = Storage::new_dense::<f64>(5).unwrap();
assert!(s.is_dense());
assert_eq!(s.len(), 5);
assert!((s.max_abs()).abs() < 1e-10);§Errors
Returns StorageError::Operation when the dense storage construction
or allocation fails.
Sourcepub fn new_diag<T: StorageScalar>(diag_data: Vec<T>) -> StorageResult<Self>
pub fn new_diag<T: StorageScalar>(diag_data: Vec<T>) -> StorageResult<Self>
Sourcepub fn new_structured<T: StorageScalar>(
data: Vec<T>,
payload_dims: Vec<usize>,
strides: Vec<isize>,
axis_classes: Vec<usize>,
) -> Result<Self>
pub fn new_structured<T: StorageScalar>( data: Vec<T>, payload_dims: Vec<usize>, strides: Vec<isize>, axis_classes: Vec<usize>, ) -> Result<Self>
Create a new structured storage (generic over scalar type).
§Errors
Returns an error when axis_classes is not in canonical
first-appearance order, when the payload_dims or strides ranks do
not match axis_classes, when a stride is negative, when a size
product would overflow usize, or when data.len() does not match the
required payload length.
§Examples
use tensor4all_tensorbackend::Storage;
// Diagonal-like structured storage: axis_classes = [0, 0]
let s = Storage::new_structured(
vec![1.0_f64, 2.0],
vec![2], // payload_dims
vec![1], // strides
vec![0, 0], // axis_classes: both axes map to payload axis 0
).unwrap();
assert!(s.is_diag());Sourcepub fn validate_structured_metadata(
payload_dims: &[usize],
strides: &[isize],
axis_classes: &[usize],
) -> Result<usize>
pub fn validate_structured_metadata( payload_dims: &[usize], strides: &[isize], axis_classes: &[usize], ) -> Result<usize>
Validate structured-storage metadata and return the required payload length.
The metadata must be internally consistent: canonical axis classes, a
payload rank implied by the axis classes, matching dim/stride ranks,
non-negative strides, and size products that fit in usize. The
returned length is exactly what a constructed Storage would
require, so untrusted payload lengths can be rejected before any
allocation.
§Errors
Returns an error if the metadata is inconsistent or its size products
overflow usize.
§Examples
use tensor4all_tensorbackend::Storage;
let required = Storage::validate_structured_metadata(
&[2],
&[1],
&[0, 0],
).unwrap();
assert_eq!(required, 2);
assert!(Storage::validate_structured_metadata(&[2], &[-1], &[0]).is_err());Sourcepub fn is_dense(&self) -> bool
pub fn is_dense(&self) -> bool
Check if this storage is logically dense.
§Examples
use tensor4all_tensorbackend::Storage;
let s = Storage::from_dense_col_major(vec![1.0_f64, 2.0], &[2]).unwrap();
assert!(s.is_dense());
let d = Storage::new_diag(vec![1.0_f64, 2.0]).unwrap();
assert!(!d.is_dense());Sourcepub fn is_diag(&self) -> bool
pub fn is_diag(&self) -> bool
Check if this storage is a Diag storage type.
§Examples
use tensor4all_tensorbackend::Storage;
let d = Storage::new_diag(vec![1.0_f64, 2.0]).unwrap();
assert!(d.is_diag());Sourcepub fn storage_kind(&self) -> StorageKind
pub fn storage_kind(&self) -> StorageKind
Returns the compact layout class for this storage.
The return value is metadata-only and never materializes dense logical values. Use it to choose whether to read compact payload metadata or dense logical values.
§Examples
use tensor4all_tensorbackend::{Storage, StorageKind};
let structured = Storage::new_structured(
vec![1.0_f64, 2.0],
vec![2],
vec![1],
vec![0, 0],
).unwrap();
assert_eq!(structured.storage_kind(), StorageKind::Diagonal);Sourcepub fn logical_dims(&self) -> Vec<usize>
pub fn logical_dims(&self) -> Vec<usize>
Returns the logical tensor dimensions represented by this storage.
The dimensions are derived from payload dimensions and axis_classes.
§Examples
use tensor4all_tensorbackend::Storage;
let diag = Storage::from_diag_col_major(vec![1.0_f64, 2.0], 2).unwrap();
assert_eq!(diag.logical_dims(), vec![2, 2]);Sourcepub fn logical_rank(&self) -> usize
pub fn logical_rank(&self) -> usize
Returns the logical tensor rank represented by this storage.
This equals axis_classes().len(), not necessarily payload_dims().len().
§Examples
use tensor4all_tensorbackend::Storage;
let diag = Storage::from_diag_col_major(vec![1.0_f64, 2.0], 3).unwrap();
assert_eq!(diag.logical_rank(), 3);
assert_eq!(diag.payload_dims(), &[2]);Sourcepub fn payload_dims(&self) -> &[usize]
pub fn payload_dims(&self) -> &[usize]
Returns the compact payload dimensions.
For dense storage these match logical dimensions. For diagonal storage this is rank-1 even when the logical tensor has multiple axes.
§Examples
use tensor4all_tensorbackend::Storage;
let diag = Storage::from_diag_col_major(vec![1.0_f64, 2.0], 2).unwrap();
assert_eq!(diag.payload_dims(), &[2]);Sourcepub fn payload_strides(&self) -> &[isize]
pub fn payload_strides(&self) -> &[isize]
Returns the compact payload strides.
Strides are measured in stored scalar elements and describe the compact payload buffer, not the logical dense tensor.
§Examples
use tensor4all_tensorbackend::Storage;
let dense = Storage::from_dense_col_major(vec![0.0_f64; 6], &[2, 3]).unwrap();
assert_eq!(dense.payload_strides(), &[1, 2]);Sourcepub fn axis_classes(&self) -> &[usize]
pub fn axis_classes(&self) -> &[usize]
Returns logical-axis equivalence classes for this storage.
Repeated class labels mean the corresponding logical axes share one
payload axis. Dense storage has [0, 1, ...]; diagonal storage has
repeated zero labels.
§Examples
use tensor4all_tensorbackend::Storage;
let diag = Storage::from_diag_col_major(vec![1.0_f64, 2.0], 2).unwrap();
assert_eq!(diag.axis_classes(), &[0, 0]);Sourcepub fn payload_len(&self) -> usize
pub fn payload_len(&self) -> usize
Returns the number of stored compact payload elements.
For dense storage this equals the logical dense length. For diagonal and structured storage this is the compact payload length.
§Examples
use tensor4all_tensorbackend::Storage;
let diag = Storage::from_diag_col_major(vec![1.0_f64, 2.0], 2).unwrap();
assert_eq!(diag.payload_len(), 2);Sourcepub fn payload_f32_col_major_vec(&self) -> StorageResult<Vec<f32>>
pub fn payload_f32_col_major_vec(&self) -> StorageResult<Vec<f32>>
Copies the compact f32 payload in column-major payload order.
This does not materialize logical dense values and never widens: a
narrow payload stays f32.
§Errors
Returns StorageError::ScalarKindMismatch if the storage scalar type
is not f32.
§Examples
use tensor4all_tensorbackend::Storage;
let diag = Storage::from_diag_col_major(vec![1.0_f32, 2.0], 2).unwrap();
assert_eq!(diag.payload_f32_col_major_vec().unwrap(), vec![1.0_f32, 2.0]);Sourcepub fn payload_f32_col_major_view_if_contiguous(
&self,
) -> StorageResult<Option<&[f32]>>
pub fn payload_f32_col_major_view_if_contiguous( &self, ) -> StorageResult<Option<&[f32]>>
Borrows the compact f32 payload when it is already contiguous in
column-major payload order.
§Errors
Returns StorageError::ScalarKindMismatch when the storage is not
f32-backed (a dtype mismatch).
Sourcepub fn payload_f64_col_major_vec(&self) -> StorageResult<Vec<f64>>
pub fn payload_f64_col_major_vec(&self) -> StorageResult<Vec<f64>>
Copies the compact f64 payload in column-major payload order.
This does not materialize logical dense values. For diagonal storage the returned vector contains only diagonal payload values.
§Errors
Returns StorageError::ScalarKindMismatch if the storage scalar type
is not f64.
§Examples
use tensor4all_tensorbackend::Storage;
let diag = Storage::from_diag_col_major(vec![1.0_f64, 2.0], 2).unwrap();
assert_eq!(diag.payload_f64_col_major_vec().unwrap(), vec![1.0, 2.0]);Sourcepub fn payload_f64_col_major_view_if_contiguous(
&self,
) -> StorageResult<Option<&[f64]>>
pub fn payload_f64_col_major_view_if_contiguous( &self, ) -> StorageResult<Option<&[f64]>>
Borrows the compact f64 payload when it is already contiguous in
column-major payload order.
§Errors
Returns StorageError::ScalarKindMismatch when the storage is not
f64-backed (a dtype mismatch).
Sourcepub fn payload_c32_col_major_vec(&self) -> StorageResult<Vec<Complex32>>
pub fn payload_c32_col_major_vec(&self) -> StorageResult<Vec<Complex32>>
Copies the compact Complex32 payload in column-major payload order.
§Errors
Returns StorageError::ScalarKindMismatch if the storage scalar type
is not Complex32.
§Examples
use num_complex::Complex32;
use tensor4all_tensorbackend::Storage;
let data = vec![Complex32::new(1.0, -2.0), Complex32::new(0.5, 0.0)];
let diag = Storage::from_diag_col_major(data.clone(), 2).unwrap();
assert_eq!(diag.payload_c32_col_major_vec().unwrap(), data);Sourcepub fn payload_c32_col_major_view_if_contiguous(
&self,
) -> StorageResult<Option<&[Complex32]>>
pub fn payload_c32_col_major_view_if_contiguous( &self, ) -> StorageResult<Option<&[Complex32]>>
Borrows the compact Complex32 payload when it is already contiguous in
column-major payload order.
§Errors
Returns StorageError::ScalarKindMismatch when the storage is not
c32-backed (a dtype mismatch).
Sourcepub fn payload_c64_col_major_vec(&self) -> StorageResult<Vec<Complex64>>
pub fn payload_c64_col_major_vec(&self) -> StorageResult<Vec<Complex64>>
Copies the compact Complex64 payload in column-major payload order.
This does not materialize logical dense values. Complex payloads are
returned as native Rust Complex64 values.
§Errors
Returns StorageError::ScalarKindMismatch if the storage scalar type
is not Complex64.
§Examples
use num_complex::Complex64;
use tensor4all_tensorbackend::Storage;
let data = vec![Complex64::new(1.0, 2.0), Complex64::new(3.0, 4.0)];
let diag = Storage::from_diag_col_major(data.clone(), 2).unwrap();
assert_eq!(diag.payload_c64_col_major_vec().unwrap(), data);Sourcepub fn payload_c64_col_major_view_if_contiguous(
&self,
) -> StorageResult<Option<&[Complex64]>>
pub fn payload_c64_col_major_view_if_contiguous( &self, ) -> StorageResult<Option<&[Complex64]>>
Borrows the compact Complex64 payload when it is already contiguous in
column-major payload order.
§Errors
Returns StorageError::ScalarKindMismatch when the storage is not
c64-backed (a dtype mismatch).
Sourcepub fn is_f64(&self) -> bool
pub fn is_f64(&self) -> bool
Check if this storage uses f64 scalar type.
§Examples
use tensor4all_tensorbackend::Storage;
let s = Storage::from_dense_col_major(vec![1.0_f64], &[1]).unwrap();
assert!(s.is_f64());
assert!(!s.is_c64());Sourcepub fn is_f32(&self) -> bool
pub fn is_f32(&self) -> bool
Check if this storage uses f32 scalar type.
§Examples
use tensor4all_tensorbackend::Storage;
let s = Storage::from_dense_col_major(vec![1.0_f32], &[1]).unwrap();
assert!(s.is_f32());
assert!(!s.is_f64());Sourcepub fn is_c64(&self) -> bool
pub fn is_c64(&self) -> bool
Check if this storage uses Complex64 scalar type.
§Examples
use tensor4all_tensorbackend::Storage;
use num_complex::Complex64;
let s = Storage::from_dense_col_major(
vec![Complex64::new(1.0, 0.0)], &[1],
).unwrap();
assert!(s.is_c64());Sourcepub fn is_c32(&self) -> bool
pub fn is_c32(&self) -> bool
Check if this storage uses Complex32 scalar type.
§Examples
use num_complex::Complex32;
use tensor4all_tensorbackend::Storage;
let s = Storage::from_dense_col_major(
vec![Complex32::new(1.0, -1.0)], &[1],
).unwrap();
assert!(s.is_c32());
assert!(s.is_complex());Sourcepub fn is_complex(&self) -> bool
pub fn is_complex(&self) -> bool
Check if this storage uses complex scalar type.
This is Complex64 or Complex32; it is not an alias for
is_c64().
§Examples
use num_complex::Complex32;
use tensor4all_tensorbackend::Storage;
let s = Storage::from_dense_col_major(vec![Complex32::new(1.0, 0.0)], &[1]).unwrap();
assert!(s.is_complex());
let r = Storage::from_dense_col_major(vec![1.0_f64], &[1]).unwrap();
assert!(!r.is_complex());Sourcepub fn dtype(&self) -> DType
pub fn dtype(&self) -> DType
Returns the stored scalar dtype.
The dtype is metadata only and never depends on payload contents. It is
the value a publication or conversion boundary should compare against
instead of assuming the payload is f64 or Complex64.
§Examples
use tensor4all_tensorbackend::Storage;
use tenferro::DType;
let dense = Storage::from_dense_col_major(vec![1.0_f32, 2.0], &[2]).unwrap();
assert_eq!(dense.dtype(), DType::F32);
let complex = Storage::from_diag_col_major(
vec![num_complex::Complex64::new(1.0, 0.0)], 2,
).unwrap();
assert_eq!(complex.dtype(), DType::C64);Sourcepub fn scalar_kind(&self) -> &'static str
pub fn scalar_kind(&self) -> &'static str
Returns this storage’s scalar-kind label used in diagnostics.
§Examples
use tensor4all_tensorbackend::Storage;
let s = Storage::from_dense_col_major(vec![1.0_f32], &[1]).unwrap();
assert_eq!(s.scalar_kind(), "f32");Sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Get the length of the storage payload (number of stored elements).
For dense storage this equals the product of logical dimensions. For diagonal storage this equals the diagonal length.
§Examples
use tensor4all_tensorbackend::Storage;
let s = Storage::from_dense_col_major(vec![1.0_f64, 2.0, 3.0], &[3]).unwrap();
assert_eq!(s.len(), 3);
let d = Storage::new_diag(vec![1.0_f64, 2.0]).unwrap();
assert_eq!(d.len(), 2);Sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Check if the storage is empty.
§Examples
use tensor4all_tensorbackend::Storage;
let s = Storage::new_dense::<f64>(0).unwrap();
assert!(s.is_empty());
let s2 = Storage::new_dense::<f64>(3).unwrap();
assert!(!s2.is_empty());Sourcepub fn sum<T: SumFromStorage>(&self) -> T
pub fn sum<T: SumFromStorage>(&self) -> T
Sum all referenced compact payload entries, converting to type T.
Stride gaps and padding in a structured backing buffer are not tensor values and are excluded from the reduction.
§Example
use tensor4all_tensorbackend::Storage;
let s = Storage::from_dense_col_major(vec![1.0, 2.0, 3.0], &[3]).unwrap();
assert_eq!(s.sum::<f64>(), 6.0);Sourcepub fn max_abs(&self) -> f64
pub fn max_abs(&self) -> f64
Maximum absolute value over all referenced compact payload entries.
Stride gaps and padding are excluded. For real storage this is max(|x|), and for complex storage this is
max(hypot(re, im)). NaN payloads, including a NaN real or imaginary
component paired with infinity, propagate to a NaN result; positive
infinity is preserved.
§Examples
use tensor4all_tensorbackend::Storage;
let s = Storage::from_dense_col_major(vec![-3.0_f64, 1.0, 2.0], &[3]).unwrap();
assert!((s.max_abs() - 3.0).abs() < 1e-10);Sourcepub fn payload_nonfinite_flags(&self) -> NonfiniteFlags
pub fn payload_nonfinite_flags(&self) -> NonfiniteFlags
Scan the compact payload without copying it.
The returned flags describe the stored payload, not the logical dense tensor. Structural zeros cannot introduce non-finite values, so this is sufficient for metric validation while preserving compact memory use.
§Examples
use tensor4all_tensorbackend::Storage;
let storage = Storage::from_dense_col_major(vec![1.0_f64, f64::INFINITY], &[2]).unwrap();
let flags = storage.payload_nonfinite_flags();
assert!(!flags.has_nan);
assert!(flags.has_infinity);Sourcepub fn scalar_at(
&self,
payload_coords: &[usize],
) -> StorageResult<BackendScalar>
pub fn scalar_at( &self, payload_coords: &[usize], ) -> StorageResult<BackendScalar>
Return one compact payload value as a dynamic BackendScalar.
payload_coords are column-major payload coordinates, not logical
coordinates. Repeated logical axis classes are represented once in the
payload, so this lookup performs only rank-bounded stride arithmetic and
never allocates coordinates or scans the payload.
§Errors
Returns StorageError when the coordinate rank or bounds are invalid
or the compact metadata points outside the backing payload.
§Examples
use num_complex::Complex64;
use tensor4all_tensorbackend::Storage;
let real = Storage::from_diag_col_major(vec![2.0_f64, 3.0], 2).unwrap();
assert_eq!(real.scalar_at(&[1]).unwrap().real(), 3.0);
let complex = Storage::from_dense_col_major(
vec![Complex64::new(1.0, -2.0)], &[1],
).unwrap();
assert_eq!(complex.scalar_at(&[0]).unwrap().as_c64(),
Some(Complex64::new(1.0, -2.0)));Sourcepub fn to_dense_f64_col_major_vec(
&self,
logical_dims: &[usize],
) -> StorageResult<Vec<f64>>
pub fn to_dense_f64_col_major_vec( &self, logical_dims: &[usize], ) -> StorageResult<Vec<f64>>
Materialize dense logical values as a column-major f64 buffer.
For diagonal storage, off-diagonal entries are filled with zero.
§Errors
Returns StorageError::ScalarKindMismatch if the storage is complex,
and StorageError::InvalidStructuredStorage if logical_dims does
not match the stored logical dimensions or the logical element count
overflows usize.
§Examples
use tensor4all_tensorbackend::Storage;
let s = Storage::from_dense_col_major(vec![1.0_f64, 2.0, 3.0, 4.0], &[2, 2]).unwrap();
let dense = s.to_dense_f64_col_major_vec(&[2, 2]).unwrap();
assert_eq!(dense, vec![1.0, 2.0, 3.0, 4.0]);Sourcepub fn to_dense_f32_col_major_vec(
&self,
logical_dims: &[usize],
) -> StorageResult<Vec<f32>>
pub fn to_dense_f32_col_major_vec( &self, logical_dims: &[usize], ) -> StorageResult<Vec<f32>>
Materialize dense logical values as a column-major f32 buffer.
For diagonal storage, off-diagonal entries are filled with zero.
§Errors
Returns StorageError::ScalarKindMismatch unless the storage is
f32-backed, and StorageError::InvalidStructuredStorage if
logical_dims does not match the stored logical dimensions or the
logical element count overflows usize.
§Examples
use tensor4all_tensorbackend::Storage;
let diag = Storage::new_diag(vec![1.0_f32, 2.0]).unwrap();
assert_eq!(diag.to_dense_f32_col_major_vec(&[2, 2]).unwrap(), vec![1.0, 0.0, 0.0, 2.0]);Sourcepub fn to_dense_c64_col_major_vec(
&self,
logical_dims: &[usize],
) -> StorageResult<Vec<Complex64>>
pub fn to_dense_c64_col_major_vec( &self, logical_dims: &[usize], ) -> StorageResult<Vec<Complex64>>
Materialize dense logical values as a column-major Complex64 buffer.
§Errors
Returns StorageError::ScalarKindMismatch unless the storage is
Complex64-backed, and StorageError::InvalidStructuredStorage if
logical_dims does not match the stored logical dimensions or the
logical element count overflows usize.
§Examples
use tensor4all_tensorbackend::Storage;
use num_complex::Complex64;
let data = vec![Complex64::new(1.0, 2.0), Complex64::new(3.0, 4.0)];
let s = Storage::from_dense_col_major(data.clone(), &[2]).unwrap();
let dense = s.to_dense_c64_col_major_vec(&[2]).unwrap();
assert_eq!(dense, data);Sourcepub fn to_dense_c32_col_major_vec(
&self,
logical_dims: &[usize],
) -> StorageResult<Vec<Complex32>>
pub fn to_dense_c32_col_major_vec( &self, logical_dims: &[usize], ) -> StorageResult<Vec<Complex32>>
Materialize dense logical values as a column-major Complex32 buffer.
§Errors
Returns StorageError::ScalarKindMismatch unless the storage is
Complex32-backed, and StorageError::InvalidStructuredStorage if
logical_dims does not match the stored logical dimensions or the
logical element count overflows usize.
§Examples
use num_complex::Complex32;
use tensor4all_tensorbackend::Storage;
let data = vec![Complex32::new(1.0, -1.0), Complex32::new(2.0, 0.5)];
let s = Storage::from_dense_col_major(data.clone(), &[2]).unwrap();
assert_eq!(s.to_dense_c32_col_major_vec(&[2]).unwrap(), data);Sourcepub fn to_dense_storage(&self, dims: &[usize]) -> StorageResult<Storage>
pub fn to_dense_storage(&self, dims: &[usize]) -> StorageResult<Storage>
Convert this storage to dense storage.
For Diag storage, creates a Dense storage with diagonal elements set and off-diagonal elements as zero. For Dense storage, returns a copy.
§Errors
Returns StorageError::InvalidStructuredStorage if dims does not
match the stored logical dimensions or the dense storage cannot be built.
§Examples
use tensor4all_tensorbackend::Storage;
let d = Storage::new_diag(vec![1.0_f64, 2.0]).unwrap();
let dense = d.to_dense_storage(&[2, 2]).unwrap();
assert!(dense.is_dense());
let vals = dense.to_dense_f64_col_major_vec(&[2, 2]).unwrap();
assert_eq!(vals, vec![1.0, 0.0, 0.0, 2.0]);Sourcepub fn permute_storage(
&self,
_dims: &[usize],
perm: &[usize],
) -> StorageResult<Storage>
pub fn permute_storage( &self, _dims: &[usize], perm: &[usize], ) -> StorageResult<Storage>
Permute the storage data according to the given permutation.
The _dims parameter is currently unused (reserved for future use).
§Examples
use tensor4all_tensorbackend::Storage;
// Diagonal 2x2 tensor, permute axes (identity perm for diag is valid)
let d = Storage::new_diag(vec![1.0_f64, 2.0]).unwrap();
let t = d.permute_storage(&[2, 2], &[1, 0]).unwrap();
assert!(t.is_diag());§Errors
Returns StorageError::Operation when perm is not a permutation of
the logical axes.
Sourcepub fn extract_real_part(&self) -> Storage
pub fn extract_real_part(&self) -> Storage
Extract real part from Complex64 storage as f64 storage. For f64 storage, returns a copy (clone).
§Examples
use tensor4all_tensorbackend::Storage;
use num_complex::Complex64;
let data = vec![Complex64::new(1.0, 2.0), Complex64::new(3.0, 4.0)];
let s = Storage::from_dense_col_major(data, &[2]).unwrap();
let re = s.extract_real_part();
assert!(re.is_f64());
assert_eq!(re.to_dense_f64_col_major_vec(&[2]).unwrap(), vec![1.0, 3.0]);Sourcepub fn extract_imag_part(&self, _dims: &[usize]) -> Storage
pub fn extract_imag_part(&self, _dims: &[usize]) -> Storage
Extract imaginary part from complex storage as the matching real storage.
Complex64 yields f64 storage and Complex32 yields f32 storage.
For real storage, returns zero storage of the same real dtype.
§Examples
use tensor4all_tensorbackend::Storage;
use num_complex::Complex64;
let data = vec![Complex64::new(1.0, 2.0), Complex64::new(3.0, 4.0)];
let s = Storage::from_dense_col_major(data, &[2]).unwrap();
let im = s.extract_imag_part(&[2]);
assert!(im.is_f64());
assert_eq!(im.to_dense_f64_col_major_vec(&[2]).unwrap(), vec![2.0, 4.0]);Sourcepub fn to_complex_storage(&self) -> Storage
pub fn to_complex_storage(&self) -> Storage
Convert real storage to its complex counterpart (zero imaginary part).
f64 becomes Complex64 and f32 becomes Complex32; complex storage
returns a clone of the same dtype.
§Examples
use tensor4all_tensorbackend::Storage;
let s = Storage::from_dense_col_major(vec![1.0_f64, 2.0], &[2]).unwrap();
let c = s.to_complex_storage();
assert!(c.is_c64());
let narrow = Storage::from_dense_col_major(vec![1.0_f32], &[1]).unwrap();
assert!(narrow.to_complex_storage().is_c32());Sourcepub fn conj(&self) -> Self
pub fn conj(&self) -> Self
Complex conjugate of all elements.
For real storage, returns a clone (conjugate of a real number is itself). For complex storage, conjugates each element without changing the dtype.
This is inspired by the conj operation in ITensorMPS.jl.
§Examples
use tensor4all_tensorbackend::Storage;
use num_complex::Complex64;
let data = vec![Complex64::new(1.0, 2.0), Complex64::new(3.0, -4.0)];
let storage = Storage::from_dense_col_major(data, &[2]).unwrap();
let conj_storage = storage.conj();
let result = conj_storage.to_dense_c64_col_major_vec(&[2]).unwrap();
assert_eq!(result[0], Complex64::new(1.0, -2.0));
assert_eq!(result[1], Complex64::new(3.0, 4.0));Sourcepub fn combine_to_complex(
real_storage: &Storage,
imag_storage: &Storage,
) -> StorageResult<Storage>
pub fn combine_to_complex( real_storage: &Storage, imag_storage: &Storage, ) -> StorageResult<Storage>
Combine two real storages into their complex counterpart.
real_storage becomes the real part and imag_storage the imaginary
part, so f64 + f64 yields Complex64 storage and f32 + f32 yields
Complex32 storage. Nothing is widened to a wider dtype.
§Errors
Returns StorageError::LengthMismatch if the payload lengths differ,
StorageError::OperationNotSupported if the two storages do not share
one real scalar kind, and
StorageError::InvalidStructuredStorage if the result layout cannot
be built.
§Examples
use tensor4all_tensorbackend::Storage;
use num_complex::Complex64;
let re = Storage::from_dense_col_major(vec![1.0_f64, 3.0], &[2]).unwrap();
let im = Storage::from_dense_col_major(vec![2.0_f64, 4.0], &[2]).unwrap();
let c = Storage::combine_to_complex(&re, &im).unwrap();
assert!(c.is_c64());
let vals = c.to_dense_c64_col_major_vec(&[2]).unwrap();
assert_eq!(vals[0], Complex64::new(1.0, 2.0));
assert_eq!(vals[1], Complex64::new(3.0, 4.0));
let narrow_re = Storage::from_dense_col_major(vec![1.0_f32], &[1]).unwrap();
let narrow_im = Storage::from_dense_col_major(vec![2.0_f32], &[1]).unwrap();
assert!(Storage::combine_to_complex(&narrow_re, &narrow_im)
.unwrap()
.is_c32());Sourcepub fn try_add(&self, other: &Storage) -> StorageResult<Storage>
pub fn try_add(&self, other: &Storage) -> StorageResult<Storage>
Add two storages element-wise, returning Result on error instead of panicking.
Both storages must have the same scalar type and payload length; mixed scalar kinds are refused rather than promoted.
§Errors
Returns StorageError::LengthMismatch if the lengths differ,
StorageError::OperationNotSupported if the scalar types differ, and
StorageError::InvalidStructuredStorage if the result layout cannot be
built.
§Examples
use tensor4all_tensorbackend::Storage;
let a = Storage::from_dense_col_major(vec![1.0_f64, 2.0], &[2]).unwrap();
let b = Storage::from_dense_col_major(vec![3.0_f64, 4.0], &[2]).unwrap();
let c = a.try_add(&b).unwrap();
assert_eq!(c.to_dense_f64_col_major_vec(&[2]).unwrap(), vec![4.0, 6.0]);
let narrow = Storage::from_dense_col_major(vec![0.5_f32, 0.5], &[2]).unwrap();
let sum = narrow.try_add(&narrow).unwrap();
assert!(sum.is_f32());
assert_eq!(sum.to_dense_f32_col_major_vec(&[2]).unwrap(), vec![1.0, 1.0]);Sourcepub fn try_sub(&self, other: &Storage) -> StorageResult<Storage>
pub fn try_sub(&self, other: &Storage) -> StorageResult<Storage>
Try to subtract two storages element-wise.
Both storages must have the same scalar type and payload length; mixed scalar kinds are refused rather than promoted.
§Errors
Returns StorageError::LengthMismatch if the lengths differ,
StorageError::OperationNotSupported if the scalar types differ, and
StorageError::InvalidStructuredStorage if the result layout cannot be
built.
§Examples
use tensor4all_tensorbackend::Storage;
let a = Storage::from_dense_col_major(vec![5.0_f64, 7.0], &[2]).unwrap();
let b = Storage::from_dense_col_major(vec![1.0_f64, 3.0], &[2]).unwrap();
let c = a.try_sub(&b).unwrap();
assert_eq!(c.to_dense_f64_col_major_vec(&[2]).unwrap(), vec![4.0, 4.0]);Sourcepub fn scale(&self, scalar: &BackendScalar) -> Storage
pub fn scale(&self, scalar: &BackendScalar) -> Storage
Scale storage by a dynamic scalar value.
The payload keeps its width and gains a complex component when the
scalar is complex (f64 -> Complex64, f32 -> Complex32), which is
exactly scale_target_dtype. Real scalars never widen a narrow
payload.
§Examples
use tensor4all_tensorbackend::{BackendScalar, Storage};
let s = Storage::from_dense_col_major(vec![1.0_f64, 2.0, 3.0], &[3]).unwrap();
let scaled = s.scale(&BackendScalar::new_real(2.0));
assert_eq!(scaled.to_dense_f64_col_major_vec(&[3]).unwrap(), vec![2.0, 4.0, 6.0]);
let narrow = Storage::from_dense_col_major(vec![1.0_f32, 2.0], &[2]).unwrap();
let complex = narrow.scale(&BackendScalar::new_complex(0.0, 1.0));
assert!(complex.is_c32());Sourcepub fn axpby(
&self,
a: &BackendScalar,
other: &Storage,
b: &BackendScalar,
) -> StorageResult<Storage>
pub fn axpby( &self, a: &BackendScalar, other: &Storage, b: &BackendScalar, ) -> StorageResult<Storage>
Compute linear combination: a * self + b * other.
Promotion has one rule, shared with Storage::scale: the two payload
dtypes promote along the lattice f32 < f64, Complex32 < Complex64,
real < complex, while a scalar never widens the payload dtype - it only
adds a complex component at the promoted width. So f32 + f32 with
f64 scalars stays f32, f32 + f64 becomes f64, and a complex
scalar turns an f32 result into Complex32.
§Errors
Returns StorageError::LengthMismatch if the lengths differ,
StorageError::OperationNotSupported when an operand dtype is not a
supported floating or complex floating dtype, and
StorageError::InvalidStructuredStorage if the result layout cannot be
built.
§Examples
use tensor4all_tensorbackend::{BackendScalar, Storage};
let x = Storage::from_dense_col_major(vec![1.0_f64, 2.0], &[2]).unwrap();
let y = Storage::from_dense_col_major(vec![3.0_f64, 4.0], &[2]).unwrap();
let a = BackendScalar::new_real(2.0);
let b = BackendScalar::new_real(3.0);
// result = 2*[1,2] + 3*[3,4] = [11, 16]
let result = x.axpby(&a, &y, &b).unwrap();
assert_eq!(result.to_dense_f64_col_major_vec(&[2]).unwrap(), vec![11.0, 16.0]);
// Real scalars do not widen a narrow payload.
let narrow = Storage::from_dense_col_major(vec![1.0_f32], &[1]).unwrap();
assert!(narrow.axpby(&a, &narrow, &b).unwrap().is_f32());
// A complex scalar adds complexity at the payload width.
use num_complex::Complex32;
let mixed = narrow
.axpby(
&BackendScalar::from(Complex32::new(0.0, 1.0)),
&narrow,
&BackendScalar::from(1.0_f32),
)
.unwrap();
assert!(mixed.is_c32());
assert_eq!(
mixed.to_dense_c32_col_major_vec(&[1]).unwrap(),
vec![Complex32::new(1.0, 1.0)],
);Trait Implementations§
Source§impl Mul<BackendScalar> for &Storage
Multiply storage by a dynamic BackendScalar.
impl Mul<BackendScalar> for &Storage
Multiply storage by a dynamic BackendScalar.
A real scalar delegates to the real-scaling implementation, so a complex payload’s components scale
independently and IEEE values propagate as they always have (inf * 1 stays inf instead of turning
into inf * 0 = NaN through the complex product). A complex scalar goes through the complex path,
which keeps the payload’s width and gains a complex component on a real payload.
Source§impl Mul<Complex<f64>> for &Storage
Multiply storage by a Complex64 scalar.
impl Mul<Complex<f64>> for &Storage
Multiply storage by a Complex64 scalar.
A real payload is promoted to its complex counterpart of the same width
(f64 -> Complex64, f32 -> Complex32); complex payloads keep their
dtype.
Auto Trait Implementations§
impl Freeze for Storage
impl RefUnwindSafe for Storage
impl Send for Storage
impl Sync for Storage
impl Unpin for Storage
impl UnsafeUnpin for Storage
impl UnwindSafe for Storage
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
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
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