use types::{VectorF64};
use ffi;
use enums;
use std::fmt;
use std::fmt::{Formatter, Debug};
use c_vec::CSlice;
pub struct Permutation {
p: *mut ffi::gsl_permutation,
d: CSlice<u64>
}
impl Permutation {
pub fn new(n: u64) -> Option<Permutation> {
let tmp = unsafe { ffi::gsl_permutation_alloc(n) };
if tmp.is_null() {
None
} else {
unsafe {
Some(Permutation {
p: tmp,
d: CSlice::new((*tmp).data, (*tmp).size as usize)
})
}
}
}
pub fn new_with_init(n: u64) -> Option<Permutation> {
let tmp = unsafe { ffi::gsl_permutation_calloc(n) };
if tmp.is_null() {
None
} else {
unsafe {
Some(Permutation {
p: tmp,
d: CSlice::new((*tmp).data, (*tmp).size as usize)
})
}
}
}
pub fn init(&self) {
unsafe { ffi::gsl_permutation_init(self.p) }
}
pub fn copy(&self, dest: &Permutation) -> enums::value::Value {
unsafe { ffi::gsl_permutation_memcpy(dest.p, self.p) }
}
pub fn get(&self, i: u64) -> u64 {
unsafe { ffi::gsl_permutation_get(self.p, i) }
}
pub fn swap(&self, i: u64, j: u64) -> enums::value::Value {
unsafe { ffi::gsl_permutation_swap(self.p, i, j) }
}
pub fn size(&self) -> u64 {
unsafe { ffi::gsl_permutation_size(self.p) }
}
pub fn data<'r>(&'r mut self) -> &'r mut [u64] {
self.d.as_mut()
}
pub fn is_valid(&self) -> bool {
match unsafe { ffi::gsl_permutation_valid(self.p) } {
::Value::Success => true,
_ => false
}
}
pub fn reverse(&self) {
unsafe { ffi::gsl_permutation_reverse(self.p) }
}
pub fn inverse(&self, inv: &Permutation) -> enums::value::Value {
unsafe { ffi::gsl_permutation_inverse(inv.p, self.p) }
}
pub fn next(&self) -> enums::value::Value {
unsafe { ffi::gsl_permutation_next(self.p) }
}
pub fn prev(&self) -> enums::value::Value {
unsafe { ffi::gsl_permutation_prev(self.p) }
}
pub fn permute(&self, data: &mut [f64], stride: u64) -> enums::value::Value {
unsafe { ffi::gsl_permute((*self.p).data, data.as_mut_ptr(), stride, data.len() as u64) }
}
pub fn permute_inverse(&self, data: &mut [f64], stride: u64) -> enums::value::Value {
unsafe { ffi::gsl_permute_inverse((*self.p).data, data.as_mut_ptr(), stride, data.len() as u64) }
}
pub fn permute_vector(&self, v: &VectorF64) -> enums::value::Value {
unsafe { ffi::gsl_permute_vector(self.p, ffi::FFI::unwrap(v)) }
}
pub fn permute_vector_inverse(&self, v: &VectorF64) -> enums::value::Value {
unsafe { ffi::gsl_permute_vector_inverse(self.p, ffi::FFI::unwrap(v)) }
}
pub fn mul(&self, pa: &Permutation, pb: &Permutation) -> enums::value::Value {
unsafe { ffi::gsl_permutation_mul(self.p, pa.p, pb.p) }
}
pub fn linear_to_canonical(&self, q: &Permutation) -> enums::value::Value {
unsafe { ffi::gsl_permutation_linear_to_canonical(q.p, self.p) }
}
pub fn canonical_to_linear(&self, p: &Permutation) -> enums::value::Value {
unsafe { ffi::gsl_permutation_canonical_to_linear(p.p, self.p) }
}
pub fn inversions(&self) -> u64 {
unsafe { ffi::gsl_permutation_inversions(self.p) }
}
pub fn linear_cycles(&self) -> u64 {
unsafe { ffi::gsl_permutation_linear_cycles(self.p) }
}
pub fn canonical_cycles(&self) -> u64 {
unsafe { ffi::gsl_permutation_canonical_cycles(self.p) }
}
}
impl Drop for Permutation {
fn drop(&mut self) {
unsafe { ffi::gsl_permutation_free(self.p) };
self.p = ::std::ptr::null_mut();
}
}
impl ffi::FFI<ffi::gsl_permutation> for Permutation {
fn wrap(p: *mut ffi::gsl_permutation) -> Permutation {
unsafe {
Permutation {
p: p,
d: CSlice::new((*p).data, (*p).size as usize)
}
}
}
fn unwrap(p: &Permutation) -> *mut ffi::gsl_permutation {
p.p
}
}
impl Debug for Permutation {
#[allow(unused_must_use)]
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "[");
unsafe {
for x in 0u64..(*self.p).size {
let tmp = (*self.p).data.offset(x as isize);
write!(f, " {}", *tmp);
}
}
write!(f, "]")
}
}