rgsl/types/
combination.rs

1//
2// A rust binding for the GSL library by Guillaume Gomez (guillaume1.gomez@gmail.com)
3//
4
5/*!
6# Combinations
7
8This chapter describes functions for creating and manipulating combinations. A combination c is
9represented by an array of k integers in the  range 0 to n-1, where each value c_i occurs at most
10once. The combination c corresponds to indices of k elements chosen from an n element  vector.
11Combinations are useful for iterating over all k-element subsets of a set.
12
13## References and Further Reading
14
15Further information on combinations can be found in,
16
17Donald L. Kreher, Douglas R. Stinson, Combinatorial Algorithms: Generation, Enumeration and Search,
181998, CRC Press LLC, ISBN 084933988X
19!*/
20
21use crate::Value;
22use ffi::FFI;
23use std::fmt::{self, Debug, Formatter};
24
25ffi_wrapper!(Combination, *mut sys::gsl_combination, gsl_combination_free);
26
27impl Combination {
28    /// This function allocates memory for a new combination with parameters n, k. The combination
29    /// is not initialized and its elements are undefined. Use the function
30    /// `Combination::new_init_first` if you want to create a combination which is initialized to
31    /// the lexicographically first combination. A null pointer is returned if insufficient memory
32    /// is available to create the combination.
33    #[doc(alias = "gsl_combination_alloc")]
34    pub fn new(n: usize, k: usize) -> Option<Self> {
35        let tmp = unsafe { sys::gsl_combination_alloc(n, k) };
36
37        if tmp.is_null() {
38            None
39        } else {
40            Some(Self::wrap(tmp))
41        }
42    }
43
44    /// This function allocates memory for a new combination with parameters n, k and initializes it
45    /// to the lexicographically first combination. A null pointer is returned if insufficient
46    /// memory is available to create the combination.
47    #[doc(alias = "gsl_combination_calloc")]
48    pub fn new_with_init(n: usize, k: usize) -> Option<Self> {
49        let tmp = unsafe { sys::gsl_combination_calloc(n, k) };
50
51        if tmp.is_null() {
52            None
53        } else {
54            Some(Self::wrap(tmp))
55        }
56    }
57
58    /// This function initializes the combination c to the lexicographically first combination, i.e.
59    /// (0,1,2,...,k-1).
60    #[doc(alias = "gsl_combination_init_first")]
61    pub fn init_first(&mut self) {
62        unsafe { sys::gsl_combination_init_first(self.unwrap_unique()) }
63    }
64
65    /// This function initializes the combination c to the lexicographically last combination, i.e.
66    /// (n-k,n-k+1,…,n-1).
67    #[doc(alias = "gsl_combination_init_last")]
68    pub fn init_last(&mut self) {
69        unsafe { sys::gsl_combination_init_last(self.unwrap_unique()) }
70    }
71
72    /// This function copies the elements of the combination self into the combination dest. The two
73    /// combinations must have the same size.
74    #[doc(alias = "gsl_combination_memcpy")]
75    pub fn copy(&self, dest: &mut Combination) -> Result<(), Value> {
76        let ret =
77            unsafe { sys::gsl_combination_memcpy(dest.unwrap_unique(), self.unwrap_shared()) };
78        result_handler!(ret, ())
79    }
80
81    /// This function returns the value of the i-th element of the combination self. If i lies
82    /// outside the allowed range of 0 to k-1 then the error handler is invoked and 0 is returned.
83    #[doc(alias = "gsl_combination_get")]
84    pub fn get(&self, i: usize) -> usize {
85        unsafe { sys::gsl_combination_get(self.unwrap_shared(), i) }
86    }
87
88    /// This function returns the range (n) of the combination self.
89    #[doc(alias = "gsl_combination_n")]
90    pub fn n(&self) -> usize {
91        unsafe { sys::gsl_combination_n(self.unwrap_shared()) }
92    }
93
94    /// This function returns the number of elements (k) in the combination self.
95    #[doc(alias = "gsl_combination_k")]
96    pub fn k(&self) -> usize {
97        unsafe { sys::gsl_combination_k(self.unwrap_shared()) }
98    }
99
100    // checker:ignore
101    #[doc(alias = "gsl_combination_data")]
102    pub fn as_slice(&self) -> &[usize] {
103        unsafe {
104            let data = sys::gsl_combination_data(self.unwrap_shared());
105            std::slice::from_raw_parts(data, self.k())
106        }
107    }
108
109    // checker:ignore
110    #[doc(alias = "gsl_combination_data")]
111    pub fn as_mut_slice(&mut self) -> &mut [usize] {
112        unsafe {
113            let data = sys::gsl_combination_data(self.unwrap_shared());
114            std::slice::from_raw_parts_mut(data, self.k())
115        }
116    }
117
118    /// This function checks that the combination self is valid. The k elements should lie in the
119    /// range 0 to n-1, with each value occurring once at most and in increasing order.
120    // checker:ignore
121    #[doc(alias = "gsl_combination_valid")]
122    pub fn is_valid(&self) -> Result<(), Value> {
123        // Little hack because `gsl_combination_valid` doesn't in fact need a mutable object...
124        let ret = unsafe { sys::gsl_combination_valid(self.inner) };
125        result_handler!(ret, ())
126    }
127
128    /// This function advances the combination self to the next combination in lexicographic order
129    /// and returns `Success`. If no further combinations are available it returns Failure and
130    /// leaves self unmodified. Starting with the first combination and repeatedly applying this
131    /// function will iterate through all possible combinations of a given order.
132    #[doc(alias = "gsl_combination_next")]
133    pub fn next(&mut self) -> Result<(), Value> {
134        let ret = unsafe { sys::gsl_combination_next(self.unwrap_unique()) };
135        result_handler!(ret, ())
136    }
137
138    /// This function steps backwards from the combination self to the previous combination in
139    /// lexicographic order, returning `Success`. If no previous combination is available it returns
140    /// `Failure` and leaves self unmodified.
141    #[doc(alias = "gsl_combination_prev")]
142    pub fn prev(&mut self) -> Result<(), Value> {
143        let ret = unsafe { sys::gsl_combination_prev(self.unwrap_unique()) };
144        result_handler!(ret, ())
145    }
146}
147
148impl Debug for Combination {
149    #[allow(unused_must_use)]
150    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
151        write!(f, "[");
152        let s = self.as_slice();
153        for (pos, v) in s.iter().enumerate() {
154            if pos == 0 {
155                write!(f, "{}", v).unwrap();
156            } else {
157                write!(f, " {}", v).unwrap();
158            }
159        }
160        write!(f, "]")
161    }
162}