Skip to main content

igraph/
vector.rs

1//! Owned igraph vectors that behave like Rust slices.
2//!
3//! igraph stores sequences in its own vector types (`igraph_vector_t` for
4//! reals, `igraph_vector_int_t` for integers, ...). The types below are
5//! *those very C structs*, enriched with Rusty behaviour:
6//!
7//! - they own their buffer and destroy it on [`Drop`];
8//! - they [`Deref`] to a Rust slice, so every slice method (`len`, `iter`,
9//!   `sort`, indexing, `contains`, ...) works with zero copies;
10//! - they convert from and to [`Vec`], slices and iterators;
11//! - they implement [`Clone`], [`Debug`], [`PartialEq`] and [`Default`].
12//!
13//! | Rust alias      | C type                    | element                |
14//! |-----------------|---------------------------|------------------------|
15//! | [`Vector`]      | `igraph_vector_t`         | [`f64`]                |
16//! | [`VectorInt`]   | `igraph_vector_int_t`     | [`i64`]                |
17//! | [`VectorBool`]  | `igraph_vector_bool_t`    | [`bool`]               |
18//! | [`VectorChar`]  | `igraph_vector_char_t`    | [`c_char`](std::ffi::c_char) |
19//! | [`VectorComplex`] | `igraph_vector_complex_t` | [`igraph_complex_t`] |
20//!
21//! Borrowed, read-only *views* over Rust slices (no copy at all) are created
22//! with `view`, e.g. [`Vector::view`]; they are what the safe wrappers use to
23//! hand weights and other inputs to igraph.
24//!
25//! Most wrappers in this crate return plain `Vec`s, so these types matter
26//! mostly when calling raw FFI functions, or to use igraph's vector
27//! algorithms (below) on any slice. Lists of vectors are in
28//! [`list`](crate::list), matrices in [`matrix`](crate::matrix), sparse
29//! matrices in [`linalg`](crate::linalg) ([`SparseMat`](crate::linalg::SparseMat)),
30//! and [`misc`](crate::misc) has more numeric helpers, e.g.
31//! [`misc::running_mean`](crate::misc::running_mean) and
32//! [`misc::power_law_fit`](crate::misc::power_law_fit).
33//!
34//! This module covers `igraph_vector_pmt.h` (and the non-templated parts of
35//! `igraph_vector.h` and `igraph_complex.h`). Besides everything slices
36//! offer, the vectors provide igraph's own algorithms:
37//!
38//! | Group | Methods | Types |
39//! |-------|---------|-------|
40//! | editing | `insert`, `remove`, `swap_remove`, `remove_section`, `extend_from_slice`, `push`, `pop`, `truncate`, `resize`, `clear` | all |
41//! | reordering | `shuffle` (igraph RNG), `permute`, `select`, `move_interval`, `get_interval`, `search` | all |
42//! | memory | `reserve`, `capacity`, `shrink_to_fit` | all |
43//! | order | `sort`, `reverse_sort`, `sort_ind`, `min`, `max`, `which_min`, `which_max`, `minmax`, `which_minmax`, `binsearch`, `contains_sorted` | real, int, char |
44//! | comparison | `lex_cmp`, `colex_cmp`, `all_l`, `all_g`, `all_le`, `all_ge`, `maxdifference`, `is_in_interval`, `any_smaller` | real, int, char |
45//! | sorted sets | `intersect_sorted`, `difference_sorted`, `intersection_size_sorted`, `difference_and_intersection_sorted`, `filter_smaller` | real, int, char |
46//! | arithmetic | `sum`, `prod`, `cumsum`, `add_constant`, `scale`, `add`, `sub`, `mul`, `div`, `abs` | real, int, complex |
47//! | floating point | `all_almost_e`, `zapsmall`, `floor`, `round`, `is_nan`, `is_any_nan`, `is_all_finite` | real (complex) |
48//! | complex | `from_parts`, `from_polar`, `real`, `imag`, `realimag`; [`igraph_complex_t`] has `+ - * /`, `abs`, `arg`, `exp`, `ln`, `sqrt`, `pow`, trigonometry, ... | complex |
49//!
50//! Integer arithmetic is done in Rust with *wrapping* semantics (signed
51//! overflow in the C implementation would be undefined behaviour); real and
52//! complex arithmetic uses igraph's functions. All index arguments are
53//! validated before reaching igraph, which does not check them.
54//!
55//! ```
56//! use igraph::prelude::*;
57//!
58//! let scores = Vector::from([0.3, 0.9, 0.1, 0.5]);
59//! let ranking = scores.sort_ind(Order::Descending);
60//! assert_eq!(ranking, vec![1, 3, 0, 2]);
61//! assert_eq!(scores.which_max(), Some(1));
62//! assert_eq!(scores.select(&[1, 3]).unwrap(), vec![0.9, 0.5]);
63//!
64//! let a = VectorInt::from([1, 3, 5, 7]);
65//! assert_eq!(a.intersect_sorted(&[3, 4, 5]), vec![3, 5]);
66//! assert_eq!(a.binsearch(4), Err(2));
67//! ```
68//!
69//! ```
70//! use igraph::prelude::*;
71//!
72//! let mut v: VectorInt = (0..5).collect();
73//! v.push(10);
74//! v[0] = -1;
75//! assert_eq!(v.len(), 6);
76//! assert_eq!(v.iter().sum::<i64>(), 19);
77//! assert_eq!(Vec::from(v), vec![-1, 1, 2, 3, 4, 10]);
78//!
79//! let weights = [0.5, 1.5];
80//! let view = Vector::view(&weights);
81//! assert_eq!(&view[..], &weights[..]);
82//! ```
83
84use crate::ffi::*;
85use std::{
86    fmt,
87    marker::PhantomData,
88    mem::{ManuallyDrop, MaybeUninit},
89    ops::{Deref, DerefMut},
90};
91
92/// Owned vector of reals (`igraph_vector_t`), see the [module docs](self).
93pub type Vector = igraph_vector_t;
94/// Owned vector of integers (`igraph_vector_int_t`), see the [module docs](self).
95pub type VectorInt = igraph_vector_int_t;
96/// Owned vector of booleans (`igraph_vector_bool_t`), see the [module docs](self).
97pub type VectorBool = igraph_vector_bool_t;
98/// Owned vector of chars (`igraph_vector_char_t`), see the [module docs](self).
99pub type VectorChar = igraph_vector_char_t;
100/// Owned vector of complex numbers (`igraph_vector_complex_t`), see the [module docs](self).
101pub type VectorComplex = igraph_vector_complex_t;
102
103/// A read-only view of a Rust slice as an igraph vector, without copying.
104///
105/// It dereferences to the underlying C vector type (e.g. [`Vector`]), so
106/// `&*view` can be passed where igraph expects a `const igraph_vector_t *`.
107/// The view never frees the borrowed memory.
108pub struct View<'a, V> {
109    raw: ManuallyDrop<V>,
110    _borrow: PhantomData<&'a ()>,
111}
112
113impl<V> Deref for View<'_, V> {
114    type Target = V;
115    fn deref(&self) -> &V {
116        &self.raw
117    }
118}
119
120impl<V: fmt::Debug> fmt::Debug for View<'_, V> {
121    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
122        (*self.raw).fmt(f)
123    }
124}
125
126impl<V> View<'_, V> {
127    /// Raw pointer to the viewed C vector, for FFI calls.
128    pub fn as_ptr(&self) -> *const V {
129        &*self.raw
130    }
131
132    /// Wraps a raw igraph *view* struct (one that does not own its buffer,
133    /// e.g. returned by `igraph_matrix_view`), so that it is never destroyed.
134    ///
135    /// # Safety
136    /// `raw` must point into memory that stays valid and unmodified for the
137    /// lifetime `'a` of the returned view.
138    pub(crate) unsafe fn from_raw<'a>(raw: V) -> View<'a, V> {
139        View {
140            raw: ManuallyDrop::new(raw),
141            _borrow: PhantomData,
142        }
143    }
144}
145
146macro_rules! impl_vector {
147    (
148        $ty:ident, $elem:ty,
149        init = $init:ident, init_array = $init_array:ident, init_copy = $init_copy:ident,
150        destroy = $destroy:ident, push_back = $push:ident, resize = $resize:ident,
151        reserve = $reserve:ident, view = $view:ident
152    ) => {
153        impl $ty {
154            /// Creates an empty vector.
155            pub fn new() -> Self {
156                Self::zeros(0)
157            }
158
159            /// Creates a vector of `len` zero (default) elements
160            /// ([`igraph_vector_init`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_init)).
161            ///
162            /// # Panics
163            /// If igraph cannot allocate the vector, or `len` does not fit in
164            /// an `i64`, like [`Vec::with_capacity`].
165            pub fn zeros(len: usize) -> Self {
166                crate::error::ensure_init();
167                let mut raw = MaybeUninit::<Self>::uninit();
168                crate::error::check(unsafe {
169                    $init(raw.as_mut_ptr(), crate::error::int_size(len))
170                })
171                .expect("igraph failed to allocate a vector");
172                unsafe { raw.assume_init() }
173            }
174
175            /// Creates a vector of `len` zero (default) elements.
176            #[deprecated(note = "it creates a zero-filled vector of length `size`: use `zeros`")]
177            pub fn with_capacity(size: usize) -> Self {
178                Self::zeros(size)
179            }
180
181            /// Creates a vector by copying the elements of a slice
182            /// ([`igraph_vector_init_array`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_init_array)).
183            pub fn from_slice(data: &[$elem]) -> Self {
184                crate::error::ensure_init();
185                let mut raw = MaybeUninit::<Self>::uninit();
186                crate::error::check(unsafe {
187                    $init_array(raw.as_mut_ptr(), data.as_ptr(), data.len() as igraph_int_t)
188                })
189                .expect("igraph failed to allocate a vector");
190                unsafe { raw.assume_init() }
191            }
192
193            /// Creates a read-only view of `data`, without copying it
194            /// ([`igraph_vector_view`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_view)); the view
195            /// dereferences to this vector type and never frees `data`.
196            pub fn view(data: &[$elem]) -> View<'_, Self> {
197                let raw = unsafe { $view(data.as_ptr(), data.len() as igraph_int_t) };
198                View {
199                    raw: ManuallyDrop::new(raw),
200                    _borrow: PhantomData,
201                }
202            }
203
204            /// Number of elements (also available through [`Deref`] as `len`).
205            pub fn size(&self) -> usize {
206                self.as_slice().len()
207            }
208
209            /// The elements as a slice.
210            pub fn as_slice(&self) -> &[$elem] {
211                if self.stor_begin.is_null() {
212                    return &[];
213                }
214                unsafe {
215                    let len = self.end.offset_from(self.stor_begin) as usize;
216                    std::slice::from_raw_parts(self.stor_begin, len)
217                }
218            }
219
220            /// The elements as a mutable slice.
221            pub fn as_mut_slice(&mut self) -> &mut [$elem] {
222                if self.stor_begin.is_null() {
223                    return &mut [];
224                }
225                unsafe {
226                    let len = self.end.offset_from(self.stor_begin) as usize;
227                    std::slice::from_raw_parts_mut(self.stor_begin, len)
228                }
229            }
230
231            /// Appends an element at the end, in amortized O(1)
232            /// ([`igraph_vector_push_back`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_push_back)).
233            pub fn push(&mut self, value: $elem) {
234                crate::error::check(unsafe { $push(self, value) })
235                    .expect("igraph failed to grow a vector");
236            }
237
238            /// Removes and returns the last element, if any.
239            pub fn pop(&mut self) -> Option<$elem> {
240                let len = self.size();
241                if len == 0 {
242                    return None;
243                }
244                let last = unsafe { std::ptr::read(self.stor_begin.add(len - 1)) };
245                self.truncate(len - 1);
246                Some(last)
247            }
248
249            /// Shortens the vector to `len` elements (no-op if already shorter).
250            pub fn truncate(&mut self, len: usize) {
251                if len < self.size() {
252                    self.end = unsafe { self.stor_begin.add(len) };
253                }
254            }
255
256            /// Removes all the elements, keeping the allocated storage.
257            pub fn clear(&mut self) {
258                self.truncate(0);
259            }
260
261            /// Resizes the vector to `len` elements
262            /// ([`igraph_vector_resize`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_resize)); new
263            /// elements are unspecified by igraph, so this wrapper zeroes them.
264            pub fn resize(&mut self, len: usize) {
265                let old = self.size();
266                crate::error::check(unsafe { $resize(self, crate::error::int_size(len)) })
267                    .expect("igraph failed to resize a vector");
268                if len > old {
269                    unsafe { std::ptr::write_bytes(self.stor_begin.add(old), 0, len - old) };
270                }
271            }
272
273            /// Reserves storage for at least `capacity` elements in total
274            /// ([`igraph_vector_reserve`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_reserve)).
275            pub fn reserve(&mut self, capacity: usize) {
276                crate::error::check(unsafe { $reserve(self, crate::error::int_size(capacity)) })
277                    .expect("igraph failed to reserve vector storage");
278            }
279
280            /// Copies the elements into a [`Vec`].
281            pub fn to_vec(&self) -> Vec<$elem> {
282                self.as_slice().to_vec()
283            }
284        }
285
286        impl Drop for $ty {
287            /// Frees the storage with the corresponding `igraph_*_destroy`.
288            ///
289            /// Never let a raw *view* created with the unsafe `igraph_*_view`
290            /// functions be dropped: use the safe `view` constructor instead.
291            fn drop(&mut self) {
292                if !self.stor_begin.is_null() {
293                    unsafe { $destroy(self) };
294                    self.stor_begin = std::ptr::null_mut();
295                }
296            }
297        }
298
299        impl Default for $ty {
300            fn default() -> Self {
301                Self::new()
302            }
303        }
304
305        impl Clone for $ty {
306            fn clone(&self) -> Self {
307                // A vector may have been moved to a thread that never called
308                // into igraph: install the error handler before allocating.
309                crate::error::ensure_init();
310                let mut raw = MaybeUninit::<Self>::uninit();
311                crate::error::check(unsafe { $init_copy(raw.as_mut_ptr(), self) })
312                    .expect("igraph failed to copy a vector");
313                unsafe { raw.assume_init() }
314            }
315        }
316
317        impl Deref for $ty {
318            type Target = [$elem];
319            fn deref(&self) -> &[$elem] {
320                self.as_slice()
321            }
322        }
323
324        impl DerefMut for $ty {
325            fn deref_mut(&mut self) -> &mut [$elem] {
326                self.as_mut_slice()
327            }
328        }
329
330        impl AsRef<[$elem]> for $ty {
331            fn as_ref(&self) -> &[$elem] {
332                self.as_slice()
333            }
334        }
335
336        impl PartialEq for $ty {
337            fn eq(&self, other: &Self) -> bool {
338                self.as_slice() == other.as_slice()
339            }
340        }
341
342        impl PartialEq<[$elem]> for $ty {
343            fn eq(&self, other: &[$elem]) -> bool {
344                self.as_slice() == other
345            }
346        }
347
348        impl PartialEq<Vec<$elem>> for $ty {
349            fn eq(&self, other: &Vec<$elem>) -> bool {
350                self.as_slice() == other.as_slice()
351            }
352        }
353
354        impl From<&[$elem]> for $ty {
355            fn from(data: &[$elem]) -> Self {
356                Self::from_slice(data)
357            }
358        }
359
360        impl<const N: usize> From<[$elem; N]> for $ty {
361            fn from(data: [$elem; N]) -> Self {
362                Self::from_slice(&data)
363            }
364        }
365
366        impl From<Vec<$elem>> for $ty {
367            fn from(data: Vec<$elem>) -> Self {
368                Self::from_slice(&data)
369            }
370        }
371
372        impl From<&Vec<$elem>> for $ty {
373            fn from(data: &Vec<$elem>) -> Self {
374                Self::from_slice(data)
375            }
376        }
377
378        impl From<$ty> for Vec<$elem> {
379            fn from(v: $ty) -> Self {
380                v.to_vec()
381            }
382        }
383
384        impl From<&$ty> for Vec<$elem> {
385            fn from(v: &$ty) -> Self {
386                v.to_vec()
387            }
388        }
389
390        impl FromIterator<$elem> for $ty {
391            fn from_iter<I: IntoIterator<Item = $elem>>(iter: I) -> Self {
392                let mut v = Self::new();
393                v.extend(iter);
394                v
395            }
396        }
397
398        impl Extend<$elem> for $ty {
399            fn extend<I: IntoIterator<Item = $elem>>(&mut self, iter: I) {
400                let iter = iter.into_iter();
401                let (lower, _) = iter.size_hint();
402                self.reserve(self.size() + lower);
403                for x in iter {
404                    self.push(x);
405                }
406            }
407        }
408
409        impl<'a> IntoIterator for &'a $ty {
410            type Item = &'a $elem;
411            type IntoIter = std::slice::Iter<'a, $elem>;
412            fn into_iter(self) -> Self::IntoIter {
413                self.as_slice().iter()
414            }
415        }
416
417        impl IntoIterator for $ty {
418            type Item = $elem;
419            type IntoIter = std::vec::IntoIter<$elem>;
420            fn into_iter(self) -> Self::IntoIter {
421                self.to_vec().into_iter()
422            }
423        }
424
425        // The buffer is uniquely owned, so moving it across threads is fine.
426        unsafe impl Send for $ty {}
427        unsafe impl Sync for $ty {}
428    };
429}
430
431impl_vector!(
432    igraph_vector_t,
433    igraph_real_t,
434    init = igraph_vector_init,
435    init_array = igraph_vector_init_array,
436    init_copy = igraph_vector_init_copy,
437    destroy = igraph_vector_destroy,
438    push_back = igraph_vector_push_back,
439    resize = igraph_vector_resize,
440    reserve = igraph_vector_reserve,
441    view = igraph_vector_view
442);
443impl_vector!(
444    igraph_vector_int_t,
445    igraph_int_t,
446    init = igraph_vector_int_init,
447    init_array = igraph_vector_int_init_array,
448    init_copy = igraph_vector_int_init_copy,
449    destroy = igraph_vector_int_destroy,
450    push_back = igraph_vector_int_push_back,
451    resize = igraph_vector_int_resize,
452    reserve = igraph_vector_int_reserve,
453    view = igraph_vector_int_view
454);
455impl_vector!(
456    igraph_vector_bool_t,
457    igraph_bool_t,
458    init = igraph_vector_bool_init,
459    init_array = igraph_vector_bool_init_array,
460    init_copy = igraph_vector_bool_init_copy,
461    destroy = igraph_vector_bool_destroy,
462    push_back = igraph_vector_bool_push_back,
463    resize = igraph_vector_bool_resize,
464    reserve = igraph_vector_bool_reserve,
465    view = igraph_vector_bool_view
466);
467impl_vector!(
468    igraph_vector_char_t,
469    std::ffi::c_char,
470    init = igraph_vector_char_init,
471    init_array = igraph_vector_char_init_array,
472    init_copy = igraph_vector_char_init_copy,
473    destroy = igraph_vector_char_destroy,
474    push_back = igraph_vector_char_push_back,
475    resize = igraph_vector_char_resize,
476    reserve = igraph_vector_char_reserve,
477    view = igraph_vector_char_view
478);
479impl_vector!(
480    igraph_vector_complex_t,
481    igraph_complex_t,
482    init = igraph_vector_complex_init,
483    init_array = igraph_vector_complex_init_array,
484    init_copy = igraph_vector_complex_init_copy,
485    destroy = igraph_vector_complex_destroy,
486    push_back = igraph_vector_complex_push_back,
487    resize = igraph_vector_complex_resize,
488    reserve = igraph_vector_complex_reserve,
489    view = igraph_vector_complex_view
490);
491
492// `Debug` for the vectors is derived by bindgen on the raw struct (showing
493// pointers); `Display` shows the elements instead.
494macro_rules! impl_display {
495    ($($ty:ident),*) => {$(
496        impl fmt::Display for $ty {
497            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
498                f.debug_list().entries(self.as_slice().iter()).finish()
499            }
500        }
501    )*};
502}
503impl_display!(
504    igraph_vector_t,
505    igraph_vector_int_t,
506    igraph_vector_bool_t,
507    igraph_vector_char_t
508);
509
510impl Clone for igraph_complex_t {
511    fn clone(&self) -> Self {
512        *self
513    }
514}
515impl Copy for igraph_complex_t {}
516impl PartialEq for igraph_complex_t {
517    fn eq(&self, other: &Self) -> bool {
518        self.dat == other.dat
519    }
520}
521
522impl igraph_complex_t {
523    /// Builds a complex number from its real and imaginary parts.
524    pub const fn new(re: f64, im: f64) -> Self {
525        Self { dat: [re, im] }
526    }
527    /// The real part.
528    pub const fn re(&self) -> f64 {
529        self.dat[0]
530    }
531    /// The imaginary part.
532    pub const fn im(&self) -> f64 {
533        self.dat[1]
534    }
535}
536
537impl From<(f64, f64)> for igraph_complex_t {
538    fn from((re, im): (f64, f64)) -> Self {
539        Self::new(re, im)
540    }
541}
542
543// ---------------------------------------------------------------------------
544// Operations available for every element type (`igraph_vector_pmt.h`).
545// ---------------------------------------------------------------------------
546
547/// Checks that `index` only contains valid, distinct positions of a vector of
548/// length `len` (what `igraph_vector_*_permute` silently assumes).
549fn check_permutation(index: &[igraph_int_t], len: usize) -> crate::error::Result<()> {
550    if index.len() > len {
551        return Err(crate::error::Error::invalid(format!(
552            "permutation index has {} entries but the vector only {len}",
553            index.len()
554        )));
555    }
556    let mut seen = vec![false; len];
557    for &i in index {
558        if i < 0 || i as usize >= len || std::mem::replace(&mut seen[i as usize], true) {
559            return Err(crate::error::Error::invalid(format!(
560                "invalid or repeated position {i} in a permutation of length {len}"
561            )));
562        }
563    }
564    Ok(())
565}
566
567/// Checks that every entry of `index` is a valid position for length `len`.
568fn check_indices(index: &[igraph_int_t], len: usize) -> crate::error::Result<()> {
569    match index.iter().find(|&&i| i < 0 || i as usize >= len) {
570        Some(i) => Err(crate::error::Error::invalid(format!(
571            "index {i} out of bounds for a vector of length {len}"
572        ))),
573        None => Ok(()),
574    }
575}
576
577macro_rules! impl_vector_common {
578    (
579        $ty:ident, $elem:ty,
580        insert = $insert:ident, remove = $remove:ident, remove_fast = $remove_fast:ident,
581        remove_section = $remove_section:ident, append = $append:ident,
582        shuffle = $shuffle:ident, index = $index:ident,
583        search = $search:ident, capacity = $capacity:ident, resize_min = $resize_min:ident,
584        move_interval = $move_interval:ident, get_interval = $get_interval:ident
585    ) => {
586        impl $ty {
587            /// Inserts `value` at position `pos`, shifting the following
588            /// elements to the right, like [`Vec::insert`]
589            /// ([`igraph_vector_insert`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_insert)).
590            ///
591            /// # Panics
592            /// If `pos > len`.
593            pub fn insert(&mut self, pos: usize, value: $elem) {
594                let len = self.size();
595                assert!(
596                    pos <= len,
597                    "insertion index {pos} out of bounds (len {len})"
598                );
599                crate::error::check(unsafe { $insert(self, pos as igraph_int_t, value) })
600                    .expect("igraph failed to grow a vector");
601            }
602
603            /// Removes and returns the element at `pos`, shifting the
604            /// following ones to the left, like [`Vec::remove`]
605            /// ([`igraph_vector_remove`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_remove)).
606            ///
607            /// # Panics
608            /// If `pos >= len`.
609            pub fn remove(&mut self, pos: usize) -> $elem {
610                let len = self.size();
611                assert!(pos < len, "removal index {pos} out of bounds (len {len})");
612                let value = self.as_slice()[pos];
613                unsafe { $remove(self, pos as igraph_int_t) };
614                value
615            }
616
617            /// Removes the element at `pos` in O(1) by moving the last
618            /// element into its place, like [`Vec::swap_remove`]
619            /// (`igraph_vector_remove_fast`, undocumented in `igraph_vector.h`).
620            ///
621            /// # Panics
622            /// If `pos >= len`.
623            pub fn swap_remove(&mut self, pos: usize) -> $elem {
624                let len = self.size();
625                assert!(pos < len, "removal index {pos} out of bounds (len {len})");
626                let value = self.as_slice()[pos];
627                unsafe { $remove_fast(self, pos as igraph_int_t) };
628                value
629            }
630
631            /// Removes the elements in `range`
632            /// ([`igraph_vector_remove_section`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_remove_section)).
633            ///
634            /// # Panics
635            /// If the range is decreasing or goes past the end.
636            pub fn remove_section(&mut self, range: std::ops::Range<usize>) {
637                let len = self.size();
638                assert!(
639                    range.start <= range.end && range.end <= len,
640                    "section {range:?} out of bounds (len {len})"
641                );
642                unsafe {
643                    $remove_section(self, range.start as igraph_int_t, range.end as igraph_int_t)
644                };
645            }
646
647            /// Appends a copy of all the elements of `other`
648            /// ([`igraph_vector_append`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_append)).
649            pub fn extend_from_slice(&mut self, other: &[$elem]) {
650                let view = Self::view(other);
651                crate::error::check(unsafe { $append(self, view.as_ptr()) })
652                    .expect("igraph failed to grow a vector");
653            }
654
655            /// Shuffles the elements in place with the Fisher-Yates algorithm,
656            /// drawing from igraph's default random number generator, so the
657            /// outcome is reproducible with [`rng::seed`](crate::rng::seed)
658            /// ([`igraph_vector_shuffle`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_shuffle)).
659            ///
660            /// ```
661            /// use igraph::prelude::*;
662            /// rng::seed(42).unwrap();
663            /// let mut deck: VectorInt = (0..52).collect();
664            /// deck.shuffle();
665            /// let mut again: VectorInt = (0..52).collect();
666            /// rng::seed(42).unwrap();
667            /// again.shuffle();
668            /// assert_eq!(deck, again);
669            /// deck.sort();
670            /// assert_eq!(deck, (0..52).collect::<Vec<i64>>());
671            /// ```
672            pub fn shuffle(&mut self) {
673                crate::error::ensure_init();
674                if !self.stor_begin.is_null() {
675                    unsafe { $shuffle(self) };
676                }
677            }
678
679            /// Permutes the elements in place so that the element at position
680            /// `index[i]` moves to position `i`, with the semantics of
681            /// [`igraph_vector_permute`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_permute).
682            ///
683            /// The index is compatible with the one returned by `sort_ind`:
684            /// permuting by it sorts the vector. If `index` is *shorter* than
685            /// the vector, the elements not mentioned are dropped.
686            ///
687            /// # Errors
688            /// [`ErrorKind::InvalidValue`](crate::error::ErrorKind::InvalidValue)
689            /// if `index` has out-of-range or repeated positions.
690            pub fn permute(&mut self, index: &[igraph_int_t]) -> crate::error::Result<()> {
691                check_permutation(index, self.size())?;
692                // Done in Rust for every type: igraph 1.0.0 and 1.0.1 declare,
693                // but do not export, `igraph_vector_{bool,complex}_permute`.
694                let permuted: Vec<$elem> =
695                    index.iter().map(|&i| self.as_slice()[i as usize]).collect();
696                self.truncate(permuted.len());
697                self.as_mut_slice().copy_from_slice(&permuted);
698                Ok(())
699            }
700
701            /// A new vector with the elements at the given positions, i.e.
702            /// `result[i] = self[index[i]]`; positions may repeat
703            /// ([`igraph_vector_index`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_index)).
704            ///
705            /// # Errors
706            /// [`ErrorKind::InvalidValue`](crate::error::ErrorKind::InvalidValue)
707            /// if some position is out of bounds.
708            pub fn select(&self, index: &[igraph_int_t]) -> crate::error::Result<Self> {
709                check_indices(index, self.size())?;
710                let idx = VectorInt::view(index);
711                let mut res = Self::new();
712                crate::igraph_call!($index(self, &mut res, idx.as_ptr()))?;
713                Ok(res)
714            }
715
716            /// Position of the first occurrence of `value` at or after `from`,
717            /// if any ([`igraph_vector_search`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_search)).
718            pub fn search(&self, from: usize, value: $elem) -> Option<usize> {
719                if from >= self.size() {
720                    return None;
721                }
722                let mut pos = 0;
723                unsafe { $search(self, from as igraph_int_t, value, &mut pos) }
724                    .then_some(pos as usize)
725            }
726
727            /// Number of elements the vector can hold without reallocating
728            /// ([`igraph_vector_capacity`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_capacity)).
729            pub fn capacity(&self) -> usize {
730                if self.stor_begin.is_null() {
731                    0
732                } else {
733                    unsafe { $capacity(self) as usize }
734                }
735            }
736
737            /// Frees the unused storage, so that the capacity equals the
738            /// length ([`igraph_vector_resize_min`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_resize_min)).
739            pub fn shrink_to_fit(&mut self) {
740                if !self.stor_begin.is_null() {
741                    unsafe { $resize_min(self) };
742                }
743            }
744
745            /// Copies the elements in `src` to the position starting at
746            /// `dest`, like [`slice::copy_within`]; the regions may overlap
747            /// (`igraph_vector_move_interval`, undocumented in `igraph_vector.h`).
748            ///
749            /// # Panics
750            /// If either region goes past the end of the vector.
751            pub fn move_interval(&mut self, src: std::ops::Range<usize>, dest: usize) {
752                let len = self.size();
753                assert!(
754                    src.start <= src.end && src.end <= len && dest + (src.end - src.start) <= len,
755                    "interval {src:?} -> {dest} out of bounds (len {len})"
756                );
757                crate::error::check(unsafe {
758                    $move_interval(
759                        self,
760                        src.start as igraph_int_t,
761                        src.end as igraph_int_t,
762                        dest as igraph_int_t,
763                    )
764                })
765                .expect("igraph_vector_move_interval cannot fail");
766            }
767
768            /// A new vector with a copy of the elements in `range`
769            /// (`igraph_vector_get_interval`, undocumented in `igraph_vector.h`).
770            ///
771            /// # Panics
772            /// If the range goes past the end.
773            pub fn get_interval(&self, range: std::ops::Range<usize>) -> Self {
774                let len = self.size();
775                assert!(
776                    range.start <= range.end && range.end <= len,
777                    "interval {range:?} out of bounds (len {len})"
778                );
779                let mut res = Self::new();
780                crate::error::check(unsafe {
781                    $get_interval(
782                        self,
783                        &mut res,
784                        range.start as igraph_int_t,
785                        range.end as igraph_int_t,
786                    )
787                })
788                .expect("igraph failed to allocate a vector");
789                res
790            }
791        }
792    };
793}
794
795impl_vector_common!(
796    igraph_vector_t,
797    igraph_real_t,
798    insert = igraph_vector_insert,
799    remove = igraph_vector_remove,
800    remove_fast = igraph_vector_remove_fast,
801    remove_section = igraph_vector_remove_section,
802    append = igraph_vector_append,
803    shuffle = igraph_vector_shuffle,
804    index = igraph_vector_index,
805    search = igraph_vector_search,
806    capacity = igraph_vector_capacity,
807    resize_min = igraph_vector_resize_min,
808    move_interval = igraph_vector_move_interval,
809    get_interval = igraph_vector_get_interval
810);
811impl_vector_common!(
812    igraph_vector_int_t,
813    igraph_int_t,
814    insert = igraph_vector_int_insert,
815    remove = igraph_vector_int_remove,
816    remove_fast = igraph_vector_int_remove_fast,
817    remove_section = igraph_vector_int_remove_section,
818    append = igraph_vector_int_append,
819    shuffle = igraph_vector_int_shuffle,
820    index = igraph_vector_int_index,
821    search = igraph_vector_int_search,
822    capacity = igraph_vector_int_capacity,
823    resize_min = igraph_vector_int_resize_min,
824    move_interval = igraph_vector_int_move_interval,
825    get_interval = igraph_vector_int_get_interval
826);
827impl_vector_common!(
828    igraph_vector_bool_t,
829    igraph_bool_t,
830    insert = igraph_vector_bool_insert,
831    remove = igraph_vector_bool_remove,
832    remove_fast = igraph_vector_bool_remove_fast,
833    remove_section = igraph_vector_bool_remove_section,
834    append = igraph_vector_bool_append,
835    shuffle = igraph_vector_bool_shuffle,
836    index = igraph_vector_bool_index,
837    search = igraph_vector_bool_search,
838    capacity = igraph_vector_bool_capacity,
839    resize_min = igraph_vector_bool_resize_min,
840    move_interval = igraph_vector_bool_move_interval,
841    get_interval = igraph_vector_bool_get_interval
842);
843impl_vector_common!(
844    igraph_vector_char_t,
845    std::ffi::c_char,
846    insert = igraph_vector_char_insert,
847    remove = igraph_vector_char_remove,
848    remove_fast = igraph_vector_char_remove_fast,
849    remove_section = igraph_vector_char_remove_section,
850    append = igraph_vector_char_append,
851    shuffle = igraph_vector_char_shuffle,
852    index = igraph_vector_char_index,
853    search = igraph_vector_char_search,
854    capacity = igraph_vector_char_capacity,
855    resize_min = igraph_vector_char_resize_min,
856    move_interval = igraph_vector_char_move_interval,
857    get_interval = igraph_vector_char_get_interval
858);
859impl_vector_common!(
860    igraph_vector_complex_t,
861    igraph_complex_t,
862    insert = igraph_vector_complex_insert,
863    remove = igraph_vector_complex_remove,
864    remove_fast = igraph_vector_complex_remove_fast,
865    remove_section = igraph_vector_complex_remove_section,
866    append = igraph_vector_complex_append,
867    shuffle = igraph_vector_complex_shuffle,
868    index = igraph_vector_complex_index,
869    search = igraph_vector_complex_search,
870    capacity = igraph_vector_complex_capacity,
871    resize_min = igraph_vector_complex_resize_min,
872    move_interval = igraph_vector_complex_move_interval,
873    get_interval = igraph_vector_complex_get_interval
874);
875
876// ---------------------------------------------------------------------------
877// Ordered element types: reals, integers, chars.
878// ---------------------------------------------------------------------------
879
880/// Whether `igraph_vector_init_range(start, end)` creates a non-empty real
881/// vector; panics if its length `trunc(end - start)` does not fit an `i64`.
882fn real_range_nonempty(start: f64, end: f64) -> bool {
883    let len = end - start;
884    if len.is_nan() || len < 1.0 {
885        return false;
886    }
887    assert!(
888        len < 9.223_372_036_854_775e18,
889        "capacity overflow: a real range of length {len}"
890    );
891    true
892}
893
894/// Whether `igraph_vector_int_init_range(start, end)` creates a non-empty
895/// vector; panics if `end - start` overflows.
896fn int_range_nonempty(start: igraph_int_t, end: igraph_int_t) -> bool {
897    if end <= start {
898        return false;
899    }
900    assert!(
901        end.checked_sub(start).is_some(),
902        "capacity overflow: the range {start}..{end} is too long"
903    );
904    true
905}
906
907/// Whether `igraph_vector_char_init_range(start, end)` creates a non-empty
908/// vector (C promotes chars to `int`, so there is no overflow).
909fn char_range_nonempty(start: std::ffi::c_char, end: std::ffi::c_char) -> bool {
910    end > start
911}
912
913macro_rules! impl_vector_ordered {
914    (
915        $ty:ident, $elem:ty,
916        init_range = $init_range:ident, range_nonempty = $range_nonempty:ident, sort = $sort:ident, reverse_sort = $reverse_sort:ident,
917        sort_ind = $sort_ind:ident, min = $min:ident, max = $max:ident,
918        which_min = $which_min:ident, which_max = $which_max:ident,
919        binsearch = $binsearch:ident, contains_sorted = $contains_sorted:ident,
920        isininterval = $isininterval:ident, any_smaller = $any_smaller:ident,
921        maxdifference = $maxdifference:ident, lex_cmp = $lex_cmp:ident, colex_cmp = $colex_cmp:ident,
922        all_l = $all_l:ident, all_g = $all_g:ident, all_le = $all_le:ident, all_ge = $all_ge:ident,
923        difference_sorted = $difference_sorted:ident, intersect_sorted = $intersect_sorted:ident,
924        intersection_size_sorted = $intersection_size_sorted:ident,
925        difference_and_intersection_sorted = $dais:ident, filter_smaller = $filter_smaller:ident
926    ) => {
927        impl $ty {
928            /// A vector with the values `start, start + 1, ...`, of length
929            /// `end - start` (rounded towards zero for reals), i.e. the
930            /// values smaller than `end` for integers; empty if `end <= start`
931            /// ([`igraph_vector_init_range`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_init_range)).
932            ///
933            /// # Panics
934            /// If the length does not fit in an `i64` (e.g. an infinite real
935            /// range), like [`Vec::with_capacity`]. A NaN bound gives an
936            /// empty vector.
937            pub fn range(start: $elem, end: $elem) -> Self {
938                // igraph computes the length as `end - start` with a plain C
939                // conversion: overflow (or a NaN / infinite real) would be
940                // undefined behaviour, so the length is validated here.
941                if !$range_nonempty(start, end) {
942                    return Self::new();
943                }
944                crate::error::ensure_init();
945                let mut raw = MaybeUninit::<Self>::uninit();
946                crate::error::check(unsafe { $init_range(raw.as_mut_ptr(), start, end) })
947                    .expect("igraph failed to allocate a vector");
948                unsafe { raw.assume_init() }
949            }
950
951            /// Sorts the elements in ascending order
952            /// ([`igraph_vector_sort`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_sort)).
953            ///
954            /// For real vectors, the position of NaN values after sorting is
955            /// unspecified.
956            pub fn sort(&mut self) {
957                if !self.is_empty() {
958                    unsafe { $sort(self) };
959                }
960            }
961
962            /// Sorts the elements in descending order
963            /// ([`igraph_vector_reverse_sort`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_reverse_sort)).
964            pub fn reverse_sort(&mut self) {
965                if !self.is_empty() {
966                    unsafe { $reverse_sort(self) };
967                }
968            }
969
970            /// The permutation that sorts the vector (an "argsort"): the
971            /// position of the smallest (or largest, with
972            /// [`Order::Descending`](crate::constants::Order::Descending))
973            /// element first, and so on. The sort is stable
974            /// ([`igraph_vector_sort_ind`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_sort_ind)).
975            ///
976            /// Passing the result to `permute` sorts the vector.
977            pub fn sort_ind(&self, order: crate::constants::Order) -> VectorInt {
978                let mut res = VectorInt::new();
979                crate::error::check(unsafe { $sort_ind(self, &mut res, order.into()) })
980                    .expect("igraph failed to allocate a vector");
981                res
982            }
983
984            /// The smallest element, or `None` if the vector is empty
985            /// ([`igraph_vector_min`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_min)).
986            /// For real vectors containing NaN, the result is NaN.
987            pub fn min(&self) -> Option<$elem> {
988                (!self.is_empty()).then(|| unsafe { $min(self) })
989            }
990
991            /// The largest element, or `None` if the vector is empty
992            /// ([`igraph_vector_max`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_max)).
993            /// For real vectors containing NaN, the result is NaN.
994            pub fn max(&self) -> Option<$elem> {
995                (!self.is_empty()).then(|| unsafe { $max(self) })
996            }
997
998            /// Position of the (first) smallest element, or `None` if empty
999            /// ([`igraph_vector_which_min`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_which_min)).
1000            pub fn which_min(&self) -> Option<usize> {
1001                (!self.is_empty()).then(|| unsafe { $which_min(self) } as usize)
1002            }
1003
1004            /// Position of the (first) largest element, or `None` if empty
1005            /// ([`igraph_vector_which_max`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_which_max)).
1006            pub fn which_max(&self) -> Option<usize> {
1007                (!self.is_empty()).then(|| unsafe { $which_max(self) } as usize)
1008            }
1009
1010            /// `(min, max)` in one pass, or `None` if empty
1011            /// (same as `igraph_vector_minmax`).
1012            pub fn minmax(&self) -> Option<($elem, $elem)> {
1013                Some((self.min()?, self.max()?))
1014            }
1015
1016            /// `(which_min, which_max)`, or `None` if empty
1017            /// (same as `igraph_vector_which_minmax`).
1018            pub fn which_minmax(&self) -> Option<(usize, usize)> {
1019                Some((self.which_min()?, self.which_max()?))
1020            }
1021
1022            /// Binary search in a **sorted** vector: `Ok(pos)` with the
1023            /// position of an element equal to `value`, or `Err(pos)` with the
1024            /// position where it could be inserted keeping the order, like
1025            /// [`slice::binary_search`]
1026            /// ([`igraph_vector_binsearch`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_binsearch)).
1027            pub fn binsearch(&self, value: $elem) -> std::result::Result<usize, usize> {
1028                if self.is_empty() {
1029                    return Err(0);
1030                }
1031                let mut pos = 0;
1032                if unsafe { $binsearch(self, value, &mut pos) } {
1033                    Ok(pos as usize)
1034                } else {
1035                    Err(pos as usize)
1036                }
1037            }
1038
1039            /// Whether a **sorted** vector contains `value`, in O(log n)
1040            /// ([`igraph_vector_contains_sorted`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_contains_sorted)).
1041            pub fn contains_sorted(&self, value: $elem) -> bool {
1042                !self.is_empty() && unsafe { $contains_sorted(self, value) }
1043            }
1044
1045            /// Whether all elements lie in the closed interval `[low, high]`
1046            /// (true for an empty vector, false if any element is NaN)
1047            /// ([`igraph_vector_isininterval`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_isininterval)).
1048            pub fn is_in_interval(&self, low: $elem, high: $elem) -> bool {
1049                self.is_empty() || unsafe { $isininterval(self, low, high) }
1050            }
1051
1052            /// Whether some element is strictly smaller than `limit`
1053            /// (`igraph_vector_any_smaller`, undocumented in `igraph_vector.h`).
1054            pub fn any_smaller(&self, limit: $elem) -> bool {
1055                !self.is_empty() && unsafe { $any_smaller(self, limit) }
1056            }
1057
1058            /// The largest absolute difference between corresponding
1059            /// elements; the extra elements of the longer vector are ignored
1060            /// ([`igraph_vector_maxdifference`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_maxdifference)).
1061            pub fn maxdifference(&self, other: &[$elem]) -> f64 {
1062                if self.is_empty() || other.is_empty() {
1063                    return 0.0;
1064                }
1065                let o = Self::view(other);
1066                unsafe { $maxdifference(self, o.as_ptr()) }
1067            }
1068
1069            /// Lexicographic comparison: the first differing element decides,
1070            /// and a proper prefix comes first
1071            /// ([`igraph_vector_lex_cmp`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_lex_cmp)).
1072            pub fn lex_cmp(&self, other: &[$elem]) -> std::cmp::Ordering {
1073                let o = Self::view(other);
1074                unsafe { $lex_cmp(self, o.as_ptr()) }.cmp(&0)
1075            }
1076
1077            /// Colexicographic comparison: like [`lex_cmp`](Self::lex_cmp)
1078            /// but starting from the *last* elements
1079            /// ([`igraph_vector_colex_cmp`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_colex_cmp)).
1080            pub fn colex_cmp(&self, other: &[$elem]) -> std::cmp::Ordering {
1081                let o = Self::view(other);
1082                unsafe { $colex_cmp(self, o.as_ptr()) }.cmp(&0)
1083            }
1084
1085            /// Whether each element is `<` the corresponding one in `other`
1086            /// (false if the lengths differ or NaN is involved)
1087            /// ([`igraph_vector_all_l`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_all_l)).
1088            pub fn all_l(&self, other: &[$elem]) -> bool {
1089                self.elementwise(other, |a, b| unsafe { $all_l(a, b) })
1090            }
1091
1092            /// Whether each element is `>` the corresponding one in `other`
1093            /// ([`igraph_vector_all_g`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_all_g)).
1094            pub fn all_g(&self, other: &[$elem]) -> bool {
1095                self.elementwise(other, |a, b| unsafe { $all_g(a, b) })
1096            }
1097
1098            /// Whether each element is `<=` the corresponding one in `other`
1099            /// ([`igraph_vector_all_le`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_all_le)).
1100            pub fn all_le(&self, other: &[$elem]) -> bool {
1101                self.elementwise(other, |a, b| unsafe { $all_le(a, b) })
1102            }
1103
1104            /// Whether each element is `>=` the corresponding one in `other`
1105            /// ([`igraph_vector_all_ge`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_all_ge)).
1106            pub fn all_ge(&self, other: &[$elem]) -> bool {
1107                self.elementwise(other, |a, b| unsafe { $all_ge(a, b) })
1108            }
1109
1110            fn elementwise(
1111                &self,
1112                other: &[$elem],
1113                f: impl FnOnce(*const Self, *const Self) -> bool,
1114            ) -> bool {
1115                if self.size() != other.len() {
1116                    return false;
1117                }
1118                if other.is_empty() {
1119                    return true;
1120                }
1121                let o = Self::view(other);
1122                f(self, o.as_ptr())
1123            }
1124
1125            /// The elements of this **sorted** vector that are not in the
1126            /// **sorted** `other` (a multiset difference)
1127            /// ([`igraph_vector_difference_sorted`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_difference_sorted)).
1128            pub fn difference_sorted(&self, other: &[$elem]) -> Self {
1129                let o = Self::view(other);
1130                let mut res = Self::new();
1131                crate::error::check(unsafe { $difference_sorted(self, o.as_ptr(), &mut res) })
1132                    .expect("igraph failed to allocate a vector");
1133                res
1134            }
1135
1136            /// The common elements of this **sorted** vector and the
1137            /// **sorted** `other` (a multiset intersection)
1138            /// ([`igraph_vector_intersect_sorted`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_intersect_sorted)).
1139            pub fn intersect_sorted(&self, other: &[$elem]) -> Self {
1140                let o = Self::view(other);
1141                let mut res = Self::new();
1142                crate::error::check(unsafe { $intersect_sorted(self, o.as_ptr(), &mut res) })
1143                    .expect("igraph failed to allocate a vector");
1144                res
1145            }
1146
1147            /// Size of the intersection of two **sorted** vectors, without
1148            /// building it
1149            /// ([`igraph_vector_intersection_size_sorted`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_intersection_size_sorted)).
1150            pub fn intersection_size_sorted(&self, other: &[$elem]) -> usize {
1151                let o = Self::view(other);
1152                unsafe { $intersection_size_sorted(self, o.as_ptr()) as usize }
1153            }
1154
1155            /// `(self \ other, other \ self, self ∩ other)` for two **sorted**
1156            /// vectors, in a single pass
1157            /// ([`igraph_vector_difference_and_intersection_sorted`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_difference_and_intersection_sorted)).
1158            pub fn difference_and_intersection_sorted(
1159                &self,
1160                other: &[$elem],
1161            ) -> (Self, Self, Self) {
1162                let o = Self::view(other);
1163                let (mut d12, mut d21, mut inter) = (Self::new(), Self::new(), Self::new());
1164                crate::error::check(unsafe {
1165                    $dais(self, o.as_ptr(), &mut d12, &mut d21, &mut inter)
1166                })
1167                .expect("igraph failed to allocate a vector");
1168                (d12, d21, inter)
1169            }
1170
1171            /// On a **sorted** vector: removes the elements smaller than
1172            /// `elem`, and the first half of the elements equal to it
1173            /// (`igraph_vector_filter_smaller`, used by igraph to compute
1174            /// medians and similar statistics).
1175            pub fn filter_smaller(&mut self, elem: $elem) {
1176                if !self.is_empty() {
1177                    crate::error::check(unsafe { $filter_smaller(self, elem) })
1178                        .expect("igraph_vector_filter_smaller cannot fail");
1179                }
1180            }
1181        }
1182    };
1183}
1184
1185impl_vector_ordered!(
1186    igraph_vector_t,
1187    igraph_real_t,
1188    init_range = igraph_vector_init_range,
1189    range_nonempty = real_range_nonempty,
1190    sort = igraph_vector_sort,
1191    reverse_sort = igraph_vector_reverse_sort,
1192    sort_ind = igraph_vector_sort_ind,
1193    min = igraph_vector_min,
1194    max = igraph_vector_max,
1195    which_min = igraph_vector_which_min,
1196    which_max = igraph_vector_which_max,
1197    binsearch = igraph_vector_binsearch,
1198    contains_sorted = igraph_vector_contains_sorted,
1199    isininterval = igraph_vector_isininterval,
1200    any_smaller = igraph_vector_any_smaller,
1201    maxdifference = igraph_vector_maxdifference,
1202    lex_cmp = igraph_vector_lex_cmp,
1203    colex_cmp = igraph_vector_colex_cmp,
1204    all_l = igraph_vector_all_l,
1205    all_g = igraph_vector_all_g,
1206    all_le = igraph_vector_all_le,
1207    all_ge = igraph_vector_all_ge,
1208    difference_sorted = igraph_vector_difference_sorted,
1209    intersect_sorted = igraph_vector_intersect_sorted,
1210    intersection_size_sorted = igraph_vector_intersection_size_sorted,
1211    difference_and_intersection_sorted = igraph_vector_difference_and_intersection_sorted,
1212    filter_smaller = igraph_vector_filter_smaller
1213);
1214impl_vector_ordered!(
1215    igraph_vector_int_t,
1216    igraph_int_t,
1217    init_range = igraph_vector_int_init_range,
1218    range_nonempty = int_range_nonempty,
1219    sort = igraph_vector_int_sort,
1220    reverse_sort = igraph_vector_int_reverse_sort,
1221    sort_ind = igraph_vector_int_sort_ind,
1222    min = igraph_vector_int_min,
1223    max = igraph_vector_int_max,
1224    which_min = igraph_vector_int_which_min,
1225    which_max = igraph_vector_int_which_max,
1226    binsearch = igraph_vector_int_binsearch,
1227    contains_sorted = igraph_vector_int_contains_sorted,
1228    isininterval = igraph_vector_int_isininterval,
1229    any_smaller = igraph_vector_int_any_smaller,
1230    maxdifference = igraph_vector_int_maxdifference,
1231    lex_cmp = igraph_vector_int_lex_cmp,
1232    colex_cmp = igraph_vector_int_colex_cmp,
1233    all_l = igraph_vector_int_all_l,
1234    all_g = igraph_vector_int_all_g,
1235    all_le = igraph_vector_int_all_le,
1236    all_ge = igraph_vector_int_all_ge,
1237    difference_sorted = igraph_vector_int_difference_sorted,
1238    intersect_sorted = igraph_vector_int_intersect_sorted,
1239    intersection_size_sorted = igraph_vector_int_intersection_size_sorted,
1240    difference_and_intersection_sorted = igraph_vector_int_difference_and_intersection_sorted,
1241    filter_smaller = igraph_vector_int_filter_smaller
1242);
1243impl_vector_ordered!(
1244    igraph_vector_char_t,
1245    std::ffi::c_char,
1246    init_range = igraph_vector_char_init_range,
1247    range_nonempty = char_range_nonempty,
1248    sort = igraph_vector_char_sort,
1249    reverse_sort = igraph_vector_char_reverse_sort,
1250    sort_ind = igraph_vector_char_sort_ind,
1251    min = igraph_vector_char_min,
1252    max = igraph_vector_char_max,
1253    which_min = igraph_vector_char_which_min,
1254    which_max = igraph_vector_char_which_max,
1255    binsearch = igraph_vector_char_binsearch,
1256    contains_sorted = igraph_vector_char_contains_sorted,
1257    isininterval = igraph_vector_char_isininterval,
1258    any_smaller = igraph_vector_char_any_smaller,
1259    maxdifference = igraph_vector_char_maxdifference,
1260    lex_cmp = igraph_vector_char_lex_cmp,
1261    colex_cmp = igraph_vector_char_colex_cmp,
1262    all_l = igraph_vector_char_all_l,
1263    all_g = igraph_vector_char_all_g,
1264    all_le = igraph_vector_char_all_le,
1265    all_ge = igraph_vector_char_all_ge,
1266    difference_sorted = igraph_vector_char_difference_sorted,
1267    intersect_sorted = igraph_vector_char_intersect_sorted,
1268    intersection_size_sorted = igraph_vector_char_intersection_size_sorted,
1269    difference_and_intersection_sorted = igraph_vector_char_difference_and_intersection_sorted,
1270    filter_smaller = igraph_vector_char_filter_smaller
1271);
1272
1273// ---------------------------------------------------------------------------
1274// Arithmetic. Floating point (real and complex) vectors use igraph's own
1275// functions; integer vectors are handled in Rust with *wrapping* arithmetic,
1276// because signed overflow in the C implementation would be undefined
1277// behaviour.
1278// ---------------------------------------------------------------------------
1279
1280macro_rules! impl_vector_float_arith {
1281    (
1282        $ty:ident, $elem:ty, $name:literal,
1283        sum = $sum:ident, prod = $prod:ident, cumsum = $cumsum:ident,
1284        add_constant = $add_constant:ident, scale = $scale:ident,
1285        add = $add:ident, sub = $sub:ident, mul = $mul:ident, div = $div:ident,
1286        all_almost_e = $all_almost_e:ident, zapsmall = $zapsmall:ident
1287    ) => {
1288        impl $ty {
1289            #[doc = concat!("Sum of the elements (", $name, "; zero for an empty vector), see ")]
1290            /// [`igraph_vector_sum`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_sum).
1291            pub fn sum(&self) -> $elem {
1292                if self.is_empty() {
1293                    return Default::default();
1294                }
1295                unsafe { $sum(self) }
1296            }
1297
1298            #[doc = concat!("Product of the elements (", $name, "; one for an empty vector), see ")]
1299            /// [`igraph_vector_prod`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_prod).
1300            pub fn prod(&self) -> $elem {
1301                if self.is_empty() {
1302                    return <$elem>::from(1.0);
1303                }
1304                unsafe { $prod(self) }
1305            }
1306
1307            /// The cumulative sums `[x0, x0 + x1, x0 + x1 + x2, ...]`
1308            /// (`igraph_vector_cumsum`, undocumented in `igraph_vector.h`).
1309            pub fn cumsum(&self) -> Self {
1310                if self.is_empty() {
1311                    return Self::new();
1312                }
1313                let mut res = Self::new();
1314                crate::error::check(unsafe { $cumsum(&mut res, self) })
1315                    .expect("igraph failed to allocate a vector");
1316                res
1317            }
1318
1319            /// Adds `value` to every element
1320            /// ([`igraph_vector_add_constant`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_add_constant)).
1321            pub fn add_constant(&mut self, value: $elem) {
1322                if !self.is_empty() {
1323                    unsafe { $add_constant(self, value) };
1324                }
1325            }
1326
1327            /// Multiplies every element by `factor`
1328            /// ([`igraph_vector_scale`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_scale)).
1329            pub fn scale(&mut self, factor: $elem) {
1330                if !self.is_empty() {
1331                    unsafe { $scale(self, factor) };
1332                }
1333            }
1334
1335            /// Element-wise `self[i] += other[i]`
1336            /// ([`igraph_vector_add`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_add)).
1337            ///
1338            /// # Errors
1339            /// [`ErrorKind::InvalidValue`](crate::error::ErrorKind::InvalidValue) if the lengths differ.
1340            pub fn add(&mut self, other: &[$elem]) -> crate::error::Result<()> {
1341                self.binary_op(other, |a, b| unsafe { $add(a, b) })
1342            }
1343
1344            /// Element-wise `self[i] -= other[i]`
1345            /// ([`igraph_vector_sub`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_sub)).
1346            ///
1347            /// # Errors
1348            /// [`ErrorKind::InvalidValue`](crate::error::ErrorKind::InvalidValue) if the lengths differ.
1349            pub fn sub(&mut self, other: &[$elem]) -> crate::error::Result<()> {
1350                self.binary_op(other, |a, b| unsafe { $sub(a, b) })
1351            }
1352
1353            /// Element-wise `self[i] *= other[i]`
1354            /// ([`igraph_vector_mul`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_mul)).
1355            ///
1356            /// # Errors
1357            /// [`ErrorKind::InvalidValue`](crate::error::ErrorKind::InvalidValue) if the lengths differ.
1358            pub fn mul(&mut self, other: &[$elem]) -> crate::error::Result<()> {
1359                self.binary_op(other, |a, b| unsafe { $mul(a, b) })
1360            }
1361
1362            /// Element-wise `self[i] /= other[i]` (IEEE semantics for
1363            /// division by zero)
1364            /// ([`igraph_vector_div`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_div)).
1365            ///
1366            /// # Errors
1367            /// [`ErrorKind::InvalidValue`](crate::error::ErrorKind::InvalidValue) if the lengths differ.
1368            pub fn div(&mut self, other: &[$elem]) -> crate::error::Result<()> {
1369                self.binary_op(other, |a, b| unsafe { $div(a, b) })
1370            }
1371
1372            fn binary_op(
1373                &mut self,
1374                other: &[$elem],
1375                f: impl FnOnce(*mut Self, *const Self) -> igraph_error_t,
1376            ) -> crate::error::Result<()> {
1377                if self.size() != other.len() {
1378                    return Err(crate::error::Error::invalid(format!(
1379                        "vectors of different lengths ({} and {})",
1380                        self.size(),
1381                        other.len()
1382                    )));
1383                }
1384                if other.is_empty() {
1385                    return Ok(());
1386                }
1387                let o = Self::view(other);
1388                crate::igraph_call!(f(self, o.as_ptr()))
1389            }
1390
1391            /// Whether both vectors have the same length and all their
1392            /// elements are equal up to a relative tolerance `eps`
1393            /// ([`igraph_vector_all_almost_e`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_all_almost_e)).
1394            pub fn all_almost_e(&self, other: &[$elem], eps: f64) -> bool {
1395                if self.size() != other.len() {
1396                    return false;
1397                }
1398                if other.is_empty() {
1399                    return true;
1400                }
1401                let o = Self::view(other);
1402                unsafe { $all_almost_e(self, o.as_ptr(), eps) }
1403            }
1404
1405            /// Replaces the elements smaller in magnitude than the *absolute*
1406            /// tolerance `tol` by exact zeros; `tol = 0` picks igraph's default,
1407            /// `f64::EPSILON^(2/3)` (about `1e-10`). For complex vectors the
1408            /// real and imaginary parts are processed separately
1409            /// ([`igraph_vector_zapsmall`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_zapsmall)).
1410            ///
1411            /// ```
1412            /// use igraph::prelude::*;
1413            /// let mut v = Vector::from([1.0, 1e-12, -3e-11, 0.5]);
1414            /// v.zapsmall(0.0).unwrap();
1415            /// assert_eq!(v, vec![1.0, 0.0, 0.0, 0.5]);
1416            /// ```
1417            ///
1418            /// # Errors
1419            /// [`ErrorKind::InvalidValue`](crate::error::ErrorKind::InvalidValue) if `tol < 0`.
1420            pub fn zapsmall(&mut self, tol: f64) -> crate::error::Result<()> {
1421                if self.is_empty() {
1422                    return if tol < 0.0 {
1423                        Err(crate::error::Error::invalid("negative tolerance"))
1424                    } else {
1425                        Ok(())
1426                    };
1427                }
1428                crate::igraph_call!($zapsmall(self, tol))
1429            }
1430        }
1431    };
1432}
1433
1434impl From<f64> for igraph_complex_t {
1435    /// A complex number with zero imaginary part.
1436    fn from(re: f64) -> Self {
1437        Self::new(re, 0.0)
1438    }
1439}
1440
1441impl Default for igraph_complex_t {
1442    fn default() -> Self {
1443        Self::new(0.0, 0.0)
1444    }
1445}
1446
1447impl_vector_float_arith!(
1448    igraph_vector_t,
1449    igraph_real_t,
1450    "reals",
1451    sum = igraph_vector_sum,
1452    prod = igraph_vector_prod,
1453    cumsum = igraph_vector_cumsum,
1454    add_constant = igraph_vector_add_constant,
1455    scale = igraph_vector_scale,
1456    add = igraph_vector_add,
1457    sub = igraph_vector_sub,
1458    mul = igraph_vector_mul,
1459    div = igraph_vector_div,
1460    all_almost_e = igraph_vector_all_almost_e,
1461    zapsmall = igraph_vector_zapsmall
1462);
1463impl_vector_float_arith!(
1464    igraph_vector_complex_t,
1465    igraph_complex_t,
1466    "complex numbers",
1467    sum = igraph_vector_complex_sum,
1468    prod = igraph_vector_complex_prod,
1469    cumsum = igraph_vector_complex_cumsum,
1470    add_constant = igraph_vector_complex_add_constant,
1471    scale = igraph_vector_complex_scale,
1472    add = igraph_vector_complex_add,
1473    sub = igraph_vector_complex_sub,
1474    mul = igraph_vector_complex_mul,
1475    div = igraph_vector_complex_div,
1476    all_almost_e = igraph_vector_complex_all_almost_e,
1477    zapsmall = igraph_vector_complex_zapsmall
1478);
1479
1480impl igraph_vector_int_t {
1481    /// Sum of the elements, wrapping around on overflow (the Rust
1482    /// counterpart of `igraph_vector_int_sum`).
1483    pub fn sum(&self) -> igraph_int_t {
1484        self.iter().fold(0, |a, &b| a.wrapping_add(b))
1485    }
1486
1487    /// Product of the elements (one for an empty vector), wrapping around
1488    /// on overflow (the Rust counterpart of `igraph_vector_int_prod`).
1489    pub fn prod(&self) -> igraph_int_t {
1490        self.iter().fold(1, |a, &b| a.wrapping_mul(b))
1491    }
1492
1493    /// The cumulative sums, wrapping around on overflow (the Rust
1494    /// counterpart of `igraph_vector_int_cumsum`).
1495    pub fn cumsum(&self) -> Self {
1496        let mut acc: igraph_int_t = 0;
1497        self.iter()
1498            .map(|&x| {
1499                acc = acc.wrapping_add(x);
1500                acc
1501            })
1502            .collect()
1503    }
1504
1505    /// Adds `value` to every element, wrapping around on overflow (the Rust
1506    /// counterpart of `igraph_vector_int_add_constant`).
1507    pub fn add_constant(&mut self, value: igraph_int_t) {
1508        self.iter_mut().for_each(|x| *x = x.wrapping_add(value));
1509    }
1510
1511    /// Multiplies every element by `factor`, wrapping around on overflow
1512    /// (the Rust counterpart of `igraph_vector_int_scale`).
1513    pub fn scale(&mut self, factor: igraph_int_t) {
1514        self.iter_mut().for_each(|x| *x = x.wrapping_mul(factor));
1515    }
1516
1517    fn zip_op(
1518        &mut self,
1519        other: &[igraph_int_t],
1520        f: impl Fn(igraph_int_t, igraph_int_t) -> igraph_int_t,
1521    ) -> crate::error::Result<()> {
1522        if self.size() != other.len() {
1523            return Err(crate::error::Error::invalid(format!(
1524                "vectors of different lengths ({} and {})",
1525                self.size(),
1526                other.len()
1527            )));
1528        }
1529        self.iter_mut().zip(other).for_each(|(a, &b)| *a = f(*a, b));
1530        Ok(())
1531    }
1532
1533    /// Element-wise `self[i] += other[i]`, wrapping around on overflow (the
1534    /// Rust counterpart of `igraph_vector_int_add`).
1535    ///
1536    /// # Errors
1537    /// [`ErrorKind::InvalidValue`](crate::error::ErrorKind::InvalidValue) if the lengths differ.
1538    pub fn add(&mut self, other: &[igraph_int_t]) -> crate::error::Result<()> {
1539        self.zip_op(other, igraph_int_t::wrapping_add)
1540    }
1541
1542    /// Element-wise `self[i] -= other[i]`, wrapping around on overflow (the
1543    /// Rust counterpart of `igraph_vector_int_sub`).
1544    ///
1545    /// # Errors
1546    /// [`ErrorKind::InvalidValue`](crate::error::ErrorKind::InvalidValue) if the lengths differ.
1547    pub fn sub(&mut self, other: &[igraph_int_t]) -> crate::error::Result<()> {
1548        self.zip_op(other, igraph_int_t::wrapping_sub)
1549    }
1550
1551    /// Element-wise `self[i] *= other[i]`, wrapping around on overflow (the
1552    /// Rust counterpart of `igraph_vector_int_mul`).
1553    ///
1554    /// # Errors
1555    /// [`ErrorKind::InvalidValue`](crate::error::ErrorKind::InvalidValue) if the lengths differ.
1556    pub fn mul(&mut self, other: &[igraph_int_t]) -> crate::error::Result<()> {
1557        self.zip_op(other, igraph_int_t::wrapping_mul)
1558    }
1559
1560    /// Element-wise integer division `self[i] /= other[i]`, rounding
1561    /// towards zero (the Rust counterpart of `igraph_vector_int_div`).
1562    ///
1563    /// # Errors
1564    /// [`ErrorKind::InvalidValue`](crate::error::ErrorKind::InvalidValue) if the lengths differ
1565    /// or some divisor is zero (nothing is modified then).
1566    pub fn div(&mut self, other: &[igraph_int_t]) -> crate::error::Result<()> {
1567        if other.contains(&0) {
1568            return Err(crate::error::Error::invalid("integer division by zero"));
1569        }
1570        self.zip_op(other, igraph_int_t::wrapping_div)
1571    }
1572
1573    /// Replaces every element by its absolute value (wrapping for
1574    /// `i64::MIN`; the Rust counterpart of `igraph_vector_int_abs`).
1575    pub fn abs(&mut self) {
1576        self.iter_mut().for_each(|x| *x = x.wrapping_abs());
1577    }
1578
1579    /// The order of the pairs `(self[i], second[i])`, sorted
1580    /// lexicographically with a two-pass radix sort in O(n + maxval); all
1581    /// values must be in `0..=maxval`, i.e. `maxval` is (an upper bound of)
1582    /// the largest value, and it also sets the size of the radix buckets
1583    /// (`igraph_vector_int_pair_order`, undocumented in `igraph_vector.h`).
1584    ///
1585    /// ```
1586    /// use igraph::prelude::*;
1587    /// let first = VectorInt::from([1, 0, 1, 0]);
1588    /// let order = first.pair_order(&[1, 1, 0, 0], 2).unwrap();
1589    /// // (0,0) at 3, (0,1) at 1, (1,0) at 2, (1,1) at 0
1590    /// assert_eq!(order, vec![3, 1, 2, 0]);
1591    /// ```
1592    ///
1593    /// # Errors
1594    /// [`ErrorKind::InvalidValue`](crate::error::ErrorKind::InvalidValue) if the lengths differ,
1595    /// `maxval` is negative or `i64::MAX`, or some value is outside `0..=maxval`.
1596    pub fn pair_order(
1597        &self,
1598        second: &[igraph_int_t],
1599        maxval: igraph_int_t,
1600    ) -> crate::error::Result<Self> {
1601        if self.size() != second.len() {
1602            return Err(crate::error::Error::invalid("vectors of different lengths"));
1603        }
1604        // igraph allocates `maxval + 1` buckets and indexes them without checks.
1605        if !(0..igraph_int_t::MAX).contains(&maxval) {
1606            return Err(crate::error::Error::invalid(format!(
1607                "invalid maximum value {maxval}"
1608            )));
1609        }
1610        if self.iter().chain(second).any(|&x| x < 0 || x > maxval) {
1611            return Err(crate::error::Error::invalid(format!(
1612                "values must be in 0..={maxval}"
1613            )));
1614        }
1615        if self.is_empty() {
1616            return Ok(Self::new());
1617        }
1618        let s = Self::view(second);
1619        let mut res = Self::new();
1620        crate::igraph_call!(igraph_vector_int_pair_order(
1621            self,
1622            s.as_ptr(),
1623            &mut res,
1624            maxval
1625        ))?;
1626        Ok(res)
1627    }
1628}
1629
1630impl igraph_vector_t {
1631    /// Replaces every element by its absolute value
1632    /// (`igraph_vector_abs`, undocumented in `igraph_vector.h`).
1633    pub fn abs(&mut self) {
1634        if !self.is_empty() {
1635            crate::error::check(unsafe { igraph_vector_abs(self) })
1636                .expect("igraph_vector_abs cannot fail");
1637        }
1638    }
1639
1640    // igraph converts with a plain C cast, which is undefined behaviour for
1641    // NaN, infinities and out-of-range values: reject them up front.
1642    fn check_integral_range(&self) -> crate::error::Result<()> {
1643        const LIMIT: f64 = 9.223_372_036_854_775e18; // 2^63
1644        match self.iter().find(|x| x.is_nan() || x.abs() >= LIMIT) {
1645            Some(x) => Err(crate::error::Error::new(
1646                crate::error::ErrorKind::Overflow,
1647                format!("{x} cannot be converted to an integer"),
1648            )),
1649            None => Ok(()),
1650        }
1651    }
1652
1653    /// The elements rounded down to integers
1654    /// ([`igraph_vector_floor`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_floor)).
1655    ///
1656    /// # Errors
1657    /// [`ErrorKind::Overflow`](crate::error::ErrorKind::Overflow) if some
1658    /// element is NaN, infinite or does not fit in an `i64`.
1659    pub fn floor(&self) -> crate::error::Result<VectorInt> {
1660        self.check_integral_range()?;
1661        let mut res = VectorInt::new();
1662        crate::igraph_call!(igraph_vector_floor(self, &mut res))?;
1663        Ok(res)
1664    }
1665
1666    /// The elements rounded to the nearest integers (halves away from zero)
1667    /// (`igraph_vector_round`, undocumented in `igraph_vector.h`).
1668    ///
1669    /// # Errors
1670    /// [`ErrorKind::Overflow`](crate::error::ErrorKind::Overflow) if some
1671    /// element is NaN, infinite or does not fit in an `i64`.
1672    pub fn round(&self) -> crate::error::Result<VectorInt> {
1673        self.check_integral_range()?;
1674        let mut res = VectorInt::new();
1675        crate::igraph_call!(igraph_vector_round(self, &mut res))?;
1676        Ok(res)
1677    }
1678
1679    /// Which elements are NaN
1680    /// ([`igraph_vector_is_nan`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_is_nan)).
1681    pub fn is_nan(&self) -> VectorBool {
1682        let mut res = VectorBool::new();
1683        crate::error::check(unsafe { igraph_vector_is_nan(self, &mut res) })
1684            .expect("igraph failed to allocate a vector");
1685        res
1686    }
1687
1688    /// Whether some element is NaN
1689    /// ([`igraph_vector_is_any_nan`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_is_any_nan)).
1690    pub fn is_any_nan(&self) -> bool {
1691        !self.is_empty() && unsafe { igraph_vector_is_any_nan(self) }
1692    }
1693
1694    /// Whether all elements are finite, i.e. neither infinite nor NaN
1695    /// ([`igraph_vector_is_all_finite`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_is_all_finite)).
1696    pub fn is_all_finite(&self) -> bool {
1697        self.is_empty() || unsafe { igraph_vector_is_all_finite(self) }
1698    }
1699}
1700
1701impl igraph_vector_char_t {
1702    /// Replaces every element by its absolute value (wrapping for the
1703    /// minimum value; the Rust counterpart of `igraph_vector_char_abs`).
1704    pub fn abs(&mut self) {
1705        self.iter_mut().for_each(|x| *x = x.wrapping_abs());
1706    }
1707}
1708
1709impl igraph_vector_complex_t {
1710    /// Builds a complex vector from the real and imaginary parts
1711    /// ([`igraph_vector_complex_create`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_complex_create)).
1712    ///
1713    /// # Errors
1714    /// [`ErrorKind::InvalidValue`](crate::error::ErrorKind::InvalidValue) if the lengths differ.
1715    pub fn from_parts(re: &[f64], im: &[f64]) -> crate::error::Result<Self> {
1716        if re.len() != im.len() {
1717            return Err(crate::error::Error::invalid(
1718                "real and imaginary parts of different lengths",
1719            ));
1720        }
1721        let (r, i) = (Vector::view(re), Vector::view(im));
1722        // `igraph_vector_complex_create` *initializes* its output: passing an
1723        // already initialized vector would leak its buffer.
1724        let mut res = MaybeUninit::<Self>::uninit();
1725        crate::igraph_call!(igraph_vector_complex_create(
1726            res.as_mut_ptr(),
1727            r.as_ptr(),
1728            i.as_ptr()
1729        ))?;
1730        Ok(unsafe { res.assume_init() })
1731    }
1732
1733    /// Builds a complex vector from moduli `r` and arguments `theta`
1734    /// (in radians) ([`igraph_vector_complex_create_polar`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_complex_create_polar)).
1735    ///
1736    /// # Errors
1737    /// [`ErrorKind::InvalidValue`](crate::error::ErrorKind::InvalidValue) if the lengths differ.
1738    pub fn from_polar(r: &[f64], theta: &[f64]) -> crate::error::Result<Self> {
1739        if r.len() != theta.len() {
1740            return Err(crate::error::Error::invalid(
1741                "moduli and arguments of different lengths",
1742            ));
1743        }
1744        let (a, b) = (Vector::view(r), Vector::view(theta));
1745        // The output is initialized by igraph (see `from_parts`).
1746        let mut res = MaybeUninit::<Self>::uninit();
1747        crate::igraph_call!(igraph_vector_complex_create_polar(
1748            res.as_mut_ptr(),
1749            a.as_ptr(),
1750            b.as_ptr()
1751        ))?;
1752        Ok(unsafe { res.assume_init() })
1753    }
1754
1755    /// The real parts ([`igraph_vector_complex_real`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_complex_real)).
1756    pub fn real(&self) -> Vector {
1757        let mut res = Vector::new();
1758        crate::error::check(unsafe { igraph_vector_complex_real(self, &mut res) })
1759            .expect("igraph failed to allocate a vector");
1760        res
1761    }
1762
1763    /// The imaginary parts ([`igraph_vector_complex_imag`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_complex_imag)).
1764    pub fn imag(&self) -> Vector {
1765        let mut res = Vector::new();
1766        crate::error::check(unsafe { igraph_vector_complex_imag(self, &mut res) })
1767            .expect("igraph failed to allocate a vector");
1768        res
1769    }
1770
1771    /// `(real parts, imaginary parts)` in one call
1772    /// ([`igraph_vector_complex_realimag`](https://igraph.org/c/html/latest/igraph-Data-structures.html#igraph_vector_complex_realimag)).
1773    pub fn realimag(&self) -> (Vector, Vector) {
1774        let (mut re, mut im) = (Vector::new(), Vector::new());
1775        crate::error::check(unsafe { igraph_vector_complex_realimag(self, &mut re, &mut im) })
1776            .expect("igraph failed to allocate a vector");
1777        (re, im)
1778    }
1779}
1780
1781impl fmt::Display for igraph_vector_complex_t {
1782    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1783        write!(f, "[")?;
1784        for (i, z) in self.iter().enumerate() {
1785            if i > 0 {
1786                write!(f, ", ")?;
1787            }
1788            write!(f, "{z}")?;
1789        }
1790        write!(f, "]")
1791    }
1792}
1793
1794// ---------------------------------------------------------------------------
1795// Complex numbers (`igraph_complex.h`).
1796// ---------------------------------------------------------------------------
1797
1798macro_rules! complex_unary {
1799    ($($(#[$meta:meta])* $name:ident => $c:ident),* $(,)?) => {
1800        impl igraph_complex_t {
1801            $(
1802                $(#[$meta])*
1803                pub fn $name(self) -> Self {
1804                    unsafe { $c(self) }
1805                }
1806            )*
1807        }
1808    };
1809}
1810
1811complex_unary! {
1812    /// The complex conjugate (`igraph_complex_conj`, undocumented in `igraph_complex.h`).
1813    conj => igraph_complex_conj,
1814    /// The multiplicative inverse `1 / z` (`igraph_complex_inv`, undocumented in `igraph_complex.h`).
1815    inv => igraph_complex_inv,
1816    /// The principal square root (`igraph_complex_sqrt`, undocumented in `igraph_complex.h`).
1817    sqrt => igraph_complex_sqrt,
1818    /// The exponential `e^z` (`igraph_complex_exp`, undocumented in `igraph_complex.h`).
1819    exp => igraph_complex_exp,
1820    /// The principal natural logarithm (`igraph_complex_log`, undocumented in `igraph_complex.h`).
1821    ln => igraph_complex_log,
1822    /// The principal base-10 logarithm (`igraph_complex_log10`, undocumented in `igraph_complex.h`).
1823    log10 => igraph_complex_log10,
1824    /// The sine (`igraph_complex_sin`, undocumented in `igraph_complex.h`).
1825    sin => igraph_complex_sin,
1826    /// The cosine (`igraph_complex_cos`, undocumented in `igraph_complex.h`).
1827    cos => igraph_complex_cos,
1828    /// The tangent (`igraph_complex_tan`, undocumented in `igraph_complex.h`).
1829    tan => igraph_complex_tan,
1830    /// The secant `1 / cos z` (`igraph_complex_sec`, undocumented in `igraph_complex.h`).
1831    sec => igraph_complex_sec,
1832    /// The cosecant `1 / sin z` (`igraph_complex_csc`, undocumented in `igraph_complex.h`).
1833    csc => igraph_complex_csc,
1834    /// The cotangent `1 / tan z` (`igraph_complex_cot`, undocumented in `igraph_complex.h`).
1835    cot => igraph_complex_cot,
1836}
1837
1838impl igraph_complex_t {
1839    /// The complex number `i`.
1840    pub const I: Self = Self::new(0.0, 1.0);
1841
1842    /// Builds `r·e^{iθ}` from polar coordinates
1843    /// (`igraph_complex_polar`, undocumented in `igraph_complex.h`).
1844    ///
1845    /// ```
1846    /// use igraph::igraph_complex_t as Complex;
1847    /// let z = Complex::from_polar(2.0, std::f64::consts::FRAC_PI_2);
1848    /// assert!(z.almost_equals(Complex::new(0.0, 2.0), 1e-12));
1849    /// assert_eq!((z * z).re(), -4.0);
1850    /// ```
1851    pub fn from_polar(r: f64, theta: f64) -> Self {
1852        unsafe { igraph_complex_polar(r, theta) }
1853    }
1854
1855    /// The (principal) square root of a real number, which may be imaginary
1856    /// (`igraph_complex_sqrt_real`, undocumented in `igraph_complex.h`).
1857    pub fn sqrt_real(x: f64) -> Self {
1858        unsafe { igraph_complex_sqrt_real(x) }
1859    }
1860
1861    /// The modulus `|z|` (`igraph_complex_abs`, undocumented in `igraph_complex.h`).
1862    pub fn abs(self) -> f64 {
1863        unsafe { igraph_complex_abs(self) }
1864    }
1865
1866    /// The natural logarithm of the modulus, `ln |z|`, computed accurately
1867    /// (`igraph_complex_logabs`, undocumented in `igraph_complex.h`).
1868    pub fn logabs(self) -> f64 {
1869        unsafe { igraph_complex_logabs(self) }
1870    }
1871
1872    /// The argument (phase angle) in `(-π, π]`
1873    /// (`igraph_complex_arg`, undocumented in `igraph_complex.h`).
1874    pub fn arg(self) -> f64 {
1875        unsafe { igraph_complex_arg(self) }
1876    }
1877
1878    /// Whether `self` and `other` are equal up to the relative tolerance `eps`
1879    /// ([`igraph_complex_almost_equals`](https://igraph.org/c/html/latest/igraph-Nongraph.html#igraph_complex_almost_equals)).
1880    pub fn almost_equals(self, other: Self, eps: f64) -> bool {
1881        unsafe { igraph_complex_almost_equals(self, other, eps) }
1882    }
1883
1884    /// The complex power `self^exponent`
1885    /// (`igraph_complex_pow`, undocumented in `igraph_complex.h`).
1886    pub fn pow(self, exponent: Self) -> Self {
1887        unsafe { igraph_complex_pow(self, exponent) }
1888    }
1889
1890    /// The real power `self^exponent`
1891    /// (`igraph_complex_pow_real`, undocumented in `igraph_complex.h`).
1892    pub fn powf(self, exponent: f64) -> Self {
1893        unsafe { igraph_complex_pow_real(self, exponent) }
1894    }
1895
1896    /// The logarithm in base `base`
1897    /// (`igraph_complex_log_b`, undocumented in `igraph_complex.h`).
1898    pub fn log(self, base: Self) -> Self {
1899        unsafe { igraph_complex_log_b(self, base) }
1900    }
1901
1902    /// Adds a real number (`igraph_complex_add_real`, undocumented in `igraph_complex.h`).
1903    pub fn add_real(self, x: f64) -> Self {
1904        unsafe { igraph_complex_add_real(self, x) }
1905    }
1906
1907    /// Adds an imaginary number `i·y` (`igraph_complex_add_imag`, undocumented in `igraph_complex.h`).
1908    pub fn add_imag(self, y: f64) -> Self {
1909        unsafe { igraph_complex_add_imag(self, y) }
1910    }
1911
1912    /// Subtracts a real number (`igraph_complex_sub_real`, undocumented in `igraph_complex.h`).
1913    pub fn sub_real(self, x: f64) -> Self {
1914        unsafe { igraph_complex_sub_real(self, x) }
1915    }
1916
1917    /// Subtracts an imaginary number `i·y` (`igraph_complex_sub_imag`, undocumented in `igraph_complex.h`).
1918    pub fn sub_imag(self, y: f64) -> Self {
1919        unsafe { igraph_complex_sub_imag(self, y) }
1920    }
1921
1922    /// Multiplies by a real number (`igraph_complex_mul_real`, undocumented in `igraph_complex.h`).
1923    pub fn mul_real(self, x: f64) -> Self {
1924        unsafe { igraph_complex_mul_real(self, x) }
1925    }
1926
1927    /// Multiplies by an imaginary number `i·y` (`igraph_complex_mul_imag`, undocumented in `igraph_complex.h`).
1928    pub fn mul_imag(self, y: f64) -> Self {
1929        unsafe { igraph_complex_mul_imag(self, y) }
1930    }
1931
1932    /// Divides by a real number (`igraph_complex_div_real`, undocumented in `igraph_complex.h`).
1933    pub fn div_real(self, x: f64) -> Self {
1934        unsafe { igraph_complex_div_real(self, x) }
1935    }
1936
1937    /// Divides by an imaginary number `i·y` (`igraph_complex_div_imag`, undocumented in `igraph_complex.h`).
1938    pub fn div_imag(self, y: f64) -> Self {
1939        unsafe { igraph_complex_div_imag(self, y) }
1940    }
1941}
1942
1943macro_rules! complex_binop {
1944    ($($trait:ident, $method:ident, $assign_trait:ident, $assign:ident => $c:ident;)*) => {$(
1945        impl std::ops::$trait for igraph_complex_t {
1946            type Output = Self;
1947            #[doc = concat!("Complex arithmetic with `", stringify!($c), "`.")]
1948            fn $method(self, rhs: Self) -> Self {
1949                unsafe { $c(self, rhs) }
1950            }
1951        }
1952        impl std::ops::$assign_trait for igraph_complex_t {
1953            fn $assign(&mut self, rhs: Self) {
1954                *self = unsafe { $c(*self, rhs) };
1955            }
1956        }
1957    )*};
1958}
1959
1960complex_binop! {
1961    Add, add, AddAssign, add_assign => igraph_complex_add;
1962    Sub, sub, SubAssign, sub_assign => igraph_complex_sub;
1963    Mul, mul, MulAssign, mul_assign => igraph_complex_mul;
1964    Div, div, DivAssign, div_assign => igraph_complex_div;
1965}
1966
1967impl std::ops::Neg for igraph_complex_t {
1968    type Output = Self;
1969    /// Negation (`igraph_complex_neg`, undocumented in `igraph_complex.h`).
1970    fn neg(self) -> Self {
1971        unsafe { igraph_complex_neg(self) }
1972    }
1973}
1974
1975impl fmt::Display for igraph_complex_t {
1976    /// Formats like igraph does (`igraph_complex_snprintf`), e.g. `1+2i`.
1977    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1978        let mut buf = [0 as std::ffi::c_char; 128];
1979        let n = unsafe { igraph_complex_snprintf(buf.as_mut_ptr(), buf.len(), *self) };
1980        if n < 0 {
1981            return write!(f, "{}{:+}i", self.re(), self.im());
1982        }
1983        let s = unsafe { std::ffi::CStr::from_ptr(buf.as_ptr()) };
1984        f.write_str(&s.to_string_lossy())
1985    }
1986}
1987
1988/// Formats a real number the way igraph does in its text output
1989/// (`igraph_real_snprintf`): `%g`-like, with `NaN`, `Inf` and `-Inf` for the
1990/// special values.
1991///
1992/// ```
1993/// use igraph::vector::format_real;
1994/// assert_eq!(format_real(0.5), "0.5");
1995/// assert_eq!(format_real(f64::INFINITY), "Inf");
1996/// assert_eq!(format_real(f64::NAN), "NaN");
1997/// ```
1998pub fn format_real(value: f64) -> String {
1999    format_real_with(value, false)
2000}
2001
2002/// Formats a real number with 15 significant digits
2003/// (`igraph_real_snprintf_precise`), as used by igraph's writers.
2004///
2005/// ```
2006/// use igraph::vector::format_real_precise;
2007/// assert_eq!(format_real_precise(0.1), "0.1");
2008/// assert_eq!(format_real_precise(1.0 / 3.0), "0.333333333333333");
2009/// ```
2010pub fn format_real_precise(value: f64) -> String {
2011    format_real_with(value, true)
2012}
2013
2014fn format_real_with(value: f64, precise: bool) -> String {
2015    let mut buf = [0 as std::ffi::c_char; 64];
2016    let n = unsafe {
2017        if precise {
2018            igraph_real_snprintf_precise(buf.as_mut_ptr(), buf.len(), value)
2019        } else {
2020            igraph_real_snprintf(buf.as_mut_ptr(), buf.len(), value)
2021        }
2022    };
2023    if n < 0 {
2024        return value.to_string();
2025    }
2026    unsafe { std::ffi::CStr::from_ptr(buf.as_ptr()) }
2027        .to_string_lossy()
2028        .into_owned()
2029}