/* find value = poly(arg) where poly is a polynomial of degree d and all the arithmetic takes place in the given Galois field.*/ int polyeval(GF & gf, int d, std::vector<int> & poly, int arg, int* value) { int ans = 0; /* note: cannot decrement with a size type because it is always > 0. this needs to go < 1 to stop */ //for (size_t i = static_cast<size_t>(d); i >= 0; --i) /* Horner's rule */ for (int i = d; i >= 0; i--) /* Horner's rule */ { size_t ui = static_cast<size_t>(i); size_t uans = static_cast<size_t>(ans); size_t uarg = static_cast<size_t>(arg); #ifdef RANGE_DEBUG size_t plusRow = static_cast<size_t>(gf.times.at(uans,uarg)); size_t plusCol = static_cast<size_t>(poly.at(ui)); ans = gf.plus.at(plusRow, plusCol); #else //ans = gf.plus(gf.times(ans,arg),poly[i]); size_t plusRow = static_cast<size_t>(gf.times(uans,uarg)); size_t plusCol = static_cast<size_t>(poly[ui]); ans = gf.plus(plusRow, plusCol); #endif } *value = ans; return UNCHECKED_RETURN; }
int bose(GF & gf, bclib::matrix<int> & A, int ncol) { size_t icol, irow; size_t q = static_cast<size_t>(gf.q); // bosecheck throws if it fails bosecheck(static_cast<int>(q), ncol); irow = 0; for (size_t i = 0; i < q; i++) { for (size_t j = 0; j < q; j++) { icol = 0; A(irow, icol++) = static_cast<int>(i); if (ncol > 1) { A(irow, icol++) = static_cast<int>(j); } for (icol = 2; icol < static_cast<size_t>(ncol); icol++) { A(irow, icol) = gf.plus(j, gf.times(i, icol - 1)); } irow++; } } return SUCCESS_CHECK; }
int bosebushl(GF & gf, int lam, bclib::matrix<int> & B, int ncol) /* Implement Bose and Bush's 1952 A.M.S. method with given lambda */ { int p, irow; int mul; p = gf.p; /* GF(q) used to generate design with q/lam levels */ size_t q = static_cast<size_t>(gf.q); size_t s = q / lam; /* number of levels in design */ bclib::matrix<int> A(s,q); // bosebushlcheck throws if it fails bosebushlcheck(static_cast<int>(s), p, lam, ncol); irow = 0; for (size_t i = 0; i < q; i++) { for (size_t j = 0; j < q; j++) { mul = gf.times(i,j); mul = mul % s; for (size_t k = 0; k < s; k++) { A(k,j) = gf.plus(mul,k); } } for (size_t k = 0; k < s; k++) { for (size_t j = 0; j < static_cast<size_t>(ncol) && j < lam * s + 1; j++) { B(irow,j) = A(k,j); } if (ncol == lam * static_cast<int>(s) + 1) { B(irow, static_cast<size_t>(ncol) - 1) = static_cast<int>(i % s); } irow++; } } return SUCCESS_CHECK; }
int bosebush(GF & gf, bclib::matrix<int> & B, int ncol) { int p; int mul; size_t irow; p = gf.p; /* GF(q) used to generate design with q/2 levels */ size_t q = static_cast<size_t>(gf.q); size_t s = q / 2; /* number of levels in design */ bclib::matrix<int> A(s, q); // bosebushcheck throws if it fails bosebushcheck(static_cast<int>(s), p, ncol); irow = 0; for (size_t i = 0; i < q; i++) { for (size_t j = 0; j < q; j++) { mul = gf.times(i,j); mul = mul % s; for (size_t k = 0; k < s; k++) { A(k,j) = gf.plus(mul,k); } } for (size_t k = 0; k < s; k++) { for (size_t j = 0; j < static_cast<size_t>(ncol) && j < 2 * s + 1; j++) { B(irow,j) = A(k,j); } if (static_cast<size_t>(ncol) == 2 * s + 1) { B(irow, static_cast<size_t>(ncol) - 1) = static_cast<int>(i % s); } irow++; } } return SUCCESS_CHECK; }
void GF_print(GF & gf) { int n, p, q; n = gf.n; p = gf.p; q = gf.q; if (q > 999) { PRINT_OUTPUT("Warning q=%d will overflow print field.\n", q); } PRINT_OUTPUT("\nFor GF(%d) p=%d n=%d\n", q, p, n); PRINT_OUTPUT("x**n = ("); for (int i = 0; i < n - 1; i++) { PRINT_OUTPUT("%d,", gf.xton[i]); } PRINT_OUTPUT("%d)\n", gf.xton[n - 1]); PRINT_OUTPUT("\n\nGF(%d) Polynomial coefficients:\n", q); for (int i = 0; i < q; i++) { PRINT_OUTPUT(" %3d ", i); for (int j = 0; j < n; j++) { PRINT_OUTPUT("%3d ", gf.poly(i,j)); } PRINT_OUTPUT("\n"); } PRINT_OUTPUT("\n\nGF(%d) Addition Table\n", q); for (int i = 0; i < q; i++) { PRINT_OUTPUT(" "); for (int j = 0; j < q; j++) { PRINT_OUTPUT(" %3d", gf.plus(i,j)); } PRINT_OUTPUT("\n"); } PRINT_OUTPUT("\n\nGF(%d) Multiplication table\n", q); for (int i = 0; i < q; i++) { PRINT_OUTPUT(" "); for (int j = 0; j < q; j++) { PRINT_OUTPUT(" %3d", gf.times(i,j)); } PRINT_OUTPUT("\n"); } PRINT_OUTPUT("\n\nGF(%d) Reciprocals\n", q); for (int i = 1; i < q; i++) { PRINT_OUTPUT(" %3d %3d\n", i, gf.inv[i]); } PRINT_OUTPUT("\n\nGF(%d) Negatives\n", q); for (int i = 0; i < q; i++) { PRINT_OUTPUT(" %3d %3d\n", i, gf.neg[i]); } PRINT_OUTPUT("\n\nGF(%d) Square roots\n", q); for (int i = 0; i < q; i++) { PRINT_OUTPUT(" %3d %3d\n", i, gf.root[i]); } }
/* Make ready the Galois Field */ int GF_ready(GF & gf, int p, int n, std::vector<int> & xton) { size_t q; std::ostringstream msg; std::vector<int> poly(n); gf.n = n; gf.p = p; q = 1; for (int i = 0; i < n; i++) { q *= p; } gf.q = q; gf.xton = std::vector<int>(n); for (size_t i = 0; i < static_cast<size_t>(n); i++) { gf.xton[i] = xton[i]; } gf.plus = bclib::matrix<int>(q,q); gf.times = bclib::matrix<int>(q,q); gf.inv = std::vector<int>(q); gf.neg = std::vector<int>(q); gf.root = std::vector<int>(q); gf.poly = bclib::matrix<int>(q, n); for (size_t i = 0; i < static_cast<size_t>(n); i++) { gf.poly(0,i) = 0; } for (size_t i = 1; i < q; i++) { size_t click; for (click = 0; gf.poly(i - 1,click) == (p - 1); click++) { gf.poly(i,click) = 0; } gf.poly(i,click) = gf.poly(i - 1,click) + 1; for (size_t j = click + 1; j < static_cast<size_t>(n); j++) { gf.poly(i,j) = gf.poly(i - 1,j); } } for (size_t i = 0; i < q; i++) { for (size_t j = 0; j < q; j++) { //GF_poly_sum(p, n, gf.poly[i], gf.poly[j], poly); GF_poly_sum(p, n, gf.poly.getrow(i), gf.poly.getrow(j), poly); gf.plus(i,j) = GF_poly2int(p, n, poly); GF_poly_prod(p, n, xton, gf.poly.getrow(i), gf.poly.getrow(j), poly); gf.times(i,j) = GF_poly2int(p, n, poly); } } for (size_t i = 0; i < q; i++) { gf.inv[i] = -1; for (size_t j = 0; j < q; j++) { if (gf.times(i,j) == 1) { gf.inv[i] = j; } } if (i > 0 && gf.inv[i] <= 0) { msg << "There is something wrong with the Galois field\n"; msg << "used for q=" << q << ". Element " << i << "has no reciprocal.\n"; throw std::runtime_error(msg.str().c_str()); } } for (size_t i = 0; i < q; i++) { gf.neg[i] = -1; for (size_t j = 0; j < q; j++) if (gf.plus(i,j) == 0) gf.neg[i] = j; if (i > 0 && gf.neg[i] <= 0) { msg << "There is something wrong with the Galois field\n"; msg << "used for q=" << q << ". Element " << i << " has no negative.\n"; throw std::runtime_error(msg.str().c_str()); } } for (size_t i = 0; i < q; i++) { gf.root[i] = -1; for (size_t j = 0; j < q; j++) { if (gf.times(j,j) == static_cast<int>(i)) { gf.root[i] = j; } } } return 1; }
int addelkemp(GF & gf, bclib::matrix<int> & A, int ncol) { int kay; /* A&K notation */ int square, ksquare, temp; size_t row, col; int p = gf.p; size_t q = gf.q; std::vector<int> b(q); std::vector<int> c(q); std::vector<int> k(q); // addelkempcheck throws if it fails addelkempcheck(static_cast<int>(q), p, ncol); for (size_t i = 0; i < q; i++) { /* First q*q rows */ square = gf.times(i,i); for (size_t j = 0; j < q; j++) { row = i * q + j; col = 0; if (col < static_cast<size_t>(ncol)) { A(row, col++) = static_cast<int>(j); } for (size_t m = 1; m < q && col < static_cast<size_t>(ncol); m++) { A(row,col++) = gf.plus(i,gf.times(m,j)); } for (size_t m = 0; m < q && col < static_cast<size_t>(ncol); m++) { temp = gf.plus(j,gf.times(m,i)); A(row,col++) = gf.plus(temp,square); /* Rgt cols */ } if (col < static_cast<size_t>(ncol)) { A(row, col++) = static_cast<int>(i); } } } if (p != 2) /* Constants kay,b,c,k for odd p */ { oaaddelkemp::akodd(gf, &kay, b, c, k); } else /* Constants kay,b,c,k for even p */ { oaaddelkemp::akeven(gf, &kay, b, c, k); } for (size_t i = 0; i < q; i++) { /* Second q*q rows */ square = gf.times(i,i); ksquare = gf.times(kay,square); for (size_t j = 0; j < q; j++) { row = q * q + i * q + j; col = 0; if (col < static_cast<size_t>(ncol)) { A(row, col++) = static_cast<int>(j); } for (size_t m = 1; m < q && col < static_cast<size_t>(ncol); m++, col++) { A(row,col) = gf.plus(A(row - q * q,col),b[m]); } if (col < static_cast<size_t>(ncol)) { A(row,col++) = gf.plus(ksquare,j); /* q+1 */ } for (size_t m = 1; m < q && col < static_cast<size_t>(ncol); m++) { temp = gf.times(i,k[m]); temp = gf.plus(ksquare,temp); temp = gf.plus(j,temp); A(row,col++) = gf.plus(temp,c[m]); } if (col < static_cast<size_t>(ncol)) { A(row, col++) = static_cast<int>(i); } } } return SUCCESS_CHECK; }