void mult(const DMat<RT>& A, const DMat<RT>& B, DMat<RT>& result_product) { //printf("entering dmat mult\n"); typedef typename RT::ElementType ElementType; typedef typename DMat<RT>::ConstIterator ConstIterator; M2_ASSERT(A.numColumns() == B.numRows()); M2_ASSERT(A.numRows() == result_product.numRows()); M2_ASSERT(B.numColumns() == result_product.numColumns()); ElementType* result = result_product.array(); ElementType tmp; A.ring().init(tmp); // WARNING: this routine expects the result matrix to be in ROW MAJOR ORDER for (size_t i = 0; i<A.numRows(); i++) for (size_t j = 0; j<B.numColumns(); j++) { ConstIterator i1 = A.rowBegin(i); ConstIterator iend = A.rowEnd(i); ConstIterator j1 = B.columnBegin(j); while (i1 != iend) { A.ring().mult(tmp, *i1, *j1); A.ring().add(*result, *result, tmp); ++i1; ++j1; } result++; } A.ring().clear(tmp); }
bool inverse(const DMatZZpFFPACK& mat, DMatZZpFFPACK& result_inv) { M2_ASSERT(mat.numRows() == mat.numColumns()); result_inv.resize(mat.numRows(), mat.numRows()); M2_ASSERT(result_inv.numRows() == mat.numRows()); M2_ASSERT(result_inv.numColumns() == mat.numRows()); if (mat.numRows() == 0) { // 26 April 2014: this branch is needed as FFPACK gives answer of 0 in this case. return true; } DMatZZpFFPACK N(mat); size_t n = mat.numRows(); int nullspacedim; FFPACK::Invert2(mat.ring().field(), n, N.array(), n, result_inv.array(), n, nullspacedim); return (nullspacedim == 0); }
SchreyerOrder *SchreyerOrder::exterior(int pp) const // p th exterior power { // This routine is only called from FreeModule::exterior. // Therefore: p is in the range 0 < p <= rk. SchreyerOrder *result = new SchreyerOrder(M); int rk = rank(); M2_ASSERT(pp > 0); M2_ASSERT(pp <= rk); size_t p = static_cast<size_t>(pp); Subset a(p, 0); for (size_t i=0; i<p; i++) a[i] = i; int *base = M->make_one(); int next = 0; do { M->one(base); for (size_t r=0; r<p; r++) M->mult(base, base_monom(a[r]), base); result->append(next++, base); } while (Subsets::increment(rk, a)); M->remove(base); return result; }
void subtractMultipleTo(DMat<RT>& C, const DMat<RT>& A, const DMat<RT>& B) // C = C - A*B { typedef typename RT::ElementType ElementType; typedef typename DMat<RT>::ConstIterator ConstIterator; M2_ASSERT(A.numColumns() == B.numRows()); M2_ASSERT(A.numRows() == C.numRows()); M2_ASSERT(B.numColumns() == C.numColumns()); ElementType* result = C.array(); ElementType tmp; A.ring().init(tmp); // WARNING: this routine expects the result matrix to be in ROW MAJOR ORDER for (size_t i = 0; i<A.numRows(); i++) for (size_t j = 0; j<B.numColumns(); j++) { ConstIterator i1 = A.rowBegin(i); ConstIterator iend = A.rowEnd(i); ConstIterator j1 = B.columnBegin(j); while (i1 != iend) { A.ring().mult(tmp, *i1, *j1); A.ring().subtract(*result, *result, tmp); ++i1; ++j1; } result++; } A.ring().clear(tmp); }
void addInPlace(SMat<RT>&A, const SMat<RT>& B) { M2_ASSERT(&B.ring() == &A.ring()); M2_ASSERT(B.numRows() == A.numRows()); M2_ASSERT(B.numColumns() == A.numColumns()); A.addInPlace(B); }
void subtractInPlace(SMat<RT>& A, const SMat<RT>& B) // A -= B { M2_ASSERT(&B.ring() == &A.ring()); M2_ASSERT(B.numRows() == A.numRows()); M2_ASSERT(B.numColumns() == A.numColumns()); A.subtractInPlace(B); }
void transpose(const SMat<RT>& A, SMat<RT>& result) { // result should be the 0 matrix of the correct size. M2_ASSERT(&A != &result); // these cannot be aliased! M2_ASSERT(result.numRows() == A.numColumns()); M2_ASSERT(result.numColumns() == A.numRows()); throw exc::engine_error("'transpose' not writtten for sparse mutable matrices"); //TODO: MES: write this!! }
void subtractInPlace(DMat<RT>& A, const DMat<RT>& B) // A -= B { M2_ASSERT(&B.ring() == &A.ring()); M2_ASSERT(B.numRows() == A.numRows()); M2_ASSERT(B.numColumns() == A.numColumns()); size_t len = A.numRows() * A.numColumns(); for (size_t i=0; i<len; i++) { A.ring().subtract(A.array()[i], A.array()[i], B.array()[i]); } }
void transpose(const DMat<RT>& A, DMat<RT>& result) { M2_ASSERT(&A != &result); // these cannot be aliased! M2_ASSERT(result.numRows() == A.numColumns()); M2_ASSERT(result.numColumns() == A.numRows()); for (size_t c = 0; c < A.numColumns(); ++c) { auto i = A.columnBegin(c); auto j = result.rowBegin(c); auto end = A.columnEnd(c); for ( ; i != end; ++i, ++j) A.ring().set(*j, *i); } }
void binomial_ring::intvector_to_binomial(vec f, binomial &result) const // result should be a preallocated binomial { for (int i=0; i<nslots; i++) { result.lead[i] = 0; result.tail[i] = 0; } for ( ; f != NULL; f = f->next) { std::pair<bool,long> res = globalZZ->coerceToLongInteger(f->coeff); M2_ASSERT(res.first); int e = static_cast<int>(res.second); if (e > 0) result.lead[f->comp] = e; else if (e < 0) result.tail[f->comp] = -e; } set_weights(result.lead); set_weights(result.tail); normalize(result); }
void ARingZZpFFPACK::power(ElementType &result, const ElementType a, STT n) const { if (is_zero(a)) { if (n < 0) ERROR("division by zero"); set(result, a); return; } ElementType base; set(base, a); if (n < 0) { invert(base,base); n = -n; } n = n % (mCharac-1); set_from_int(result, 1); if (n == 0) return; // Now use doubling algorithm M2_ASSERT(n > 0); for (;;) { if ((n % 2) != 0) mFfpackField.mulin(result,base); // result *= base n >>= 1; if (n == 0) return; else mFfpackField.mulin(base, base); // base = base^2 } }
void ARingZZGMP::syzygy(const ElementType& a, const ElementType& b, ElementType& x, ElementType& y) const { M2_ASSERT(!is_zero(b)); // First check the special cases a = 0, b = 1, -1. Other cases: use gcd. if (is_zero(a)) { set_from_long(x, 1); set_zero(y); return; } if (mpz_cmp_ui(&b,1) == 0) { set_from_long(x, 1); negate(y, a); return; } if (mpz_cmp_si(&b,-1) == 0) { set_from_long(x, 1); set(y, a); return; } elem g; init(g); mpz_gcd(&g,&a,&b); divide(y,a,g); divide(x,b,g); if (mpz_sgn(&x) > 0) negate(y,y); else negate(x,x); clear(g); }
ring_elem GF::from_rational(mpq_ptr q) const { // a should be an element of ZZ/p ring_elem a = _originalR->getCoefficients()->from_rational(q); std::pair<bool,long> b = _originalR->getCoefficients()->coerceToLongInteger(a); M2_ASSERT(b.first); return GF::from_long(b.second); }
ARingZZpFFPACK::ARingZZpFFPACK(UTT charact) : mFfpackField (FieldType(static_cast<double>(charact))), mFfpackRandomIterator (mFfpackField), mCharac (charact), mDimension (1), mGeneratorComputed (false) { M2_ASSERT( FieldType::getMaxModulus()>=mCharac ); }
void set(DMat<RT>& A, MatrixWindow wA, const DMat<RT>& B, MatrixWindow wB) { M2_ASSERT(wA.sameSize(wB)); long rA = wA.begin_row; long rB = wB.begin_row; for ( ; rA < wA.end_row; ++rA, ++rB) { long cA = wA.begin_column; long cB = wB.begin_column; for ( ; cA < wA.end_column; ++cA, ++cB) A.ring().set(A.entry(rA,cA), B.entry(rB,cB)); } }
bool isEqual(const DMat<RT>& A, const DMat<RT>& B) { M2_ASSERT(&A.ring() == &B.ring()); if (B.numRows() != A.numRows()) return false; if (B.numColumns() != A.numColumns()) return false; size_t top = A.numRows() * A.numColumns(); auto elemsA = A.array(); auto elemsB = B.array(); for (size_t i = 0; i < top; i++) if (!A.ring().is_equal(*elemsA++, *elemsB++)) return false; return true; }
void scalarMultInPlace(DMat<RT>& A, MatrixWindow wA, const typename RT::ElementType& c) { M2_ASSERT(wA.sameSize(wB)); long rA = wA.begin_row; for ( ; rA < wA.end_row; ++rA) { long cA = wA.begin_column; for ( ; cA < wA.end_column; ++cA) { auto& a = A.entry(rA,cA); A.ring().mult(a, a, c); } } }
void operator=(SubMatrix<MatType> src) { M2_ASSERT(sameSize(src)); long rA = begin_row; long rB = src.begin_row; for ( ; rA < end_row; ++rA, ++rB) { long cA = begin_column; long cB = src.begin_column; for ( ; cA < end_column; ++cA, ++cB) matrix.ring().set(matrix.entry(rA,cA), src.matrix.entry(rB,cB)); } }
void addMultipleTo(DMatZZpFFPACK& C, const DMatZZpFFPACK::ElementType& a, const DMatZZpFFPACK& A, const DMatZZpFFPACK& B) { // Compute C := C + a*A*B // Both DMat, and FFPACK store dense matrices in row major order. // Note that the leading dimension in gemm arguments is #columns, // as the matrix is in row-major order FFLAS::FFLAS_TRANSPOSE tA = FFLAS::FflasNoTrans; FFLAS::FFLAS_TRANSPOSE tB = FFLAS::FflasNoTrans; size_t m = A.numRows(); size_t k = A.numColumns(); M2_ASSERT(A.numColumns() == B.numRows()); size_t n = B.numColumns(); M2_ASSERT(C.numRows() == m); M2_ASSERT(C.numColumns() == n); DMatZZpFFPACK::ElementType b; C.ring().init(b); C.ring().set_from_long(b, 1); FFLAS::fgemm( C.ring().field(), tB, tA, m,n,k, a, A.array(), A.numColumns(), B.array(), B.numColumns(), b, C.array(), C.numColumns() ); }
void scalarMult(DMat<RT>& A, MatrixWindow wA, const typename RT::ElementType& c, const DMat<RT>& B, MatrixWindow wB) { M2_ASSERT(wA.sameSize(wB)); long rA = wA.begin_row; long rB = wB.begin_row; for ( ; rA < wA.end_row; ++rA, ++rB) { long cA = wA.begin_column; long cB = wB.begin_column; for ( ; cA < wA.end_column; ++cA, ++cB) { A.ring().mult(A.entry(rA,cA), c, B.entry(rB,cB)); } } }
void addMultipleTo(ElementType& c, SubMatrix<MatType> src) { M2_ASSERT(sameSize(src)); long rA = begin_row; long rB = src.begin_row; for ( ; rA < end_row; ++rA, ++rB) { long cA = begin_column; long cB = src.begin_column; for ( ; cA < end_column; ++cA, ++cB) matrix.ring().addMultipleTo(matrix.entry(rA,cA), c, src.matrix.entry(rB,cB)); } }
void addMultipleTo(DMat<RT>& A, MatrixWindow wA, const typename RT::ElementType& c, const DMat<RT>& B, MatrixWindow wB) { M2_ASSERT(wA.sameSize(wB)); typename RT::ElementType tmp; A.ring().init(tmp); long rA = wA.begin_row; long rB = wB.begin_row; for ( ; rA < wA.end_row; ++rA, ++rB) { long cA = wA.begin_column; long cB = wB.begin_column; for ( ; cA < wA.end_column; ++cA, ++cB) { A.ring().mult(tmp, c, B.entry(rB,cB)); auto& a = A.entry(rA,cA); A.ring().add(a, a, tmp); } } A.ring().clear(tmp); }
ARingZZpFFPACK::ElementType ARingZZpFFPACK::computeGenerator() const { for (UTT currIntElem=2; currIntElem < mCharac; currIntElem++) { ElementType currElem; set_from_int(currElem, currIntElem); bool found = true; ElementType tmpElem = currElem; for (UTT count=0;count < mCharac-2; count++) { mult(tmpElem, tmpElem, currElem); if (is_equal(currElem, tmpElem)) found = false; } if (found) { std::cerr << "generator = " << currElem << std::endl; return currElem; } } M2_ASSERT(false); // we should not get here, if the program logic is OK return ElementType(1); }
bool GF::promote(const Ring *Rf, const ring_elem f, ring_elem &result) const { // Rf = Z/p[x]/F(x) ---> GF(p,n) // promotion: need to be able to know the value of 'x'. // lift: need to compute (primite_element)^e if (Rf != _originalR) return false; result = from_long(0); int exp[1]; for (Nterm *t = f; t != NULL; t = t->next) { std::pair<bool,long> b = _originalR->getCoefficients()->coerceToLongInteger(t->coeff); M2_ASSERT(b.first); ring_elem coef = from_long(b.second); _originalR->getMonoid()->to_expvector(t->monom, exp); // exp[0] is the variable we want. Notice that since the ring is a quotient, // this degree is < n (where Q_ = P^n). ring_elem g = power(_x_exponent, exp[0]); g = mult(g, coef); internal_add_to(result, g); } return true; }
void power(ElementType& result, const ElementType& a, long n) const { M2_ASSERT(n >= 0); return fmpq_pow_si(&result,&a,n); }
int LLLoperations::doLLL(MutableMatrix *A, MutableMatrix *Achange, MutableMatrix *LLLstate, int nsteps) { size_t n = A->n_cols(); if (n == 0) return COMP_DONE; // Extract the state from LLLstate: int k, kmax; ring_elem a, alphaTop, alphaBottom; buffer o; if (LLLstate->get_entry(0,n,a)) { std::pair<bool,long> res = globalZZ->coerceToLongInteger(a); M2_ASSERT(res.first); k = static_cast<int>(res.second); } else k = 0; if (LLLstate->get_entry(0,n+1,a)) { std::pair<bool,long> res = globalZZ->coerceToLongInteger(a); M2_ASSERT(res.first); kmax = static_cast<int>(res.second); } else kmax = 0; LLLstate->get_entry(0,n+2,alphaTop); // Don't free alphaTop! LLLstate->get_entry(0,n+3,alphaBottom); while (k < n && nsteps != 0 && !system_interrupted()) { if (M2_gbTrace >= 1) { o.reset(); o << "."; if (M2_gbTrace >= 2) o << k; if (nsteps % 20 == 0) o << newline; emit(o.str()); } nsteps--; if (k > kmax) { if (M2_gbTrace == 1) { o.reset(); o << "." << k; if (nsteps % 20 == 0) o << newline; emit(o.str()); } kmax = k; for (int j=0; j<=k; j++) { ring_elem u; A->dot_product(k,j,u); for (int i=0; i<=j-1; i++) { // u = (D#i * u - lambda#(k,i) * lambda#(j,i)) // D#(i-1) ring_elem Di, mki, mji, Di1; LLLstate->get_entry(i,i,Di); globalZZ->mult_to(u, Di); if (LLLstate->get_entry(i,k,mki) && LLLstate->get_entry(i,j,mji)) { ring_elem t1 = globalZZ->mult(mki,mji); globalZZ->subtract_to(u,t1); } if (i > 0) { LLLstate->get_entry(i-1,i-1,Di1); // Cannot be zero!! ring_elem t1 = globalZZ->divide(u,Di1); globalZZ->remove(u); u = t1; } } // At this point we have our element: LLLstate->set_entry(j,k,u); if (j == k && globalZZ->is_zero(u)) { ERROR("LLL vectors not independent"); return COMP_ERROR; } } } // end of the k>kmax initialization REDI(k,k-1,A,Achange,LLLstate); if (Lovasz(LLLstate,k,alphaTop,alphaBottom)) { SWAPI(k,kmax,A,Achange,LLLstate); k--; if (k == 0) k = 1; } else { for (int ell=k-2; ell>=0; ell--) REDI(k,ell,A,Achange,LLLstate); k++; } } // Before returning, reset k,kmax: LLLstate->set_entry(0,n,globalZZ->from_long(k)); LLLstate->set_entry(0,n+1,globalZZ->from_long(kmax)); if (k >= n) return COMP_DONE; if (nsteps == 0) return COMP_DONE_STEPS; return COMP_INTERRUPTED; }
void ARingZZpFFPACK::unsafeInvert(ElementType &result, const ElementType a) const { M2_ASSERT(not is_zero(a)); mFfpackField.inv(result, a); }
void power(ElementType& result, const ElementType& a, long n) const { M2_ASSERT(n >= 0); mpz_pow_ui(mpq_numref(&result),mpq_numref(&a),n); mpz_pow_ui(mpq_denref(&result),mpq_denref(&a),n); }
GaloisFieldTable::GaloisFieldTable(const PolynomialRing& R, const ring_elem prim): mCharac(static_cast<int>(R.characteristic())), mOriginalRing(R), mPrimitiveElement(prim) { M2_ASSERT(mOriginalRing.n_quotients() == 1); mGenerator = RingElement::make_raw(&R, R.copy(prim)); ring_elem f = mOriginalRing.quotient_element(0); Nterm *t = f; mDimension = mOriginalRing.getMonoid()->primary_degree(t->monom); mOrder = mCharac; for (int i=1; i<mDimension; i++) mOrder *= mCharac; mOne = mOrder - 1; // representation for the number 1: p^n - 1. mOrderMinusOne = mOne; // p^n - 1 mMinusOne = (mCharac == 2 ? mOne : mOne/2); // Get ready to create mOneTable. std::vector<ring_elem> polys; polys.push_back(mOriginalRing.from_long(0)); polys.push_back(mOriginalRing.copy(mPrimitiveElement)); ring_elem oneR = mOriginalRing.from_long(1); mGeneratorExponent = static_cast<GFElement>(-1); ring_elem x = mOriginalRing.var(0); if (mOriginalRing.is_equal(mPrimitiveElement, x)) mGeneratorExponent = 1; for (GFElement i=2; i<=mOne; i++) { ring_elem g = mOriginalRing.mult(polys[i-1], mPrimitiveElement); polys.push_back(g); if (mOriginalRing.is_equal(g, oneR)) break; if (mOriginalRing.is_equal(g, x)) mGeneratorExponent = i; } #if 0 for (size_t i = 0; i < polys.size(); i++) { std::cerr << i << " "; dringelem(&R, polys[i]); std::cerr << "\n"; } #endif M2_ASSERT(polys.size() == mOrder); M2_ASSERT(mGeneratorExponent != static_cast<GFElement>(-1)); // Set 'one_table'. mOneTable = newarray_atomic(GFElement,mOrder); mOneTable[0] = mOrderMinusOne; for (GFElement i=1; i<=mOrderMinusOne; i++) { if (system_interrupted()) { // first clean up? return; } ring_elem f1 = mOriginalRing.add(polys[i], oneR); GFElement j; for (j=0; j<=mOrderMinusOne; j++) if (mOriginalRing.is_equal(f1, polys[j])) break; if (j > mOrderMinusOne) { std::cout << "oops: didn't find element " << i << " !!" << std::endl; } mOneTable[i] = j; } // Create the ZZ/P ---> GF(Q) inclusion map mFromIntTable = newarray_atomic(GFElement,mCharac); GFElement a = mOne;; mFromIntTable[0] = 0; for (GFElement i=1; i<mCharac; i++) { mFromIntTable[i] = a; a = mOneTable[a]; } }
const ElementType& entry(size_t row, size_t column) const { M2_ASSERT(row < numRows()); M2_ASSERT(column < numColumns()); return * fmpq_mat_entry(mArray, row, column); }