void AddToCol(mat_GF2& x, long j, const vec_GF2& a) // add a to column j of x // ALIAS RESTRICTION: a should not alias any row of x { long n = x.NumRows(); long m = x.NumCols(); if (a.length() != n || j < 0 || j >= m) Error("AddToCol: bad args"); long wj = j/NTL_BITS_PER_LONG; long bj = j - wj*NTL_BITS_PER_LONG; _ntl_ulong j_mask = 1UL << bj; const _ntl_ulong *ap = a.rep.elts(); _ntl_ulong a_mask = 1; long i; for (i = 0; i < n; i++) { if (*ap & a_mask) x[i].rep.elts()[wj] ^= j_mask; a_mask <<= 1; if (!a_mask) { a_mask = 1; ap++; } } }
static void mul_aux(vec_GF2& x, const vec_GF2& a, const mat_GF2& B) { long n = B.NumRows(); long l = B.NumCols(); if (n != a.length()) Error("matrix mul: dimension mismatch"); x.SetLength(l); clear(x); const _ntl_ulong *ap = a.rep.elts(); _ntl_ulong a_mask = 1; _ntl_ulong *xp = x.rep.elts(); long lw = (l + NTL_BITS_PER_LONG - 1)/NTL_BITS_PER_LONG; long i; for (i = 0; i < n; i++) { if (*ap & a_mask) { const _ntl_ulong *bp = B[i].rep.elts(); long j; for (j = 0; j < lw; j++) xp[j] ^= bp[j]; } a_mask <<= 1; if (!a_mask) { a_mask = 1; ap++; } } }
static void ClearBit(vec_GF2& v, long i) { if (i < 0 || i >= v.length()) LogicError("vec_GF2: subscript out of range"); long q = i/NTL_BITS_PER_LONG; long p = i - q*NTL_BITS_PER_LONG; v.rep[q] &= ~(1UL << p); }
void vec_GF2::swap(vec_GF2& y) { long xf = fixed(); long yf = y.fixed(); if (xf != yf || (xf && length() != y.length())) LogicError("swap: can't swap these vec_GF2s"); rep.swap(y.rep); _ntl_swap(_len, y._len); _ntl_swap(_maxlen, y._maxlen); }
static void mul_aux(vec_GF2& x, const mat_GF2& A, const vec_GF2& b) { long n = A.NumRows(); long l = A.NumCols(); if (l != b.length()) Error("matrix mul: dimension mismatch"); x.SetLength(n); long i; for (i = 0; i < n; i++) { x.put(i, A[i] * b); } }
void vec_GF2::append(const vec_GF2& a) { long a_len = a.length(); long x_len = length(); if (a_len == 0) return; if (x_len == 0) { *this = a; return; } SetLength(x_len + a_len); // new bits are guaranteed zero ShiftAdd(rep.elts(), a.rep.elts(), a.rep.length(), x_len); }
long operator==(const vec_GF2& a, const vec_GF2& b) { return a.length() == b.length() && a.rep == b.rep; }
void solve(GF2& d, vec_GF2& X, const mat_GF2& A, const vec_GF2& b) { long n = A.NumRows(); if (A.NumCols() != n) Error("solve: nonsquare matrix"); if (b.length() != n) Error("solve: dimension mismatch"); if (n == 0) { X.SetLength(0); set(d); return; } long i, j, k, pos; mat_GF2 M; M.SetDims(n, n+1); for (i = 0; i < n; i++) { AddToCol(M, i, A[i]); } AddToCol(M, n, b); long wn = ((n+1) + NTL_BITS_PER_LONG - 1)/NTL_BITS_PER_LONG; for (k = 0; k < n; k++) { long wk = k/NTL_BITS_PER_LONG; long bk = k - wk*NTL_BITS_PER_LONG; _ntl_ulong k_mask = 1UL << bk; pos = -1; for (i = k; i < n; i++) { if (M[i].rep.elts()[wk] & k_mask) { pos = i; break; } } if (pos != -1) { if (k != pos) { swap(M[pos], M[k]); } _ntl_ulong *y = M[k].rep.elts(); for (i = k+1; i < n; i++) { // M[i] = M[i] + M[k]*M[i,k] if (M[i].rep.elts()[wk] & k_mask) { _ntl_ulong *x = M[i].rep.elts(); for (j = wk; j < wn; j++) x[j] ^= y[j]; } } } else { clear(d); return; } } vec_GF2 XX; XX.SetLength(n+1); XX.put(n, 1); for (i = n-1; i >= 0; i--) { XX.put(i, XX*M[i]); } XX.SetLength(n); X = XX; set(d); return; }