use feanor_math::ring::*;
use feanor_math::rings::zn::{ZnRing, ZnRingStore};
use feanor_math::matrix::*;
pub mod lift;
pub mod bfv_rescale;
pub mod bgv_rescale;
pub mod shared_lift;
pub mod matrix_lift;
pub trait RNSOperation {
type Ring: ZnRingStore<Type = Self::RingType>;
type RingType: ?Sized + ZnRing;
fn input_rings<'a>(&'a self) -> &'a [Self::Ring];
fn output_rings<'a>(&'a self) -> &'a [Self::Ring];
fn apply<V1, V2>(&self, input: Submatrix<V1, El<Self::Ring>>, output: SubmatrixMut<V2, El<Self::Ring>>)
where V1: AsPointerToSlice<El<Self::Ring>>,
V2: AsPointerToSlice<El<Self::Ring>>;
}
fn sort_unstable_permutation<T, F>(data: Vec<T>, mut sort_by: F) -> (Vec<T>, Vec<usize>)
where F: FnMut(&T, &T) -> std::cmp::Ordering
{
let len = data.len();
let mut enumerated = data.into_iter().enumerate().collect::<Vec<_>>();
enumerated.sort_unstable_by(|(_, x), (_, y)| sort_by(x, y));
let mut perm = (0..len).map(|_| 0).collect::<Vec<_>>();
let mut data_sorted = Vec::with_capacity(len);
for (j, (i, x)) in enumerated.into_iter().enumerate() {
data_sorted.push(x);
perm[i] = j;
}
return (data_sorted, perm);
}