use std::iter;
use std::usize;
use num::traits::Zero;
use num::zero;
pub fn to_csc<T: Copy>(nrow: usize, ncol: usize, ap: &[usize], aj: &[usize], ax: &[T]) -> (Vec<usize>, Vec<usize>, Vec<T>) {
let nnz = ap[nrow];
let mut bp: Vec<usize> = iter::repeat(0).take(ncol+1).collect();
let mut bi: Vec<usize> = iter::repeat(0).take(nnz).collect();
let mut bx: Vec<T> = Vec::with_capacity(nnz);
unsafe {
bx.set_len(nnz);
}
for n in 0 .. nnz {
bp[aj[n]] += 1;
}
let mut cumsum = 0;
for col in 0 .. ncol {
let temp = bp[col];
bp[col] = cumsum;
cumsum += temp;
}
bp[ncol] = nnz;
for row in 0 .. nrow {
for jj in ap[row] .. ap[row+1] {
let col = aj[jj];
let dest = bp[col];
bi[dest] = row;
bx[dest] = ax[jj];
bp[col] += 1;
}
}
let mut last = 0;
for col in 0 .. ncol+1 {
let temp = bp[col];
bp[col] = last;
last = temp;
}
(bp, bi, bx)
}
pub fn sort_indices<T: Copy>(nrow: usize, ap: &[usize], aj: &mut [usize], ax: &mut [T]) {
let mut temp: Vec<(usize,T)> = vec![];
for i in 0 .. nrow {
let row_start = ap[i];
let row_end = ap[i+1];
temp.clear();
for jj in row_start .. row_end {
temp.push((aj[jj], ax[jj]));
}
temp.sort_by(|a,b| a.0.cmp(&b.0));
for (n, jj) in (row_start .. row_end).enumerate() {
aj[jj] = temp[n].0;
ax[jj] = temp[n].1;
}
}
}
pub fn has_canonical_format(nrow: usize, ap: &[usize], aj: &[usize]) -> bool {
for i in 0 .. nrow {
if ap[i] > ap[i+1] {
return false;
}
for jj in ap[i]+1 .. ap[i+1] {
if !(aj[jj-1] < aj[jj]) {
return false;
}
}
}
true
}
pub fn binop_csr_general<T: Zero + PartialOrd + Copy, U: Zero + PartialOrd + Copy, F>(
nrow: usize, ncol: usize,
ap: &[usize], aj: &[usize], ax: &[T],
bp: &[usize], bj: &[usize], bx: &[T],
mut f: F) -> (Vec<usize>, Vec<usize>, Vec<U>) where F: FnMut(T,T) -> U {
let nnz = ap[nrow] + bp[nrow];
let mut cp: Vec<usize> = iter::repeat(0).take(ncol+1).collect();
let mut cj: Vec<usize> = iter::repeat(0).take(nnz).collect();
let mut cx: Vec<U> = Vec::with_capacity(nnz);
let mut next: Vec<usize> = iter::repeat(usize::MAX).take(ncol).collect();
let mut a_row: Vec<T> = iter::repeat(Zero::zero()).take(ncol).collect();
let mut b_row: Vec<T> = iter::repeat(Zero::zero()).take(ncol).collect();
let mut nnz = 0;
cp[0] = 0;
for i in 0 .. nrow {
let mut head = usize::MAX - 1;
let mut length = 0;
let i_start = ap[i];
let i_end = ap[i+1];
for jj in i_start .. i_end {
let j = aj[jj];
a_row[j] = ax[jj];
if next[j] == usize::MAX {
next[j] = head;
head = j;
length += 1;
}
}
let i_start = bp[i];
let i_end = bp[i+1];
for jj in i_start .. i_end {
let j = bj[jj];
b_row[j] = bx[jj];
if next[j] == usize::MAX {
next[j] = head;
head = j;
length += 1;
}
}
for _ in 0 .. length {
let result = f(a_row[head], b_row[head]);
if result != Zero::zero() {
cj[nnz] = head;
cx[nnz] = result;
nnz += 1;
}
let temp = head;
head = next[head];
next[temp] = usize::MAX;
a_row[temp] = zero();
b_row[temp] = zero();
}
cp[i+1] = nnz;
}
(cp, cj, cx)
}