use crate::amd::*;
use crate::internal::*;
use crate::valid::*;
use num_traits::{NumAssignOps, PrimInt};
use std::cmp::max;
pub fn preprocess<I: PrimInt + NumAssignOps>(n: I, a_p: &[I], a_i: &[I]) -> (Vec<I>, Vec<I>) {
let un = n.to_usize().unwrap();
debug_assert!(valid(n, n, a_p, a_i) != Status::Invalid);
let mut w: Vec<I> = vec![I::zero(); un];
let mut flag: Vec<isize> = vec![0; un];
for i in 0..un {
w[i] = I::zero(); flag[i] = EMPTY; }
for j in 0..un {
let p1 = a_p[j].to_usize().unwrap();
let p2 = a_p[j + 1].to_usize().unwrap();
for p in p1..p2 {
let i = a_i[p].to_usize().unwrap();
if flag[i] != j as isize {
w[i] += I::one(); flag[i] = j as isize; }
}
}
let nz: usize = a_p[un].to_usize().unwrap();
let mut r_p: Vec<I> = vec![I::zero(); un + 1];
let mut r_i: Vec<I> = vec![I::zero(); max(nz, 1)];
r_p[0] = I::zero();
for i in 0..un {
r_p[i + 1] = r_p[i] + w[i];
}
for i in 0..un {
w[i] = r_p[i];
flag[i] = EMPTY
}
for j in 0..un {
let p1 = a_p[j].to_usize().unwrap();
let p2 = a_p[j + 1].to_usize().unwrap();
for p in p1..p2 {
let i = a_i[p].to_usize().unwrap();
if flag[i] != j as isize {
r_i[w[i].to_usize().unwrap()] = I::from(j).unwrap(); w[i] += I::one();
flag[i] = j as isize; }
}
}
debug_assert!(valid(n, n, &r_p, &r_i) == Status::OK);
for j in 0..un {
debug_assert!(w[j] == r_p[j + 1])
}
(r_p, r_i)
}