pub fn symbolic<Iptr: SpIndex, I: SpIndex>(
    a_indptr: &[Iptr],
    a_indices: &[I],
    b_cols: usize,
    b_indptr: &[Iptr],
    b_indices: &[I],
    c_indptr: &mut [Iptr],
    // TODO look for litterature on the nnz of C to be able to have a slice here
    c_indices: &mut Vec<I>,
    seen: &mut [bool],
) {
    assert!(a_indptr.len() == c_indptr.len());
    let a_rows = a_indptr.len() - 1;
    let b_rows = b_indptr.len() - 1;
    let a_nnz = a_indptr[a_rows].index();
    let b_nnz = b_indptr[b_rows].index();
    c_indices.clear();
    c_indices.reserve_exact(a_nnz + b_nnz);

    let ind_len = a_rows.max(b_rows.max(b_cols));
    assert!(seen.len() == ind_len);
    for elt in seen.iter_mut() {
        *elt = false;
    }

    c_indptr[0] = Iptr::from_usize(0);
    for a_row in 0..a_rows {
        let mut length = 0;

        let a_start = a_indptr[a_row].index();
        let a_stop = a_indptr[a_row + 1].index();
        for &a_col in &a_indices[a_start..a_stop] {
            let b_row = a_col.index();
            let b_start = b_indptr[b_row].index();
            let b_stop = b_indptr[b_row + 1].index();
            for b_col in &b_indices[b_start..b_stop] {
                let b_col = b_col.index();
                if !seen[b_col] {
                    seen[b_col] = true;
                    c_indices.push(I::from_usize(b_col));
                    length += 1;
                }
            }
        }
        c_indptr[a_row + 1] = c_indptr[a_row] + Iptr::from_usize(length);
        let c_start = c_indptr[a_row].index();
        let c_end = c_start + length;
        // TODO maybe sorting should be done outside, to have an even parallel
        // workload
        c_indices[c_start..c_end].sort_unstable();
        for c_col in &c_indices[c_start..c_end] {
            seen[c_col.index()] = false;
        }
    }
}
/// Compute the symbolic structure of the matrix product C = A * B, with
/// A, B and C stored in the CSR matrix format.
///
/// This algorithm has a complexity of O(n * k * log(k)), where k is the
/// average number of nonzeros in the rows of the result.
///
/// # Panics
///
/// `index.len()` should be equal to the maximum dimension among the input
/// matrices.
///
/// The matrices should be in proper CSR structure, and their dimensions
/// should be compatible. Failures to do so may result in out of bounds errors
/// (though some cases might go unnoticed).
///
/// # Minimizing allocations
///
/// This function will reserve
/// `a_indptr.last().unwrap() + b_indptr.last.unwrap()` in `c_indices`.
/// Therefore, to prevent this function from allocating, it is required
/// to have reserved at least this amount of memory.
Compute the symbolic structure of the matrix product C = A * B, with
A, B and C stored in the CSR matrix format.

