provekit-skyscraper 0.1.0

Skyscraper hash function implementation over BN254
Documentation
use core::{array, cmp::Ordering};

#[inline(always)]
pub const fn add(l: [u64; 4], r: [u64; 4]) -> [u64; 4] {
    let (r, carry) = overflowing_add(l, r);
    debug_assert!(!carry);
    r
}

#[inline(always)]
pub fn addv<const N: usize>(l: [[u64; 4]; N], r: [[u64; 4]; N]) -> [[u64; 4]; N] {
    array::from_fn(|i| add(l[i], r[i]))
}

#[inline(always)]
pub const fn sub(l: [u64; 4], r: [u64; 4]) -> [u64; 4] {
    let (r, borrow) = overflowing_sub(l, r);
    debug_assert!(!borrow);
    r
}

#[inline(always)]
pub const fn wrapping_add(l: [u64; 4], r: [u64; 4]) -> [u64; 4] {
    overflowing_add(l, r).0
}

#[inline(always)]
pub const fn wrapping_sub(l: [u64; 4], r: [u64; 4]) -> [u64; 4] {
    overflowing_sub(l, r).0
}

#[inline(always)]
pub const fn overflowing_add(l: [u64; 4], r: [u64; 4]) -> ([u64; 4], bool) {
    let (r0, carry) = l[0].overflowing_add(r[0]);
    let (r1, carry) = l[1].carrying_add(r[1], carry);
    let (r2, carry) = l[2].carrying_add(r[2], carry);
    let (r3, carry) = l[3].carrying_add(r[3], carry);
    ([r0, r1, r2, r3], carry)
}

#[inline(always)]
pub const fn overflowing_sub(l: [u64; 4], r: [u64; 4]) -> ([u64; 4], bool) {
    let (r0, borrow) = l[0].overflowing_sub(r[0]);
    let (r1, borrow) = l[1].borrowing_sub(r[1], borrow);
    let (r2, borrow) = l[2].borrowing_sub(r[2], borrow);
    let (r3, borrow) = l[3].borrowing_sub(r[3], borrow);
    ([r0, r1, r2, r3], borrow)
}

pub fn less_than(l: [u64; 4], r: [u64; 4]) -> bool {
    for (l, r) in l.iter().rev().zip(r.iter().rev()) {
        match l.cmp(r) {
            Ordering::Less => return true,
            Ordering::Greater => return false,
            Ordering::Equal => {}
        }
    }
    false
}