pub fn row_reduce(&mut self) -> usize {
        let p = self.p;
        self.initialize_pivots();

        let mut empty_rows = Vec::with_capacity(self.rows());

        if *self.p == 2 {
            // the m4ri C library uses a similar formula but with a hard cap of 7 instead of 8
            let k = std::cmp::min(8, crate::prime::log2(1 + self.rows()) * 3 / 4);
            let mut table = M4riTable::new(k, self.columns());

            for i in 0..self.rows() {
                table.reduce_naive(&mut *self, i);

                if let Some((c, _)) = self[i].first_nonzero() {
                    self.pivots[c] = i as isize;
                    for &row in table.rows() {
                        unsafe {
                            self.row_op(row, i, c, p);
                        }
                    }
                    table.add(c, i);

                    if table.len() == k {
                        table.generate(self);
                        for j in 0..table.rows()[0] {
                            table.reduce(self[j].limbs_mut());
                        }
                        for j in i + 1..self.rows() {
                            table.reduce(self[j].limbs_mut());
                        }
                        table.clear();
                    }
                } else {
                    empty_rows.push(i);
                }
            }
            if !table.is_empty() {
                table.generate(self);
                for j in 0..table.rows()[0] {
                    table.reduce(self[j].limbs_mut());
                }
                table.clear();
            }
        } else {
            for i in 0..self.rows() {
                if let Some((c, v)) = self[i].first_nonzero() {
                    self.pivots[c] = i as isize;
                    self[i].scale(prime::inverse(p, v));
                    for j in 0..self.rows() {
                        if i == j {
                            continue;
                        }
                        unsafe {
                            self.row_op(j, i, c, p);
                        }
                    }
                } else {
                    empty_rows.push(i);
                }
            }
        }

        // Now reorder the vectors. There are O(n) in-place permutation algorithms but the way we
        // get the permutation makes the naive strategy easier.
        let old_capacity = self.vectors.capacity();
        let mut old_rows = std::mem::replace(&mut self.vectors, Vec::with_capacity(old_capacity));

        for row in &mut self.pivots {
            if *row >= 0 {
                self.vectors.push(std::mem::replace(
                    &mut old_rows[*row as usize],
                    FpVector::new(p, 0),
                ));
                *row = self.vectors.len() as isize - 1;
            }
        }

        let num_rows = self.vectors.len();
        for row in empty_rows {
            self.vectors
                .push(std::mem::replace(&mut old_rows[row], FpVector::new(p, 0)))
        }
        num_rows
    }
/// Perform row reduction to reduce it to reduced row echelon form. This modifies the matrix in
/// place and records the pivots in `column_to_pivot_row`. The way the pivots are recorded is
/// that `column_to_pivot_row[i]` is the row of the pivot if the `i`th row contains a pivot,
/// and `-1` otherwise.
///
/// # Returns
/// The number of non-empty rows in the matrix
///
/// # Arguments
///  * `column_to_pivot_row` - A vector for the function to write the pivots into. The length
///  should be at least as long as the number of columns (and the extra entries are ignored).
///
/// # Example
/// ```
/// # use fp::prime::ValidPrime;
/// let p = ValidPrime::new(7);
/// # use fp::matrix::Matrix;
///
/// let input  = [vec![1, 3, 6],
///               vec![0, 3, 4]];
///
/// let result = [vec![1, 0, 2],
///               vec![0, 1, 6]];
///
/// let mut m = Matrix::from_vec(p, &input);
/// m.row_reduce();
///
/// assert_eq!(m, Matrix::from_vec(p, &result));
/// ```
Perform row reduction to reduce it to reduced row echelon form. This modifies the matrix in
place and records the pivots in `column_to_pivot_row`.
Perform row reduction to reduce it to reduced row echelon form . This modifies the matrix in place and records the pivots in ` column_to_pivot_row ` .
pub fn row_reduce(&mut self) -> usize {
        let p = self.p;
        self.initialize_pivots();
        let mut empty_rows = Vec::with_capacity(self.rows());
        if *self.p == 2 {
            // the m4ri C library uses a similar formula but with a hard cap of 7 instead of 8
            let k = std::cmp::min(8, crate::prime::log2(1 + self.rows()) * 3 / 4);
            let mut table = M4riTable::new(k, self.columns());
            for i in 0..self.rows() {
                table.reduce_naive(&mut *self, i);
                if let Some((c, _)) = self[i].first_nonzero() {
                    self.pivots[c] = i as isize;
                    for &row in table.rows() {
                        unsafe {
                            self.row_op(row, i, c, p);
                        }
                    }
                    table.add(c, i);
                    if table.len() == k {
                        table.generate(self);
                        for j in 0..table.rows()[0] {
                            table.reduce(self[j].limbs_mut());
                        }
                        for j in i + 1..self.rows() {
                            table.reduce(self[j].limbs_mut());
                        }
                        table.clear();
                    }
                } else {
                    empty_rows.push(i);
                }
            }
            if !table.is_empty() {
                table.generate(self);
                for j in 0..table.rows()[0] {
                    table.reduce(self[j].limbs_mut());
                }
                table.clear();
            }
        } else {
            for i in 0..self.rows() {
                if let Some((c, v)) = self[i].first_nonzero() {
                    self.pivots[c] = i as isize;
                    self[i].scale(prime::inverse(p, v));
                    for j in 0..self.rows() {
                        if i == j {
                            continue;
                        }
                        unsafe {
                            self.row_op(j, i, c, p);
                        }
                    }
                } else {
                    empty_rows.push(i);
                }
            }
        }
        // Now reorder the vectors. There are O(n) in-place permutation algorithms but the way we
        // get the permutation makes the naive strategy easier.
        let old_capacity = self.vectors.capacity();
        let mut old_rows = std::mem::replace(&mut self.vectors, Vec::with_capacity(old_capacity));
        for row in &mut self.pivots {
            if *row >= 0 {
                self.vectors.push(std::mem::replace(
                    &mut old_rows[*row as usize],
                    FpVector::new(p, 0),
                ));
                *row = self.vectors.len() as isize - 1;
            }
        }
        let num_rows = self.vectors.len();
        for row in empty_rows {
            self.vectors
                .push(std::mem::replace(&mut old_rows[row], FpVector::new(p, 0)))
        }
        num_rows
    }
