tensor/
tensor.rs

1use traits;
2use std::ops::Mul;
3
4pub struct Rank1Tensor<T: traits::TensorTrait<T>> {
5    dim: i32,
6    components: Vec<T>, 
7}
8
9pub struct Rank2Tensor<T: traits::TensorTrait<T>> {
10    dim: i32,
11    components: Vec<Vec<T>>,
12}
13
14pub struct Rank3Tensor<T: traits::TensorTrait<T>> {
15    dim: i32,
16    components: Vec<Vec<Vec<T>>>,
17}
18
19//generalized tensor
20pub struct Tensor<T: traits::TensorTrait<T>> {
21   dim: i32,
22   rank: i32,
23   components: Vec<T>, 
24}
25
26//generalized tensor impl
27impl<T: traits::TensorTrait<T>> Tensor<T> {
28    pub fn build(d: i32, r: i32, v: Vec<T>) -> Self {
29        Tensor {
30            //dim of basis vector
31            dim: d,
32            rank: r,
33            components: v,
34        } 
35    } 
36    pub fn clone(&self) -> Self {
37        Tensor::build(self.dim.clone(), self.rank.clone(), self.components.clone())
38    }
39    //improve - perf is still O(rank) 
40    pub fn get(&self, indices: &[i32]) -> T {
41        let mut i: i32 = 0;
42        //We can build dim^(rank) ahead of time
43        for x in 0..self.rank {
44            i = i + scalar_power(self.dim, x as i32) * indices[x as usize];
45        }     
46        self.components[i as usize].clone() 
47    }
48    pub fn set(&mut self, indices: &[i32], value: T) {
49        let mut i: i32 = 0;
50        //We can build dim^(rank) ahead of time
51        for x in 0..self.rank {
52            i = i + scalar_power(self.dim, x as i32) * indices[x as usize];
53        }
54        self.components[i as usize] = value;
55    } 
56    pub fn inner_product(&self, other: &Tensor<T>) -> Self {
57        //equality assumptions for now
58        assert_eq!(self.rank, (*other).rank);
59        assert_eq!(self.dim, (*other).dim);
60
61        let mut args: Vec<i32> = Vec::new();
62        for _ in 0..(self.rank + other.rank - 2) {
63            args.push(self.dim);
64        }
65        let new_rank: i32 = self.rank + other.rank - 2;
66        let len = scalar_power(self.dim, new_rank) as usize;
67        let mut new_tensor = &mut Tensor::build(self.dim, new_rank, vec![T::zero(); len]);
68
69        inner_product_loop(args, Tensor::print_inner_product, &self, &other, new_tensor);
70
71        //this clone is bad
72        (*new_tensor).clone()
73    } 
74    fn print_inner_product(&mut self, t1: &Tensor<T>, t2: &Tensor<T>, indices: &[i32]) {
75        let i: usize = (t1.rank - 1) as usize;
76        let j: usize = (t1.rank - 1) as usize;
77        let mut v1 = indices[0..i].to_vec();
78        let mut v2 = indices[j..].to_vec(); 
79
80        //sum over contracted indices 
81        v1.push(0);
82        v2.insert(0, 0);
83
84        let mut total: T = T::zero(); 
85        for x in 0..t1.dim {
86            v1[(t1.rank - 1) as usize] = x;
87            v2[0] = x;
88            total = total + t1.get(&v1) * t2.get(&v2);  
89        } 
90        
91        //we set the indices of mut self
92        self.set(indices, total);
93    } 
94    pub fn print(&self) {
95       let mut v: Vec<i32> = Vec::new();
96       for _ in 0..self.rank {
97           v.push(self.dim.clone());
98       }
99       print_loop(v, Tensor::print_element, &self);
100    }
101    fn print_element(&self, v: Vec<i32>) {
102        println!( "T{:?} : {:?}", v, self.get(&v) ); 
103    }
104}
105
106//tmp solution for n^p 
107pub fn scalar_power(n: i32, p: i32) -> i32 {
108    let mut a: i32 = 1;
109    for _ in 0..p { a = a*n; } 
110    a
111}
112
113//entry point for inner_product_loop_many
114pub fn inner_product_loop<T: traits::TensorTrait<T>>(max_indices: Vec<i32>, f: fn(&mut Tensor<T>, &Tensor<T>, &Tensor<T>, &[i32]),
115t1: &Tensor<T>, t2: &Tensor<T>, t3: &mut Tensor<T>) {
116    inner_product_loop_many(max_indices.clone(), f, t1, t2, t3, Vec::new(), 0);
117}
118
119//variable depth inner product loop
120pub fn inner_product_loop_many<T: traits::TensorTrait<T>>(max_indices: Vec<i32>, f: fn(&mut Tensor<T>, &Tensor<T>, &Tensor<T>, &[i32]), 
121t1: &Tensor<T>, t2: &Tensor<T>, t3: &mut Tensor<T>, pargs: Vec<i32>, index: i32) {
122    if max_indices.len() == 0 {
123        f(t3, t1, t2, &pargs); 
124    } else {
125        let mut args = pargs.clone();
126        let rest: Vec<i32> = max_indices[1..].to_vec();
127        for _ in 0..max_indices[0] {
128            if args.len() == index as usize { args.push(0); }
129            if args[index as usize] < max_indices[0] {
130                inner_product_loop_many(rest.clone(), f, t1, t2, t3, args.clone(), index + 1);
131                args[index as usize] = args[index as usize] + 1;
132            }
133        }
134    }
135}
136
137//entry point for print_loop_many
138pub fn print_loop<T: traits::TensorTrait<T>>(max_indices: Vec<i32>, f: fn(&Tensor<T>, Vec<i32>), t: &Tensor<T>) {
139    print_loop_many(max_indices.clone(), f, t, Vec::new(), 0);
140}
141
142//variable depth print loop
143pub fn print_loop_many<T: traits::TensorTrait<T>>(max_indices: Vec<i32>, f: fn(&Tensor<T>, Vec<i32>), 
144t: &Tensor<T>, pargs: Vec<i32>, index: i32) {
145    if max_indices.len() == 0 {
146        f(t, pargs); 
147    } else {
148        let mut args = pargs.clone();
149        let rest: Vec<i32> = max_indices[1..].to_vec();
150        for _ in 0..max_indices[0] {
151            if args.len() == index as usize { args.push(0); }
152            if args[index as usize] < max_indices[0] {
153                print_loop_many(rest.clone(), f, t, args.clone(), index + 1);
154                args[index as usize] = args[index as usize] + 1;
155            }
156        }
157    }
158}
159
160impl<T: traits::TensorTrait<T>> Rank1Tensor<T> {
161    pub fn new(d: i32) -> Self { 
162        Rank1Tensor { 
163            dim: d, 
164            components: Vec::new(),
165        } 
166    }
167    pub fn build(d: i32, c: Vec<T>) -> Self {
168        Rank1Tensor {
169            dim: d,
170            components: c,
171        }
172    }
173    pub fn get(&self, i: i32) -> T {
174       self.components[i as usize].clone() 
175    }
176    pub fn dim(&self) -> i32 {
177        self.dim.clone()
178    }
179}
180
181impl<T: traits::TensorTrait<T>> Rank2Tensor<T> {
182    pub fn new(d: i32) -> Self { 
183        let mut temp_vec = Vec::new();
184        for _ in 0..d {
185            temp_vec.push(Vec::new());
186        }
187        Rank2Tensor { 
188            dim: d, 
189            components: temp_vec,
190        } 
191    }
192    pub fn build(d: i32, c: Vec<Vec<T>>) -> Self {
193        Rank2Tensor {
194            dim: d,
195            components: c,
196        }
197    }
198    pub fn get(&self, i: i32, j: i32) -> T {
199        self.components[i as usize][j as usize].clone()
200    } 
201    pub fn dim(&self) -> i32 {
202        self.dim.clone()
203    }
204    pub fn print(&self) {
205        for i in 0..self.dim() {
206            for j in 0..self.dim() {
207                print!{ "T[{},{}]: {}\n", i, j, self.get(i, j) };
208            }
209        }
210    }
211}
212
213impl<T: traits::TensorTrait<T>> Rank3Tensor<T> {
214    pub fn new(d: i32) -> Self { 
215        let mut temp_vec = Vec::new();
216        for _ in 0..d {
217            let mut temp_vec_2 = Vec::new();
218            for _ in 0..d {
219                temp_vec_2.push(Vec::new());
220            }
221            temp_vec.push(temp_vec_2);
222        }
223        Rank3Tensor { 
224            dim: d, 
225            components: temp_vec,
226        } 
227    }
228    pub fn build(d: i32, c: Vec<Vec<Vec<T>>>) -> Self {
229        Rank3Tensor {
230            dim: d,
231            components: c,
232        }
233    }
234    pub fn get(&self, i: i32, j: i32, k: i32) -> T {
235       self.components[i as usize][j as usize][k as usize].clone() 
236    }
237    pub fn dim(&self) -> i32 {
238        self.dim.clone()
239    }
240}
241
242impl<T: traits::TensorTrait<T>> Mul<Rank1Tensor<T>> for Rank1Tensor<T> {
243    type Output = Rank2Tensor<T>;
244    fn mul(self, other: Rank1Tensor<T>) -> Rank2Tensor<T> {
245        let mut vec = Vec::new();    
246        for i in 0..self.dim() {
247            let mut temp_vec = Vec::new();
248            for j in 0..other.dim() {
249                temp_vec.push(self.get(i) * other.get(j))
250            }
251            vec.push(temp_vec)
252        }
253        Rank2Tensor::build(self.dim(), vec)
254    }
255}