rgsl/types/permutation.rs
1//
2// A rust binding for the GSL library by Guillaume Gomez (guillaume1.gomez@gmail.com)
3//
4
5#[cfg(feature = "v2_2")]
6use crate::MatrixF64;
7use crate::Value;
8use crate::{MatrixComplexF32, MatrixComplexF64, MatrixF32, VectorF64};
9use ffi::FFI;
10use std::fmt::{self, Debug, Formatter};
11use std::slice;
12
13ffi_wrapper!(Permutation, *mut sys::gsl_permutation, gsl_permutation_free);
14
15/// ## Permutations in cyclic form
16///
17/// A permutation can be represented in both linear and cyclic notations. The functions described in this section convert between the two forms.
18/// The linear notation is an index mapping, and has already been described above. The cyclic notation expresses a permutation as a series of
19/// circular rearrangements of groups of elements, or cycles.
20///
21/// For example, under the cycle (1 2 3), 1 is replaced by 2, 2 is replaced by 3 and 3 is replaced by 1 in a circular fashion. Cycles of different
22/// sets of elements can be combined independently, for example (1 2 3) (4 5) combines the cycle (1 2 3) with the cycle (4 5), which is an exchange
23/// of elements 4 and 5. A cycle of length one represents an element which is unchanged by the permutation and is referred to as a singleton.
24///
25/// It can be shown that every permutation can be decomposed into combinations of cycles. The decomposition is not unique, but can always be
26/// rearranged into a standard canonical form by a reordering of elements. The library uses the canonical form defined in Knuth’s Art of Computer
27/// Programming (Vol 1, 3rd Ed, 1997) Section 1.3.3, p.178.
28///
29/// The procedure for obtaining the canonical form given by Knuth is,
30///
31/// Write all singleton cycles explicitly
32/// Within each cycle, put the smallest number first
33/// Order the cycles in decreasing order of the first number in the cycle.
34/// For example, the linear representation (2 4 3 0 1) is represented as (1 4) (0 2 3) in canonical form. The permutation corresponds to an exchange
35/// of elements 1 and 4, and rotation of elements 0, 2 and 3.
36///
37/// The important property of the canonical form is that it can be reconstructed from the contents of each cycle without the brackets. In addition,
38/// by removing the brackets it can be considered as a linear representation of a different permutation. In the example given above the permutation
39/// (2 4 3 0 1) would become (1 4 0 2 3). This mapping has many applications in the theory of permutations.
40impl Permutation {
41 /// This function allocates memory for a new permutation of size n. The permutation is not initialized and its elements are undefined.
42 /// Use the function gsl_permutation_calloc if you want to create a permutation which is initialized to the identity. A null pointer is
43 /// returned if insufficient memory is available to create the permutation.
44 #[doc(alias = "gsl_permutation_alloc")]
45 pub fn new(n: usize) -> Option<Permutation> {
46 let tmp = unsafe { sys::gsl_permutation_alloc(n) };
47
48 if tmp.is_null() {
49 None
50 } else {
51 Some(Self::wrap(tmp))
52 }
53 }
54
55 /// This function allocates memory for a new permutation of size n and initializes it to the identity. A null pointer is returned if
56 /// insufficient memory is available to create the permutation.
57 #[doc(alias = "gsl_permutation_calloc")]
58 pub fn new_with_init(n: usize) -> Option<Permutation> {
59 let tmp = unsafe { sys::gsl_permutation_calloc(n) };
60
61 if tmp.is_null() {
62 None
63 } else {
64 Some(Self::wrap(tmp))
65 }
66 }
67
68 /// This function initializes the permutation p to the identity, i.e. (0,1,2,…,n-1).
69 #[doc(alias = "gsl_permutation_init")]
70 pub fn init(&mut self) {
71 unsafe { sys::gsl_permutation_init(self.unwrap_unique()) }
72 }
73
74 /// This function copies the elements of the permutation src into the permutation dest. The two
75 /// permutations must have the same size.
76 // checker:ignore
77 #[doc(alias = "gsl_permutation_memcpy")]
78 pub fn copy(&self, dest: &mut Permutation) -> Result<(), Value> {
79 let ret =
80 unsafe { sys::gsl_permutation_memcpy(dest.unwrap_unique(), self.unwrap_shared()) };
81 result_handler!(ret, ())
82 }
83
84 /// This function returns the value of the i-th element of the permutation p. If i lies outside the allowed range of 0 to n-1 then
85 /// the error handler is invoked and 0 is returned.
86 #[doc(alias = "gsl_permutation_get")]
87 pub fn get(&self, i: usize) -> usize {
88 unsafe { sys::gsl_permutation_get(self.unwrap_shared(), i) }
89 }
90
91 /// This function exchanges the i-th and j-th elements of the permutation p.
92 #[doc(alias = "gsl_permutation_swap")]
93 pub fn swap(&mut self, i: usize, j: usize) -> Result<(), Value> {
94 let ret = unsafe { sys::gsl_permutation_swap(self.unwrap_unique(), i, j) };
95 result_handler!(ret, ())
96 }
97
98 /// This function returns the size of the permutation p.
99 #[doc(alias = "gsl_permutation_size")]
100 pub fn size(&self) -> usize {
101 unsafe { sys::gsl_permutation_size(self.unwrap_shared()) }
102 }
103
104 // checker:ignore
105 #[doc(alias = "gsl_permutation_data")]
106 pub fn as_slice(&self) -> &[usize] {
107 unsafe {
108 let data = sys::gsl_permutation_data(self.unwrap_shared());
109 slice::from_raw_parts(data, self.size())
110 }
111 }
112
113 // checker:ignore
114 #[doc(alias = "gsl_permutation_data")]
115 pub fn as_mut_slice(&mut self) -> &mut [usize] {
116 unsafe {
117 let data = sys::gsl_permutation_data(self.unwrap_shared());
118 slice::from_raw_parts_mut(data, self.size())
119 }
120 }
121
122 /// This function checks that the permutation p is valid. The n elements should contain each of
123 /// the numbers 0 to n-1 once and only once.
124 // checker:ignore
125 #[doc(alias = "gsl_permutation_valid")]
126 pub fn is_valid(&self) -> bool {
127 let ret = unsafe { sys::gsl_permutation_valid(self.unwrap_shared()) };
128 Value::from(ret) == Value::Success
129 }
130
131 /// This function reverses the elements of the permutation p.
132 #[doc(alias = "gsl_permutation_reverse")]
133 pub fn reverse(&mut self) {
134 unsafe { sys::gsl_permutation_reverse(self.unwrap_unique()) }
135 }
136
137 /// This function computes the inverse of the permutation p, storing the result in inv.
138 #[doc(alias = "gsl_permutation_inverse")]
139 pub fn inverse(&self, inv: &mut Permutation) -> Result<(), Value> {
140 let ret =
141 unsafe { sys::gsl_permutation_inverse(inv.unwrap_unique(), self.unwrap_shared()) };
142 result_handler!(ret, ())
143 }
144
145 /// This function advances the permutation p to the next permutation in lexicographic order and returns GSL_SUCCESS. If no further
146 /// permutations are available it returns GSL_FAILURE and leaves p unmodified. Starting with the identity permutation and repeatedly
147 /// applying this function will iterate through all possible permutations of a given order.
148 #[doc(alias = "gsl_permutation_next")]
149 pub fn next(&mut self) -> Result<(), Value> {
150 let ret = unsafe { sys::gsl_permutation_next(self.unwrap_unique()) };
151 result_handler!(ret, ())
152 }
153
154 /// This function steps backwards from the permutation p to the previous permutation in lexicographic order, returning GSL_SUCCESS.
155 /// If no previous permutation is available it returns GSL_FAILURE and leaves p unmodified.
156 #[doc(alias = "gsl_permutation_prev")]
157 pub fn prev(&mut self) -> Result<(), Value> {
158 let ret = unsafe { sys::gsl_permutation_prev(self.unwrap_unique()) };
159 result_handler!(ret, ())
160 }
161
162 /// This function applies the permutation to the array data of size n with stride stride.
163 #[doc(alias = "gsl_permute")]
164 pub fn permute(&mut self, data: &mut [f64], stride: usize) -> Result<(), Value> {
165 let ret = unsafe {
166 let data_ptr = sys::gsl_permutation_data(self.unwrap_shared());
167 sys::gsl_permute(data_ptr, data.as_mut_ptr(), stride, data.len() as _)
168 };
169 result_handler!(ret, ())
170 }
171
172 /// This function applies the inverse of the permutation p to the array data of size n with stride stride.
173 #[doc(alias = "gsl_permute_inverse")]
174 pub fn permute_inverse(&mut self, data: &mut [f64], stride: usize) -> Result<(), Value> {
175 let ret = unsafe {
176 let data_ptr = sys::gsl_permutation_data(self.unwrap_shared());
177 sys::gsl_permute_inverse(data_ptr, data.as_mut_ptr(), stride, data.len() as _)
178 };
179 result_handler!(ret, ())
180 }
181
182 /// This function applies the permutation p to the elements of the vector v, considered as a row-vector acted on by a permutation
183 /// matrix from the right, v' = v P. The j-th column of the permutation matrix P is given by the p_j-th column of the identity matrix.
184 /// The permutation p and the vector v must have the same length.
185 #[doc(alias = "gsl_permute_vector")]
186 pub fn permute_vector(&mut self, v: &mut VectorF64) -> Result<(), Value> {
187 let ret = unsafe { sys::gsl_permute_vector(self.unwrap_unique(), v.unwrap_unique()) };
188 result_handler!(ret, ())
189 }
190
191 /// This function applies the inverse of the permutation p to the elements of the vector v, considered as a row-vector acted on by an inverse permutation
192 /// matrix from the right, v' = v P^T. Note that for permutation matrices the inverse is the same as the transpose. The j-th column of the permutation
193 /// matrix P is given by the p_j-th column of the identity matrix. The permutation p and the vector v must have the same length.
194 #[doc(alias = "gsl_permute_vector_inverse")]
195 pub fn permute_vector_inverse(&self, v: &mut VectorF64) -> Result<(), Value> {
196 let ret =
197 unsafe { sys::gsl_permute_vector_inverse(self.unwrap_shared(), v.unwrap_unique()) };
198 result_handler!(ret, ())
199 }
200
201 #[cfg(feature = "v2_2")]
202 #[cfg_attr(feature = "dox", doc(cfg(feature = "v2_2")))]
203 #[doc(alias = "gsl_permute_matrix")]
204 pub fn permute_matrix(&self, A: &mut MatrixF64) -> Result<(), Value> {
205 let ret = unsafe { sys::gsl_permute_matrix(self.unwrap_shared(), A.unwrap_unique()) };
206 result_handler!(ret, ())
207 }
208
209 #[doc(alias = "gsl_permute_matrix_float")]
210 pub fn permute_matrix_float(&self, A: &mut MatrixF32) -> Result<(), Value> {
211 let ret = unsafe { sys::gsl_permute_matrix_float(self.unwrap_shared(), A.unwrap_unique()) };
212 result_handler!(ret, ())
213 }
214
215 #[doc(alias = "gsl_permute_matrix_complex")]
216 pub fn permute_matrix_complex(&self, A: &mut MatrixComplexF64) -> Result<(), Value> {
217 let ret =
218 unsafe { sys::gsl_permute_matrix_complex(self.unwrap_shared(), A.unwrap_unique()) };
219 result_handler!(ret, ())
220 }
221
222 #[doc(alias = "gsl_permute_matrix_complex_float")]
223 pub fn permute_matrix_complex_float(&self, A: &mut MatrixComplexF32) -> Result<(), Value> {
224 let ret = unsafe {
225 sys::gsl_permute_matrix_complex_float(self.unwrap_shared(), A.unwrap_unique())
226 };
227 result_handler!(ret, ())
228 }
229
230 /// This function combines the two permutations pa and pb into a single permutation p, where p = pa * pb. The permutation p is equivalent to applying pb
231 /// first and then pa.
232 #[doc(alias = "gsl_permutation_mul")]
233 pub fn mul(&mut self, pa: &Permutation, pb: &Permutation) -> Result<(), Value> {
234 let ret = unsafe {
235 sys::gsl_permutation_mul(self.unwrap_unique(), pa.unwrap_shared(), pb.unwrap_shared())
236 };
237 result_handler!(ret, ())
238 }
239
240 /// This function computes the canonical form of the permutation self and stores it in the output argument q.
241 #[doc(alias = "gsl_permutation_linear_to_canonical")]
242 pub fn linear_to_canonical(&self, q: &mut Permutation) -> Result<(), Value> {
243 let ret = unsafe {
244 sys::gsl_permutation_linear_to_canonical(q.unwrap_unique(), self.unwrap_shared())
245 };
246 result_handler!(ret, ())
247 }
248
249 /// This function converts the self permutation in canonical form back into linear form storing it in the output argument p.
250 #[doc(alias = "gsl_permutation_canonical_to_linear")]
251 pub fn canonical_to_linear(&self, p: &mut Permutation) -> Result<(), Value> {
252 let ret = unsafe {
253 sys::gsl_permutation_canonical_to_linear(p.unwrap_unique(), self.unwrap_shared())
254 };
255 result_handler!(ret, ())
256 }
257
258 /// This function counts the number of inversions in the self permutation. An inversion is any pair of elements that are not in order. For example, the
259 /// permutation 2031 has three inversions, corresponding to the pairs (2,0) (2,1) and (3,1). The identity permutation has no inversions.
260 #[doc(alias = "gsl_permutation_inversions")]
261 pub fn inversions(&self) -> usize {
262 unsafe { sys::gsl_permutation_inversions(self.unwrap_shared()) }
263 }
264
265 /// This function counts the number of cycles in the self permutation, given in linear form.
266 #[doc(alias = "gsl_permutation_linear_cycles")]
267 pub fn linear_cycles(&self) -> usize {
268 unsafe { sys::gsl_permutation_linear_cycles(self.unwrap_shared()) }
269 }
270
271 /// This function counts the number of cycles in the self permutation, given in canonical form.
272 #[doc(alias = "gsl_permutation_canonical_cycles")]
273 pub fn canonical_cycles(&self) -> usize {
274 unsafe { sys::gsl_permutation_canonical_cycles(self.unwrap_shared()) }
275 }
276}
277
278impl Debug for Permutation {
279 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
280 if self.unwrap_shared().is_null() {
281 write!(f, "<null>")
282 } else {
283 write!(f, "{:?}", self.as_slice())
284 }
285 }
286}