mirror of
https://github.com/logos-storage/nim-groth16.git
synced 2026-01-02 21:53:09 +00:00
365 lines
9.1 KiB
C++
365 lines
9.1 KiB
C++
|
|
#include "fr_element.hpp"
|
||
|
|
#include <gmp.h>
|
||
|
|
#include <cstring>
|
||
|
|
|
||
|
|
static uint64_t Fr_rawq[] = {0x43e1f593f0000001,0x2833e84879b97091,0xb85045b68181585d,0x30644e72e131a029, 0};
|
||
|
|
static FrRawElement Fr_rawR2 = {0x1bb8e645ae216da7,0x53fe3ab1e35c59e3,0x8c49833d53bb8085,0x0216d0b17f4e44a5};
|
||
|
|
static uint64_t Fr_np = {0xc2e1f593efffffff};
|
||
|
|
static uint64_t lboMask = 0x3fffffffffffffff;
|
||
|
|
|
||
|
|
|
||
|
|
void Fr_rawAdd(FrRawElement pRawResult, const FrRawElement pRawA, const FrRawElement pRawB)
|
||
|
|
{
|
||
|
|
uint64_t carry = mpn_add_n(pRawResult, pRawA, pRawB, Fr_N64);
|
||
|
|
|
||
|
|
if(carry || mpn_cmp(pRawResult, Fr_rawq, Fr_N64) >= 0)
|
||
|
|
{
|
||
|
|
mpn_sub_n(pRawResult, pRawResult, Fr_rawq, Fr_N64);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Fr_rawAddLS(FrRawElement pRawResult, FrRawElement pRawA, uint64_t rawB)
|
||
|
|
{
|
||
|
|
uint64_t carry = mpn_add_1(pRawResult, pRawA, Fr_N64, rawB);
|
||
|
|
|
||
|
|
if(carry || mpn_cmp(pRawResult, Fr_rawq, Fr_N64) >= 0)
|
||
|
|
{
|
||
|
|
mpn_sub_n(pRawResult, pRawResult, Fr_rawq, Fr_N64);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Fr_rawSub(FrRawElement pRawResult, const FrRawElement pRawA, const FrRawElement pRawB)
|
||
|
|
{
|
||
|
|
uint64_t carry = mpn_sub_n(pRawResult, pRawA, pRawB, Fr_N64);
|
||
|
|
|
||
|
|
if(carry)
|
||
|
|
{
|
||
|
|
mpn_add_n(pRawResult, pRawResult, Fr_rawq, Fr_N64);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Fr_rawSubRegular(FrRawElement pRawResult, FrRawElement pRawA, FrRawElement pRawB)
|
||
|
|
{
|
||
|
|
mpn_sub_n(pRawResult, pRawA, pRawB, Fr_N64);
|
||
|
|
}
|
||
|
|
|
||
|
|
void Fr_rawSubSL(FrRawElement pRawResult, uint64_t rawA, FrRawElement pRawB)
|
||
|
|
{
|
||
|
|
FrRawElement pRawA = {rawA, 0, 0, 0};
|
||
|
|
|
||
|
|
uint64_t carry = mpn_sub_n(pRawResult, pRawA, pRawB, Fr_N64);
|
||
|
|
|
||
|
|
if(carry)
|
||
|
|
{
|
||
|
|
mpn_add_n(pRawResult, pRawResult, Fr_rawq, Fr_N64);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Fr_rawSubLS(FrRawElement pRawResult, FrRawElement pRawA, uint64_t rawB)
|
||
|
|
{
|
||
|
|
uint64_t carry = mpn_sub_1(pRawResult, pRawA, Fr_N64, rawB);
|
||
|
|
|
||
|
|
if(carry)
|
||
|
|
{
|
||
|
|
mpn_add_n(pRawResult, pRawResult, Fr_rawq, Fr_N64);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Fr_rawNeg(FrRawElement pRawResult, const FrRawElement pRawA)
|
||
|
|
{
|
||
|
|
const uint64_t zero[Fr_N64] = {0, 0, 0, 0};
|
||
|
|
|
||
|
|
if (mpn_cmp(pRawA, zero, Fr_N64) != 0)
|
||
|
|
{
|
||
|
|
mpn_sub_n(pRawResult, Fr_rawq, pRawA, Fr_N64);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
mpn_copyi(pRawResult, zero, Fr_N64);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Substracts a long element and a short element form 0
|
||
|
|
void Fr_rawNegLS(FrRawElement pRawResult, FrRawElement pRawA, uint64_t rawB)
|
||
|
|
{
|
||
|
|
uint64_t carry1 = mpn_sub_1(pRawResult, Fr_rawq, Fr_N64, rawB);
|
||
|
|
uint64_t carry2 = mpn_sub_n(pRawResult, pRawResult, pRawA, Fr_N64);
|
||
|
|
|
||
|
|
if (carry1 || carry2)
|
||
|
|
{
|
||
|
|
mpn_add_n(pRawResult, pRawResult, Fr_rawq, Fr_N64);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Fr_rawCopy(FrRawElement pRawResult, const FrRawElement pRawA)
|
||
|
|
{
|
||
|
|
pRawResult[0] = pRawA[0];
|
||
|
|
pRawResult[1] = pRawA[1];
|
||
|
|
pRawResult[2] = pRawA[2];
|
||
|
|
pRawResult[3] = pRawA[3];
|
||
|
|
}
|
||
|
|
|
||
|
|
int Fr_rawIsEq(const FrRawElement pRawA, const FrRawElement pRawB)
|
||
|
|
{
|
||
|
|
return mpn_cmp(pRawA, pRawB, Fr_N64) == 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
void Fr_rawMMul(FrRawElement pRawResult, const FrRawElement pRawA, const FrRawElement pRawB)
|
||
|
|
{
|
||
|
|
const mp_size_t N = Fr_N64+1;
|
||
|
|
const uint64_t *mq = Fr_rawq;
|
||
|
|
|
||
|
|
uint64_t np0;
|
||
|
|
|
||
|
|
uint64_t product0[N] = {0};
|
||
|
|
uint64_t product1[N] = {0};
|
||
|
|
uint64_t product2[N] = {0};
|
||
|
|
uint64_t product3[N] = {0};
|
||
|
|
|
||
|
|
product0[4] = mpn_mul_1(product0, pRawB, Fr_N64, pRawA[0]);
|
||
|
|
|
||
|
|
np0 = Fr_np * product0[0];
|
||
|
|
product1[1] = mpn_addmul_1(product0, mq, N, np0);
|
||
|
|
|
||
|
|
product1[4] = mpn_addmul_1(product1, pRawB, Fr_N64, pRawA[1]);
|
||
|
|
mpn_add(product1, product1, N, product0+1, N-1);
|
||
|
|
|
||
|
|
np0 = Fr_np * product1[0];
|
||
|
|
product2[1] = mpn_addmul_1(product1, mq, N, np0);
|
||
|
|
|
||
|
|
product2[4] = mpn_addmul_1(product2, pRawB, Fr_N64, pRawA[2]);
|
||
|
|
mpn_add(product2, product2, N, product1+1, N-1);
|
||
|
|
|
||
|
|
np0 = Fr_np * product2[0];
|
||
|
|
product3[1] = mpn_addmul_1(product2, mq, N, np0);
|
||
|
|
|
||
|
|
product3[4] = mpn_addmul_1(product3, pRawB, Fr_N64, pRawA[3]);
|
||
|
|
mpn_add(product3, product3, N, product2+1, N-1);
|
||
|
|
|
||
|
|
np0 = Fr_np * product3[0];
|
||
|
|
mpn_addmul_1(product3, mq, N, np0);
|
||
|
|
|
||
|
|
mpn_copyi(pRawResult, product3+1, Fr_N64);
|
||
|
|
|
||
|
|
if (mpn_cmp(pRawResult, mq, Fr_N64) >= 0)
|
||
|
|
{
|
||
|
|
mpn_sub_n(pRawResult, pRawResult, mq, Fr_N64);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Fr_rawMSquare(FrRawElement pRawResult, const FrRawElement pRawA)
|
||
|
|
{
|
||
|
|
Fr_rawMMul(pRawResult, pRawA, pRawA);
|
||
|
|
}
|
||
|
|
|
||
|
|
void Fr_rawMMul1(FrRawElement pRawResult, const FrRawElement pRawA, uint64_t pRawB)
|
||
|
|
{
|
||
|
|
const mp_size_t N = Fr_N64+1;
|
||
|
|
const uint64_t *mq = Fr_rawq;
|
||
|
|
|
||
|
|
uint64_t np0;
|
||
|
|
|
||
|
|
uint64_t product0[N] = {0};
|
||
|
|
uint64_t product1[N] = {0};
|
||
|
|
uint64_t product2[N] = {0};
|
||
|
|
uint64_t product3[N] = {0};
|
||
|
|
|
||
|
|
product0[4] = mpn_mul_1(product0, pRawA, Fr_N64, pRawB);
|
||
|
|
|
||
|
|
np0 = Fr_np * product0[0];
|
||
|
|
product1[1] = mpn_addmul_1(product0, mq, N, np0);
|
||
|
|
mpn_add(product1, product1, N, product0+1, N-1);
|
||
|
|
|
||
|
|
np0 = Fr_np * product1[0];
|
||
|
|
product2[1] = mpn_addmul_1(product1, mq, N, np0);
|
||
|
|
mpn_add(product2, product2, N, product1+1, N-1);
|
||
|
|
|
||
|
|
np0 = Fr_np * product2[0];
|
||
|
|
product3[1] = mpn_addmul_1(product2, mq, N, np0);
|
||
|
|
mpn_add(product3, product3, N, product2+1, N-1);
|
||
|
|
|
||
|
|
np0 = Fr_np * product3[0];
|
||
|
|
mpn_addmul_1(product3, mq, N, np0);
|
||
|
|
|
||
|
|
mpn_copyi(pRawResult, product3+1, Fr_N64);
|
||
|
|
|
||
|
|
if (mpn_cmp(pRawResult, mq, Fr_N64) >= 0)
|
||
|
|
{
|
||
|
|
mpn_sub_n(pRawResult, pRawResult, mq, Fr_N64);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Fr_rawToMontgomery(FrRawElement pRawResult, const FrRawElement &pRawA)
|
||
|
|
{
|
||
|
|
Fr_rawMMul(pRawResult, pRawA, Fr_rawR2);
|
||
|
|
}
|
||
|
|
|
||
|
|
void Fr_rawFromMontgomery(FrRawElement pRawResult, const FrRawElement &pRawA)
|
||
|
|
{
|
||
|
|
const mp_size_t N = Fr_N64+1;
|
||
|
|
const uint64_t *mq = Fr_rawq;
|
||
|
|
|
||
|
|
uint64_t np0;
|
||
|
|
|
||
|
|
uint64_t product0[N];
|
||
|
|
uint64_t product1[N] = {0};
|
||
|
|
uint64_t product2[N] = {0};
|
||
|
|
uint64_t product3[N] = {0};
|
||
|
|
|
||
|
|
mpn_copyi(product0, pRawA, Fr_N64); product0[4] = 0;
|
||
|
|
|
||
|
|
np0 = Fr_np * product0[0];
|
||
|
|
product1[1] = mpn_addmul_1(product0, mq, N, np0);
|
||
|
|
mpn_add(product1, product1, N, product0+1, N-1);
|
||
|
|
|
||
|
|
np0 = Fr_np * product1[0];
|
||
|
|
product2[1] = mpn_addmul_1(product1, mq, N, np0);
|
||
|
|
mpn_add(product2, product2, N, product1+1, N-1);
|
||
|
|
|
||
|
|
np0 = Fr_np * product2[0];
|
||
|
|
product3[1] = mpn_addmul_1(product2, mq, N, np0);
|
||
|
|
mpn_add(product3, product3, N, product2+1, N-1);
|
||
|
|
|
||
|
|
np0 = Fr_np * product3[0];
|
||
|
|
mpn_addmul_1(product3, mq, N, np0);
|
||
|
|
|
||
|
|
mpn_copyi(pRawResult, product3+1, Fr_N64);
|
||
|
|
|
||
|
|
if (mpn_cmp(pRawResult, mq, Fr_N64) >= 0)
|
||
|
|
{
|
||
|
|
mpn_sub_n(pRawResult, pRawResult, mq, Fr_N64);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
int Fr_rawIsZero(const FrRawElement rawA)
|
||
|
|
{
|
||
|
|
return mpn_zero_p(rawA, Fr_N64) ? 1 : 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
int Fr_rawCmp(FrRawElement pRawA, FrRawElement pRawB)
|
||
|
|
{
|
||
|
|
return mpn_cmp(pRawA, pRawB, Fr_N64);
|
||
|
|
}
|
||
|
|
|
||
|
|
void Fr_rawSwap(FrRawElement pRawResult, FrRawElement pRawA)
|
||
|
|
{
|
||
|
|
FrRawElement temp;
|
||
|
|
|
||
|
|
temp[0] = pRawResult[0];
|
||
|
|
temp[1] = pRawResult[1];
|
||
|
|
temp[2] = pRawResult[2];
|
||
|
|
temp[3] = pRawResult[3];
|
||
|
|
|
||
|
|
pRawResult[0] = pRawA[0];
|
||
|
|
pRawResult[1] = pRawA[1];
|
||
|
|
pRawResult[2] = pRawA[2];
|
||
|
|
pRawResult[3] = pRawA[3];
|
||
|
|
|
||
|
|
pRawA[0] = temp[0];
|
||
|
|
pRawA[1] = temp[1];
|
||
|
|
pRawA[2] = temp[2];
|
||
|
|
pRawA[3] = temp[3];
|
||
|
|
}
|
||
|
|
|
||
|
|
void Fr_rawCopyS2L(FrRawElement pRawResult, int64_t val)
|
||
|
|
{
|
||
|
|
pRawResult[0] = val;
|
||
|
|
pRawResult[1] = 0;
|
||
|
|
pRawResult[2] = 0;
|
||
|
|
pRawResult[3] = 0;
|
||
|
|
|
||
|
|
if (val < 0)
|
||
|
|
{
|
||
|
|
pRawResult[1] = -1;
|
||
|
|
pRawResult[2] = -1;
|
||
|
|
pRawResult[3] = -1;
|
||
|
|
|
||
|
|
mpn_add_n(pRawResult, pRawResult, Fr_rawq, Fr_N64);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Fr_rawAnd(FrRawElement pRawResult, FrRawElement pRawA, FrRawElement pRawB)
|
||
|
|
{
|
||
|
|
mpn_and_n(pRawResult, pRawA, pRawB, Fr_N64);
|
||
|
|
|
||
|
|
pRawResult[3] &= lboMask;
|
||
|
|
|
||
|
|
if (mpn_cmp(pRawResult, Fr_rawq, Fr_N64) >= 0)
|
||
|
|
{
|
||
|
|
mpn_sub_n(pRawResult, pRawResult, Fr_rawq, Fr_N64);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Fr_rawOr(FrRawElement pRawResult, FrRawElement pRawA, FrRawElement pRawB)
|
||
|
|
{
|
||
|
|
mpn_ior_n(pRawResult, pRawA, pRawB, Fr_N64);
|
||
|
|
|
||
|
|
pRawResult[3] &= lboMask;
|
||
|
|
|
||
|
|
if (mpn_cmp(pRawResult, Fr_rawq, Fr_N64) >= 0)
|
||
|
|
{
|
||
|
|
mpn_sub_n(pRawResult, pRawResult, Fr_rawq, Fr_N64);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Fr_rawXor(FrRawElement pRawResult, FrRawElement pRawA, FrRawElement pRawB)
|
||
|
|
{
|
||
|
|
mpn_xor_n(pRawResult, pRawA, pRawB, Fr_N64);
|
||
|
|
|
||
|
|
pRawResult[3] &= lboMask;
|
||
|
|
|
||
|
|
if (mpn_cmp(pRawResult, Fr_rawq, Fr_N64) >= 0)
|
||
|
|
{
|
||
|
|
mpn_sub_n(pRawResult, pRawResult, Fr_rawq, Fr_N64);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Fr_rawShl(FrRawElement r, FrRawElement a, uint64_t b)
|
||
|
|
{
|
||
|
|
uint64_t bit_shift = b % 64;
|
||
|
|
uint64_t word_shift = b / 64;
|
||
|
|
uint64_t word_count = Fr_N64 - word_shift;
|
||
|
|
|
||
|
|
mpn_copyi(r + word_shift, a, word_count);
|
||
|
|
std::memset(r, 0, word_shift * sizeof(uint64_t));
|
||
|
|
|
||
|
|
if (bit_shift)
|
||
|
|
{
|
||
|
|
mpn_lshift(r, r, Fr_N64, bit_shift);
|
||
|
|
}
|
||
|
|
|
||
|
|
r[3] &= lboMask;
|
||
|
|
|
||
|
|
if (mpn_cmp(r, Fr_rawq, Fr_N64) >= 0)
|
||
|
|
{
|
||
|
|
mpn_sub_n(r, r, Fr_rawq, Fr_N64);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Fr_rawShr(FrRawElement r, FrRawElement a, uint64_t b)
|
||
|
|
{
|
||
|
|
const uint64_t bit_shift = b % 64;
|
||
|
|
const uint64_t word_shift = b / 64;
|
||
|
|
const uint64_t word_count = Fr_N64 - word_shift;
|
||
|
|
|
||
|
|
mpn_copyi(r, a + word_shift, word_count);
|
||
|
|
std::memset(r + word_count, 0, word_shift * sizeof(uint64_t));
|
||
|
|
|
||
|
|
if (bit_shift)
|
||
|
|
{
|
||
|
|
mpn_rshift(r, r, Fr_N64, bit_shift);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Fr_rawNot(FrRawElement pRawResult, FrRawElement pRawA)
|
||
|
|
{
|
||
|
|
mpn_com(pRawResult, pRawA, Fr_N64);
|
||
|
|
|
||
|
|
pRawResult[3] &= lboMask;
|
||
|
|
|
||
|
|
if (mpn_cmp(pRawResult, Fr_rawq, Fr_N64) >= 0)
|
||
|
|
{
|
||
|
|
mpn_sub_n(pRawResult, pRawResult, Fr_rawq, Fr_N64);
|
||
|
|
}
|
||
|
|
}
|