pub fn row_reduce ( & mut self ) -> usize { let p = self . p ; self . initialize_pivots ( ) ; let mut empty_rows = Vec :: with_capacity ( self . rows ( ) ) ; if * self . p == 2 { // the m4ri C library uses a similar formula but with a hard cap of 7 instead of 8 let k = std :: cmp :: min ( 8 , crate :: prime :: log2 ( 1 + self . rows ( ) ) * 3 / 4 ) ; let mut table = M4riTable :: new ( k , self . columns ( ) ) ; for i in 0 .. self . rows ( ) { table . reduce_naive ( & mut * self , i ) ; if let Some ( ( c , _ ) ) = self [ i ] . first_nonzero ( ) { self . pivots [ c ] = i as isize ; for & row in table . rows ( ) { unsafe { self . row_op ( row , i , c , p ) ; } } table . add ( c , i ) ; if table . len ( ) == k { table . generate ( self ) ; for j in 0 .. table . rows ( ) [ 0 ] { table . reduce ( self [ j ] . limbs_mut ( ) ) ; } for j in i + 1 .. self . rows ( ) { table . reduce ( self [ j ] . limbs_mut ( ) ) ; } table . clear ( ) ; } } else { empty_rows . push ( i ) ; } } if ! table . is_empty ( ) { table . generate ( self ) ; for j in 0 .. table . rows ( ) [ 0 ] { table . reduce ( self [ j ] . limbs_mut ( ) ) ; } table . clear ( ) ; } } else { for i in 0 .. self . rows ( ) { if let Some ( ( c , v ) ) = self [ i ] . first_nonzero ( ) { self . pivots [ c ] = i as isize ; self [ i ] . scale ( prime :: inverse ( p , v ) ) ; for j in 0 .. self . rows ( ) { if i == j { continue ; } unsafe { self . row_op ( j , i , c , p ) ; } } } else { empty_rows . push ( i ) ; } } } // Now reorder the vectors. There are O(n) in-place permutation algorithms but the way we // get the permutation makes the naive strategy easier. let old_capacity = self . vectors . capacity ( ) ; let mut old_rows = std :: mem :: replace ( & mut self . vectors , Vec :: with_capacity ( old_capacity ) ) ; for row in & mut self . pivots { if * row >= 0 { self . vectors . push ( std :: mem :: replace ( & mut old_rows [ * row as usize ] , FpVector :: new ( p , 0 ) , ) ) ; * row = self . vectors . len ( ) as isize - 1 ; } } let num_rows = self . vectors . len ( ) ; for row in empty_rows { self . vectors . push ( std :: mem :: replace ( & mut old_rows [ row ] , FpVector :: new ( p , 0 ) ) ) } num_rows }
Perform row reduction to reduce it to reduced row echelon form.
Perform row reduction to reduce it to reduced row echelon form .
&mut self
The number of non-empty rows in the matrix
The number of non - empty rows in the matrix
&mut self
example
None
use fp::prime::validprime;
let p = ValidPrime::new(7).
let p = ValidPrime :: new ( 7 ) .
use fp::matrix::matrix;




let mut m = Matrix::from_vec(p, &input);
m.row_reduce().


let mut m = Matrix :: from_vec ( p &input ) ; m . row_reduce () .