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