rgsl/types/
matrix_complex.rs

1//
2// A rust binding for the GSL library by Guillaume Gomez (guillaume1.gomez@gmail.com)
3//
4
5use crate::paste::paste;
6use crate::Value;
7use ffi::FFI;
8use std::fmt::{self, Debug, Formatter};
9
10macro_rules! gsl_matrix_complex {
11    ($rust_name:ident, $name:ident, $complex:ident, $complex_c:ident) => (
12paste! {
13
14use types::{$complex, [<Vector $complex>], [<Vector $complex View>]};
15
16ffi_wrapper!(
17    $rust_name,
18    *mut sys::$name,
19    [<$name _free>]
20);
21
22impl $rust_name {
23    /// Creates a new MatrixF64.
24    #[doc(alias = $name _alloc)]
25    pub fn new(n1: usize, n2: usize) -> Option<Self> {
26        let tmp = unsafe { sys::[<$name _alloc>](n1, n2) };
27
28        if tmp.is_null() {
29            None
30        } else {
31            Some(Self::wrap(tmp))
32        }
33    }
34
35    /// Creates a new MatrixF64 with all elements set to zero.
36    #[doc(alias = $name _calloc)]
37    pub fn new_with_init(n1: usize, n2: usize) -> Option<Self> {
38        let tmp = unsafe { sys::[<$name _calloc>](n1, n2) };
39
40        if tmp.is_null() {
41            None
42        } else {
43            Some(Self::wrap(tmp))
44        }
45    }
46
47    /// This function returns the (i,j)-th element of the matrix.
48    /// If y or x lie outside the allowed range of 0 to n1-1 and 0 to n2-1 then the error handler is
49    /// invoked and 0 is returned.
50    #[doc(alias = $name _get)]
51    pub fn get(&self, y: usize, x: usize) -> $complex {
52        unsafe { std::mem::transmute(sys::[<$name _get>](self.unwrap_shared(), y, x)) }
53    }
54
55    /// This function sets the value of the (i,j)-th element of the matrix to value.
56    /// If y or x lies outside the allowed range of 0 to n1-1 and 0 to n2-1 then the error handler
57    /// is invoked.
58    #[doc(alias = $name _set)]
59    pub fn set(&mut self, y: usize, x: usize, value: &$complex) -> &Self {
60        unsafe {
61            sys::[<$name _set>](self.unwrap_unique(), y, x, std::mem::transmute(*value))
62        };
63        self
64    }
65
66    /// This function sets all the elements of the matrix to the value x.
67    #[doc(alias = $name _set_all)]
68    pub fn set_all(&mut self, x: &$complex) -> &Self {
69        unsafe { sys::[<$name _set_all>](self.unwrap_unique(), std::mem::transmute(*x)) };
70        self
71    }
72
73    /// This function sets all the elements of the matrix to zero.
74    #[doc(alias = $name _set_zero)]
75    pub fn set_zero(&mut self) -> &Self {
76        unsafe { sys::[<$name _set_zero>](self.unwrap_unique()) };
77        self
78    }
79
80    /// This function sets the elements of the matrix to the corresponding elements of the identity
81    /// matrix, m(i,j) = \delta(i,j), i.e. a unit diagonal with all off-diagonal elements zero.
82    /// This applies to both square and rectangular matrices.
83    #[doc(alias = $name _set_identity)]
84    pub fn set_identity(&mut self) -> &Self {
85        unsafe { sys::[<$name _set_identity>](self.unwrap_unique()) };
86        self
87    }
88
89    /// This function copies the elements of the other matrix into the self matrix. The two matrices
90    /// must have the same size.
91    #[doc(alias = $name _memcpy)]
92    pub fn copy_from(&mut self, other: &$rust_name) -> Result<(), Value> {
93        let ret = unsafe {
94            sys::[<$name _memcpy>](self.unwrap_unique(), other.unwrap_shared())
95        };
96        result_handler!(ret, ())
97    }
98
99    /// This function copies the elements of the self matrix into the other matrix. The two matrices
100    /// must have the same size.
101    #[doc(alias = $name _memcpy)]
102    pub fn copy_to(&self, other: &mut $rust_name) -> Result<(), Value> {
103        let ret = unsafe {
104            sys::[<$name _memcpy>](other.unwrap_unique(), self.unwrap_shared())
105        };
106        result_handler!(ret, ())
107    }
108
109    /// This function exchanges the elements of the matrices self and other by copying. The two
110    /// matrices must have the same size.
111    #[doc(alias = $name _swap)]
112    pub fn swap(&mut self, other: &mut $rust_name) -> Result<(), Value> {
113        let ret = unsafe {
114            sys::[<$name _swap>](self.unwrap_unique(), other.unwrap_unique())
115        };
116        result_handler!(ret, ())
117    }
118
119    /// This function copies the elements of the y-th row of the matrix into the returned vector.
120    #[doc(alias = $name _get_row)]
121    pub fn get_row(&self, y: usize) -> Result<[<Vector $complex>], Value> {
122        let tmp = unsafe { sys::[<$complex_c _alloc>](self.size2()) };
123
124        if tmp.is_null() {
125            Err(Value::NoMemory)
126        } else {
127            let ret = unsafe { sys::[<$name _get_row>](tmp, self.unwrap_shared(), y) };
128
129            result_handler!(ret, FFI::wrap(tmp))
130        }
131    }
132
133    /// This function copies the elements of the x-th column of the matrix into the returned vector.
134    #[doc(alias = $name _get_col)]
135    pub fn get_col(&self, x: usize) -> Result<[<Vector $complex>], Value> {
136        let tmp = unsafe { sys::[<$complex_c _alloc>](self.size1()) };
137
138        if tmp.is_null() {
139            Err(Value::NoMemory)
140        } else {
141            let ret = unsafe { sys::[<$name _get_col>](tmp, self.unwrap_shared(), x) };
142
143            result_handler!(ret, FFI::wrap(tmp))
144        }
145    }
146
147    /// This function copies the elements of the vector v into the y-th row of the matrix.
148    /// The length of the vector must be the same as the length of the row.
149    #[doc(alias = $name _set_row)]
150    pub fn set_row(&mut self, y: usize, v: &[<Vector $complex>]) -> Result<(), Value> {
151        let ret = unsafe {
152            sys::[<$name _set_row>](self.unwrap_unique(), y, v.unwrap_shared())
153        };
154        result_handler!(ret, ())
155    }
156
157    /// This function copies the elements of the vector v into the x-th column of the matrix.
158    /// The length of the vector must be the same as the length of the column.
159    #[doc(alias = $name _set_col)]
160    pub fn set_col(&mut self, x: usize, v: &[<Vector $complex>]) -> Result<(), Value> {
161        let ret = unsafe {
162            sys::[<$name _set_col>](self.unwrap_unique(), x, v.unwrap_shared())
163        };
164        result_handler!(ret, ())
165    }
166
167    /// This function exchanges the y1-th and y2-th rows of the matrix in-place.
168    #[doc(alias = $name _swap_rows)]
169    pub fn swap_rows(&mut self, y1: usize, y2: usize) -> Result<(), Value> {
170        let ret = unsafe { sys::[<$name _swap_rows>](self.unwrap_unique(), y1, y2) };
171        result_handler!(ret, ())
172    }
173
174    /// This function exchanges the x1-th and x2-th columns of the matrix in-place.
175    #[doc(alias = $name _swap_columns)]
176    pub fn swap_columns(&mut self, x1: usize, x2: usize) -> Result<(), Value> {
177        let ret = unsafe { sys::[<$name _swap_columns>](self.unwrap_unique(), x1, x2) };
178        result_handler!(ret, ())
179    }
180
181    /// This function exchanges the i-th row and j-th column of the matrix in-place. The matrix must
182    /// be square for this operation to be possible.
183    #[doc(alias = $name _swap_rowcol)]
184    pub fn swap_row_col(&mut self, i: usize, j: usize) -> Result<(), Value> {
185        let ret = unsafe { sys::[<$name _swap_rowcol>](self.unwrap_unique(), i, j) };
186        result_handler!(ret, ())
187    }
188
189    /// This function returns the transpose of the matrix by copying the elements into it.
190    /// This function works for all matrices provided that the dimensions of the matrix dest match
191    /// the transposed dimensions of the matrix.
192    #[doc(alias = $name _transpose_memcpy)]
193    pub fn transpose_memcpy(&self) -> Result<$rust_name, Value> {
194        let dest = unsafe { sys::[<$name _alloc>](self.size2(), self.size1()) };
195
196        if dest.is_null() {
197            Err(Value::NoMemory)
198        } else {
199            let ret =
200                unsafe { sys::[<$name _transpose_memcpy>](dest, self.unwrap_shared()) };
201
202            result_handler!(ret, Self::wrap(dest))
203        }
204    }
205
206    /// This function replaces the matrix m by its transpose by copying the elements of the matrix
207    /// in-place. The matrix must be square for this operation to be possible.
208    #[doc(alias = $name _transpose)]
209    pub fn transpose(&mut self) -> Result<(), Value> {
210        let ret = unsafe { sys::[<$name _transpose>](self.unwrap_unique()) };
211        result_handler!(ret, ())
212    }
213
214    /// This function adds the elements of the other matrix to the elements of the `self` matrix.
215    /// The result self(i,j) <- self(i,j) + other(i,j) is stored in `self` and other remains
216    /// unchanged. The two matrices must have the same dimensions.
217    #[doc(alias = $name _add)]
218    pub fn add(&mut self, other: &$rust_name) -> Result<(), Value> {
219        let ret = unsafe {
220            sys::[<$name _add>](self.unwrap_unique(), other.unwrap_shared())
221        };
222        result_handler!(ret, ())
223    }
224
225    /// This function subtracts the elements of the other matrix from the elements of the `self`
226    /// matrix. The result self(i,j) <- self(i,j) - other(i,j) is stored in `self` and other remains
227    /// unchanged. The two matrices must have the same dimensions.
228    #[doc(alias = $name _sub)]
229    pub fn sub(&mut self, other: &$rust_name) -> Result<(), Value> {
230        let ret = unsafe {
231            sys::[<$name _sub>](self.unwrap_unique(), other.unwrap_shared())
232        };
233        result_handler!(ret, ())
234    }
235
236    /// This function multiplies the elements of the self matrix by the elements of the other
237    /// matrix. The result self(i,j) <- self(i,j) * other(i,j) is stored in self and other remains
238    /// unchanged. The two matrices must have the same dimensions.
239    #[doc(alias = $name _mul_elements)]
240    pub fn mul_elements(&mut self, other: &$rust_name) -> Result<(), Value> {
241        let ret = unsafe {
242            sys::[<$name _mul_elements>](self.unwrap_unique(), other.unwrap_shared())
243        };
244        result_handler!(ret, ())
245    }
246
247    /// This function divides the elements of the self matrix by the elements of the other matrix.
248    /// The result self(i,j) <- self(i,j) / other(i,j) is stored in self and other remains
249    /// unchanged. The two matrices must have the same dimensions.
250    #[doc(alias = $name _div_elements)]
251    pub fn div_elements(&mut self, other: &$rust_name) -> Result<(), Value> {
252        let ret = unsafe {
253            sys::[<$name _div_elements>](self.unwrap_unique(), other.unwrap_shared())
254        };
255        result_handler!(ret, ())
256    }
257
258    /// This function multiplies the elements of the self matrix by the constant factor x. The
259    /// result self(i,j) <- x self(i,j) is stored in self.
260    #[doc(alias = $name _scale)]
261    pub fn scale(&mut self, x: &$complex) -> Result<(), Value> {
262        let ret = unsafe {
263            sys::[<$name _scale>](self.unwrap_unique(), std::mem::transmute(*x))
264        };
265        result_handler!(ret, ())
266    }
267
268    /// This function adds the constant value x to the elements of the self matrix. The result
269    /// self(i,j) <- self(i,j) + x is stored in self.
270    #[doc(alias = $name _add_constant)]
271    pub fn add_constant(&mut self, x: &$complex) -> Result<(), Value> {
272        let ret = unsafe {
273            sys::[<$name _add_constant>](self.unwrap_unique(), std::mem::transmute(*x))
274        };
275        result_handler!(ret, ())
276    }
277
278    /// This function returns true if all the elements of the self matrix are stricly zero.
279    #[doc(alias = $name _isnull)]
280    pub fn is_null(&self) -> bool {
281        unsafe { sys::[<$name _isnull>](self.unwrap_shared()) == 1 }
282    }
283
284    /// This function returns true if all the elements of the self matrix are stricly positive.
285    #[doc(alias = $name _ispos)]
286    pub fn is_pos(&self) -> bool {
287        unsafe { sys::[<$name _ispos>](self.unwrap_shared()) == 1 }
288    }
289
290    /// This function returns true if all the elements of the self matrix are stricly negative.
291    #[doc(alias = $name _isneg)]
292    pub fn is_neg(&self) -> bool {
293        unsafe { sys::[<$name _isneg>](self.unwrap_shared()) == 1 }
294    }
295
296    /// This function returns true if all the elements of the self matrix are stricly non-negative.
297    #[doc(alias = $name _isnonneg)]
298    pub fn is_non_neg(&self) -> bool {
299        unsafe { sys::[<$name _isnonneg>](self.unwrap_shared()) == 1 }
300    }
301
302    /// This function returns true if all elements of the two matrix are equal.
303    #[doc(alias = $name _equal)]
304    pub fn equal(&self, other: &$rust_name) -> bool {
305        unsafe { sys::[<$name _equal>](self.unwrap_shared(), other.unwrap_shared()) == 1 }
306    }
307
308    #[doc(alias = $name _row)]
309    pub fn row<F: FnOnce(Option<[<Vector $complex View>]>)>(&mut self, i: usize, f: F) {
310        [<Vector $complex View>]::wrap(unsafe { sys::[<$name _row>](self.unwrap_unique(), i) }, f)
311    }
312
313    #[doc(alias = $name _column)]
314    pub fn column<F: FnOnce(Option<[<Vector $complex View>]>)>(&mut self, j: usize, f: F) {
315        [<Vector $complex View>]::wrap(unsafe { sys::[<$name _column>](self.unwrap_unique(), j) }, f)
316    }
317
318    #[doc(alias = $name _diagonal)]
319    pub fn diagonal<F: FnOnce(Option<[<Vector $complex View>]>)>(&mut self, f: F) {
320        [<Vector $complex View>]::wrap(unsafe { sys::[<$name _diagonal>](self.unwrap_unique()) }, f)
321    }
322
323    #[doc(alias = $name _subdiagonal)]
324    pub fn subdiagonal<F: FnOnce(Option<[<Vector $complex View>]>)>(&mut self, k: usize, f: F) {
325        [<Vector $complex View>]::wrap(unsafe { sys::[<$name _subdiagonal>](self.unwrap_unique(), k) }, f)
326    }
327
328    #[doc(alias = $name _superdiagonal)]
329    pub fn superdiagonal<F: FnOnce(Option<[<Vector $complex View>]>)>(&mut self, k: usize, f: F) {
330        [<Vector $complex View>]::wrap(unsafe { sys::[<$name _superdiagonal>](self.unwrap_unique(), k) }, f)
331    }
332
333    #[doc(alias = $name _subrow)]
334    pub fn subrow<F: FnOnce(Option<[<Vector $complex View>]>)>(&mut self, i: usize, offset: usize, n: usize, f: F) {
335        [<Vector $complex View>]::wrap(unsafe { sys::[<$name _subrow>](self.unwrap_unique(), i, offset, n) }, f)
336    }
337
338    #[doc(alias = $name _subcolumn)]
339    pub fn subcolumn<F: FnOnce(Option<[<Vector $complex View>]>)>(&mut self, i: usize, offset: usize, n: usize, f: F) {
340        [<Vector $complex View>]::wrap(unsafe { sys::[<$name _subcolumn>](self.unwrap_unique(), i, offset, n) }, f)
341    }
342
343    pub fn size1(&self) -> usize {
344        if self.unwrap_shared().is_null() {
345            0
346        } else {
347            unsafe { (*self.unwrap_shared()).size1 }
348        }
349    }
350
351    pub fn size2(&self) -> usize {
352        if self.unwrap_shared().is_null() {
353            0
354        } else {
355            unsafe { (*self.unwrap_shared()).size2 }
356        }
357    }
358
359    pub fn clone(&self) -> Option<Self> {
360        if self.unwrap_shared().is_null() {
361            None
362        } else {
363            if let Some(mut m) = Self::new(self.size1(), self.size2()) {
364                if m.copy_from(self).is_err() {
365                    None
366                } else {
367                    Some(m)
368                }
369            } else {
370                None
371            }
372        }
373    }
374}
375
376impl Debug for $rust_name {
377    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
378        if self.unwrap_shared().is_null() {
379            write!(f, "<null>")
380        } else {
381            let size1 = self.size1();
382            let size2 = self.size2();
383            for y in 0..size1 {
384                write!(f, "[")?;
385                for x in 0..size2 {
386                    if x < size2 - 1 {
387                        write!(f, "{:?}, ", self.get(y, x))?;
388                    } else {
389                        write!(f, "{:?}", self.get(y, x))?;
390                    }
391                }
392                if y < size1 - 1 {
393                    write!(f, "]\n")?;
394                }
395            }
396            write!(f, "]")
397        }
398    }
399}
400
401} // end of paste! block
402); // end of macro block
403}
404
405gsl_matrix_complex!(
406    MatrixComplexF64,
407    gsl_matrix_complex,
408    ComplexF64,
409    gsl_vector_complex
410);
411gsl_matrix_complex!(
412    MatrixComplexF32,
413    gsl_matrix_complex_float,
414    ComplexF32,
415    gsl_vector_complex_float
416);