arnaucube
arnaucube/miden-cryptoPublic Self-hosted repository
Updated doc comments
Paul-Henry Kajfasz kajfaszph@gmail.com
Wed, 21 Aug 2024 14:03:43 +0100
commit

e2aeb25e01fa5e59412653265ea7eed318ed7bfc

parent

790846cc73780fc276bc8324ddc8fa36c132d2a1

3 files changed, 32 insertions(+), 24 deletions(-)

jump to
M src/hash/rescue/arch/x86_64_avx2.rs → src/hash/rescue/arch/x86_64_avx2.rs

@@ -5,28 +5,38 @@ // https://github.com/0xPolygonZero/plonky2/blob/main/plonky2/src/hash/arch/x86_64/poseidon_goldilocks_avx2_bmi2.rs

// Preliminary notes: // 1. AVX does not support addition with carry but 128-bit (2-word) addition can be easily emulated. -// The method recognizes that for a + b overflowed iff (a + b) < a: i. res_lo = a_lo + b_lo ii. -// carry_mask = res_lo < a_lo iii. res_hi = a_hi + b_hi - carry_mask Notice that carry_mask is -// subtracted, not added. This is because AVX comparison instructions return -1 (all bits 1) for -// true and 0 for false. +// The method recognizes that for a + b overflowed iff (a + b) < a: +// - i. res_lo = a_lo + b_lo +// - ii. carry_mask = res_lo < a_lo +// - iii. res_hi = a_hi + b_hi - carry_mask Notice that carry_mask is subtracted, not added. +// This is because AVX comparison instructions return -1 (all bits 1) for true and 0 for false. // // 2. AVX does not have unsigned 64-bit comparisons. Those can be emulated with signed comparisons // by recognizing that a <u b iff a + (1 << 63) <s b + (1 << 63), where the addition wraps around // and the comparisons are unsigned and signed respectively. The shift function adds/subtracts 1 -// << 63 to enable this trick. Example: addition with carry. i. a_lo_s = shift(a_lo) ii. res_lo_s -// = a_lo_s + b_lo iii. carry_mask = res_lo_s <s a_lo_s iv. res_lo = shift(res_lo_s) v. res_hi = -// a_hi + b_hi - carry_mask The suffix _s denotes a value that has been shifted by 1 << 63. The -// result of addition is shifted if exactly one of the operands is shifted, as is the case on +// << 63 to enable this trick. Addition with carry example: +// - i. a_lo_s = shift(a_lo) +// - ii. res_lo_s = a_lo_s + b_lo +// - iii. carry_mask = res_lo_s <s a_lo_s +// - iv. res_lo = shift(res_lo_s) +// - v. res_hi = a_hi + b_hi - carry_mask The suffix _s denotes a value that has been +// shifted by 1 << 63. +// +// The result of addition is shifted if exactly one of the operands is shifted, as is the case on // line ii. Line iii. performs a signed comparison res_lo_s <s a_lo_s on shifted values to // emulate unsigned comparison res_lo <u a_lo on unshifted values. Finally, line iv. reverses the // shift so the result can be returned. When performing a chain of calculations, we can often // save instructions by letting the shift propagate through and only undoing it when necessary. -// For example, to compute the addition of three two-word (128-bit) numbers we can do: i. a_lo_s -// = shift(a_lo) ii. tmp_lo_s = a_lo_s + b_lo iii. tmp_carry_mask = tmp_lo_s <s a_lo_s iv. tmp_hi -// = a_hi + b_hi - tmp_carry_mask v. res_lo_s = tmp_lo_s + c_lo vi. res_carry_mask = res_lo_s <s -// tmp_lo_s vii. res_lo = shift(res_lo_s) viii. res_hi = tmp_hi + c_hi - res_carry_mask Notice -// that the above 3-value addition still only requires two calls to shift, just like our 2-value -// addition. +// For example, to compute the addition of three two-word (128-bit) numbers we can do: +// - i. a_lo_s = shift(a_lo) +// - ii. tmp_lo_s = a_lo_s + b_lo +// - iii. tmp_carry_mask = tmp_lo_s <s a_lo_s +// - iv. tmp_hi = a_hi + b_hi - tmp_carry_mask +// - v. res_lo_s = tmp_lo_s + c_lo vi. res_carry_mask = res_lo_s <s tmp_lo_s +// - vii. res_lo = shift(res_lo_s) +// - viii. res_hi = tmp_hi + c_hi - res_carry_mask +// Notice that the above 3-value addition still only requires two calls to shift, just like our +// 2-value addition. #[inline(always)] pub fn branch_hint() {
M src/hash/rescue/rpo/tests.rs → src/hash/rescue/rpo/tests.rs

@@ -59,8 +59,7 @@ RpoDigest::new(elements[4..].try_into().unwrap()),

]; let merge_result = Rpo256::merge(&digests); - // ------------- merge with domain = 0 - // ---------------------------------------------------------- + // ------------- merge with domain = 0 ------------- // set domain to ZERO. This should not change the result. let domain = ZERO;

@@ -68,8 +67,7 @@

let merge_in_domain_result = Rpo256::merge_in_domain(&digests, domain); assert_eq!(merge_result, merge_in_domain_result); - // ------------- merge with domain = 1 - // ---------------------------------------------------------- + // ------------- merge with domain = 1 ------------- // set domain to ONE. This should change the result. let domain = ONE;
M src/merkle/mmr/peaks.rs → src/merkle/mmr/peaks.rs

@@ -19,12 +19,12 @@ /// bits in `num_leaves` conveniently encode the size of each individual tree.

/// /// Examples: /// - /// - With 5 leaves, the binary `0b101`. The number of set bits is equal the number of - /// peaks, in this case there are 2 peaks. The 0-indexed least-significant position of the - /// bit determines the number of elements of a tree, so the rightmost tree has `2**0` - /// elements and the left most has `2**2`. - /// - With 12 leaves, the binary is `0b1100`, this case also has 2 peaks, the leftmost tree - /// has `2**3=8` elements, and the right most has `2**2=4` elements. + /// - With 5 leaves, the binary `0b101`. The number of set bits is equal the number of + /// peaks, in this case there are 2 peaks. The 0-indexed least-significant position of the + /// bit determines the number of elements of a tree, so the rightmost tree has `2**0` + /// elements and the left most has `2**2`. + /// - With 12 leaves, the binary is `0b1100`, this case also has 2 peaks, the leftmost tree + /// has `2**3=8` elements, and the right most has `2**2=4` elements. num_leaves: usize, /// All the peaks of every tree in the MMR forest. The peaks are always ordered by number of