mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-08-22 11:03:06 +02:00
Update to v106r65 release.
byuu says: This synchronizes bsnes/higan with many recent internal nall changes. This will be the last WIP until I am situated in Japan. Apologies for the bugfixes that didn't get applied yet, I ran out of time.
This commit is contained in:
@@ -1,79 +1,84 @@
|
||||
#pragma once
|
||||
|
||||
//warning: this implementation leaks side-channel information
|
||||
//use modulo25519-optimized.hpp in production
|
||||
|
||||
#include <nall/arithmetic/barrett.hpp>
|
||||
|
||||
namespace nall { namespace EllipticCurve {
|
||||
|
||||
static const uint256_t P = (1_u256 << 255) - 19;
|
||||
static const uint256_t L = (1_u256 << 252) + 27742317777372353535851937790883648493_u256;
|
||||
|
||||
static BarrettReduction modP{P};
|
||||
static BarrettReduction modL{L};
|
||||
struct Modulo25519 {
|
||||
inline Modulo25519() = default;
|
||||
inline Modulo25519(const Modulo25519& source) : value(source.value) {}
|
||||
template<typename T> inline Modulo25519(const T& value) : value(value) {}
|
||||
inline explicit operator bool() const { return (bool)value; }
|
||||
inline auto operator()() const -> uint256_t { return value; }
|
||||
|
||||
struct Modulo25519 : uint256_t {
|
||||
using type = Modulo25519;
|
||||
using uint256_t::uint256_t;
|
||||
|
||||
alwaysinline auto operator()() const -> uint256_t {
|
||||
return *this;
|
||||
}
|
||||
|
||||
alwaysinline auto operator-() const -> type {
|
||||
return P.operator-(*this);
|
||||
}
|
||||
|
||||
template<typename T> alwaysinline auto operator+(const T& rhs) const -> type {
|
||||
auto lhs = (uint512_t)*this + rhs;
|
||||
if(lhs >= P) lhs -= P;
|
||||
return lhs;
|
||||
}
|
||||
|
||||
template<typename T> alwaysinline auto operator-(const T& rhs) const -> type {
|
||||
auto lhs = (uint512_t)*this;
|
||||
if(lhs < rhs) lhs += P;
|
||||
return lhs - rhs;
|
||||
}
|
||||
|
||||
template<typename T> alwaysinline auto operator*(const T& rhs) const -> type {
|
||||
uint256_t hi, lo;
|
||||
nall::mul(*this, rhs, hi, lo);
|
||||
return modP(uint512_t{hi, lo});
|
||||
}
|
||||
|
||||
alwaysinline auto square() const -> type {
|
||||
uint256_t hi, lo;
|
||||
nall::square(*this, hi, lo);
|
||||
return modP(uint512_t{hi, lo});
|
||||
}
|
||||
|
||||
inline auto expmod(uint256_t e) const -> type {
|
||||
type x = 1;
|
||||
for(auto n : rrange(256)) {
|
||||
x = x.square();
|
||||
if(e >> n & 1) x = operator*(x);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
inline auto reciprocal() const -> type {
|
||||
return expmod(P - 2);
|
||||
}
|
||||
|
||||
inline auto squareRoot() const -> type {
|
||||
static const type i = type(2).expmod((P - 1) >> 2); //i = sqrt(-1)
|
||||
type x = expmod((P + 3) >> 3);
|
||||
if(operator!=(x.square())) x = x * i;
|
||||
if(x & 1) x = -x;
|
||||
return x;
|
||||
}
|
||||
private:
|
||||
uint256_t value;
|
||||
};
|
||||
|
||||
inline auto cmove(bool bit, Modulo25519& lhs, const Modulo25519& rhs) -> void {
|
||||
if(bit) lhs = rhs;
|
||||
inline auto operator-(const Modulo25519& lhs) -> Modulo25519 {
|
||||
return P - lhs();
|
||||
}
|
||||
|
||||
inline auto cswap(bool bit, Modulo25519& lhs, Modulo25519& rhs) -> void {
|
||||
if(bit) swap(lhs, rhs);
|
||||
inline auto operator+(const Modulo25519& lhs, const Modulo25519& rhs) -> Modulo25519 {
|
||||
uint512_t value = (uint512_t)lhs() + rhs();
|
||||
if(value >= P) value -= P;
|
||||
return value;
|
||||
}
|
||||
|
||||
inline auto operator-(const Modulo25519& lhs, const Modulo25519& rhs) -> Modulo25519 {
|
||||
uint512_t value = (uint512_t)lhs();
|
||||
if(value < rhs()) value += P;
|
||||
return uint256_t(value - rhs());
|
||||
}
|
||||
|
||||
inline auto operator*(const Modulo25519& lhs, const Modulo25519& rhs) -> Modulo25519 {
|
||||
static const BarrettReduction<256> P{EllipticCurve::P};
|
||||
uint256_t hi, lo;
|
||||
mul(lhs(), rhs(), hi, lo);
|
||||
return uint512_t{hi, lo} % P;
|
||||
}
|
||||
|
||||
inline auto operator&(const Modulo25519& lhs, uint256_t rhs) -> uint256_t {
|
||||
return lhs() & rhs;
|
||||
}
|
||||
|
||||
inline auto square(const Modulo25519& lhs) -> Modulo25519 {
|
||||
static const BarrettReduction<256> P{EllipticCurve::P};
|
||||
uint256_t hi, lo;
|
||||
square(lhs(), hi, lo);
|
||||
return uint512_t{hi, lo} % P;
|
||||
}
|
||||
|
||||
inline auto exponentiate(const Modulo25519& lhs, uint256_t exponent) -> Modulo25519 {
|
||||
if(exponent == 0) return 1;
|
||||
Modulo25519 value = square(exponentiate(lhs, exponent >> 1));
|
||||
if(exponent & 1) value = value * lhs;
|
||||
return value;
|
||||
}
|
||||
|
||||
inline auto reciprocal(const Modulo25519& lhs) -> Modulo25519 {
|
||||
return exponentiate(lhs, P - 2);
|
||||
}
|
||||
|
||||
inline auto squareRoot(const Modulo25519& lhs) -> Modulo25519 {
|
||||
static const Modulo25519 I = exponentiate(Modulo25519(2), P - 1 >> 2); //I = sqrt(-1)
|
||||
Modulo25519 value = exponentiate(lhs, P + 3 >> 3);
|
||||
if(square(value) - lhs) value = value * I;
|
||||
if(value & 1) value = -value;
|
||||
return value;
|
||||
}
|
||||
|
||||
inline auto cmove(bool condition, Modulo25519& lhs, const Modulo25519& rhs) -> void {
|
||||
if(condition) lhs = rhs;
|
||||
}
|
||||
|
||||
inline auto cswap(bool condition, Modulo25519& lhs, Modulo25519& rhs) -> void {
|
||||
if(condition) swap(lhs, rhs);
|
||||
}
|
||||
|
||||
}}
|
||||
|
Reference in New Issue
Block a user