rgsl/types/
vector.rs

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