xref: /aosp_15_r20/external/bazelbuild-rules_rust/examples/ffi/rust_calling_c/src/matrix.rs (revision d4726bddaa87cc4778e7472feed243fa4b6c267f)
1 // Copyright 2017 The Bazel Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 extern crate libc;
16 
17 mod ffi;
18 
19 use std::ops;
20 use std::ptr;
21 
22 /// Wrapper around pointer to FFI Matrix struct.
23 pub struct Matrix {
24     matrix: *mut ffi::Matrix,
25 }
26 
27 /// Wrapper around low-level FFI Matrix API.
28 impl Matrix {
29     /// Constructs a new Matrix from the given data. Matrix returned contains a copy of the data
30     /// provided.
31     ///
32     /// # Panics
33     ///
34     /// If rows * cols does not equal data.len() or if matrix could not be allocated.
new(rows: usize, cols: usize, data: &[u64]) -> Matrix35     pub fn new(rows: usize, cols: usize, data: &[u64]) -> Matrix {
36         if data.len() != rows * cols {
37             panic!(
38                 "rows * cols ({}) do not equal data.len() ({})",
39                 rows * cols,
40                 data.len()
41             );
42         }
43 
44         let mut data_copy: Vec<u64> = vec![0; data.len()];
45         data_copy.clone_from_slice(data);
46         unsafe {
47             let matrix: *mut ffi::Matrix = ffi::matrix_new(rows, cols, data_copy.as_ptr());
48             if matrix.is_null() {
49                 panic!("Failed to allocate Matrix.");
50             }
51             Matrix { matrix }
52         }
53     }
54 
55     /// Fetches the value at the specified row and column.
at(&self, row: usize, col: usize) -> Option<u64>56     pub fn at(&self, row: usize, col: usize) -> Option<u64> {
57         let mut n: u64 = 0;
58         unsafe {
59             if ffi::matrix_at(self.matrix, row, col, &mut n) == 0 {
60                 return None;
61             }
62         }
63         Some(n)
64     }
65 
66     /// Sets the value at the specified row and column.
67     ///
68     /// # Panics
69     ///
70     /// If row, col is out of bounds.
set(&mut self, row: usize, col: usize, n: u64)71     pub fn set(&mut self, row: usize, col: usize, n: u64) {
72         unsafe {
73             if ffi::matrix_set(self.matrix, row, col, n) == 0 {
74                 panic!("Row {}, col {} is out of bounds.", row, col);
75             }
76         }
77     }
78 
79     /// Returns the number of rows of the matrix.
rows(&self) -> usize80     pub fn rows(&self) -> usize {
81         unsafe { (*self.matrix).rows }
82     }
83 
84     /// Returns the number of cols of the matrix.
cols(&self) -> usize85     pub fn cols(&self) -> usize {
86         unsafe { (*self.matrix).cols }
87     }
88 
89     /// Performs an in-place transposition of the matrix.
transpose(&mut self)90     pub fn transpose(&mut self) {
91         unsafe {
92             ffi::matrix_transpose(self.matrix);
93         }
94     }
95 
96     /// Checks whether the matrix is equal to the provided Matrix.
equal(&self, other: &Matrix) -> bool97     pub fn equal(&self, other: &Matrix) -> bool {
98         unsafe { ffi::matrix_equal(self.matrix, other.matrix) != 0 }
99     }
100 }
101 
102 impl ops::Drop for Matrix {
drop(&mut self)103     fn drop(&mut self) {
104         unsafe {
105             ffi::matrix_free(self.matrix);
106         }
107         self.matrix = ptr::null_mut();
108     }
109 }
110 
111 #[cfg(test)]
112 mod test {
113     use super::Matrix;
114 
115     #[test]
test_size()116     fn test_size() {
117         let matrix = Matrix::new(2, 4, &[11, 12, 13, 14, 21, 22, 23, 24]);
118         assert_eq!(2, matrix.rows());
119         assert_eq!(4, matrix.cols());
120     }
121 
122     #[test]
test_equal()123     fn test_equal() {
124         let matrix_a = Matrix::new(2, 4, &[11, 12, 13, 14, 21, 22, 23, 24]);
125         let matrix_b = Matrix::new(2, 4, &[11, 12, 13, 14, 21, 22, 23, 24]);
126         assert!(matrix_a.equal(&matrix_b));
127 
128         let matrix_c = Matrix::new(2, 4, &[12, 13, 14, 15, 23, 24, 25, 26]);
129         assert!(!matrix_a.equal(&matrix_c));
130     }
131 
132     #[test]
test_transpose()133     fn test_transpose() {
134         let mut matrix = Matrix::new(2, 4, &[11, 12, 13, 14, 21, 22, 23, 24]);
135         matrix.transpose();
136         let expected = Matrix::new(4, 2, &[11, 21, 12, 22, 13, 23, 14, 24]);
137         assert!(matrix.equal(&expected));
138     }
139 }
140