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<usize>
}
impl Permutation {
pub fn new(n: usize) -> 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: usize) -> 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(&mut self) {
unsafe { ffi::gsl_permutation_init(self.p) }
}
pub fn copy(&self, dest: &mut Permutation) -> enums::Value {
enums::Value::from(unsafe { ffi::gsl_permutation_memcpy(dest.p, self.p) })
}
pub fn get(&self, i: usize) -> usize {
unsafe { ffi::gsl_permutation_get(self.p, i) }
}
pub fn swap(&mut self, i: usize, j: usize) -> enums::Value {
enums::Value::from(unsafe { ffi::gsl_permutation_swap(self.p, i, j) })
}
pub fn size(&self) -> usize {
unsafe { ffi::gsl_permutation_size(self.p) }
}
pub fn data<'r>(&'r mut self) -> &'r mut [usize] {
self.d.as_mut()
}
pub fn is_valid(&self) -> bool {
match unsafe { ffi::gsl_permutation_valid(self.p) }.into() {
::Value::Success => true,
_ => false
}
}
pub fn reverse(&mut self) {
unsafe { ffi::gsl_permutation_reverse(self.p) }
}
pub fn inverse(&self, inv: &mut Permutation) -> enums::Value {
enums::Value::from(unsafe { ffi::gsl_permutation_inverse(inv.p, self.p) })
}
pub fn next(&mut self) -> enums::Value {
enums::Value::from(unsafe { ffi::gsl_permutation_next(self.p) })
}
pub fn prev(&mut self) -> enums::Value {
enums::Value::from(unsafe { ffi::gsl_permutation_prev(self.p) })
}
pub fn permute(&mut self, data: &mut [f64], stride: usize) -> enums::Value {
enums::Value::from(unsafe {
ffi::gsl_permute((*self.p).data, data.as_mut_ptr(), stride, data.len() as usize)
})
}
pub fn permute_inverse(&mut self, data: &mut [f64], stride: usize) -> enums::Value {
enums::Value::from(unsafe {
ffi::gsl_permute_inverse((*self.p).data, data.as_mut_ptr(), stride, data.len() as usize)
})
}
pub fn permute_vector(&mut self, v: &mut VectorF64) -> enums::Value {
enums::Value::from(unsafe { ffi::gsl_permute_vector(self.p, ffi::FFI::unwrap_unique(v)) })
}
pub fn permute_vector_inverse(&self, v: &mut VectorF64) -> enums::Value {
enums::Value::from(unsafe {
ffi::gsl_permute_vector_inverse(self.p, ffi::FFI::unwrap_unique(v))
})
}
pub fn mul(&mut self, pa: &Permutation, pb: &Permutation) -> enums::Value {
enums::Value::from(unsafe { ffi::gsl_permutation_mul(self.p, pa.p, pb.p) })
}
pub fn linear_to_canonical(&self, q: &mut Permutation) -> enums::Value {
enums::Value::from(unsafe { ffi::gsl_permutation_linear_to_canonical(q.p, self.p) })
}
pub fn canonical_to_linear(&self, p: &mut Permutation) -> enums::Value {
enums::Value::from(unsafe { ffi::gsl_permutation_canonical_to_linear(p.p, self.p) })
}
pub fn inversions(&self) -> usize {
unsafe { ffi::gsl_permutation_inversions(self.p) }
}
pub fn linear_cycles(&self) -> usize {
unsafe { ffi::gsl_permutation_linear_cycles(self.p) }
}
pub fn canonical_cycles(&self) -> usize {
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 soft_wrap(p: *mut ffi::gsl_permutation) -> Permutation {
Self::wrap(p)
}
fn unwrap_shared(p: &Permutation) -> *const ffi::gsl_permutation {
p.p as *const _
}
fn unwrap_unique(p: &mut 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 0usize..(*self.p).size {
let tmp = (*self.p).data.offset(x as isize);
write!(f, " {}", *tmp);
}
}
write!(f, "]")
}
}