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}