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}