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_vector::Dot;
use crate::math::component::big_vector::{MutViewBigVector, OwnedBigVector, ViewBigVector};
use crate::util::util::filled_vec;
use malachite::base::num::basic::traits::{One, Zero};
use malachite::rational::Rational;
use std::ops::{Add, Mul, Sub};

pub struct BigMatrix {
    pub numbers: Vec<Rational>,
    pub row_count: usize,
    pub column_count: usize,
}

impl BigMatrix {
    pub fn identity(size: usize) -> BigMatrix {
        let mut matrix = Self::new(size, size);

        for i in 0..size {
            matrix.set(i, i, Rational::ONE);
        }

        matrix
    }

    pub fn new(row_count: usize, column_count: usize) -> BigMatrix {
        BigMatrix {
            numbers: filled_vec(row_count * column_count, |_i| Rational::ZERO),
            row_count,
            column_count,
        }
    }

    pub fn new_provided<F: Fn(usize, usize) -> Rational>(
        row_count: usize,
        column_count: usize,
        generator: F,
    ) -> BigMatrix {
        let mut numbers: Vec<Rational> = Vec::with_capacity(row_count * column_count);

        for row in 0..row_count {
            for col in 0..column_count {
                numbers.push(generator(row, col));
            }
        }

        BigMatrix {
            numbers,
            row_count,
            column_count,
        }
    }

    pub fn is_square(&self) -> bool {
        self.row_count == self.column_count
    }

    pub fn get(&self, row: usize, col: usize) -> &Rational {
        &self.numbers[col + self.column_count * row]
    }

    pub fn set(&mut self, row: usize, col: usize, value: Rational) {
        self.numbers[col + self.column_count * row] = value;
    }

    pub fn get_row(&self, row: usize) -> ViewBigVector {
        ViewBigVector::new(self.column_count, &self.numbers, row * self.column_count, 1)
    }

    pub fn get_row_mut(&mut self, row: usize) -> MutViewBigVector {
        MutViewBigVector::new(
            self.column_count,
            &mut self.numbers,
            row * self.column_count,
            1,
        )
    }

    pub fn get_column(&self, column: usize) -> ViewBigVector {
        ViewBigVector::new(self.row_count, &self.numbers, column, self.column_count)
    }

    pub fn get_column_mut(&mut self, column: usize) -> MutViewBigVector {
        MutViewBigVector::new(self.row_count, &mut self.numbers, column, self.column_count)
    }

    pub fn set_row(&mut self, row: usize, value: OwnedBigVector) {
        let mut i = 0;
        for x in value.numbers {
            self.set(row, i, x);
            i += 1;
        }
    }

    pub fn set_column(&mut self, column: usize, value: OwnedBigVector) {
        let mut i = 0;
        for x in value.numbers {
            self.set(i, column, x);
            i += 1;
        }
    }

    pub fn shink(
        &mut self,
        start_row: usize,
        start_column: usize,
        row_count: usize,
        column_count: usize,
    ) {
        if start_row == 0
            && start_column == 0
            && self.row_count == row_count
            && self.column_count == column_count
        {
            return;
        }

        let old_numbers = std::mem::replace(
            &mut self.numbers,
            Vec::with_capacity(row_count * column_count),
        );

        let start = start_row * self.column_count + start_column;
        let skip = self.column_count - column_count;

        let mut iter = old_numbers.into_iter().skip(start);

        for _ in 0..row_count {
            for _ in 0..column_count {
                self.numbers.push(iter.next().unwrap());
            }

            for _ in 0..skip {
                iter.next();
            }
        }

        self.row_count = row_count;
        self.column_count = column_count;
    }

    pub fn transpose(&self) -> BigMatrix {
        let mut dest: BigMatrix = BigMatrix::new(self.row_count, self.column_count);

        for i in 0..self.column_count {
            dest.set_row(i, self.get_column(i).to_owned());
        }

        dest
    }

    pub fn swap_rows(&mut self, row1: usize, row2: usize) {
        let n = &mut self.numbers;

        for i in 0..self.column_count {
            n.swap(i + self.column_count * row1, i + self.column_count * row2);
        }
    }

    pub fn swap_elements(&mut self, row1: usize, col1: usize, row2: usize, col2: usize) {
        self.numbers.swap(
            col1 + self.column_count * row1,
            col2 + self.column_count * row2,
        );
    }
}

macro_rules! impl_for_owned_and_refs {
    ($macro: ident, $a: ty) => {
        $macro!($a, BigMatrix);
        $macro!(&$a, BigMatrix);
        $macro!($a, &BigMatrix);
        $macro!(&$a, &BigMatrix);
    };
}

macro_rules! impl_operation {
    ($a: ty, $b: ty, $t: ident, $m: ident, $f: tt) => {
        impl $t<$a> for $b {

            type Output = BigMatrix;

            fn $m(self, other: $a) -> BigMatrix {
                let mut vec: Vec<Rational> = Vec::with_capacity(self.row_count * self.column_count);
                for row in 0..self.row_count {
                    for col in 0..self.column_count {
                        vec.push(&*self.get(row, col) $f other.get(row, col))
                    }
                }

                BigMatrix {
                    numbers: vec,
                    row_count: self.row_count,
                    column_count: self.column_count
                }
            }

        }
    };
}

macro_rules! add {
    ($a: ty, $b: ty) => {
        impl_operation!($a, $b, Add, add, +);
    };
}
impl_for_owned_and_refs!(add, BigMatrix);

macro_rules! sub {
    ($a: ty, $b: ty) => {
        impl_operation!($a, $b, Sub, sub, -);
    };
}
impl_for_owned_and_refs!(sub, BigMatrix);

macro_rules! mul_with_vec {
    ($a: ty, $b: ty) => {
        impl Mul<$a> for $b {
            type Output = OwnedBigVector;

            fn mul(self, v: $a) -> OwnedBigVector {
                OwnedBigVector::new_from(self.row_count, |i| v.dot(&self.get_row(i)))
            }
        }
    };
}

impl_for_owned_and_refs!(mul_with_vec, OwnedBigVector);

macro_rules! mul_with_matrix {
    ($a: ty, $b: ty) => {
        impl Mul<$a> for $b {
            type Output = BigMatrix;

            fn mul(self, m: $a) -> BigMatrix {
                BigMatrix::new_provided(self.row_count, self.column_count, |row, col| {
                    self.get_row(row).dot(&m.get_column(col))
                })
            }
        }
    };
}

impl_for_owned_and_refs!(mul_with_matrix, BigMatrix);

impl Clone for BigMatrix {
    fn clone(&self) -> BigMatrix {
        BigMatrix {
            numbers: self.numbers.clone(),
            row_count: self.row_count,
            column_count: self.column_count,
        }
    }
}

impl PartialEq for BigMatrix {
    fn eq(&self, other: &Self) -> bool {
        if self.row_count != other.row_count || self.column_count != other.column_count {
            return false;
        }

        for row in 0..self.row_count {
            for col in 0..self.column_count {
                if self.get(row, col) != other.get(row, col) {
                    return false;
                }
            }
        }

        true
    }
}