?? gf2x.cpp
字號:
#include <NTL/GF2X.h>
#include <NTL/vec_long.h>
#include <NTL/new.h>
NTL_START_IMPL
long GF2X::HexOutput = 0;
void GF2X::SetMaxLength(long n)
{
if (n < 0) Error("GF2X::SetMaxLength: negative length");
if (NTL_OVERFLOW(n, 1, 0))
Error("GF2X::SetMaxLength: excessive length");
long w = (n + NTL_BITS_PER_LONG - 1)/NTL_BITS_PER_LONG;
xrep.SetMaxLength(w);
}
GF2X::GF2X(INIT_SIZE_TYPE, long n)
{
SetMaxLength(n);
}
const GF2X& GF2X::zero()
{
static GF2X z;
return z;
}
void GF2X::normalize()
{
long n;
const _ntl_ulong *p;
n = xrep.length();
if (n == 0) return;
p = xrep.elts() + n;
while (n > 0 && (*--p) == 0) {
n--;
}
xrep.QuickSetLength(n);
}
long IsZero(const GF2X& a)
{ return a.xrep.length() == 0; }
long IsOne(const GF2X& a)
{ return a.xrep.length() == 1 && a.xrep[0] == 1; }
long IsX(const GF2X& a)
{
return a.xrep.length() == 1 && a.xrep[0] == 2;
}
GF2 coeff(const GF2X& a, long i)
{
if (i < 0) return to_GF2(0);
long wi = i/NTL_BITS_PER_LONG;
if (wi >= a.xrep.length()) return to_GF2(0);
long bi = i - wi*NTL_BITS_PER_LONG;
return to_GF2((a.xrep[wi] & (1UL << bi)) != 0);
}
GF2 LeadCoeff(const GF2X& a)
{
if (IsZero(a))
return to_GF2(0);
else
return to_GF2(1);
}
GF2 ConstTerm(const GF2X& a)
{
if (IsZero(a))
return to_GF2(0);
else
return to_GF2((a.xrep[0] & 1) != 0);
}
void set(GF2X& x)
{
x.xrep.SetLength(1);
x.xrep[0] = 1;
}
void SetX(GF2X& x)
{
x.xrep.SetLength(1);
x.xrep[0] = 2;
}
void SetCoeff(GF2X& x, long i)
{
if (i < 0) {
Error("SetCoeff: negative index");
return;
}
long n, j;
n = x.xrep.length();
long wi = i/NTL_BITS_PER_LONG;
if (wi >= n) {
x.xrep.SetLength(wi+1);
for (j = n; j <= wi; j++)
x.xrep[j] = 0;
}
long bi = i - wi*NTL_BITS_PER_LONG;
x.xrep[wi] |= (1UL << bi);
}
void SetCoeff(GF2X& x, long i, long val)
{
if (i < 0) {
Error("SetCoeff: negative index");
return;
}
val = val & 1;
if (val) {
SetCoeff(x, i);
return;
}
// we want to clear position i
long n;
n = x.xrep.length();
long wi = i/NTL_BITS_PER_LONG;
if (wi >= n)
return;
long bi = i - wi*NTL_BITS_PER_LONG;
x.xrep[wi] &= ~(1UL << bi);
if (wi == n-1) x.normalize();
}
void SetCoeff(GF2X& x, long i, GF2 a)
{
SetCoeff(x, i, rep(a));
}
void swap(GF2X& a, GF2X& b)
{
swap(a.xrep, b.xrep);
}
long deg(const GF2X& aa)
{
long n = aa.xrep.length();
if (n == 0)
return -1;
_ntl_ulong a = aa.xrep[n-1];
long i = 0;
if (a == 0) Error("GF2X: unnormalized polynomial detected in deg");
while (a>=256)
i += 8, a >>= 8;
if (a >=16)
i += 4, a >>= 4;
if (a >= 4)
i += 2, a >>= 2;
if (a >= 2)
i += 2;
else if (a >= 1)
i++;
return NTL_BITS_PER_LONG*(n-1) + i - 1;
}
long operator==(const GF2X& a, const GF2X& b)
{
return a.xrep == b.xrep;
}
long operator==(const GF2X& a, long b)
{
if (b & 1)
return IsOne(a);
else
return IsZero(a);
}
long operator==(const GF2X& a, GF2 b)
{
if (b == 1)
return IsOne(a);
else
return IsZero(a);
}
static
istream & HexInput(istream& s, GF2X& a)
{
long n;
long c;
long i;
long val;
GF2X ibuf;
n = 0;
clear(ibuf);
c = s.peek();
val = CharToIntVal(c);
while (val != -1) {
for (i = 0; i < 4; i++)
if (val & (1L << i))
SetCoeff(ibuf, n+i);
n += 4;
s.get();
c = s.peek();
val = CharToIntVal(c);
}
a = ibuf;
return s;
}
istream & operator>>(istream& s, GF2X& a)
{
static ZZ ival;
long c;
if (!s) Error("bad GF2X input");
c = s.peek();
while (IsWhiteSpace(c)) {
s.get();
c = s.peek();
}
if (c == '0') {
s.get();
c = s.peek();
if (c == 'x' || c == 'X') {
s.get();
return HexInput(s, a);
}
else {
Error("bad GF2X input");
}
}
if (c != '[') {
Error("bad GF2X input");
}
GF2X ibuf;
long n;
n = 0;
clear(ibuf);
s.get();
c = s.peek();
while (IsWhiteSpace(c)) {
s.get();
c = s.peek();
}
while (c != ']' && c != EOF) {
if (!(s >> ival)) Error("bad GF2X input");
SetCoeff(ibuf, n, to_GF2(ival));
n++;
c = s.peek();
while (IsWhiteSpace(c)) {
s.get();
c = s.peek();
}
}
if (c == EOF) Error("bad GF2X input");
s.get();
a = ibuf;
return s;
}
static
ostream & HexOutput(ostream& s, const GF2X& a)
{
s << "0x";
long da = deg(a);
if (da < 0) {
s << '0';
return s;
}
long i, n, val;
val = 0;
n = 0;
for (i = 0; i <= da; i++) {
val = val | (rep(coeff(a, i)) << n);
n++;
if (n == 4) {
s << IntValToChar(val);
val = 0;
n = 0;
}
}
if (val)
s << IntValToChar(val);
return s;
}
ostream& operator<<(ostream& s, const GF2X& a)
{
if (GF2X::HexOutput)
return HexOutput(s, a);
long i, da;
GF2 c;
da = deg(a);
s << '[';
for (i = 0; i <= da; i++) {
c = coeff(a, i);
if (c == 0)
s << "0";
else
s << "1";
if (i < da) s << " ";
}
s << ']';
return s;
}
void random(GF2X& x, long n)
{
if (n < 0) Error("GF2X random: negative length");
if (NTL_OVERFLOW(n, 1, 0))
Error("GF2X random: excessive length");
long wl = (n+NTL_BITS_PER_LONG-1)/NTL_BITS_PER_LONG;
x.xrep.SetLength(wl);
long i;
for (i = 0; i < wl-1; i++) {
x.xrep[i] = RandomWord();
}
if (n > 0) {
long pos = n % NTL_BITS_PER_LONG;
if (pos == 0) pos = NTL_BITS_PER_LONG;
x.xrep[wl-1] = RandomBits_ulong(pos);
}
x.normalize();
}
void add(GF2X& x, const GF2X& a, const GF2X& b)
{
long sa = a.xrep.length();
long sb = b.xrep.length();
long i;
if (sa == sb) {
x.xrep.SetLength(sa);
if (sa == 0) return;
_ntl_ulong *xp = x.xrep.elts();
const _ntl_ulong *ap = a.xrep.elts();
const _ntl_ulong *bp = b.xrep.elts();
for (i = 0; i < sa; i++)
xp[i] = ap[i] ^ bp[i];
i = sa-1;
while (i >= 0 && !xp[i]) i--;
x.xrep.QuickSetLength(i+1);
}
else if (sa < sb) {
x.xrep.SetLength(sb);
_ntl_ulong *xp = x.xrep.elts();
const _ntl_ulong *ap = a.xrep.elts();
const _ntl_ulong *bp = b.xrep.elts();
for (i = 0; i < sa; i++)
xp[i] = ap[i] ^ bp[i];
for (; i < sb; i++)
xp[i] = bp[i];
}
else { // sa > sb
x.xrep.SetLength(sa);
_ntl_ulong *xp = x.xrep.elts();
const _ntl_ulong *ap = a.xrep.elts();
const _ntl_ulong *bp = b.xrep.elts();
for (i = 0; i < sb; i++)
xp[i] = ap[i] ^ bp[i];
for (; i < sa; i++)
xp[i] = ap[i];
}
}
/*
* The bodies of mul1, Mul1, AddMul1, and mul_half
* are generated by the MakeDesc program, and the
* macros NTL_BB_MUL_CODE... are defined in mach_desc.h.
* Thanks to Paul Zimmermann for providing improvements
* to this approach.
*/
#if (defined(NTL_GF2X_ALTCODE1))
#define NTL_EFF_BB_MUL_CODE0 NTL_ALT1_BB_MUL_CODE0
#define NTL_EFF_BB_MUL_CODE1 NTL_ALT1_BB_MUL_CODE1
#define NTL_EFF_BB_MUL_CODE2 NTL_ALT1_BB_MUL_CODE2
#define NTL_EFF_SHORT_BB_MUL_CODE1 NTL_ALT1_SHORT_BB_MUL_CODE1
#define NTL_EFF_HALF_BB_MUL_CODE0 NTL_ALT1_HALF_BB_MUL_CODE0
#elif (defined(NTL_GF2X_ALTCODE))
#define NTL_EFF_BB_MUL_CODE0 NTL_ALT_BB_MUL_CODE0
#define NTL_EFF_BB_MUL_CODE1 NTL_ALT_BB_MUL_CODE1
#define NTL_EFF_BB_MUL_CODE2 NTL_ALT_BB_MUL_CODE2
#define NTL_EFF_SHORT_BB_MUL_CODE1 NTL_ALT_SHORT_BB_MUL_CODE1
#define NTL_EFF_HALF_BB_MUL_CODE0 NTL_ALT_HALF_BB_MUL_CODE0
#else
#define NTL_EFF_BB_MUL_CODE0 NTL_BB_MUL_CODE0
#define NTL_EFF_BB_MUL_CODE1 NTL_BB_MUL_CODE1
#define NTL_EFF_BB_MUL_CODE2 NTL_BB_MUL_CODE2
#define NTL_EFF_SHORT_BB_MUL_CODE1 NTL_SHORT_BB_MUL_CODE1
#define NTL_EFF_HALF_BB_MUL_CODE0 NTL_HALF_BB_MUL_CODE0
#endif
static
void mul1(_ntl_ulong *c, _ntl_ulong a, _ntl_ulong b)
{
NTL_EFF_BB_MUL_CODE0
}
#ifdef NTL_GF2X_NOINLINE
#define mul1_IL mul1
#else
static inline
void mul1_inline(_ntl_ulong *c, _ntl_ulong a, _ntl_ulong b)
{
NTL_EFF_BB_MUL_CODE0
}
#define mul1_IL mul1_inline
#endif
static
void Mul1(_ntl_ulong *cp, const _ntl_ulong *bp, long sb, _ntl_ulong a)
{
NTL_EFF_BB_MUL_CODE1
}
static
void AddMul1(_ntl_ulong *cp, const _ntl_ulong* bp, long sb, _ntl_ulong a)
{
NTL_EFF_BB_MUL_CODE2
}
static
void Mul1_short(_ntl_ulong *cp, const _ntl_ulong *bp, long sb, _ntl_ulong a)
{
NTL_EFF_SHORT_BB_MUL_CODE1
}
static
void mul_half(_ntl_ulong *c, _ntl_ulong a, _ntl_ulong b)
{
NTL_EFF_HALF_BB_MUL_CODE0
}
// mul2...mul8 hard-code 2x2...8x8 word multiplies.
// I adapted these routines from LiDIA (except mul3, see below).
// Inlining these seems to hurt, not help.
static
void mul2(_ntl_ulong *c, const _ntl_ulong *a, const _ntl_ulong *b)
{
_ntl_ulong hs0, hs1;
_ntl_ulong hl2[2];
hs0 = a[0] ^ a[1];
hs1 = b[0] ^ b[1];
mul1_IL(c, a[0], b[0]);
mul1_IL(c+2, a[1], b[1]);
mul1_IL(hl2, hs0, hs1);
hl2[0] = hl2[0] ^ c[0] ^ c[2];
hl2[1] = hl2[1] ^ c[1] ^ c[3];
c[1] ^= hl2[0];
c[2] ^= hl2[1];
}
/*
* This version of mul3 I got from Weimerskirch, Stebila,
* and Shantz, "Generic GF(2^m) arithmetic in software
* an its application to ECC" (ACISP 2003).
*/
static
void mul3 (_ntl_ulong *c, const _ntl_ulong *a, const _ntl_ulong *b)
{
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -