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);