use criterion::{criterion_group, criterion_main, Criterion, Throughput};
use rand::rngs::mock::StepRng;

pub fn dot(c: &mut Criterion) {
    use smyl::maths::matrix::Matrix;

    let mut group = c.benchmark_group("dot");
    for (x, y, z) in &[
        (1, 2, 4),
        (10, 20, 16),
        (1, 784, 100),
        (100, 1, 10),
        (64, 64, 1),
    ] {
        let mut rng = StepRng::new(0, 1);
        let matrix_a: Matrix<f64> = Matrix::random(*x, *y, &mut rng);
        let matrix_b: Matrix<f64> = Matrix::random(*y, *z, &mut rng);

        group.throughput(Throughput::Bytes(1));
        group.bench_with_input(
            format!("{x}x{y}.{y}x{z}"),
            &(matrix_a, matrix_b),
            |b, (matrix_a, matrix_b)| {
                b.iter(|| matrix_a.clone().dot(matrix_b));
            },
        );
    }
    group.finish();
}

pub fn transpose(c: &mut Criterion) {
    use smyl::maths::matrix::Matrix;

    let mut group = c.benchmark_group("transpose");
    for (x, y) in &[(1, 2), (10, 20), (1, 784), (100, 1), (64, 64)] {
        let mut rng = StepRng::new(0, 1);
        let matrix: Matrix<f64> = Matrix::random(*x, *y, &mut rng);

        group.throughput(Throughput::Bytes(1));
        group.bench_with_input(format!("{x}x{y}"), &matrix, |b, matrix| {
            b.iter(|| matrix.transpose());
        });
    }
    group.finish();
}

pub fn matrix(c: &mut Criterion) {
    dot(c);
    transpose(c);
}

pub fn maths(c: &mut Criterion) { matrix(c); }

criterion_group!(benches, maths);
criterion_main!(benches);
