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