You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
177 lines
5.7 KiB
177 lines
5.7 KiB
#pragma once
|
|
/**
|
|
@file
|
|
@brief operator class
|
|
@author MITSUNARI Shigeo(@herumi)
|
|
@license modified new BSD license
|
|
http://opensource.org/licenses/BSD-3-Clause
|
|
*/
|
|
#include <mcl/op.hpp>
|
|
#include <mcl/util.hpp>
|
|
#ifdef _MSC_VER
|
|
#ifndef MCL_FORCE_INLINE
|
|
#define MCL_FORCE_INLINE __forceinline
|
|
#endif
|
|
#pragma warning(push)
|
|
#pragma warning(disable : 4714)
|
|
#else
|
|
#ifndef MCL_FORCE_INLINE
|
|
#define MCL_FORCE_INLINE __attribute__((always_inline))
|
|
#endif
|
|
#endif
|
|
|
|
namespace mcl { namespace fp {
|
|
|
|
template<class T>
|
|
struct Empty {};
|
|
|
|
/*
|
|
T must have add, sub, mul, inv, neg
|
|
*/
|
|
template<class T, class E = Empty<T> >
|
|
struct Operator : public E {
|
|
template<class S> MCL_FORCE_INLINE T& operator+=(const S& rhs) { T::add(static_cast<T&>(*this), static_cast<const T&>(*this), rhs); return static_cast<T&>(*this); }
|
|
template<class S> MCL_FORCE_INLINE T& operator-=(const S& rhs) { T::sub(static_cast<T&>(*this), static_cast<const T&>(*this), rhs); return static_cast<T&>(*this); }
|
|
template<class S> friend MCL_FORCE_INLINE T operator+(const T& a, const S& b) { T c; T::add(c, a, b); return c; }
|
|
template<class S> friend MCL_FORCE_INLINE T operator-(const T& a, const S& b) { T c; T::sub(c, a, b); return c; }
|
|
template<class S> MCL_FORCE_INLINE T& operator*=(const S& rhs) { T::mul(static_cast<T&>(*this), static_cast<const T&>(*this), rhs); return static_cast<T&>(*this); }
|
|
template<class S> friend MCL_FORCE_INLINE T operator*(const T& a, const S& b) { T c; T::mul(c, a, b); return c; }
|
|
MCL_FORCE_INLINE T& operator/=(const T& rhs) { T c; T::inv(c, rhs); T::mul(static_cast<T&>(*this), static_cast<const T&>(*this), c); return static_cast<T&>(*this); }
|
|
static MCL_FORCE_INLINE void div(T& c, const T& a, const T& b) { T t; T::inv(t, b); T::mul(c, a, t); }
|
|
friend MCL_FORCE_INLINE T operator/(const T& a, const T& b) { T c; T::inv(c, b); c *= a; return c; }
|
|
MCL_FORCE_INLINE T operator-() const { T c; T::neg(c, static_cast<const T&>(*this)); return c; }
|
|
template<class tag2, size_t maxBitSize2, template<class _tag, size_t _maxBitSize> class FpT>
|
|
static void pow(T& z, const T& x, const FpT<tag2, maxBitSize2>& y)
|
|
{
|
|
fp::Block b;
|
|
y.getBlock(b);
|
|
powArray(z, x, b.p, b.n, false, false);
|
|
}
|
|
template<class tag2, size_t maxBitSize2, template<class _tag, size_t _maxBitSize> class FpT>
|
|
static void powGeneric(T& z, const T& x, const FpT<tag2, maxBitSize2>& y)
|
|
{
|
|
fp::Block b;
|
|
y.getBlock(b);
|
|
powArrayBase(z, x, b.p, b.n, false, false);
|
|
}
|
|
template<class tag2, size_t maxBitSize2, template<class _tag, size_t _maxBitSize> class FpT>
|
|
static void powCT(T& z, const T& x, const FpT<tag2, maxBitSize2>& y)
|
|
{
|
|
fp::Block b;
|
|
y.getBlock(b);
|
|
powArray(z, x, b.p, b.n, false, true);
|
|
}
|
|
static void pow(T& z, const T& x, int64_t y)
|
|
{
|
|
const uint64_t u = fp::abs_(y);
|
|
#if MCL_SIZEOF_UNIT == 8
|
|
powArray(z, x, &u, 1, y < 0, false);
|
|
#else
|
|
uint32_t ua[2] = { uint32_t(u), uint32_t(u >> 32) };
|
|
size_t un = ua[1] ? 2 : 1;
|
|
powArray(z, x, ua, un, y < 0, false);
|
|
#endif
|
|
}
|
|
static void pow(T& z, const T& x, const mpz_class& y)
|
|
{
|
|
powArray(z, x, gmp::getUnit(y), gmp::getUnitSize(y), y < 0, false);
|
|
}
|
|
static void powGeneric(T& z, const T& x, const mpz_class& y)
|
|
{
|
|
powArrayBase(z, x, gmp::getUnit(y), gmp::getUnitSize(y), y < 0, false);
|
|
}
|
|
static void powCT(T& z, const T& x, const mpz_class& y)
|
|
{
|
|
powArray(z, x, gmp::getUnit(y), gmp::getUnitSize(y), y < 0, true);
|
|
}
|
|
static void setPowArrayGLV(void f(T& z, const T& x, const Unit *y, size_t yn, bool isNegative, bool constTime))
|
|
{
|
|
powArrayGLV = f;
|
|
}
|
|
private:
|
|
static void (*powArrayGLV)(T& z, const T& x, const Unit *y, size_t yn, bool isNegative, bool constTime);
|
|
static void powArray(T& z, const T& x, const Unit *y, size_t yn, bool isNegative, bool constTime)
|
|
{
|
|
if (powArrayGLV && (constTime || yn > 1)) {
|
|
powArrayGLV(z, x, y, yn, isNegative, constTime);
|
|
return;
|
|
}
|
|
powArrayBase(z, x, y, yn, isNegative, constTime);
|
|
}
|
|
static void powArrayBase(T& z, const T& x, const Unit *y, size_t yn, bool isNegative, bool constTime)
|
|
{
|
|
T tmp;
|
|
const T *px = &x;
|
|
if (&z == &x) {
|
|
tmp = x;
|
|
px = &tmp;
|
|
}
|
|
z = 1;
|
|
fp::powGeneric(z, *px, y, yn, T::mul, T::sqr, (void (*)(T&, const T&))0, constTime ? T::BaseFp::getBitSize() : 0);
|
|
if (isNegative) {
|
|
T::inv(z, z);
|
|
}
|
|
}
|
|
};
|
|
|
|
template<class T, class E>
|
|
void (*Operator<T, E>::powArrayGLV)(T& z, const T& x, const Unit *y, size_t yn, bool isNegative, bool constTime);
|
|
|
|
/*
|
|
T must have save and load
|
|
*/
|
|
template<class T, class E = Empty<T> >
|
|
struct Serializable : public E {
|
|
void setStr(bool *pb, const char *str, int ioMode = 0)
|
|
{
|
|
size_t len = strlen(str);
|
|
size_t n = deserialize(str, len, ioMode);
|
|
*pb = n > 0 && n == len;
|
|
}
|
|
// return strlen(buf) if success else 0
|
|
size_t getStr(char *buf, size_t maxBufSize, int ioMode = 0) const
|
|
{
|
|
size_t n = serialize(buf, maxBufSize, ioMode);
|
|
if (n == 0 || n == maxBufSize - 1) return 0;
|
|
buf[n] = '\0';
|
|
return n;
|
|
}
|
|
#ifndef CYBOZU_DONT_USE_STRING
|
|
void setStr(const std::string& str, int ioMode = 0)
|
|
{
|
|
cybozu::StringInputStream is(str);
|
|
static_cast<T&>(*this).load(is, ioMode);
|
|
}
|
|
void getStr(std::string& str, int ioMode = 0) const
|
|
{
|
|
str.clear();
|
|
cybozu::StringOutputStream os(str);
|
|
static_cast<const T&>(*this).save(os, ioMode);
|
|
}
|
|
std::string getStr(int ioMode = 0) const
|
|
{
|
|
std::string str;
|
|
getStr(str, ioMode);
|
|
return str;
|
|
}
|
|
#endif
|
|
// return written bytes
|
|
size_t serialize(void *buf, size_t maxBufSize, int ioMode = IoSerialize) const
|
|
{
|
|
cybozu::MemoryOutputStream os(buf, maxBufSize);
|
|
bool b;
|
|
static_cast<const T&>(*this).save(&b, os, ioMode);
|
|
return b ? os.getPos() : 0;
|
|
}
|
|
// return read bytes
|
|
size_t deserialize(const void *buf, size_t bufSize, int ioMode = IoSerialize)
|
|
{
|
|
cybozu::MemoryInputStream is(buf, bufSize);
|
|
bool b;
|
|
static_cast<T&>(*this).load(&b, is, ioMode);
|
|
return b ? is.getPos() : 0;
|
|
}
|
|
};
|
|
|
|
} } // mcl::fp
|
|
|
|
|