2390 lines
46 KiB
C++
Raw Normal View History

2023-11-20 21:15:41 -07:00
#include "fr.hpp"
#include <cstdint>
#include <cstring>
#include <cassert>
FrElement Fr_q = {0, 0x80000000, {0x43e1f593f0000001,0x2833e84879b97091,0xb85045b68181585d,0x30644e72e131a029}};
FrElement Fr_R2 = {0, 0x80000000, {0x1bb8e645ae216da7,0x53fe3ab1e35c59e3,0x8c49833d53bb8085,0x0216d0b17f4e44a5}};
FrElement Fr_R3 = {0, 0x80000000, {0x5e94d8e1b4bf0040,0x2a489cbe1cfbb6b8,0x893cc664a19fcfed,0x0cf8594b7fcc657c}};
static FrRawElement half = {0xa1f0fac9f8000000,0x9419f4243cdcb848,0xdc2822db40c0ac2e,0x183227397098d014};
void Fr_copy(PFrElement r, const PFrElement a)
{
*r = *a;
}
void Fr_toNormal(PFrElement r, PFrElement a)
{
if (a->type == Fr_LONGMONTGOMERY)
{
r->type = Fr_LONG;
Fr_rawFromMontgomery(r->longVal, a->longVal);
}
else
{
Fr_copy(r, a);
}
}
static inline int has_mul32_overflow(int64_t val)
{
int64_t sign = val >> 31;
if (sign)
{
sign = ~sign;
}
return sign ? 1 : 0;
}
static inline int Fr_rawSMul(int64_t *r, int32_t a, int32_t b)
{
*r = (int64_t)a * b;
return has_mul32_overflow(*r);
}
static inline void mul_s1s2(PFrElement r, PFrElement a, PFrElement b)
{
int64_t result;
int overflow = Fr_rawSMul(&result, a->shortVal, b->shortVal);
if (overflow)
{
Fr_rawCopyS2L(r->longVal, result);
r->type = Fr_LONG;
r->shortVal = 0;
}
else
{
// done the same way as in intel asm implementation
r->shortVal = (int32_t)result;
r->type = Fr_SHORT;
//
Fr_rawCopyS2L(r->longVal, result);
r->type = Fr_LONG;
r->shortVal = 0;
}
}
static inline void mul_l1nl2n(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONGMONTGOMERY;
Fr_rawMMul(r->longVal, a->longVal, b->longVal);
Fr_rawMMul(r->longVal, r->longVal, Fr_R3.longVal);
}
static inline void mul_l1nl2m(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONG;
Fr_rawMMul(r->longVal, a->longVal, b->longVal);
}
static inline void mul_l1ml2m(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONGMONTGOMERY;
Fr_rawMMul(r->longVal, a->longVal, b->longVal);
}
static inline void mul_l1ml2n(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONG;
Fr_rawMMul(r->longVal, a->longVal, b->longVal);
}
static inline void mul_l1ns2n(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONGMONTGOMERY;
if (b->shortVal < 0)
{
int64_t b_shortVal = b->shortVal;
Fr_rawMMul1(r->longVal, a->longVal, -b_shortVal);
Fr_rawNeg(r->longVal, r->longVal);
}
else
{
Fr_rawMMul1(r->longVal, a->longVal, b->shortVal);
}
Fr_rawMMul(r->longVal, r->longVal, Fr_R3.longVal);
}
static inline void mul_s1nl2n(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONGMONTGOMERY;
if (a->shortVal < 0)
{
int64_t a_shortVal = a->shortVal;
Fr_rawMMul1(r->longVal, b->longVal, -a_shortVal);
Fr_rawNeg(r->longVal, r->longVal);
}
else
{
Fr_rawMMul1(r->longVal, b->longVal, a->shortVal);
}
Fr_rawMMul(r->longVal, r->longVal, Fr_R3.longVal);
}
static inline void mul_l1ms2n(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONG;
if (b->shortVal < 0)
{
int64_t b_shortVal = b->shortVal;
Fr_rawMMul1(r->longVal, a->longVal, -b_shortVal);
Fr_rawNeg(r->longVal, r->longVal);
}
else
{
Fr_rawMMul1(r->longVal, a->longVal, b->shortVal);
}
}
static inline void mul_s1nl2m(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONG;
if (a->shortVal < 0)
{
int64_t a_shortVal = a->shortVal;
Fr_rawMMul1(r->longVal, b->longVal, -a_shortVal);
Fr_rawNeg(r->longVal, r->longVal);
}
else
{
Fr_rawMMul1(r->longVal, b->longVal, a->shortVal);
}
}
static inline void mul_l1ns2m(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONG;
Fr_rawMMul(r->longVal, a->longVal, b->longVal);
}
static inline void mul_l1ms2m(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONGMONTGOMERY;
Fr_rawMMul(r->longVal, a->longVal, b->longVal);
}
static inline void mul_s1ml2m(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONGMONTGOMERY;
Fr_rawMMul(r->longVal, a->longVal, b->longVal);
}
static inline void mul_s1ml2n(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONG;
Fr_rawMMul(r->longVal, a->longVal, b->longVal);
}
void Fr_mul(PFrElement r, PFrElement a, PFrElement b)
{
if (a->type & Fr_LONG)
{
if (b->type & Fr_LONG)
{
if (a->type & Fr_MONTGOMERY)
{
if (b->type & Fr_MONTGOMERY)
{
mul_l1ml2m(r, a, b);
}
else
{
mul_l1ml2n(r, a, b);
}
}
else
{
if (b->type & Fr_MONTGOMERY)
{
mul_l1nl2m(r, a, b);
}
else
{
mul_l1nl2n(r, a, b);
}
}
}
else if (a->type & Fr_MONTGOMERY)
{
if (b->type & Fr_MONTGOMERY)
{
mul_l1ms2m(r, a, b);
}
else
{
mul_l1ms2n(r, a, b);
}
}
else
{
if (b->type & Fr_MONTGOMERY)
{
mul_l1ns2m(r, a, b);
}
else
{
mul_l1ns2n(r, a, b);
}
}
}
else if (b->type & Fr_LONG)
{
if (a->type & Fr_MONTGOMERY)
{
if (b->type & Fr_MONTGOMERY)
{
mul_s1ml2m(r, a, b);
}
else
{
mul_s1ml2n(r,a, b);
}
}
else if (b->type & Fr_MONTGOMERY)
{
mul_s1nl2m(r, a, b);
}
else
{
mul_s1nl2n(r, a, b);
}
}
else
{
mul_s1s2(r, a, b);
}
}
void Fr_toLongNormal(PFrElement r, PFrElement a)
{
if (a->type & Fr_LONG)
{
if (a->type & Fr_MONTGOMERY)
{
Fr_rawFromMontgomery(r->longVal, a->longVal);
r->type = Fr_LONG;
}
else
{
Fr_copy(r, a);
}
}
else
{
Fr_rawCopyS2L(r->longVal, a->shortVal);
r->type = Fr_LONG;
r->shortVal = 0;
}
}
void Fr_toMontgomery(PFrElement r, PFrElement a)
{
if (a->type & Fr_MONTGOMERY)
{
Fr_copy(r, a);
}
else if (a->type & Fr_LONG)
{
r->shortVal = a->shortVal;
Fr_rawMMul(r->longVal, a->longVal, Fr_R2.longVal);
r->type = Fr_LONGMONTGOMERY;
}
else if (a->shortVal < 0)
{
int64_t a_shortVal = a->shortVal;
Fr_rawMMul1(r->longVal, Fr_R2.longVal, -a_shortVal);
Fr_rawNeg(r->longVal, r->longVal);
r->type = Fr_SHORTMONTGOMERY;
}
else
{
Fr_rawMMul1(r->longVal, Fr_R2.longVal, a->shortVal);
r->type = Fr_SHORTMONTGOMERY;
}
}
void Fr_copyn(PFrElement r, PFrElement a, int n)
{
std::memcpy(r, a, n * sizeof(FrElement));
}
static inline int has_add32_overflow(int64_t val)
{
int64_t signs = (val >> 31) & 0x3;
return signs == 1 || signs == 2;
}
static inline int Fr_rawSSub(int64_t *r, int32_t a, int32_t b)
{
*r = (int64_t)a - b;
return has_add32_overflow(*r);
}
static inline void sub_s1s2(PFrElement r, PFrElement a, PFrElement b)
{
int64_t diff;
int overflow = Fr_rawSSub(&diff, a->shortVal, b->shortVal);
if (overflow)
{
Fr_rawCopyS2L(r->longVal, diff);
r->type = Fr_LONG;
r->shortVal = 0;
}
else
{
r->type = Fr_SHORT;
r->shortVal = (int32_t)diff;
}
}
static inline void sub_l1nl2n(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONG;
Fr_rawSub(r->longVal, a->longVal, b->longVal);
}
static inline void sub_l1nl2m(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONGMONTGOMERY;
FrElement a_m;
Fr_toMontgomery(&a_m, a);
Fr_rawSub(r->longVal, a_m.longVal, b->longVal);
}
static inline void sub_l1ml2m(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONGMONTGOMERY;
Fr_rawSub(r->longVal, a->longVal, b->longVal);
}
static inline void sub_l1ml2n(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONGMONTGOMERY;
FrElement b_m;
Fr_toMontgomery(&b_m, b);
Fr_rawSub(r->longVal, a->longVal, b_m.longVal);
}
static inline void sub_s1l2n(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONG;
if (a->shortVal >= 0)
{
Fr_rawSubSL(r->longVal, a->shortVal, b->longVal);
}
else
{
int64_t a_shortVal = a->shortVal;
Fr_rawNegLS(r->longVal, b->longVal, -a_shortVal);
}
}
static inline void sub_l1ms2n(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONGMONTGOMERY;
FrElement b_m;
Fr_toMontgomery(&b_m, b);
Fr_rawSub(r->longVal, a->longVal, b_m.longVal);
}
static inline void sub_s1nl2m(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONGMONTGOMERY;
FrElement a_m;
Fr_toMontgomery(&a_m, a);
Fr_rawSub(r->longVal, a_m.longVal, b->longVal);
}
static inline void sub_l1ns2(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONG;
if (b->shortVal < 0)
{
int64_t b_shortVal = b->shortVal;
Fr_rawAddLS(r->longVal, a->longVal, -b_shortVal);
}
else
{
Fr_rawSubLS(r->longVal, a->longVal, b->shortVal);
}
}
static inline void sub_l1ms2m(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONGMONTGOMERY;
Fr_rawSub(r->longVal, a->longVal, b->longVal);
}
static inline void sub_s1ml2m(PFrElement r,PFrElement a,PFrElement b)
{
r->type = Fr_LONGMONTGOMERY;
Fr_rawSub(r->longVal, a->longVal, b->longVal);
}
void Fr_sub(PFrElement r, PFrElement a, PFrElement b)
{
if (a->type & Fr_LONG)
{
if (b->type & Fr_LONG)
{
if (a->type & Fr_MONTGOMERY)
{
if (b->type & Fr_MONTGOMERY)
{
sub_l1ml2m(r, a, b);
}
else
{
sub_l1ml2n(r, a, b);
}
}
else if (b->type & Fr_MONTGOMERY)
{
sub_l1nl2m(r, a, b);
}
else
{
sub_l1nl2n(r, a, b);
}
}
else if (a->type & Fr_MONTGOMERY)
{
if (b->type & Fr_MONTGOMERY)
{
sub_l1ms2m(r, a, b);
}
else
{
sub_l1ms2n(r, a, b);
}
}
else
{
sub_l1ns2(r, a, b);
}
}
else if (b->type & Fr_LONG)
{
if (b->type & Fr_MONTGOMERY)
{
if (a->type & Fr_MONTGOMERY)
{
sub_s1ml2m(r,a,b);
}
else
{
sub_s1nl2m(r,a,b);
}
}
else
{
sub_s1l2n(r,a,b);
}
}
else
{
sub_s1s2(r, a, b);
}
}
static inline int Fr_rawSAdd(int64_t *r, int32_t a, int32_t b)
{
*r = (int64_t)a + b;
return has_add32_overflow(*r);
}
static inline void add_s1s2(PFrElement r, PFrElement a, PFrElement b)
{
int64_t sum;
int overflow = Fr_rawSAdd(&sum, a->shortVal, b->shortVal);
if (overflow)
{
Fr_rawCopyS2L(r->longVal, sum);
r->type = Fr_LONG;
r->shortVal = 0;
}
else
{
r->type = Fr_SHORT;
r->shortVal = (int32_t)sum;
}
}
static inline void add_l1nl2n(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONG;
Fr_rawAdd(r->longVal, a->longVal, b->longVal);
}
static inline void add_l1nl2m(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONGMONTGOMERY;
FrElement a_m;
Fr_toMontgomery(&a_m, a);
Fr_rawAdd(r->longVal, a_m.longVal, b->longVal);
}
static inline void add_l1ml2m(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONGMONTGOMERY;
Fr_rawAdd(r->longVal, a->longVal, b->longVal);
}
static inline void add_l1ml2n(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONGMONTGOMERY;
FrElement b_m;
Fr_toMontgomery(&b_m, b);
Fr_rawAdd(r->longVal, a->longVal, b_m.longVal);
}
static inline void add_s1l2n(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONG;
if (a->shortVal >= 0)
{
Fr_rawAddLS(r->longVal, b->longVal, a->shortVal);
}
else
{
int64_t a_shortVal = a->shortVal;
Fr_rawSubLS(r->longVal, b->longVal, -a_shortVal);
}
}
static inline void add_l1ms2n(PFrElement r, PFrElement a, PFrElement b)
{
FrElement b_m;
r->type = Fr_LONGMONTGOMERY;
Fr_toMontgomery(&b_m, b);
Fr_rawAdd(r->longVal, a->longVal, b_m.longVal);
}
static inline void add_s1nl2m(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONGMONTGOMERY;
FrElement m_a;
Fr_toMontgomery(&m_a, a);
Fr_rawAdd(r->longVal, m_a.longVal, b->longVal);
}
static inline void add_l1ns2(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONG;
if (b->shortVal >= 0)
{
Fr_rawAddLS(r->longVal, a->longVal, b->shortVal);
}
else
{
int64_t b_shortVal = b->shortVal;
Fr_rawSubLS(r->longVal, a->longVal, -b_shortVal);
}
}
static inline void add_l1ms2m(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONGMONTGOMERY;
Fr_rawAdd(r->longVal, a->longVal, b->longVal);
}
static inline void add_s1ml2m(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONGMONTGOMERY;
Fr_rawAdd(r->longVal, a->longVal, b->longVal);
}
void Fr_add(PFrElement r, PFrElement a, PFrElement b)
{
if (a->type & Fr_LONG)
{
if (b->type & Fr_LONG)
{
if (a->type & Fr_MONTGOMERY)
{
if (b->type & Fr_MONTGOMERY)
{
add_l1ml2m(r, a, b);
}
else
{
add_l1ml2n(r, a, b);
}
}
else
{
if (b->type & Fr_MONTGOMERY)
{
add_l1nl2m(r, a, b);
}
else
{
add_l1nl2n(r, a, b);
}
}
}
else if (a->type & Fr_MONTGOMERY)
{
if (b->type & Fr_MONTGOMERY)
{
add_l1ms2m(r, a, b);
}
else
{
add_l1ms2n(r, a, b);
}
}
else
{
add_l1ns2(r, a, b);
}
}
else if (b->type & Fr_LONG)
{
if (b->type & Fr_MONTGOMERY)
{
if (a->type & Fr_MONTGOMERY)
{
add_s1ml2m(r, a, b);
}
else
{
add_s1nl2m(r, a, b);
}
}
else
{
add_s1l2n(r, a, b);
}
}
else
{
add_s1s2(r, a, b);
}
}
int Fr_isTrue(PFrElement pE)
{
int result;
if (pE->type & Fr_LONG)
{
result = !Fr_rawIsZero(pE->longVal);
}
else
{
result = pE->shortVal != 0;
}
return result;
}
int Fr_longNeg(PFrElement pE)
{
if(Fr_rawCmp(pE->longVal, Fr_q.longVal) >= 0)
{
Fr_longErr();
return 0;
}
int64_t result = pE->longVal[0] - Fr_q.longVal[0];
int64_t is_long = (result >> 31) + 1;
if(is_long)
{
Fr_longErr();
return 0;
}
return result;
}
int Fr_longNormal(PFrElement pE)
{
uint64_t is_long = 0;
uint64_t result;
result = pE->longVal[0];
is_long = result >> 31;
if (is_long)
{
return Fr_longNeg(pE);
}
if (pE->longVal[1] || pE->longVal[2] || pE->longVal[3])
{
return Fr_longNeg(pE);
}
return result;
}
// Convert a 64 bit integer to a long format field element
int Fr_toInt(PFrElement pE)
{
int result;
if (pE->type & Fr_LONG)
{
if (pE->type & Fr_MONTGOMERY)
{
FrElement e_n;
Fr_toNormal(&e_n, pE);
result = Fr_longNormal(&e_n);
}
else
{
result = Fr_longNormal(pE);
}
}
else
{
result = pE->shortVal;
}
return result;
}
static inline int rlt_s1s2(PFrElement a, PFrElement b)
{
return (a->shortVal < b->shortVal) ? 1 : 0;
}
static inline int rltRawL1L2(FrRawElement pRawA, FrRawElement pRawB)
{
int result = Fr_rawCmp(pRawB, pRawA);
return result > 0 ? 1 : 0;
}
static inline int rltl1l2_n1(FrRawElement pRawA, FrRawElement pRawB)
{
int result = Fr_rawCmp(half, pRawB);
if (result < 0)
{
return rltRawL1L2(pRawA, pRawB);
}
return 1;
}
static inline int rltl1l2_p1(FrRawElement pRawA, FrRawElement pRawB)
{
int result = Fr_rawCmp(half, pRawB);
if (result < 0)
{
return 0;
}
return rltRawL1L2(pRawA, pRawB);
}
static inline int rltL1L2(FrRawElement pRawA, FrRawElement pRawB)
{
int result = Fr_rawCmp(half, pRawA);
if (result < 0)
{
return rltl1l2_n1(pRawA, pRawB);
}
return rltl1l2_p1(pRawA, pRawB);
}
static inline int rlt_l1nl2n(PFrElement a, PFrElement b)
{
return rltL1L2(a->longVal, b->longVal);
}
static inline int rlt_l1nl2m(PFrElement a, PFrElement b)
{
FrElement b_n;
Fr_toNormal(&b_n, b);
return rltL1L2(a->longVal, b_n.longVal);
}
static inline int rlt_l1ml2m(PFrElement a, PFrElement b)
{
FrElement a_n;
FrElement b_n;
Fr_toNormal(&a_n, a);
Fr_toNormal(&b_n, b);
return rltL1L2(a_n.longVal, b_n.longVal);
}
static inline int rlt_l1ml2n(PFrElement a, PFrElement b)
{
FrElement a_n;
Fr_toNormal(&a_n, a);
return rltL1L2(a_n.longVal, b->longVal);
}
static inline int rlt_s1l2n(PFrElement a,PFrElement b)
{
FrElement a_n;
Fr_toLongNormal(&a_n,a);
return rltL1L2(a_n.longVal, b->longVal);
}
static inline int rlt_l1ms2(PFrElement a, PFrElement b)
{
FrElement a_n;
FrElement b_ln;
Fr_toLongNormal(&b_ln ,b);
Fr_toNormal(&a_n, a);
return rltL1L2(a_n.longVal, b_ln.longVal);
}
static inline int rlt_s1l2m(PFrElement a, PFrElement b)
{
FrElement a_n;
FrElement b_n;
Fr_toLongNormal(&a_n, a);
Fr_toNormal(&b_n, b);
return rltL1L2(a_n.longVal, b_n.longVal);
}
static inline int rlt_l1ns2(PFrElement a, PFrElement b)
{
FrElement b_n;
Fr_toLongNormal(&b_n, b);
return rltL1L2(a->longVal, b_n.longVal);
}
int32_t Fr_rlt(PFrElement a, PFrElement b)
{
int32_t result;
if (a->type & Fr_LONG)
{
if (b->type & Fr_LONG)
{
if (a->type & Fr_MONTGOMERY)
{
if (b->type & Fr_MONTGOMERY)
{
result = rlt_l1ml2m(a, b);
}
else
{
result = rlt_l1ml2n(a, b);
}
}
else if (b->type & Fr_MONTGOMERY)
{
result = rlt_l1nl2m(a, b);
}
else
{
result = rlt_l1nl2n(a, b);
}
}
else if (a->type & Fr_MONTGOMERY)
{
result = rlt_l1ms2(a, b);
}
else
{
result = rlt_l1ns2(a, b);
}
}
else if (b->type & Fr_LONG)
{
if (b->type & Fr_MONTGOMERY)
{
result = rlt_s1l2m(a,b);
}
else
{
result = rlt_s1l2n(a,b);
}
}
else
{
result = rlt_s1s2(a, b);
}
return result;
}
void Fr_lt(PFrElement r, PFrElement a, PFrElement b)
{
r->shortVal = Fr_rlt(a, b);
r->type = Fr_SHORT;
}
void Fr_geq(PFrElement r, PFrElement a, PFrElement b)
{
int32_t result = Fr_rlt(a, b);
result ^= 0x1;
r->shortVal = result;
r->type = Fr_SHORT;
}
static inline int Fr_rawSNeg(int64_t *r, int32_t a)
{
*r = -(int64_t)a;
return has_add32_overflow(*r);
}
void Fr_neg(PFrElement r, PFrElement a)
{
if (a->type & Fr_LONG)
{
r->type = a->type;
r->shortVal = a->shortVal;
Fr_rawNeg(r->longVal, a->longVal);
}
else
{
int64_t a_shortVal;
int overflow = Fr_rawSNeg(&a_shortVal, a->shortVal);
if (overflow)
{
Fr_rawCopyS2L(r->longVal, a_shortVal);
r->type = Fr_LONG;
r->shortVal = 0;
}
else
{
r->type = Fr_SHORT;
r->shortVal = (int32_t)a_shortVal;
}
}
}
static inline int reqL1L2(FrRawElement pRawA, FrRawElement pRawB)
{
return Fr_rawCmp(pRawB, pRawA) == 0;
}
static inline int req_s1s2(PFrElement r, PFrElement a, PFrElement b)
{
return (a->shortVal == b->shortVal) ? 1 : 0;
}
static inline int req_l1nl2n(PFrElement r, PFrElement a, PFrElement b)
{
return reqL1L2(a->longVal, b->longVal);
}
static inline int req_l1nl2m(PFrElement r, PFrElement a, PFrElement b)
{
FrElement a_m;
Fr_toMontgomery(&a_m, a);
return reqL1L2(a_m.longVal, b->longVal);
}
static inline int req_l1ml2m(PFrElement r, PFrElement a, PFrElement b)
{
return reqL1L2(a->longVal, b->longVal);
}
static inline int req_l1ml2n(PFrElement r, PFrElement a, PFrElement b)
{
FrElement b_m;
Fr_toMontgomery(&b_m, b);
return reqL1L2(a->longVal, b_m.longVal);
}
static inline int req_s1l2n(PFrElement r, PFrElement a, PFrElement b)
{
FrElement a_n;
Fr_toLongNormal(&a_n, a);
return reqL1L2(a_n.longVal, b->longVal);
}
static inline int req_l1ms2(PFrElement r, PFrElement a, PFrElement b)
{
FrElement b_m;
Fr_toMontgomery(&b_m, b);
return reqL1L2(a->longVal, b_m.longVal);
}
static inline int req_s1l2m(PFrElement r, PFrElement a, PFrElement b)
{
FrElement a_m;
Fr_toMontgomery(&a_m, a);
return reqL1L2(a_m.longVal, b->longVal);
}
static inline int req_l1ns2(PFrElement r, PFrElement a, PFrElement b)
{
FrElement b_n;
Fr_toLongNormal(&b_n, b);
return reqL1L2(a->longVal, b_n.longVal);
}
// Compares two elements of any kind
int Fr_req(PFrElement r, PFrElement a, PFrElement b)
{
int result;
if (a->type & Fr_LONG)
{
if (b->type & Fr_LONG)
{
if (a->type & Fr_MONTGOMERY)
{
if (b->type & Fr_MONTGOMERY)
{
result = req_l1ml2m(r, a, b);
}
else
{
result = req_l1ml2n(r, a, b);
}
}
else if (b->type & Fr_MONTGOMERY)
{
result = req_l1nl2m(r, a, b);
}
else
{
result = req_l1nl2n(r, a, b);
}
}
else if (a->type & Fr_MONTGOMERY)
{
result = req_l1ms2(r, a, b);
}
else
{
result = req_l1ns2(r, a, b);
}
}
else if (b->type & Fr_LONG)
{
if (b->type & Fr_MONTGOMERY)
{
result = req_s1l2m(r, a, b);
}
else
{
result = req_s1l2n(r, a, b);
}
}
else
{
result = req_s1s2(r, a, b);
}
return result;
}
void Fr_eq(PFrElement r, PFrElement a, PFrElement b)
{
r->shortVal = Fr_req(r, a, b);
r->type = Fr_SHORT;
}
void Fr_neq(PFrElement r, PFrElement a, PFrElement b)
{
int result = Fr_req(r, a, b);
r->shortVal = result ^ 0x1;
r->type = Fr_SHORT;
}
// Logical or between two elements
void Fr_lor(PFrElement r, PFrElement a, PFrElement b)
{
int32_t is_true_a;
if (a->type & Fr_LONG)
{
is_true_a = !Fr_rawIsZero(a->longVal);
}
else
{
is_true_a = a->shortVal ? 1 : 0;
}
int32_t is_true_b;
if (b->type & Fr_LONG)
{
is_true_b = !Fr_rawIsZero(b->longVal);
}
else
{
is_true_b = b->shortVal ? 1 : 0;
}
r->shortVal = is_true_a | is_true_b;
r->type = Fr_SHORT;
}
void Fr_lnot(PFrElement r, PFrElement a)
{
if (a->type & Fr_LONG)
{
r->shortVal = Fr_rawIsZero(a->longVal);
}
else
{
r->shortVal = a->shortVal ? 0 : 1;
}
r->type = Fr_SHORT;
}
static inline int rgt_s1s2(PFrElement a, PFrElement b)
{
return (a->shortVal > b->shortVal) ? 1 : 0;
}
static inline int rgtRawL1L2(FrRawElement pRawA, FrRawElement pRawB)
{
int result = Fr_rawCmp(pRawB, pRawA);
return (result < 0) ? 1 : 0;
}
static inline int rgtl1l2_n1(FrRawElement pRawA, FrRawElement pRawB)
{
int result = Fr_rawCmp(half, pRawB);
if (result < 0)
{
return rgtRawL1L2(pRawA, pRawB);
}
return 0;
}
static inline int rgtl1l2_p1(FrRawElement pRawA, FrRawElement pRawB)
{
int result = Fr_rawCmp(half, pRawB);
if (result < 0)
{
return 1;
}
return rgtRawL1L2(pRawA, pRawB);
}
static inline int rgtL1L2(FrRawElement pRawA, FrRawElement pRawB)
{
int result = Fr_rawCmp(half, pRawA);
if (result < 0)
{
return rgtl1l2_n1(pRawA, pRawB);
}
return rgtl1l2_p1(pRawA, pRawB);
}
static inline int rgt_l1nl2n(PFrElement a, PFrElement b)
{
return rgtL1L2(a->longVal, b->longVal);
}
static inline int rgt_l1nl2m(PFrElement a, PFrElement b)
{
FrElement b_n;
Fr_toNormal(&b_n, b);
return rgtL1L2(a->longVal, b_n.longVal);
}
static inline int rgt_l1ml2m(PFrElement a, PFrElement b)
{
FrElement a_n;
FrElement b_n;
Fr_toNormal(&a_n, a);
Fr_toNormal(&b_n, b);
return rgtL1L2(a_n.longVal, b_n.longVal);
}
static inline int rgt_l1ml2n(PFrElement a, PFrElement b)
{
FrElement a_n;
Fr_toNormal(&a_n, a);
return rgtL1L2(a_n.longVal, b->longVal);
}
static inline int rgt_s1l2n(PFrElement a, PFrElement b)
{
FrElement a_n;
Fr_toLongNormal(&a_n, a);
return rgtL1L2(a_n.longVal, b->longVal);
}
static inline int rgt_l1ms2(PFrElement a, PFrElement b)
{
FrElement a_n;
FrElement b_n;
Fr_toNormal(&a_n, a);
Fr_toLongNormal(&b_n, b);
return rgtL1L2(a_n.longVal, b_n.longVal);
}
static inline int rgt_s1l2m(PFrElement a, PFrElement b)
{
FrElement a_n;
FrElement b_n;
Fr_toLongNormal(&a_n, a);
Fr_toNormal(&b_n, b);
return rgtL1L2(a_n.longVal, b_n.longVal);
}
static inline int rgt_l1ns2(PFrElement a, PFrElement b)
{
FrElement b_n;
Fr_toLongNormal(&b_n, b);
return rgtL1L2(a->longVal, b_n.longVal);
}
int Fr_rgt(PFrElement r, PFrElement a, PFrElement b)
{
int result = 0;
if (a->type & Fr_LONG)
{
if (b->type & Fr_LONG)
{
if (a->type & Fr_MONTGOMERY)
{
if (b->type & Fr_MONTGOMERY)
{
result = rgt_l1ml2m(a, b);
}
else
{
result = rgt_l1ml2n(a, b);
}
}
else if (b->type & Fr_MONTGOMERY)
{
result = rgt_l1nl2m(a, b);
}
else
{
result = rgt_l1nl2n(a, b);
}
}
else if (a->type & Fr_MONTGOMERY)
{
result = rgt_l1ms2(a, b);
}
else
{
result = rgt_l1ns2(a, b);
}
}
else if (b->type & Fr_LONG)
{
if (b->type & Fr_MONTGOMERY)
{
result = rgt_s1l2m(a, b);
}
else
{
result = rgt_s1l2n(a,b);
}
}
else
{
result = rgt_s1s2(a, b);
}
return result;
}
void Fr_gt(PFrElement r, PFrElement a, PFrElement b)
{
r->shortVal = Fr_rgt(r, a, b);
r->type = Fr_SHORT;
}
void Fr_leq(PFrElement r, PFrElement a, PFrElement b)
{
int32_t result = Fr_rgt(r, a, b);
result ^= 0x1;
r->shortVal = result;
r->type = Fr_SHORT;
}
// Logical and between two elements
void Fr_land(PFrElement r, PFrElement a, PFrElement b)
{
int32_t is_true_a;
if (a->type & Fr_LONG)
{
is_true_a = !Fr_rawIsZero(a->longVal);
}
else
{
is_true_a = a->shortVal ? 1 : 0;
}
int32_t is_true_b;
if (b->type & Fr_LONG)
{
is_true_b = !Fr_rawIsZero(b->longVal);
}
else
{
is_true_b = b->shortVal ? 1 : 0;
}
r->shortVal = is_true_a & is_true_b;
r->type = Fr_SHORT;
}
static inline void and_s1s2(PFrElement r, PFrElement a, PFrElement b)
{
if (a->shortVal >= 0 && b->shortVal >= 0)
{
int32_t result = a->shortVal & b->shortVal;
r->shortVal = result;
r->type = Fr_SHORT;
return;
}
r->type = Fr_LONG;
FrElement a_n;
FrElement b_n;
Fr_toLongNormal(&a_n, a);
Fr_toLongNormal(&b_n, b);
Fr_rawAnd(r->longVal, a_n.longVal, b_n.longVal);
}
static inline void and_l1nl2n(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONG;
Fr_rawAnd(r->longVal, a->longVal, b->longVal);
}
static inline void and_l1nl2m(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONG;
FrElement b_n;
Fr_toNormal(&b_n, b);
Fr_rawAnd(r->longVal, a->longVal, b_n.longVal);
}
static inline void and_l1ml2m(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONG;
FrElement a_n;
FrElement b_n;
Fr_toNormal(&a_n, a);
Fr_toNormal(&b_n, b);
Fr_rawAnd(r->longVal, a_n.longVal, b_n.longVal);
}
static inline void and_l1ml2n(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONG;
FrElement a_n;
Fr_toNormal(&a_n, a);
Fr_rawAnd(r->longVal, a_n.longVal, b->longVal);
}
static inline void and_s1l2n(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONG;
FrElement a_n;
if (a->shortVal >= 0)
{
a_n = {0, 0, {(uint64_t)a->shortVal, 0, 0, 0}};
}
else
{
Fr_toLongNormal(&a_n, a);
}
Fr_rawAnd(r->longVal, a_n.longVal, b->longVal);
}
static inline void and_l1ms2(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONG;
FrElement a_n;
FrElement b_n;
Fr_toNormal(&a_n, a);
if (b->shortVal >= 0)
{
b_n = {0, 0, {(uint64_t)b->shortVal, 0, 0, 0}};
}
else
{
Fr_toLongNormal(&b_n, b);
}
Fr_rawAnd(r->longVal, b_n.longVal, a_n.longVal);
}
static inline void and_s1l2m(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONG;
FrElement a_n;
FrElement b_n;
Fr_toNormal(&b_n, b);
if (a->shortVal >= 0)
{
a_n = {0, 0, {(uint64_t)a->shortVal, 0, 0, 0}};
}
else
{
Fr_toLongNormal(&a_n, a);
}
Fr_rawAnd(r->longVal, a_n.longVal, b_n.longVal);
}
static inline void and_l1ns2(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONG;
FrElement b_n;
if (b->shortVal >= 0)
{
b_n = {0, 0, {(uint64_t)b->shortVal, 0, 0, 0}};
}
else
{
Fr_toLongNormal(&b_n, b);
}
Fr_rawAnd(r->longVal, a->longVal, b_n.longVal);
}
// Ands two elements of any kind
void Fr_band(PFrElement r, PFrElement a, PFrElement b)
{
if (a->type & Fr_LONG)
{
if (b->type & Fr_LONG)
{
if (a->type & Fr_MONTGOMERY)
{
if (b->type & Fr_MONTGOMERY)
{
and_l1ml2m(r, a, b);
}
else
{
and_l1ml2n(r, a, b);
}
}
else if (b->type & Fr_MONTGOMERY)
{
and_l1nl2m(r, a, b);
}
else
{
and_l1nl2n(r, a, b);
}
}
else if (a->type & Fr_MONTGOMERY)
{
and_l1ms2(r, a, b);
}
else
{
and_l1ns2(r, a, b);
}
}
else if (b->type & Fr_LONG)
{
if (b->type & Fr_MONTGOMERY)
{
and_s1l2m(r, a, b);
}
else
{
and_s1l2n(r, a, b);
}
}
else
{
and_s1s2(r, a, b);
}
}
void Fr_rawZero(FrRawElement pRawResult)
{
std::memset(pRawResult, 0, sizeof(FrRawElement));
}
static inline void rawShl(FrRawElement r, FrRawElement a, uint64_t b)
{
if (b == 0)
{
Fr_rawCopy(r, a);
return;
}
if (b >= 254)
{
Fr_rawZero(r);
return;
}
Fr_rawShl(r, a, b);
}
static inline void rawShr(FrRawElement r, FrRawElement a, uint64_t b)
{
if (b == 0)
{
Fr_rawCopy(r, a);
return;
}
if (b >= 254)
{
Fr_rawZero(r);
return;
}
Fr_rawShr(r,a, b);
}
static inline void Fr_setzero(PFrElement r)
{
r->type = 0;
r->shortVal = 0;
}
static inline void do_shlcl(PFrElement r, PFrElement a, uint64_t b)
{
FrElement a_long;
Fr_toLongNormal(&a_long, a);
r->type = Fr_LONG;
rawShl(r->longVal, a_long.longVal, b);
}
static inline void do_shlln(PFrElement r, PFrElement a, uint64_t b)
{
r->type = Fr_LONG;
rawShl(r->longVal, a->longVal, b);
}
static inline void do_shl(PFrElement r, PFrElement a, uint64_t b)
{
if (a->type & Fr_LONG)
{
if (a->type == Fr_LONGMONTGOMERY)
{
FrElement a_long;
Fr_toNormal(&a_long, a);
do_shlln(r, &a_long, b);
}
else
{
do_shlln(r, a, b);
}
}
else
{
int64_t a_shortVal = a->shortVal;
if (a_shortVal == 0)
{
Fr_setzero(r);
}
else if (a_shortVal < 0)
{
do_shlcl(r, a, b);
}
else if(b >= 31)
{
do_shlcl(r, a, b);
}
else
{
a_shortVal <<= b;
const uint64_t a_is_over_short = a_shortVal >> 31;
if (a_is_over_short)
{
do_shlcl(r, a, b);
}
else
{
r->type = Fr_SHORT;
r->shortVal = a_shortVal;
}
}
}
}
static inline void do_shrln(PFrElement r, PFrElement a, uint64_t b)
{
r->type = Fr_LONG;
rawShr(r->longVal, a->longVal, b);
}
static inline void do_shrl(PFrElement r, PFrElement a, uint64_t b)
{
if (a->type == Fr_LONGMONTGOMERY)
{
FrElement a_long;
Fr_toNormal(&a_long, a);
do_shrln(r, &a_long, b);
}
else
{
do_shrln(r, a, b);
}
}
static inline void do_shr(PFrElement r, PFrElement a, uint64_t b)
{
if (a->type & Fr_LONG)
{
do_shrl(r, a, b);
}
else
{
int64_t a_shortVal = a->shortVal;
if (a_shortVal == 0)
{
Fr_setzero(r);
}
else if (a_shortVal < 0)
{
FrElement a_long;
Fr_toLongNormal(&a_long, a);
do_shrl(r, &a_long, b);
}
else if(b >= 31)
{
Fr_setzero(r);
}
else
{
a_shortVal >>= b;
r->shortVal = a_shortVal;
r->type = Fr_SHORT;
}
}
}
static inline void Fr_shr_big_shift(PFrElement r, PFrElement a, PFrElement b)
{
static FrRawElement max_shift = {254, 0, 0, 0};
FrRawElement shift;
Fr_rawSubRegular(shift, Fr_q.longVal, b->longVal);
if (Fr_rawCmp(shift, max_shift) >= 0)
{
Fr_setzero(r);
}
else
{
do_shl(r, a, shift[0]);
}
}
static inline void Fr_shr_long(PFrElement r, PFrElement a, PFrElement b)
{
static FrRawElement max_shift = {254, 0, 0, 0};
if (Fr_rawCmp(b->longVal, max_shift) >= 0)
{
Fr_shr_big_shift(r, a, b);
}
else
{
do_shr(r, a, b->longVal[0]);
}
}
void Fr_shr(PFrElement r, PFrElement a, PFrElement b)
{
if (b->type & Fr_LONG)
{
if (b->type == Fr_LONGMONTGOMERY)
{
FrElement b_long;
Fr_toNormal(&b_long, b);
Fr_shr_long(r, a, &b_long);
}
else
{
Fr_shr_long(r, a, b);
}
}
else
{
int64_t b_shortVal = b->shortVal;
if (b_shortVal < 0)
{
b_shortVal = -b_shortVal;
if (b_shortVal >= 254)
{
Fr_setzero(r);
}
else
{
do_shl(r, a, b_shortVal);
}
}
else if (b_shortVal >= 254)
{
Fr_setzero(r);
}
else
{
do_shr(r, a, b_shortVal);
}
}
}
static inline void Fr_shl_big_shift(PFrElement r, PFrElement a, PFrElement b)
{
static FrRawElement max_shift = {254, 0, 0, 0};
FrRawElement shift;
Fr_rawSubRegular(shift, Fr_q.longVal, b->longVal);
if (Fr_rawCmp(shift, max_shift) >= 0)
{
Fr_setzero(r);
}
else
{
do_shr(r, a, shift[0]);
}
}
static inline void Fr_shl_long(PFrElement r, PFrElement a, PFrElement b)
{
static FrRawElement max_shift = {254, 0, 0, 0};
if (Fr_rawCmp(b->longVal, max_shift) >= 0)
{
Fr_shl_big_shift(r, a, b);
}
else
{
do_shl(r, a, b->longVal[0]);
}
}
void Fr_shl(PFrElement r, PFrElement a, PFrElement b)
{
if (b->type & Fr_LONG)
{
if (b->type == Fr_LONGMONTGOMERY)
{
FrElement b_long;
Fr_toNormal(&b_long, b);
Fr_shl_long(r, a, &b_long);
}
else
{
Fr_shl_long(r, a, b);
}
}
else
{
int64_t b_shortVal = b->shortVal;
if (b_shortVal < 0)
{
b_shortVal = -b_shortVal;
if (b_shortVal >= 254)
{
Fr_setzero(r);
}
else
{
do_shr(r, a, b_shortVal);
}
}
else if (b_shortVal >= 254)
{
Fr_setzero(r);
}
else
{
do_shl(r, a, b_shortVal);
}
}
}
void Fr_square(PFrElement r, PFrElement a)
{
if (a->type & Fr_LONG)
{
if (a->type == Fr_LONGMONTGOMERY)
{
r->type = Fr_LONGMONTGOMERY;
Fr_rawMSquare(r->longVal, a->longVal);
}
else
{
r->type = Fr_LONGMONTGOMERY;
Fr_rawMSquare(r->longVal, a->longVal);
Fr_rawMMul(r->longVal, r->longVal, Fr_R3.longVal);
}
}
else
{
int64_t result;
int overflow = Fr_rawSMul(&result, a->shortVal, a->shortVal);
if (overflow)
{
Fr_rawCopyS2L(r->longVal, result);
r->type = Fr_LONG;
r->shortVal = 0;
}
else
{
// done the same way as in intel asm implementation
r->shortVal = (int32_t)result;
r->type = Fr_SHORT;
//
Fr_rawCopyS2L(r->longVal, result);
r->type = Fr_LONG;
r->shortVal = 0;
}
}
}
static inline void or_s1s2(PFrElement r, PFrElement a, PFrElement b)
{
if (a->shortVal >= 0 && b->shortVal >= 0)
{
r->shortVal = a->shortVal | b->shortVal;
r->type = Fr_SHORT;
return;
}
r->type = Fr_LONG;
FrElement a_n;
FrElement b_n;
Fr_toLongNormal(&a_n, a);
Fr_toLongNormal(&b_n, b);
Fr_rawOr(r->longVal, a_n.longVal, b_n.longVal);
}
static inline void or_s1l2m(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONG;
FrElement a_n;
FrElement b_n;
Fr_toNormal(&b_n, b);
if (a->shortVal >= 0)
{
a_n = {0, 0, {(uint64_t)a->shortVal, 0, 0, 0}};
}
else
{
Fr_toLongNormal(&a_n, a);
}
Fr_rawOr(r->longVal, a_n.longVal, b_n.longVal);
}
static inline void or_s1l2n(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONG;
FrElement a_n;
if (a->shortVal >= 0)
{
a_n = {0, 0, {(uint64_t)a->shortVal, 0, 0, 0}};
}
else
{
Fr_toLongNormal(&a_n, a);
}
Fr_rawOr(r->longVal, a_n.longVal, b->longVal);
}
static inline void or_l1ns2(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONG;
FrElement b_n;
if (b->shortVal >= 0)
{
b_n = {0, 0, {(uint64_t)b->shortVal, 0, 0, 0}};
}
else
{
Fr_toLongNormal(&b_n, b);
}
Fr_rawOr(r->longVal, a->longVal, b_n.longVal);
}
static inline void or_l1ms2(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONG;
FrElement a_n;
FrElement b_n;
Fr_toNormal(&a_n, a);
if (b->shortVal >= 0)
{
b_n = {0, 0, {(uint64_t)b->shortVal, 0, 0, 0}};
}
else
{
Fr_toLongNormal(&b_n, b);
}
Fr_rawOr(r->longVal, b_n.longVal, a_n.longVal);
}
static inline void or_l1nl2n(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONG;
Fr_rawOr(r->longVal, a->longVal, b->longVal);
}
static inline void or_l1nl2m(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONG;
FrElement b_n;
Fr_toNormal(&b_n, b);
Fr_rawOr(r->longVal, a->longVal, b_n.longVal);
}
static inline void or_l1ml2n(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONG;
FrElement a_n;
Fr_toNormal(&a_n, a);
Fr_rawOr(r->longVal, a_n.longVal, b->longVal);
}
static inline void or_l1ml2m(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONG;
FrElement a_n;
FrElement b_n;
Fr_toNormal(&a_n, a);
Fr_toNormal(&b_n, b);
Fr_rawOr(r->longVal, a_n.longVal, b_n.longVal);
}
void Fr_bor(PFrElement r, PFrElement a, PFrElement b)
{
if (a->type & Fr_LONG)
{
if (b->type & Fr_LONG)
{
if (a->type & Fr_MONTGOMERY)
{
if (b->type & Fr_MONTGOMERY)
{
or_l1ml2m(r, a, b);
}
else
{
or_l1ml2n(r, a, b);
}
}
else if (b->type & Fr_MONTGOMERY)
{
or_l1nl2m(r, a, b);
}
else
{
or_l1nl2n(r, a, b);
}
}
else if (a->type & Fr_MONTGOMERY)
{
or_l1ms2(r, a, b);
}
else
{
or_l1ns2(r, a, b);
}
}
else if (b->type & Fr_LONG)
{
if (b->type & Fr_MONTGOMERY)
{
or_s1l2m(r, a, b);
}
else
{
or_s1l2n(r, a, b);
}
}
else
{
or_s1s2(r, a, b);
}
}
static inline void xor_s1s2(PFrElement r, PFrElement a, PFrElement b)
{
if (a->shortVal >= 0 && b->shortVal >= 0)
{
r->shortVal = a->shortVal ^ b->shortVal;
r->type = Fr_SHORT;
return;
}
r->type = Fr_LONG;
FrElement a_n;
FrElement b_n;
Fr_toLongNormal(&a_n, a);
Fr_toLongNormal(&b_n, b);
Fr_rawXor(r->longVal, a_n.longVal, b_n.longVal);
}
static inline void xor_s1l2n(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONG;
FrElement a_n;
if (a->shortVal >= 0)
{
a_n = {0, 0, {(uint64_t)a->shortVal, 0, 0, 0}};
}
else
{
Fr_toLongNormal(&a_n, a);
}
Fr_rawXor(r->longVal, a_n.longVal, b->longVal);
}
static inline void xor_s1l2m(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONG;
FrElement a_n;
FrElement b_n;
Fr_toNormal(&b_n, b);
if (a->shortVal >= 0)
{
a_n = {0, 0, {(uint64_t)a->shortVal, 0, 0, 0}};
}
else
{
Fr_toLongNormal(&a_n, a);
}
Fr_rawXor(r->longVal, a_n.longVal, b_n.longVal);
}
static inline void xor_l1ns2(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONG;
FrElement b_n;
if (b->shortVal >= 0)
{
b_n = {0, 0, {(uint64_t)b->shortVal, 0, 0, 0}};
}
else
{
Fr_toLongNormal(&b_n, b);
}
Fr_rawXor(r->longVal, a->longVal, b_n.longVal);
}
static inline void xor_l1ms2(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONG;
FrElement a_n;
FrElement b_n;
Fr_toNormal(&a_n, a);
if (b->shortVal >= 0)
{
b_n = {0, 0, {(uint64_t)b->shortVal, 0, 0, 0}};
}
else
{
Fr_toLongNormal(&b_n, b);
}
Fr_rawXor(r->longVal, b_n.longVal, a_n.longVal);
}
static inline void xor_l1nl2n(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONG;
Fr_rawXor(r->longVal, a->longVal, b->longVal);
}
static inline void xor_l1nl2m(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONG;
FrElement b_n;
Fr_toNormal(&b_n, b);
Fr_rawXor(r->longVal, a->longVal, b_n.longVal);
}
static inline void xor_l1ml2n(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONG;
FrElement a_n;
Fr_toNormal(&a_n, a);
Fr_rawXor(r->longVal, a_n.longVal, b->longVal);
}
static inline void xor_l1ml2m(PFrElement r, PFrElement a, PFrElement b)
{
r->type = Fr_LONG;
FrElement a_n;
FrElement b_n;
Fr_toNormal(&a_n, a);
Fr_toNormal(&b_n, b);
Fr_rawXor(r->longVal, a_n.longVal, b_n.longVal);
}
void Fr_bxor(PFrElement r, PFrElement a, PFrElement b)
{
if (a->type & Fr_LONG)
{
if (b->type & Fr_LONG)
{
if (a->type & Fr_MONTGOMERY)
{
if (b->type & Fr_MONTGOMERY)
{
xor_l1ml2m(r, a, b);
}
else
{
xor_l1ml2n(r, a, b);
}
}
else if (b->type & Fr_MONTGOMERY)
{
xor_l1nl2m(r, a, b);
}
else
{
xor_l1nl2n(r, a, b);
}
}
else if (a->type & Fr_MONTGOMERY)
{
xor_l1ms2(r, a, b);
}
else
{
xor_l1ns2(r, a, b);
}
}
else if (b->type & Fr_LONG)
{
if (b->type & Fr_MONTGOMERY)
{
xor_s1l2m(r, a, b);
}
else
{
xor_s1l2n(r, a, b);
}
}
else
{
xor_s1s2(r, a, b);
}
}
void Fr_bnot(PFrElement r, PFrElement a)
{
r->type = Fr_LONG;
if (a->type == Fr_LONG)
{
if (a->type & Fr_MONTGOMERY)
{
FrElement a_n;
Fr_toNormal(&a_n, a);
Fr_rawNot(r->longVal, a_n.longVal);
}
else
{
Fr_rawNot(r->longVal, a->longVal);
}
}
else
{
FrElement a_n;
Fr_toLongNormal(&a_n, a);
Fr_rawNot(r->longVal, a_n.longVal);
}
}