rgsl/types/multiset.rs
1//
2// A rust binding for the GSL library by Guillaume Gomez (guillaume1.gomez@gmail.com)
3//
4
5/*!
6# Multisets
7
8This chapter describes functions for creating and manipulating multisets. A multiset c is represented by an array of k integers in the
9range 0 to n-1, where each value c_i may occur more than once. The multiset c corresponds to indices of k elements chosen from an n element
10vector with replacement. In mathematical terms, n is the cardinality of the multiset while k is the maximum multiplicity of any value.
11Multisets are useful, for example, when iterating over the indices of a k-th order symmetric tensor in n-space.
12!*/
13
14use crate::Value;
15use ffi::FFI;
16use std::io;
17
18ffi_wrapper!(MultiSet, *mut sys::gsl_multiset, gsl_multiset_free);
19
20impl MultiSet {
21 /// This function allocates memory for a new multiset with parameters n, k. The multiset is not
22 /// initialized and its elements are undefined. Use the function [`Self::new_with_init`] if you
23 /// want to create a multiset which is initialized to the lexicographically first multiset
24 /// element. A null pointer is returned if insufficient memory is available to create the
25 /// multiset.
26 #[doc(alias = "gsl_multiset_alloc")]
27 pub fn new(n: usize, k: usize) -> Option<Self> {
28 let tmp = unsafe { sys::gsl_multiset_alloc(n, k) };
29
30 if tmp.is_null() {
31 None
32 } else {
33 Some(Self::wrap(tmp))
34 }
35 }
36
37 /// This function allocates memory for a new multiset with parameters n, k and initializes it to
38 /// the lexicographically first multiset element. A null pointer is returned if insufficient
39 /// memory is available to create the multiset.
40 #[doc(alias = "gsl_multiset_calloc")]
41 pub fn new_with_init(n: usize, k: usize) -> Option<Self> {
42 let tmp = unsafe { sys::gsl_multiset_calloc(n, k) };
43
44 if tmp.is_null() {
45 None
46 } else {
47 Some(Self::wrap(tmp))
48 }
49 }
50
51 /// This function initializes the multiset c to the lexicographically first multiset element,
52 /// i.e. 0 repeated k times.
53 #[doc(alias = "gsl_multiset_init_first")]
54 pub fn init_first(&mut self) {
55 unsafe { sys::gsl_multiset_init_first(self.unwrap_unique()) }
56 }
57
58 /// This function initializes the multiset c to the lexicographically last multiset element,
59 /// i.e. n-1 repeated k times.
60 #[doc(alias = "gsl_multiset_init_last")]
61 pub fn init_last(&mut self) {
62 unsafe { sys::gsl_multiset_init_last(self.unwrap_unique()) }
63 }
64
65 /// This function copies the elements of the multiset `self` into the multiset dest. The two
66 /// multisets must have the same size.
67 #[doc(alias = "gsl_multiset_memcpy")]
68 pub fn copy(&self, dest: &mut MultiSet) -> Result<(), Value> {
69 let ret = unsafe { sys::gsl_multiset_memcpy(dest.unwrap_unique(), self.unwrap_shared()) };
70 result_handler!(ret, ())
71 }
72
73 /// This function returns the value of the i-th element of the multiset c. If i lies outside the
74 /// allowed range of 0 to k-1 then the error handler is invoked and 0 is returned.
75 #[doc(alias = "gsl_multiset_get")]
76 pub fn get(&self, i: usize) -> usize {
77 unsafe { sys::gsl_multiset_get(self.unwrap_shared(), i) }
78 }
79
80 /// This function returns the range (n) of the multiset `self`.
81 #[doc(alias = "gsl_multiset_n")]
82 pub fn n(&self) -> usize {
83 unsafe { sys::gsl_multiset_n(self.unwrap_shared()) }
84 }
85
86 /// This function returns the number of elements (k) in the multiset `self`.
87 #[doc(alias = "gsl_multiset_k")]
88 pub fn k(&self) -> usize {
89 unsafe { sys::gsl_multiset_k(self.unwrap_shared()) }
90 }
91
92 /// This function returns a pointer to the array of elements in the multiset `self`.
93 #[doc(alias = "gsl_multiset_data")]
94 pub fn data(&self) -> &[usize] {
95 unsafe {
96 let ptr = sys::gsl_multiset_data(self.unwrap_shared());
97 std::slice::from_raw_parts(ptr, self.k())
98 }
99 }
100
101 /// This function returns a pointer to the array of elements in the multiset `self`.
102 // checker:ignore
103 #[doc(alias = "gsl_multiset_data")]
104 pub fn data_mut(&mut self) -> &mut [usize] {
105 unsafe {
106 let ptr = sys::gsl_multiset_data(self.unwrap_shared());
107 std::slice::from_raw_parts_mut(ptr, self.k())
108 }
109 }
110
111 /// This function checks that the multiset self is valid. The k elements should lie in the range
112 /// 0 to n-1, with each value occurring in non-decreasing order.
113 ///
114 /// Returns `OK(())` if valid.
115 #[doc(alias = "gsl_multiset_valid")]
116 pub fn valid(&self) -> Result<(), Value> {
117 // Little trick here: the function is expecting a mutable pointer whereas it doesn't need
118 // to be...
119 let ret = unsafe { sys::gsl_multiset_valid(self.inner) };
120 result_handler!(ret, ())
121 }
122
123 /// This function advances the multiset self to the next multiset element in lexicographic order
124 /// and returns `Ok(())`. If no further multisets elements are available it returns
125 /// [`Err(Value::Failure)`](Value::Failure) and leaves self unmodified. Starting with the first
126 /// multiset and repeatedly applying this function will iterate through all possible multisets
127 /// of a given order.
128 #[doc(alias = "gsl_multiset_next")]
129 pub fn next(&mut self) -> Result<(), Value> {
130 let ret = unsafe { sys::gsl_multiset_next(self.unwrap_unique()) };
131 result_handler!(ret, ())
132 }
133
134 /// This function steps backwards from the multiset self to the previous multiset element in
135 /// lexicographic order, returning [`Value::Success`]. If no previous multiset is available it
136 /// returns [`Value::Failure`] and leaves self unmodified.
137 #[doc(alias = "gsl_multiset_prev")]
138 pub fn prev(&mut self) -> Result<(), Value> {
139 let ret = unsafe { sys::gsl_multiset_prev(self.unwrap_unique()) };
140 result_handler!(ret, ())
141 }
142
143 pub fn print<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
144 write!(writer, "{:?}", self.data())
145 }
146}