rust_blas/math/
mat.rs

1// Copyright 2015 Michael Yang. All rights reserved.
2// Use of this source code is governed by a MIT-style
3// license that can be found in the LICENSE file.
4#![macro_use]
5
6use crate::vector::ops::Copy;
7use crate::Matrix;
8use num::traits::NumCast;
9use std::fmt;
10use std::iter::repeat;
11use std::ops::Index;
12use std::slice;
13
14#[derive(Debug, PartialEq)]
15pub struct Mat<T> {
16    rows: usize,
17    cols: usize,
18    data: Vec<T>,
19}
20
21impl<T> Mat<T> {
22    pub fn new_from_data(rows: usize, cols: usize, data: Vec<T>) -> Mat<T> {
23        Mat { rows, cols, data }
24    }
25
26    pub fn new(n: usize, m: usize) -> Mat<T> {
27        let len = n * m;
28        let mut data = Vec::with_capacity(len);
29        unsafe {
30            data.set_len(len);
31        }
32
33        Self::new_from_data(n, m, data)
34    }
35
36    pub fn rows(&self) -> usize {
37        self.rows
38    }
39    pub fn cols(&self) -> usize {
40        self.cols
41    }
42    /// Set Matrix Rows Manually
43    /// # Safety
44    /// This only sets the value for rows, and does not include any guarantees that the
45    /// number of elements is equal to rows x columns after the operation takes place.
46    pub unsafe fn set_rows(&mut self, n: usize) {
47        self.rows = n;
48    }
49    /// Set Matrix Columns Manually
50    /// # Safety
51    /// This only sets the value for columns, and does not include any guarantees that the
52    /// number of elements is equal to rows x columns after the operation takes place.
53    pub unsafe fn set_cols(&mut self, n: usize) {
54        self.cols = n;
55    }
56    /// Push a single value to matrix data backing
57    /// # Safety
58    /// This makes no checks that rows x columns remains equivalent to the length of pushed elements
59    pub unsafe fn push(&mut self, val: T) {
60        self.data.push(val);
61    }
62}
63
64impl<T: Clone> Mat<T> {
65    pub fn fill(value: T, n: usize, m: usize) -> Mat<T> {
66        Mat {
67            rows: n,
68            cols: m,
69            data: repeat(value).take(n * m).collect(),
70        }
71    }
72}
73
74impl<T> Index<usize> for Mat<T> {
75    type Output = [T];
76
77    fn index(&self, index: usize) -> &[T] {
78        let offset = (index * self.cols) as isize;
79
80        unsafe {
81            let ptr = (&self.data[..]).as_ptr().offset(offset);
82            slice::from_raw_parts(ptr, self.cols)
83        }
84    }
85}
86
87impl<T: fmt::Display> fmt::Display for Mat<T> {
88    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
89        for i in 0usize..self.rows {
90            for j in 0usize..self.cols {
91                match write!(f, "{}", self[i][j]) {
92                    Ok(_) => (),
93                    x => return x,
94                }
95            }
96
97            match writeln!(f) {
98                Ok(_) => (),
99                x => return x,
100            }
101        }
102
103        Ok(())
104    }
105}
106
107impl<T> Matrix<T> for Mat<T> {
108    fn rows(&self) -> u32 {
109        let n: Option<u32> = NumCast::from(self.rows);
110        n.unwrap()
111    }
112
113    fn cols(&self) -> u32 {
114        let n: Option<u32> = NumCast::from(self.cols);
115        n.unwrap()
116    }
117
118    fn as_ptr(&self) -> *const T {
119        self.data[..].as_ptr()
120    }
121
122    fn as_mut_ptr(&mut self) -> *mut T {
123        (&mut self.data[..]).as_mut_ptr()
124    }
125}
126
127impl<'a, T> From<&'a dyn Matrix<T>> for Mat<T>
128where
129    T: Copy,
130{
131    fn from(a: &dyn Matrix<T>) -> Mat<T> {
132        let n = a.rows() as usize;
133        let m = a.cols() as usize;
134        let len = n * m;
135
136        let mut result = Mat {
137            rows: n,
138            cols: m,
139            data: Vec::with_capacity(len),
140        };
141        unsafe {
142            result.data.set_len(len);
143        }
144
145        Copy::copy_mat(a, &mut result);
146        result
147    }
148}
149
150#[macro_export]
151macro_rules! mat(
152    ($($($e: expr),+);*) => ({
153        // leading _ to allow empty construction without a warning.
154        let mut _temp = Mat::new(0, 0);
155        let mut rows = 0usize;
156        let mut _cols;
157        $(
158            rows += 1;
159            _cols = 0usize;
160            $(
161                _cols += 1;
162                unsafe {
163                    _temp.push($e);
164                }
165            )+
166        )*
167
168        unsafe {
169            _temp.set_rows(rows);
170            _temp.set_cols(_cols);
171        }
172
173        _temp
174    });
175);
176
177#[cfg(test)]
178mod tests {
179    use crate::math::Mat;
180
181    #[test]
182    fn index() {
183        let a = mat![1f32, 2f32];
184        assert_eq!(1.0, a[0][0]);
185        assert_eq!(2.0, a[0][1]);
186
187        let b = mat![1f32; 2f32];
188        assert_eq!(1.0, b[0][0]);
189        assert_eq!(2.0, b[1][0]);
190
191        let m = mat![1f32, 2f32; 3f32, 4f32];
192        assert_eq!(1.0, m[0][0]);
193        assert_eq!(2.0, m[0][1]);
194        assert_eq!(3.0, m[1][0]);
195        assert_eq!(4.0, m[1][1]);
196    }
197}