ariadnetor_tensor/dense/scalar_ops.rs
1//! Scalar-dependent operations for `DenseTensorData<T>` (conjugate,
2//! norm, complex conversion).
3//!
4//! Element-wise transforms (`conj`, `real`, `imag`, `to_complex`)
5//! preserve the layout; norm-related operations route through the
6//! storage half.
7
8use crate::DenseTensorData;
9
10impl<T> DenseTensorData<T>
11where
12 T: ariadnetor_core::Scalar,
13{
14 /// Element-wise complex conjugate.
15 pub fn conj(&self) -> Self {
16 self.map(|x| x.conj())
17 }
18
19 /// Convert each element to its complex representation.
20 pub fn to_complex(&self) -> DenseTensorData<T::Complex> {
21 self.map(|x| x.into_complex())
22 }
23
24 /// Extract the real part of each element.
25 pub fn real(&self) -> DenseTensorData<T::Real> {
26 self.map(|x| x.re())
27 }
28
29 /// Extract the imaginary part of each element.
30 pub fn imag(&self) -> DenseTensorData<T::Real> {
31 self.map(|x| x.im())
32 }
33
34 /// Compute Frobenius norm: √(Σ |element|²).
35 pub fn norm_frobenius(&self) -> T::Real {
36 self.storage().norm_frobenius()
37 }
38
39 /// Compute Frobenius norm (alias for [`norm_frobenius`](Self::norm_frobenius)).
40 pub fn norm(&self) -> T::Real {
41 self.storage().norm()
42 }
43
44 /// Normalize to unit Frobenius norm (in-place).
45 ///
46 /// Returns the norm before normalization. Panics if the tensor
47 /// has zero norm.
48 pub fn normalize(&mut self) -> T::Real {
49 self.storage_mut().normalize()
50 }
51
52 /// Normalize and return a new tensor (out-of-place).
53 ///
54 /// Returns `(normalized_tensor, original_norm)`. Panics if the
55 /// tensor has zero norm.
56 pub fn normalized(&self) -> (Self, T::Real) {
57 let mut result = self.clone();
58 let norm = result.normalize();
59 (result, norm)
60 }
61}