cralgebra 0.2.1

A fast crypto algebra library
Documentation
use cralgebra::{algorithms::*, dists::*, ops::*, types::*};
use rand::{Rng, distributions::Distribution, rngs::mock::StepRng};
use std::hint::black_box;
use std::time::Instant;

fn bench_add<'a, C: 'a, T: ClosedAddDyn<C>>(name: &str, ctx: &'a C)
where
    StandardDyn<'a, C>: Distribution<T>,
{
    let mut rng = StepRng::new(0, 0x1234567898765431);
    let dist = StandardDyn::new(ctx);
    let mut a = black_box(rng.sample(&dist));
    let mut b: [T; 10] = black_box(std::array::from_fn(|_| black_box(rng.sample(&dist))));
    let t = Instant::now();
    for _ in 0..100 {
        a.add_assign_d(&b[0], ctx);
        a.add_assign_d(&b[1], ctx);
        a.add_assign_d(&b[2], ctx);
        a.add_assign_d(&b[3], ctx);
        a.add_assign_d(&b[4], ctx);
        a.add_assign_d(&b[5], ctx);
        a.add_assign_d(&b[6], ctx);
        a.add_assign_d(&b[7], ctx);
        a.add_assign_d(&b[8], ctx);
        a.add_assign_d(&b[9], ctx);
        a = black_box(a);
        b = black_box(b);
    }
    black_box(a);
    let cost = t.elapsed().div_f64(1000.0);
    println!("{name:.<40} {cost:9.1?}");
}

fn bench_mul<'a, C: 'a, T: ClosedMulDyn<C>>(name: &str, ctx: &'a C)
where
    StandardDyn<'a, C>: Distribution<T>,
{
    let mut rng = StepRng::new(0, 0x1234567898765431);
    let dist = StandardDyn::new(ctx);
    let mut a = black_box(rng.sample(&dist));
    let mut b: [T; 10] = black_box(std::array::from_fn(|_| black_box(rng.sample(&dist))));
    let t = Instant::now();
    for _ in 0..100 {
        a.mul_assign_d(&b[0], ctx);
        a.mul_assign_d(&b[1], ctx);
        a.mul_assign_d(&b[2], ctx);
        a.mul_assign_d(&b[3], ctx);
        a.mul_assign_d(&b[4], ctx);
        a.mul_assign_d(&b[5], ctx);
        a.mul_assign_d(&b[6], ctx);
        a.mul_assign_d(&b[7], ctx);
        a.mul_assign_d(&b[8], ctx);
        a.mul_assign_d(&b[9], ctx);
        a = black_box(a);
        b = black_box(b);
    }
    black_box(a);
    let cost = t.elapsed().div_f64(1000.0);
    println!("{name:.<40} {cost:9.1?}");
}

fn bench_closure<'a, C: 'a, W, T, F: Fn(&T, &T, &'a C) -> W>(name: &str, f: F, ctx: &'a C)
where
    StandardDyn<'a, C>: Distribution<T>,
{
    let mut rng = StepRng::new(0, 0x1234567898765431);
    let dist = StandardDyn::new(ctx);
    let mut b: [(T, T); 10] = black_box(std::array::from_fn(|_| {
        black_box((rng.sample(&dist), rng.sample(&dist)))
    }));
    let t = Instant::now();
    for _ in 0..100 {
        black_box(f(&b[0].0, &b[0].1, ctx));
        black_box(f(&b[1].0, &b[1].1, ctx));
        black_box(f(&b[2].0, &b[2].1, ctx));
        black_box(f(&b[3].0, &b[3].1, ctx));
        black_box(f(&b[4].0, &b[4].1, ctx));
        black_box(f(&b[5].0, &b[5].1, ctx));
        black_box(f(&b[6].0, &b[6].1, ctx));
        black_box(f(&b[7].0, &b[7].1, ctx));
        black_box(f(&b[8].0, &b[8].1, ctx));
        black_box(f(&b[9].0, &b[9].1, ctx));
        b = black_box(b);
    }
    let cost = t.elapsed().div_f64(1000.0);
    println!("{name:.<40} {cost:9.1?}");
}

fn main() {
    println!("\nClosedAddDyn");
    bench_add::<_, Z2_8>("Z2_8", &());
    bench_add::<_, Z2_16>("Z2_16", &());
    bench_add::<_, Z2_32>("Z2_32", &());
    bench_add::<_, Z2_64>("Z2_64", &());
    bench_add::<_, Z2_128>("Z2_128", &());

    bench_add::<_, Z2_64N<2>>("Z2_N<2>", &());
    bench_add::<_, Z2_64N<32>>("Z2_N<32>", &());

    bench_add::<_, ModularDyn<Z2_8>>(
        "ModularDyn<Z2_8>",
        &(ModularCtx::new(Z2_8::one_d(&()), &()), &()),
    );
    bench_add::<_, ModularDyn<Z2_16>>(
        "ModularDyn<Z2_16>",
        &(ModularCtx::new(Z2_16::one_d(&()), &()), &()),
    );
    bench_add::<_, ModularDyn<Z2_32>>(
        "ModularDyn<Z2_32>",
        &(ModularCtx::new(Z2_32::one_d(&()), &()), &()),
    );
    bench_add::<_, ModularDyn<Z2_64>>(
        "ModularDyn<Z2_64>",
        &(ModularCtx::new(Z2_64::one_d(&()), &()), &()),
    );
    bench_add::<_, ModularDyn<Z2_128>>(
        "ModularDyn<Z2_128>",
        &(ModularCtx::new(Z2_128::one_d(&()), &()), &()),
    );

    bench_add::<_, MontgomeryDyn<Z2_8>>(
        "MontgomeryDyn<Z2_8>",
        &(MontgomeryCtx::new(Z2_8::one_d(&()), &()), &()),
    );
    bench_add::<_, MontgomeryDyn<Z2_16>>(
        "MontgomeryDyn<Z2_16>",
        &(MontgomeryCtx::new(Z2_16::one_d(&()), &()), &()),
    );
    bench_add::<_, MontgomeryDyn<Z2_32>>(
        "MontgomeryDyn<Z2_32>",
        &(MontgomeryCtx::new(Z2_32::one_d(&()), &()), &()),
    );
    bench_add::<_, MontgomeryDyn<Z2_64>>(
        "MontgomeryDyn<Z2_64>",
        &(MontgomeryCtx::new(Z2_64::one_d(&()), &()), &()),
    );
    bench_add::<_, MontgomeryDyn<Z2_128>>(
        "MontgomeryDyn<Z2_128>",
        &(MontgomeryCtx::new(Z2_128::one_d(&()), &()), &()),
    );

    println!("\nClosedMulDyn");
    bench_mul::<_, Z2_8>("Z2_8", &());
    bench_mul::<_, Z2_16>("Z2_16", &());
    bench_mul::<_, Z2_32>("Z2_32", &());
    bench_mul::<_, Z2_64>("Z2_64", &());
    bench_mul::<_, Z2_128>("Z2_128", &());

    bench_mul::<_, Z2_64N<2>>("Z2_64N<2>", &());
    bench_mul::<_, Z2_64N<32>>("Z2_64N<32>", &());

    bench_mul::<_, ModularDyn<Z2_8>>(
        "ModularDyn<Z2_8> (L)",
        &(ModularCtx::new(Z2_8 { inner: 10 }, &()), &()),
    );
    bench_mul::<_, ModularDyn<Z2_8>>(
        "ModularDyn<Z2_8> (B)",
        &(ModularCtx::new(Z2_8 { inner: 1 << 6 }, &()), &()),
    );
    bench_mul::<_, ModularDyn<Z2_16>>(
        "ModularDyn<Z2_16> (L)",
        &(ModularCtx::new(Z2_16 { inner: 10 }, &()), &()),
    );
    bench_mul::<_, ModularDyn<Z2_16>>(
        "ModularDyn<Z2_16> (B)",
        &(ModularCtx::new(Z2_16 { inner: 1 << 10 }, &()), &()),
    );
    bench_mul::<_, ModularDyn<Z2_32>>(
        "ModularDyn<Z2_32> (L)",
        &(ModularCtx::new(Z2_32 { inner: 10 }, &()), &()),
    );
    bench_mul::<_, ModularDyn<Z2_32>>(
        "ModularDyn<Z2_32> (B)",
        &(ModularCtx::new(Z2_32 { inner: 1 << 18 }, &()), &()),
    );
    bench_mul::<_, ModularDyn<Z2_64>>(
        "ModularDyn<Z2_64> (L)",
        &(ModularCtx::new(Z2_64 { inner: 10 }, &()), &()),
    );
    bench_mul::<_, ModularDyn<Z2_64>>(
        "ModularDyn<Z2_64> (B)",
        &(ModularCtx::new(Z2_64 { inner: 1 << 34 }, &()), &()),
    );
    bench_mul::<_, ModularDyn<Z2_128>>(
        "ModularDyn<Z2_128> (L)",
        &(ModularCtx::new(Z2_128 { inner: 10 }, &()), &()),
    );
    bench_mul::<_, ModularDyn<Z2_128>>(
        "ModularDyn<Z2_128> (B)",
        &(ModularCtx::new(Z2_128 { inner: 1 << 66 }, &()), &()),
    );

    bench_mul::<_, MontgomeryDyn<Z2_8>>(
        "MontgomeryDyn<Z2_8>",
        &(MontgomeryCtx::new(Z2_8 { inner: 100 }, &()), &()),
    );
    bench_mul::<_, MontgomeryDyn<Z2_16>>(
        "MontgomeryDyn<Z2_16>",
        &(MontgomeryCtx::new(Z2_16 { inner: 10000 }, &()), &()),
    );
    bench_mul::<_, MontgomeryDyn<Z2_32>>(
        "MontgomeryDyn<Z2_32>",
        &(MontgomeryCtx::new(Z2_32 { inner: 100000000 }, &()), &()),
    );
    bench_mul::<_, MontgomeryDyn<Z2_64>>(
        "MontgomeryDyn<Z2_64>",
        &(
            MontgomeryCtx::new(
                Z2_64 {
                    inner: 10000000000000000,
                },
                &(),
            ),
            &(),
        ),
    );
    bench_mul::<_, MontgomeryDyn<Z2_128>>(
        "MontgomeryDyn<Z2_128>",
        &(
            MontgomeryCtx::new(
                Z2_128 {
                    inner: 100000000000000000000000000000000,
                },
                &(),
            ),
            &(),
        ),
    );

    println!("\nPowDyn");
    bench_closure(
        "ModularDyn<Z2_8> (2)",
        |a: &ModularDyn<Z2_8>, _, ctx| a.pow_d(&Z2_8 { inner: 100 }, ctx, &()),
        &(ModularCtx::new(Z2_8 { inner: 1 << 6 }, &()), &()),
    );
    bench_closure(
        "ModularDyn<Z2_8> (38)",
        |a: &ModularDyn<Z2_8>, _, ctx| {
            a.pow_d(
                &Z2_128 {
                    inner: 100000000000000000000000000000000000000,
                },
                ctx,
                &(),
            )
        },
        &(ModularCtx::new(Z2_8 { inner: 1 << 6 }, &()), &()),
    );
    bench_closure(
        "ModularDyn<Z2_128> (2)",
        |a: &ModularDyn<Z2_128>, _, ctx| a.pow_d(&Z2_8 { inner: 100 }, ctx, &()),
        &(ModularCtx::new(Z2_128 { inner: 1 << 66 }, &()), &()),
    );
    bench_closure(
        "ModularDyn<Z2_128> (38)",
        |a: &ModularDyn<Z2_128>, _, ctx| {
            a.pow_d(
                &Z2_128 {
                    inner: 100000000000000000000000000000000000000,
                },
                ctx,
                &(),
            )
        },
        &(ModularCtx::new(Z2_128 { inner: 1 << 66 }, &()), &()),
    );

    bench_closure(
        "MontgomeryDyn<Z2_8> (2)",
        |a: &MontgomeryDyn<Z2_8>, _, ctx| a.pow_d(&Z2_8 { inner: 100 }, ctx, &()),
        &(MontgomeryCtx::new(Z2_8 { inner: 1 << 6 }, &()), &()),
    );
    bench_closure(
        "MontgomeryDyn<Z2_8> (38)",
        |a: &MontgomeryDyn<Z2_8>, _, ctx| {
            a.pow_d(
                &Z2_128 {
                    inner: 100000000000000000000000000000000000000,
                },
                ctx,
                &(),
            )
        },
        &(MontgomeryCtx::new(Z2_8 { inner: 1 << 6 }, &()), &()),
    );
    bench_closure(
        "MontgomeryDyn<Z2_128> (2)",
        |a: &MontgomeryDyn<Z2_128>, _, ctx| a.pow_d(&Z2_8 { inner: 100 }, ctx, &()),
        &(MontgomeryCtx::new(Z2_128 { inner: 1 << 66 }, &()), &()),
    );
    bench_closure(
        "MontgomeryDyn<Z2_128> (38)",
        |a: &MontgomeryDyn<Z2_128>, _, ctx| {
            a.pow_d(
                &Z2_128 {
                    inner: 100000000000000000000000000000000000000,
                },
                ctx,
                &(),
            )
        },
        &(MontgomeryCtx::new(Z2_128 { inner: 1 << 66 }, &()), &()),
    );

    println!("\nInvDyn");
    bench_closure("Z2_8", |n: &Z2_8, _, ctx| n.inv_d(ctx), &());
    bench_closure("Z2_16", |n: &Z2_16, _, ctx| n.inv_d(ctx), &());
    bench_closure("Z2_32", |n: &Z2_32, _, ctx| n.inv_d(ctx), &());
    bench_closure("Z2_64", |n: &Z2_64, _, ctx| n.inv_d(ctx), &());
    bench_closure("Z2_128", |n: &Z2_128, _, ctx| n.inv_d(ctx), &());

    println!("\nnew");
    bench_closure(
        "ModularCtx<Z2_8, _>",
        |a: &Z2_8, _, ctx| ModularCtx::new(Z2_8 { inner: a.inner | 1 }, ctx),
        &(),
    );
    bench_closure(
        "ModularCtx<Z2_16, _>",
        |a: &Z2_16, _, ctx| ModularCtx::new(Z2_16 { inner: a.inner | 1 }, ctx),
        &(),
    );
    bench_closure(
        "ModularCtx<Z2_32, _>",
        |a: &Z2_32, _, ctx| ModularCtx::new(Z2_32 { inner: a.inner | 1 }, ctx),
        &(),
    );
    bench_closure(
        "ModularCtx<Z2_64, _>",
        |a: &Z2_64, _, ctx| ModularCtx::new(Z2_64 { inner: a.inner | 1 }, ctx),
        &(),
    );
    bench_closure(
        "ModularCtx<Z2_128, _>",
        |a: &Z2_128, _, ctx| ModularCtx::new(Z2_128 { inner: a.inner | 1 }, ctx),
        &(),
    );

    bench_closure(
        "MontgomeryCtx<Z2_8, _>",
        |a: &Z2_8, _, ctx| MontgomeryCtx::new(Z2_8 { inner: a.inner | 1 }, ctx),
        &(),
    );
    bench_closure(
        "MontgomeryCtx<Z2_16, _>",
        |a: &Z2_16, _, ctx| MontgomeryCtx::new(Z2_16 { inner: a.inner | 1 }, ctx),
        &(),
    );
    bench_closure(
        "MontgomeryCtx<Z2_32, _>",
        |a: &Z2_32, _, ctx| MontgomeryCtx::new(Z2_32 { inner: a.inner | 1 }, ctx),
        &(),
    );
    bench_closure(
        "MontgomeryCtx<Z2_64, _>",
        |a: &Z2_64, _, ctx| MontgomeryCtx::new(Z2_64 { inner: a.inner | 1 }, ctx),
        &(),
    );
    bench_closure(
        "MontgomeryCtx<Z2_128, _>",
        |a: &Z2_128, _, ctx| MontgomeryCtx::new(Z2_128 { inner: a.inner | 1 }, ctx),
        &(),
    );

    println!("\nmiller_rabin");
    bench_closure(
        "Z2_8",
        |n: &Z2_8, _, ctx| miller_rabin(n, &n.sub_d(&Z2_8::one_d(ctx), ctx), ctx),
        &(),
    );
    bench_closure(
        "Z2_16",
        |n: &Z2_16, _, ctx| miller_rabin(n, &n.sub_d(&Z2_16::one_d(ctx), ctx), ctx),
        &(),
    );
    bench_closure(
        "Z2_32",
        |n: &Z2_32, _, ctx| miller_rabin(n, &n.sub_d(&Z2_32::one_d(ctx), ctx), ctx),
        &(),
    );
    bench_closure(
        "Z2_64",
        |n: &Z2_64, _, ctx| miller_rabin(n, &n.sub_d(&Z2_64::one_d(ctx), ctx), ctx),
        &(),
    );
    bench_closure(
        "Z2_128",
        |n: &Z2_128, _, ctx| miller_rabin(n, &n.sub_d(&Z2_128::one_d(ctx), ctx), ctx),
        &(),
    );
}