📄 zz_p.c
字号:
#include <NTL/ZZ_p.h>#include <NTL/FFT.h>#include <NTL/new.h>NTL_START_IMPLZZ_pInfoT::ZZ_pInfoT(const ZZ& NewP){ if (NewP <= 1) Error("ZZ_pContext: p must be > 1"); ref_count = 1; p = NewP; size = p.size(); ExtendedModulusSize = 2*size + (NTL_BITS_PER_LONG + NTL_ZZ_NBITS - 1)/NTL_ZZ_NBITS; initialized = 0; x = 0; u = 0; tbl = 0; tbl1 = 0; long i; for (i = 0; i < MAX_ZZ_p_TEMPS; i++) temps[i] = 0; temps_top = 0;}void ZZ_pInfoT::init(){ ZZ B, M, M1, M2, M3; long n, i; long q, t; initialized = 1; sqr(B, p); LeftShift(B, B, NTL_FFTMaxRoot+NTL_FFTFudge); set(M); n = 0; while (M <= B) { UseFFTPrime(n); q = FFTPrime[n]; n++; mul(M, M, q); } NumPrimes = n; MaxRoot = CalcMaxRoot(q); double fn = double(n); // I've re-calculated the error bounds... // Although the bounds in versions < 3.7 were incorrect, // on any currently existing machine, this bug is "benign". if (fn*(fn+32) > 0.5*NTL_FDOUBLE_PRECISION) Error("modulus too big"); if (fn*(fn+32) > (0.5*NTL_FDOUBLE_PRECISION)/double(NTL_SP_BOUND)) QuickCRT = 0; else QuickCRT = 1; if (!(x = (double *) malloc(n * (sizeof (double))))) Error("out of space"); if (!(u = (long *) malloc(n * (sizeof (long))))) Error("out of space"); ZZ_p_rem_struct_init(&rem_struct, n, p, FFTPrime); ZZ_p_crt_struct_init(&crt_struct, n, p, FFTPrime); if (ZZ_p_crt_struct_special(crt_struct)) return; ZZ qq, rr; DivRem(qq, rr, M, p); NegateMod(MinusMModP, rr, p); for (i = 0; i < n; i++) { q = FFTPrime[i]; long tt = rem(qq, q); mul(M2, p, tt); add(M2, M2, rr); div(M2, M2, q); // = (M/q) rem p div(M1, M, q); t = rem(M1, q); t = InvMod(t, q); mul(M3, M2, t); rem(M3, M3, p); ZZ_p_crt_struct_insert(crt_struct, i, M3); x[i] = ((double) t)/((double) q); u[i] = t; }}ZZ_pInfoT::~ZZ_pInfoT(){ long i; for (i = 0; i < MAX_ZZ_p_TEMPS; i++) if (temps[i]) delete temps[i]; if (initialized) { ZZ_p_rem_struct_free(rem_struct); ZZ_p_crt_struct_free(crt_struct); free(x); free(u); }}ZZ_pInfoT *ZZ_pInfo = 0; typedef ZZ_pInfoT *ZZ_pInfoPtr;static void CopyPointer(ZZ_pInfoPtr& dst, ZZ_pInfoPtr src){ if (src == dst) return; if (dst) { dst->ref_count--; if (dst->ref_count < 0) Error("internal error: negative ZZ_pContext ref_count"); if (dst->ref_count == 0) delete dst; } if (src) { src->ref_count++; if (src->ref_count < 0) Error("internal error: ZZ_pContext ref_count overflow"); } dst = src;} void ZZ_p::init(const ZZ& p){ ZZ_pContext c(p); c.restore();}ZZ_pContext::ZZ_pContext(const ZZ& p){ ptr = NTL_NEW_OP ZZ_pInfoT(p);}ZZ_pContext::ZZ_pContext(const ZZ_pContext& a){ ptr = 0; CopyPointer(ptr, a.ptr);}ZZ_pContext& ZZ_pContext::operator=(const ZZ_pContext& a){ CopyPointer(ptr, a.ptr); return *this;}ZZ_pContext::~ZZ_pContext(){ CopyPointer(ptr, 0);}void ZZ_pContext::save(){ CopyPointer(ptr, ZZ_pInfo);}void ZZ_pContext::restore() const{ CopyPointer(ZZ_pInfo, ptr);}ZZ_pBak::~ZZ_pBak(){ if (MustRestore) CopyPointer(ZZ_pInfo, ptr); CopyPointer(ptr, 0);}void ZZ_pBak::save(){ MustRestore = 1; CopyPointer(ptr, ZZ_pInfo);}void ZZ_pBak::restore(){ MustRestore = 0; CopyPointer(ZZ_pInfo, ptr);}ZZ_pTemp::ZZ_pTemp(){ if (ZZ_pInfo->temps_top == MAX_ZZ_p_TEMPS) Error("ZZ_p temporary: out of temps"); pos = ZZ_pInfo->temps_top; ZZ_pInfo->temps_top++;}ZZ_pTemp::~ZZ_pTemp(){ ZZ_pInfo->temps_top--;}ZZ_p& ZZ_pTemp::val() const{ if (!ZZ_pInfo->temps[pos]) ZZ_pInfo->temps[pos] = NTL_NEW_OP ZZ_p; return *(ZZ_pInfo->temps[pos]);}const ZZ_p& ZZ_p::zero(){ static ZZ_p z(ZZ_p_NoAlloc); return z;}ZZ_p::DivHandlerPtr ZZ_p::DivHandler = 0;ZZ_p::ZZ_p(){ _ZZ_p__rep.SetSize(ModulusSize());} ZZ_p::ZZ_p(INIT_VAL_TYPE, const ZZ& a) { _ZZ_p__rep.SetSize(ModulusSize()); conv(*this, a);} ZZ_p::ZZ_p(INIT_VAL_TYPE, long a){ _ZZ_p__rep.SetSize(ModulusSize()); conv(*this, a);}void conv(ZZ_p& x, long a){ if (a == 0) clear(x); else if (a == 1) set(x); else { static ZZ y; conv(y, a); conv(x, y); }}istream& operator>>(istream& s, ZZ_p& x){ static ZZ y; s >> y; conv(x, y); return s;}void div(ZZ_p& x, const ZZ_p& a, const ZZ_p& b){ ZZ_pTemp TT; ZZ_p& T = TT.val(); inv(T, b); mul(x, a, T);}void inv(ZZ_p& x, const ZZ_p& a){ if (InvModStatus(x._ZZ_p__rep, a._ZZ_p__rep, ZZ_p::modulus())) { if (IsZero(a._ZZ_p__rep)) Error("ZZ_p: division by zero"); else if (ZZ_p::DivHandler) (*ZZ_p::DivHandler)(a); else Error("ZZ_p: division by non-invertible element"); }}long operator==(const ZZ_p& a, long b){ if (b == 0) return IsZero(a); if (b == 1) return IsOne(a); ZZ_pTemp TT; ZZ_p& T = TT.val(); conv(T, b); return a == T;}void add(ZZ_p& x, const ZZ_p& a, long b){ ZZ_pTemp TT; ZZ_p& T = TT.val(); conv(T, b); add(x, a, T);}void sub(ZZ_p& x, const ZZ_p& a, long b){ ZZ_pTemp TT; ZZ_p& T = TT.val(); conv(T, b); sub(x, a, T);}void sub(ZZ_p& x, long a, const ZZ_p& b){ ZZ_pTemp TT; ZZ_p& T = TT.val(); conv(T, a); sub(x, T, b);}void mul(ZZ_p& x, const ZZ_p& a, long b){ ZZ_pTemp TT; ZZ_p& T = TT.val(); conv(T, b); mul(x, a, T);}void div(ZZ_p& x, const ZZ_p& a, long b){ ZZ_pTemp TT; ZZ_p& T = TT.val(); conv(T, b); div(x, a, T);}void div(ZZ_p& x, long a, const ZZ_p& b){ if (a == 1) { inv(x, b); } else { ZZ_pTemp TT; ZZ_p& T = TT.val(); conv(T, a); div(x, T, b); }}NTL_END_IMPL
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -