dlt/tensor/
element.rs

1use crate::complex::c64;
2
3// create a trait for weak FP multiplication
4pub trait WeakMul {
5    fn weak_mul(self, other: f64) -> Self;
6}
7
8impl WeakMul for c64 {
9    fn weak_mul(self, other: f64) -> Self {
10        c64::new(self.re() * other, self.im() * other)
11    }
12}
13
14impl WeakMul for f64 {
15    fn weak_mul(self, other: f64) -> Self {
16        self * other
17    }
18}
19
20impl WeakMul for i64 {
21    fn weak_mul(self, other: f64) -> Self {
22        (self as f64 * other) as i64
23    }
24}
25
26// implment mul for f32 * complex
27impl WeakMul for f32 {
28    fn weak_mul(self, other: f64) -> Self {
29        (self as f64 * other) as f32
30    }
31}
32
33
34pub trait TensorElement:
35 Copy + Clone +
36    std::ops::Add<Output = Self> +
37    std::ops::Sub<Output = Self> +
38    std::ops::Mul<Output = Self> +
39    std::ops::Div<Output = Self> +
40    std::ops::Neg<Output = Self> +
41    std::ops::AddAssign +
42    std::ops::SubAssign +
43    std::ops::MulAssign +
44    std::ops::DivAssign +
45    std::cmp::PartialEq +
46    std::cmp::PartialOrd +
47
48    // Mul with f64
49    WeakMul +
50
51    Into<c64> +
52    From<c64> +
53 std::fmt::Debug +
54 std::fmt::Display 
55 {
56    /// Returns the additive identity.
57    fn zero() -> Self;
58    fn one() -> Self;
59
60    /// Generate a random value between min and max.
61    /// For types where min and max don’t really apply (e.g. bool)
62    /// you can provide a custom behavior.
63    fn random(min: Self, max: Self) -> Self;
64
65//    fn c(self) -> c64; // convert to complex for maxi
66
67    fn mag(self) -> f64;
68
69    fn conjugate(self) -> Self;
70
71    const EPSILON: Self;
72    
73}
74
75use rand::Rng;
76
77impl TensorElement for c64 {
78    fn zero() -> Self {
79        c64::ZERO
80    }
81    fn one() -> Self {
82        c64::ONE
83    }
84
85    fn random(min: Self, max: Self) -> Self {
86        let mut rng = rand::rng();
87        let a = rng.random::<f64>() * (max.re() - min.re()) + min.re();
88        let b = rng.random::<f64>() * (max.im() - min.im()) + min.im();
89        c64::new(a, b)
90    }
91
92    fn mag(self) -> f64 {
93        self.mag()
94    }
95
96    fn conjugate(self) -> Self {
97        self.conjugate()
98    }
99
100    const EPSILON: Self = c64::EPSILON;
101}
102
103impl TensorElement for f64 {
104    fn zero() -> Self {
105        0.0
106    }
107    fn one() -> Self {
108        1.0
109    }
110
111    fn random(min: Self, max: Self) -> Self {
112        let mut rng = rand::rng();
113        rng.random_range(min..max)
114    }
115
116    fn mag(self) -> f64 {
117        self.abs()
118    }
119
120    fn conjugate(self) -> Self {
121        self
122    }
123
124    const EPSILON: Self = 1e-10;
125}
126
127impl TensorElement for f32 {
128    fn zero() -> Self {
129        0.0
130    }
131    fn one() -> Self {
132        1.0
133    }
134
135    fn random(min: Self, max: Self) -> Self {
136        let mut rng = rand::rng();
137        rng.random_range(min..max)
138    }
139
140    fn mag(self) -> f64 {
141        self.abs() as f64
142    }
143
144    fn conjugate(self) -> Self {
145        self
146    }
147
148    const EPSILON: Self = 1e-20;
149}
150
151impl TensorElement for i64 {
152    fn zero() -> Self {
153        0
154    }
155    fn one() -> Self {
156        1
157    }
158
159    fn random(min: Self, max: Self) -> Self {
160        let mut rng = rand::rng();
161        rng.random_range(min..max)
162    }
163
164    fn mag(self) -> f64 {
165        self.abs() as f64
166    }
167
168    fn conjugate(self) -> Self {
169        self
170    }
171
172    const EPSILON: Self = 1;
173}