#pragma once
#include "fp.h"
struct FpExt {
union {
Fp elems[4];
bb31_4_t rep;
};
__device__ FpExt() : rep(bb31_t{0u}) {}
__device__ explicit FpExt(uint32_t x) : rep(bb31_t{x}) {}
__device__ explicit FpExt(Fp x) : rep(static_cast<bb31_t>(x)) {}
__device__ FpExt(Fp a, Fp b, Fp c, Fp d) {
elems[0] = a;
elems[1] = b;
elems[2] = c;
elems[3] = d;
}
__device__ FpExt operator+=(FpExt rhs) {
rep += rhs.rep;
return *this;
}
__device__ FpExt operator-=(FpExt rhs) {
rep -= rhs.rep;
return *this;
}
__device__ FpExt operator+(FpExt rhs) const {
FpExt result = *this;
result += rhs;
return result;
}
__device__ FpExt operator-(FpExt rhs) const {
FpExt result = *this;
result -= rhs;
return result;
}
__device__ FpExt operator-(Fp rhs) const {
FpExt result = *this;
result.elems[0] -= rhs;
return result;
}
__device__ FpExt operator-() const { return FpExt() - *this; }
__device__ FpExt operator*=(Fp rhs) {
rep *= static_cast<bb31_t>(rhs);
return *this;
}
__device__ FpExt operator*(Fp rhs) const {
FpExt result = *this;
result *= rhs;
return result;
}
__device__ FpExt operator*=(FpExt rhs) {
rep *= rhs.rep;
return *this;
}
__device__ FpExt operator*(FpExt rhs) const {
FpExt result = *this;
result *= rhs;
return result;
}
__device__ bool operator==(FpExt rhs) const { return rep == rhs.rep; }
__device__ bool operator!=(FpExt rhs) const { return rep != rhs.rep; }
__device__ Fp constPart() const { return elems[0]; }
};
__device__ inline FpExt operator*(Fp a, FpExt b) { return b * a; }
__device__ inline FpExt pow(FpExt x, uint32_t n) {
FpExt r; r.rep = x.rep ^ n;
return r;
}
template <class I, std::enable_if_t<std::is_integral_v<I>, int> = 0>
__device__ inline FpExt pow(FpExt x, I n) {
return pow(x, static_cast<uint32_t>(n));
}
__device__ inline FpExt inv(FpExt in) {
FpExt result;
result.rep = in.rep.reciprocal();
return result;
}
static_assert(sizeof(FpExt) == 16, "FpExt must be 16 bytes");
static_assert(sizeof(FpExt) == sizeof(bb31_4_t), "FpExt and bb31_4_t sizes must match");
static_assert(alignof(FpExt) == alignof(bb31_4_t), "FpExt and bb31_4_t align must match");