This algorithm has a complexity of O(n * k * log(k)), where k is the
average number of nonzeros in the rows of the result.
Compute the symbolic structure of the matrix product C = A * B with A B and C stored in the CSR matrix format . This algorithm has a complexity of O ( n * k * log ( k )) where k is the average number of nonzeros in the rows of the result .
pub fn symbolic<Iptr: SpIndex, I: SpIndex>(
    a_indptr: &[Iptr],
    a_indices: &[I],
    b_cols: usize,
    b_indptr: &[Iptr],
    b_indices: &[I],
    c_indptr: &mut [Iptr],
    // TODO look for litterature on the nnz of C to be able to have a slice here
    c_indices: &mut Vec<I>,
    seen: &mut [bool],
) {
    assert!(a_indptr.len() == c_indptr.len());
    let a_rows = a_indptr.len() - 1;
    let b_rows = b_indptr.len() - 1;
    let a_nnz = a_indptr[a_rows].index();
    let b_nnz = b_indptr[b_rows].index();
    c_indices.clear();
    c_indices.reserve_exact(a_nnz + b_nnz);
    let ind_len = a_rows.max(b_rows.max(b_cols));
    assert!(seen.len() == ind_len);
    for elt in seen.iter_mut() {
        *elt = false;
    }
    c_indptr[0] = Iptr::from_usize(0);
    for a_row in 0..a_rows {
        let mut length = 0;
        let a_start = a_indptr[a_row].index();
        let a_stop = a_indptr[a_row + 1].index();
        for &a_col in &a_indices[a_start..a_stop] {
            let b_row = a_col.index();
            let b_start = b_indptr[b_row].index();
            let b_stop = b_indptr[b_row + 1].index();
            for b_col in &b_indices[b_start..b_stop] {
                let b_col = b_col.index();
                if !seen[b_col] {
                    seen[b_col] = true;
                    c_indices.push(I::from_usize(b_col));
                    length += 1;
                }
            }
        }
        c_indptr[a_row + 1] = c_indptr[a_row] + Iptr::from_usize(length);
        let c_start = c_indptr[a_row].index();
        let c_end = c_start + length;
        // TODO maybe sorting should be done outside, to have an even parallel
        // workload
        c_indices[c_start..c_end].sort_unstable();
        for c_col in &c_indices[c_start..c_end] {
            seen[c_col.index()] = false;
        }
    }
}
pub fn symbolic < Iptr : SpIndex , I : SpIndex > ( a_indptr : & [ Iptr ] , a_indices : & [ I ] , b_cols : usize , b_indptr : & [ Iptr ] , b_indices : & [ I ] , c_indptr : & mut [ Iptr ] , // TODO look for litterature on the nnz of C to be able to have a slice here c_indices : & mut Vec < I > , seen : & mut [ bool ] , ) { assert ! ( a_indptr len ( ) c_indptr len ( ) ) ; let a_rows = a_indptr . len ( ) - 1 ; let b_rows = b_indptr . len ( ) - 1 ; let a_nnz = a_indptr [ a_rows ] . index ( ) ; let b_nnz = b_indptr [ b_rows ] . index ( ) ; c_indices . clear ( ) ; c_indices . reserve_exact ( a_nnz + b_nnz ) ; let ind_len = a_rows . max ( b_rows . max ( b_cols ) ) ; assert ! ( seen len ( ) ind_len ) ; for elt in seen . iter_mut ( ) { * elt = false ; } c_indptr [ 0 ] = Iptr :: from_usize ( 0 ) ; for a_row in 0 .. a_rows { let mut length = 0 ; let a_start = a_indptr [ a_row ] . index ( ) ; let a_stop = a_indptr [ a_row + 1 ] . index ( ) ; for & a_col in & a_indices [ a_start .. a_stop ] { let b_row = a_col . index ( ) ; let b_start = b_indptr [ b_row ] . index ( ) ; let b_stop = b_indptr [ b_row + 1 ] . index ( ) ; for b_col in & b_indices [ b_start .. b_stop ] { let b_col = b_col . index ( ) ; if ! seen [ b_col ] { seen [ b_col ] = true ; c_indices . push ( I :: from_usize ( b_col ) ) ; length += 1 ; } } } c_indptr [ a_row + 1 ] = c_indptr [ a_row ] + Iptr :: from_usize ( length ) ; let c_start = c_indptr [ a_row ] . index ( ) ; let c_end = c_start + length ; // TODO maybe sorting should be done outside, to have an even parallel // workload c_indices [ c_start .. c_end ] . sort_unstable ( ) ; for c_col in & c_indices [ c_start .. c_end ] { seen [ c_col . index ( ) ] = false ; } } }
Compute the symbolic structure of the matrix product C = A * B, with
A, B and C stored in the CSR matrix format.
Compute the symbolic structure of the matrix product C = A * B with A B and C stored in the CSR matrix format .
a_indptr
&[Iptr]
a_indices
&[I]
b_cols
usize
b_indptr
&[Iptr]
b_indices
&[I]
c_indptr
&mut [Iptr]
c_indices
&mut Vec<I>
seen
&mut [bool]
a_indptr
&[Iptr]
a_indices
&[I]
b_cols
usize
b_indptr
&[Iptr]
b_indices
&[I]
c_indptr
&mut [Iptr]
c_indices
&mut Vec<I>
seen
&mut [bool]
panics
`index.len()` should be equal to the maximum dimension among the input
matrices.

The matrices should be in proper CSR structure, and their dimensions
should be compatible. Failures to do so may result in out of bounds errors
(though some cases might go unnoticed).
` index . len () ` should be equal to the maximum dimension among the input matrices . The matrices should be in proper CSR structure and their dimensions should be compatible . Failures to do so may result in out of bounds errors ( though some cases might go unnoticed ) .
minimizing allocations
This function will reserve
`a_indptr.last().unwrap() + b_indptr.last.unwrap()` in `c_indices`.
Therefore, to prevent this function from allocating, it is required
to have reserved at least this amount of memory.
This function will reserve ` a_indptr . last () . unwrap () + b_indptr . last . unwrap () ` in ` c_indices ` . Therefore to prevent this function from allocating it is required to have reserved at least this amount of memory .