rgsl/types/
vector_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;
9use std::fmt::{Debug, Formatter};
10use std::marker::PhantomData;
11
12macro_rules! gsl_vec_complex {
13    ($rust_name:ident, $name:ident, $complex:ident, $rust_ty:ident) => {
14        paste! {
15
16        use types::$complex;
17
18        pub struct $rust_name {
19            vec: *mut sys::$name,
20            can_free: bool,
21        }
22
23        impl Drop for $rust_name {
24            #[doc(alias = $name _free)]
25            fn drop(&mut self) {
26                if self.can_free {
27                    unsafe { sys::[<$name _free>](self.vec) };
28                    self.vec = std::ptr::null_mut();
29                }
30            }
31        }
32
33        impl Debug for $rust_name {
34            fn fmt(&self, f: &mut Formatter) -> fmt::Result {
35                let ptr = self.unwrap_shared();
36                if ptr.is_null() {
37                    write!(f, "<null>")
38                } else {
39                    write!(f, "{:?}", self.as_slice().expect("conversion to slice failed"))
40                }
41            }
42        }
43
44        impl FFI<sys::$name> for $rust_name {
45            fn wrap(vec: *mut sys::$name) -> Self {
46                Self {
47                    vec,
48                    can_free: true,
49                }
50            }
51
52            fn soft_wrap(vec: *mut sys::$name) -> Self {
53                Self {
54                    vec,
55                    can_free: false,
56                }
57            }
58
59            fn unwrap_shared(&self) -> *const sys::$name {
60                self.vec as *const _
61            }
62
63            fn unwrap_unique(&mut self) -> *mut sys::$name {
64                self.vec
65            }
66        }
67
68        impl $rust_name {
69            #[doc = "Create a new " $rust_name "with all elements set to zero"]
70            #[doc(alias = $name _calloc)]
71            pub fn new(size: usize) -> Option<Self> {
72                let tmp = unsafe { sys::[<$name _calloc>](size) };
73
74                if tmp.is_null() {
75                    None
76                } else {
77                    Some(Self::wrap(tmp))
78                }
79            }
80
81            #[doc(alias = $name _alloc)]
82            pub fn from_slice(slice: &[$complex]) -> Option<Self> {
83                let tmp = unsafe { sys::[<$name _alloc>](slice.len() as _) };
84
85                if tmp.is_null() {
86                    None
87                } else {
88                    let mut v = Self::wrap(tmp);
89
90                    for (pos, tmp) in slice.iter().enumerate() {
91                        v.set(pos as _, tmp);
92                    }
93                    Some(v)
94                }
95            }
96
97            pub fn len(&self) -> usize {
98                let ptr = self.unwrap_shared();
99                if ptr.is_null() {
100                    0
101                } else {
102                    unsafe { (*ptr).size }
103                }
104            }
105
106            pub fn is_empty(&self) -> bool {
107                self.len() == 0
108            }
109
110            pub fn as_slice(&self) -> Option<&[$rust_ty]> {
111                let ptr = unsafe { (*self.unwrap_shared()).data };
112                if ptr.is_null() {
113                    None
114                } else {
115                    Some(unsafe { std::slice::from_raw_parts(ptr, self.len()) })
116                }
117            }
118
119            pub fn as_slice_mut(&mut self) -> Option<&mut [$rust_ty]> {
120                let ptr = unsafe { (*self.unwrap_shared()).data };
121                if ptr.is_null() {
122                    None
123                } else {
124                    Some(unsafe { std::slice::from_raw_parts_mut(ptr, self.len()) })
125                }
126            }
127
128            /// This function returns the i-th element of a vector v. If i lies outside the allowed range of
129            /// 0 to n-1 then the error handler is invoked and 0 is returned.
130            #[doc(alias = $name _get)]
131            pub fn get(&self, i: usize) -> $complex {
132                unsafe { std::mem::transmute(sys::[<$name _get>](self.unwrap_shared(), i)) }
133            }
134
135            /// This function sets the value of the i-th element of a vector v to x. If i lies outside the
136            /// allowed range of 0 to n-1 then the error handler is invoked.
137            #[doc(alias = $name _set)]
138            pub fn set(&mut self, i: usize, x: &$complex) -> &Self {
139                unsafe {
140                    sys::[<$name _set>](self.unwrap_unique(), i, std::mem::transmute(*x))
141                };
142                self
143            }
144
145            /// This function sets all the elements of the vector v to the value x.
146            #[doc(alias = $name _set_all)]
147            pub fn set_all(&mut self, x: &$complex) -> &Self {
148                unsafe {
149                    sys::[<$name _set_all>](self.unwrap_unique(), std::mem::transmute(*x))
150                };
151                self
152            }
153
154            /// This function sets all the elements of the vector v to zero.
155            #[doc(alias = $name _set_zero)]
156            pub fn set_zero(&mut self) -> &$rust_name {
157                unsafe { sys::[<$name _set_zero>](self.unwrap_unique()) };
158                self
159            }
160
161            /// This function makes a basis vector by setting all the elements of the vector v to zero
162            /// except for the i-th element which is set to one.
163            #[doc(alias = $name _set_basis)]
164            pub fn set_basis(&mut self, i: usize) -> &Self {
165                unsafe { sys::[<$name _set_basis>](self.unwrap_unique(), i) };
166                self
167            }
168
169            /// This function copies the elements of the other vector into the self vector. The two vectors
170            /// must have the same length.
171            #[doc(alias = $name _memcpy)]
172            pub fn copy_from(&mut self, other: &$rust_name) -> Result<(), Value> {
173                let ret = unsafe {
174                    sys::[<$name _memcpy>](self.unwrap_unique(), other.unwrap_shared())
175                };
176                result_handler!(ret, ())
177            }
178
179            /// This function copies the elements of the self vector into the other vector. The two vectors
180            /// must have the same length.
181            #[doc(alias = $name _memcpy)]
182            pub fn copy_to(&self, other: &mut $rust_name) -> Result<(), Value> {
183                let ret = unsafe {
184                    sys::[<$name _memcpy>](other.unwrap_unique(), self.unwrap_shared())
185                };
186                result_handler!(ret, ())
187            }
188
189            /// This function exchanges the elements of the vectors by copying. The two vectors must have
190            /// the same length.
191            #[doc(alias = $name _swap)]
192            pub fn swap(&mut self, other: &mut $rust_name) -> Result<(), Value> {
193                let ret = unsafe {
194                    sys::[<$name _swap>](other.unwrap_unique(), self.unwrap_unique())
195                };
196                result_handler!(ret, ())
197            }
198
199            /// This function exchanges the i-th and j-th elements of the vector v in-place.
200            #[doc(alias = $name _swap_elements)]
201            pub fn swap_elements(&mut self, i: usize, j: usize) -> Result<(), Value> {
202                let ret = unsafe {
203                    sys::[<$name _swap_elements>](self.unwrap_unique(), i, j)
204                };
205                result_handler!(ret, ())
206            }
207
208            /// This function reverses the order of the elements of the vector v.
209            #[doc(alias = $name _reverse)]
210            pub fn reverse(&mut self) -> Result<(), Value> {
211                let ret = unsafe { sys::[<$name _reverse>](self.unwrap_unique()) };
212                result_handler!(ret, ())
213            }
214
215            /// This function adds the elements of the other vector to the elements of the `self` vector.
216            /// The result a_i <- a_i + b_i is stored in self and other remains unchanged. The two vectors
217            /// must have the same length.
218            #[doc(alias = $name _add)]
219            pub fn add(&mut self, other: &$rust_name) -> Result<(), Value> {
220                let ret = unsafe {
221                    sys::[<$name _add>](self.unwrap_unique(), other.unwrap_shared())
222                };
223                result_handler!(ret, ())
224            }
225
226            /// This function subtracts the elements of the self vector from the elements of the other
227            /// vector. The result a_i <- a_i - b_i is stored in self and other remains unchanged. The two
228            /// vectors must have the same length.
229            #[doc(alias = $name _sub)]
230            pub fn sub(&mut self, other: &$rust_name) -> Result<(), Value> {
231                let ret = unsafe {
232                    sys::[<$name _sub>](self.unwrap_unique(), other.unwrap_shared())
233                };
234                result_handler!(ret, ())
235            }
236
237            /// This function multiplies the elements of the self vector a by the elements of the other
238            /// vector. The result a_i <- a_i * b_i is stored in self and other remains unchanged. The two
239            /// vectors must have the same length.
240            #[doc(alias = $name _mul)]
241            pub fn mul(&mut self, other: &$rust_name) -> Result<(), Value> {
242                let ret = unsafe {
243                    sys::[<$name _mul>](self.unwrap_unique(), other.unwrap_shared())
244                };
245                result_handler!(ret, ())
246            }
247
248            /// This function divides the elements of the self vector by the elements of the other vector.
249            /// The result a_i <- a_i / b_i is stored in self and other remains unchanged. The two vectors
250            /// must have the same length.
251            #[doc(alias = $name _div)]
252            pub fn div(&mut self, other: &$rust_name) -> Result<(), Value> {
253                let ret = unsafe {
254                    sys::[<$name _div>](self.unwrap_unique(), other.unwrap_shared())
255                };
256                result_handler!(ret, ())
257            }
258
259            /// This function multiplies the elements of the self vector by the constant factor x. The
260            /// result a_i <- a_i is stored in self.
261            #[doc(alias = $name _scale)]
262            pub fn scale(&mut self, x: &$complex) -> Result<(), Value> {
263                let ret = unsafe {
264                    sys::[<$name _scale>](self.unwrap_unique(), std::mem::transmute(*x))
265                };
266                result_handler!(ret, ())
267            }
268
269            /// This function adds the constant value x to the elements of the self vector. The result
270            /// a_i <- a_i + x is stored in self.
271            #[doc(alias = $name _add_constant)]
272            pub fn add_constant(&mut self, x: &$complex) -> Result<(), Value> {
273                let ret = unsafe {
274                    sys::[<$name _add_constant>](
275                        self.unwrap_unique(),
276                        std::mem::transmute(*x),
277                    )
278                };
279                result_handler!(ret, ())
280            }
281
282            /// This function returns true if all the elements of the self vector are equal to 0.
283            #[doc(alias = $name _isnull)]
284            pub fn is_null(&self) -> bool {
285                unsafe { sys::[<$name _isnull>](self.unwrap_shared()) == 1 }
286            }
287
288            /// This function returns true if all the elements of the self vector are stricly positive.
289            #[doc(alias = $name _ispos)]
290            pub fn is_pos(&self) -> bool {
291                unsafe { sys::[<$name _ispos>](self.unwrap_shared()) == 1 }
292            }
293
294            /// This function returns true if all the elements of the self vector are stricly negative.
295            #[doc(alias = $name _isneg)]
296            pub fn is_neg(&self) -> bool {
297                unsafe { sys::[<$name _isneg>](self.unwrap_shared()) == 1 }
298            }
299
300            /// This function returns true if all the elements of the self vector are stricly non-negative.
301            #[doc(alias = $name _isnonneg)]
302            pub fn is_non_neg(&self) -> bool {
303                unsafe { sys::[<$name _isnonneg>](self.unwrap_shared()) == 1 }
304            }
305
306            #[doc(alias = $name _equal)]
307            pub fn equal(&self, other: &$rust_name) -> bool {
308                unsafe {
309                    sys::[<$name _equal>](self.unwrap_shared(), other.unwrap_shared()) == 1
310                }
311            }
312
313            pub fn clone(&self) -> Option<Self> {
314                if self.unwrap_shared().is_null() {
315                    None
316                } else {
317                    if let Some(mut v) = Self::new(self.len()) {
318                        if v.copy_from(self).is_err() {
319                            None
320                        } else {
321                            Some(v)
322                        }
323                    } else {
324                        None
325                    }
326                }
327            }
328        }
329
330        pub struct [<$rust_name View>]<'a> {
331            v: sys::[<$name _view>],
332            #[allow(dead_code)]
333            phantom: PhantomData<&'a ()>,
334        }
335
336        impl<'a> [<$rust_name View>]<'a> {
337            #[doc(hidden)]
338            pub(crate) fn wrap<F: FnOnce(Option<Self>)>(v: sys::[<$name _view>], f: F) {
339                let tmp = Self {
340                    v,
341                    phantom: PhantomData,
342                };
343                let is_none = {
344                    let v = &tmp.v.vector;
345                    let tmp = $rust_name::soft_wrap(v as *const _ as usize as *mut _);
346                    tmp.as_slice().is_none()
347                };
348                if is_none {
349                    f(None)
350                } else {
351                    f(Some(tmp))
352                }
353            }
354
355            /// These functions return a vector view of a subvector of another vector v. The start of the
356            /// new vector is offset by offset elements from the start of the original vector. The new
357            /// vector has n elements. Mathematically, the i-th element of the new vector v’ is given by,
358            ///
359            /// v'(i) = v->data[(offset + i)*v->stride]
360            ///
361            /// where the index i runs from 0 to n-1.
362            ///
363            /// The data pointer of the returned vector struct is set to null if the combined parameters
364            /// (offset,n) overrun the end of the original vector.
365            ///
366            /// The new vector is only a view of the block underlying the original vector, v. The block
367            /// containing the elements of v is not owned by the new vector. When the view goes out of scope
368            /// the original vector v and its block will continue to exist. The original memory can only be
369            /// deallocated by freeing the original vector. Of course, the original vector should not be
370            /// deallocated while the view is still in use.
371            ///
372            /// The function gsl_vector_const_subvector is equivalent to gsl_vector_subvector but can be
373            /// used for vectors which are declared const.
374            // checker:ignore
375            #[doc(alias = $name _subvector)]
376            pub fn from_vector(v: &'a mut $rust_name, offset: usize, n: usize) -> Self {
377                unsafe {
378                    Self {
379                        v: sys::[<$name _subvector>](v.unwrap_unique(), offset, n),
380                        phantom: PhantomData,
381                    }
382                }
383            }
384
385            /// These functions return a vector view of a subvector of another vector v with an additional
386            /// stride argument. The subvector is formed in the same way as for gsl_vector_subvector but the
387            /// new vector has n elements with a step-size of stride from one element to the next in the
388            /// original vector. Mathematically, the i-th element of the new vector v’ is given by,
389            ///
390            /// v'(i) = v->data[(offset + i*stride)*v->stride]
391            /// where the index i runs from 0 to n-1.
392            ///
393            /// Note that subvector views give direct access to the underlying elements of the original
394            /// vector. For example, the following code will zero the even elements of the vector v of
395            /// length n, while leaving the odd elements untouched,
396            ///
397            /// ```C
398            /// gsl_vector_view v_even
399            ///   = gsl_vector_subvector_with_stride (v, 0, 2, n/2);
400            /// gsl_vector_set_zero (&v_even.vector);
401            /// ```
402            /// A vector view can be passed to any subroutine which takes a vector argument just as a
403            /// directly allocated vector would be, using &view.vector.
404            /// For example, the following code computes the norm of the odd elements of v using the BLAS
405            /// routine DNRM2,
406            ///
407            /// ```C
408            /// gsl_vector_view v_odd
409            ///   = gsl_vector_subvector_with_stride (v, 1, 2, n/2);
410            /// double r = gsl_blas_dnrm2 (&v_odd.vector);
411            /// ```
412            /// The function gsl_vector_const_subvector_with_stride is equivalent to
413            /// gsl_vector_subvector_with_stride but can be used for vectors which are declared const.
414            // checker:ignore
415            #[doc(alias = $name _subvector_with_stride)]
416            pub fn from_vector_with_stride(
417                v: &'a mut $rust_name,
418                offset: usize,
419                stride: usize,
420                n: usize,
421            ) -> Self {
422                unsafe {
423                    Self {
424                        v: sys::[<$name _subvector_with_stride>](v.vec, offset, stride, n),
425                        phantom: PhantomData,
426                    }
427                }
428            }
429
430            /// These functions return a vector view of an array. The start of the new vector is given by
431            /// base and has n elements. Mathematically, the i-th element of the new vector v’ is given by,
432            ///
433            /// ```text
434            /// v'(i) = base[i]
435            /// ```
436            ///
437            /// where the index i runs from 0 to n-1.
438            ///
439            /// The array containing the elements of v is not owned by the new vector view. When the view
440            /// goes out of scope the original array will continue to exist. The original memory can only be
441            /// deallocated by freeing the original pointer base. Of course, the original array should not
442            /// be deallocated while the view is still in use.
443            ///
444            /// The function gsl_vector_const_view_array is equivalent to gsl_vector_view_array but can be
445            /// used for arrays which are declared const.
446            // checker:ignore
447            #[doc(alias = $name _view_array)]
448            pub fn from_array(base: &'a mut [f64]) -> Self {
449                unsafe {
450                    Self {
451                        v: sys::[<$name _view_array>](base.as_mut_ptr() as _, base.len() as _),
452                        phantom: PhantomData,
453                    }
454                }
455            }
456
457            /// These functions return a vector view of an array base with an additional stride argument.
458            /// The subvector is formed in the same way as for gsl_vector_view_array but the new vector has
459            /// n elements with a step-size of stride from one element to the next in the original
460            /// array. Mathematically, the i-th element of the new vector v’ is given by,
461            ///
462            /// v'(i) = base[i*stride]
463            ///
464            /// where the index i runs from 0 to n-1.
465            ///
466            /// Note that the view gives direct access to the underlying elements of the original array. A
467            /// vector view can be passed to any subroutine which takes a vector argument just as a directly
468            /// allocated vector would be, using &view.vector.
469            ///
470            /// The function gsl_vector_const_view_array_with_stride is equivalent to
471            /// gsl_vector_view_array_with_stride but can be used for arrays which are declared const.
472            // checker:ignore
473            #[doc(alias = $name _view_array_with_stride)]
474            pub fn from_array_with_stride(base: &'a mut [$rust_ty], stride: usize) -> Self {
475                unsafe {
476                    Self {
477                        v: sys::[<$name _view_array_with_stride>](
478                            base.as_mut_ptr(),
479                            stride,
480                            base.len() as _,
481                        ),
482                        phantom: PhantomData,
483                    }
484                }
485            }
486
487            pub fn vector<F: FnOnce(Option<&$rust_name>)>(&self, f: F) {
488                let v = &self.v.vector;
489                let tmp = $rust_name::soft_wrap(v as *const _ as usize as *mut _);
490                if tmp.as_slice().is_none() {
491                    f(None)
492                } else {
493                    f(Some(&tmp))
494                }
495            }
496
497            pub fn vector_mut<F: FnOnce(Option<&mut $rust_name>)>(&mut self, f: F) {
498                let v = &mut self.v.vector;
499                let mut tmp = $rust_name::soft_wrap(v as *mut _);
500                if tmp.as_slice().is_none() {
501                    f(None)
502                } else {
503                    f(Some(&mut tmp))
504                }
505            }
506        } // end of impl block
507
508        } // end of paste! block
509    }; // end of macro block
510}
511
512gsl_vec_complex!(VectorComplexF32, gsl_vector_complex_float, ComplexF32, f32);
513gsl_vec_complex!(VectorComplexF64, gsl_vector_complex, ComplexF64, f64);