rusticg 1.0.1

Reverses possible internal seeds of an LCG using a system of inequalities on the output of random calls
Documentation
use crate::math::component::big_matrix::BigMatrix;
use std::ops::{DivAssign, SubAssign};

#[inline(always)]
fn for_all<T: Fn(&mut BigMatrix)>(matrix: &mut BigMatrix, other: &mut Vec<BigMatrix>, action: T) {
    action(matrix);
    for x in other {
        action(x);
    }
}

pub fn reduce_with_action<T: Fn(usize, &Vec<i32>) -> bool>(
    matrix: &mut BigMatrix,
    action: T,
) -> Vec<i32> {
    reduce(matrix, &mut Vec::new(), action)
}

pub fn reduce_matrix(matrix: &mut BigMatrix) -> Vec<i32> {
    reduce(matrix, &mut Vec::new(), |_col: usize, _rows: &Vec<i32>| {
        true
    })
}

pub fn reduce<T: Fn(usize, &Vec<i32>) -> bool>(
    matrix: &mut BigMatrix,
    others: &mut Vec<BigMatrix>,
    action: T,
) -> Vec<i32> {
    let mut pivot_rows: Vec<i32> = Vec::with_capacity(matrix.column_count);
    for _i in 0..matrix.column_count {
        pivot_rows.push(-1);
    }

    let mut row: usize = 0;
    let mut pivot_column: usize = 0;

    while row < matrix.row_count && pivot_column < matrix.column_count {
        let mut pivot_row = row;
        while pivot_row < matrix.row_count {
            if *matrix.get(pivot_row, pivot_column) != 0 {
                break;
            }

            pivot_row += 1;
        }

        if pivot_row < matrix.row_count {
            let pivot = matrix.get(pivot_row, pivot_column).clone();

            for_all(matrix, others, |matrix| {
                matrix.get_row_mut(pivot_row).div_assign(&pivot)
            });

            for i in 0..matrix.row_count {
                if i == pivot_row {
                    continue;
                }

                let scale = matrix.get(i, pivot_column).clone();
                for_all(matrix, others, |matrix| {
                    let scaled_row = matrix.get_row(pivot_row) * &scale;
                    matrix.get_row_mut(i).sub_assign(scaled_row);
                });
            }

            for_all(matrix, others, |matrix| matrix.swap_rows(row, pivot_row));
            pivot_rows[pivot_column] = row as i32;
            row += 1;
        }

        loop {
            pivot_column += 1;
            if pivot_column >= matrix.column_count || action(pivot_column, &pivot_rows) {
                break;
            }
        }
    }

    pivot_rows
}