Smith form by sparse elmination, Integer Smith by valence method, or local at a prime power.See smithvalence for valence method with more options and information.
For local smith, moduli greater than 2^32 are not supported here (easily changed). matrix is read from file or generated from a small selection of example families. Run the program with no arguments for a synopsis of the command line parameters.
#include <iostream>
#include <string>
#include <vector>
#include <list>
#include <linbox/algorithms/smith-form-sparseelim-local.h>
#include <linbox/algorithms/smith-form-sparseelim-poweroftwo.h>
#include <linbox/ring/pir-modular-int32.h>
#define SILENT
#define NOT_USING_OMP
#include "smithvalence.h"
#undef NOT_USING_OMP
#undef SILENT
template<
class I1,
class Lp>
void distinct (I1 a, I1 b, Lp& c);
template <class I> void display(I b, I e);
template<class Int_type, class Ring_type = Givaro::ZRing<Int_type> >
void runpoweroftworank(ifstream& input, const size_t exponent, size_t StPr);
int main(int argc, char* argv[])
{
Givaro::Timer chrono;
if (argc < 2 or 3 < argc) {
cout <<
"Usage: " << "smithsparse file [m]" << endl <<
" where file contains the matrix in any supported format and m is the modulus." << endl <<
" With no m, Smith form over Z by the valence method is done." << endl <<
" Use smithvalence.C to have more options and get more output info." << endl <<
" Given m, a prime power, local Smith form over Z_m is done via sparse elim." << endl <<
" Use power_ranks.C or poweroftwo_rank.C to have more options and get more output info." << endl <<
" See mats.C for some examples that have been used in smith form algorithm testing" << endl;
return 0;
}
chrono.start();
ifstream input(argv[1]);
if (argc > 2) {
unsigned long m = atoi(argv[2]);
if (m > 4967296) {
cerr << "Modulus too large for this example" << endl;
return -1;
}
if (m%2 == 0) {
runpoweroftworank<uint64_t, Givaro::ZRing<int64_t> >(input, 32, 0);
} else {
typedef Givaro::Modular<int32_t> SPIR;
SPIR R(m);
SparseMatrix<SPIR, SparseMatrixFormat::SparseSeq > B (R);
B.read(input);
Integer p(m), im(m);
Givaro::IntPrimeDom IPD;
for(unsigned int k = 2; ( ( ! IPD.isprime(p) ) && (p > 1) ); ++k)
Givaro::root( p, im, k );
vector<pair<size_t,SPIR::Element> > vec;
LinBox::Permutation<SPIR> Q(R,B.coldim());
PGD(vec, B, Q, (int32_t)m, (int32_t)p);
typedef list< SPIR::Element > List;
List L;
for ( auto p_it = vec.begin(); p_it != vec.end(); ++p_it) {
for(size_t i = 0; i < (size_t) p_it->first; ++i)
L.push_back((SPIR::Element)p_it->second);
}
size_t M = (B.rowdim() > B.coldim() ? B.coldim() : B.rowdim());
size_t Min = (B.rowdim() < B.coldim() ? B.coldim() : B.rowdim());
for (size_t i = L.size(); i < M; ++i)
L.push_back(0);
list<pair<SPIR::Element, size_t> > pl;
display(pl.begin(), pl.end());
chrono.stop();
cout << "T" << M << "local(PowerGaussDomain<int32_t>)" << m << " := "
<< chrono << endl;
}
} else {
Givaro::ZRing<Integer> ZZ;
typedef SparseMatrix<Givaro::ZRing<Integer> > Blackbox;
Blackbox A (ZZ);
A.read(input);
Givaro::ZRing<Integer>::Element val_A;
chrono.start();
if (A.rowdim() > A.coldim()) {
}
else if (A.rowdim() < A.coldim()) {
}
else {
}
vector<integer> Moduli;
vector<size_t> exponents;
Givaro::IntFactorDom<> FTD;
typedef pair<integer,unsigned long> PairIntRk;
vector< PairIntRk > smith;
while ( gcd(val_A,coprimeV) > 1 ) {
FTD.nextprimein(coprimeV);
}
unsigned long coprimeR; LRank(coprimeR, argv[1], coprimeV);
smith.push_back(PairIntRk(coprimeV, coprimeR));
FTD.set(Moduli, exponents, val_A, 5000);
vector<size_t>::const_iterator eit=exponents.begin();
vector<integer> SmithDiagonal(coprimeR,
integer(1));
for(vector<integer>::const_iterator mit=Moduli.begin();
mit != Moduli.end(); ++mit) {
size_t r; LRank(r, argv[1], *mit);
smith.push_back(PairIntRk(*mit, r));
for(size_t i=r; i < coprimeR; ++i)
SmithDiagonal[i] *= *mit;
}
eit=exponents.begin();
vector<PairIntRk>::const_iterator sit=smith.begin();
for( ++sit; sit != smith.end(); ++sit, ++eit) {
if (sit->second != coprimeR) {
vector<size_t> ranks;
ranks.push_back(sit->second);
size_t effexp;
if (*eit > 1) {
PRank(ranks, effexp, argv[1], sit->first, *eit, coprimeR);
}
else {
PRank(ranks, effexp, argv[1], sit->first, 2, coprimeR);
}
if (ranks.size() == 1) ranks.push_back(coprimeR);
if (effexp < *eit) {
for(size_t expo = effexp<<1; ranks.back() < coprimeR; expo<<=1) {
PRankInteger(ranks, argv[1], sit->first, expo, coprimeR);
}
} else {
for(size_t expo = (*eit)<<1; ranks.back() < coprimeR; expo<<=1) {
PRank(ranks, effexp, argv[1], sit->first, expo, coprimeR);
if (ranks.size() < expo) {
PRankInteger(ranks, argv[1], sit->first, expo, coprimeR);
}
}
}
vector<size_t>::const_iterator rit=ranks.begin();
for(++rit; rit!= ranks.end(); ++rit) {
if ((*rit)>= coprimeR) break;
for(size_t i=(*rit); i < coprimeR; ++i)
SmithDiagonal[i] *= sit->first;
}
}
}
size_t num=0;
cout << '(';
for( vector<integer>::const_iterator dit=SmithDiagonal.begin();
dit != SmithDiagonal.end(); ++dit) {
if (*dit == si) ++num;
else {
if (num > 0)
cout << '[' << si << ',' << num << "] ";
num=1;
si = *dit;
}
}
cout << '[' << si << ',' << num << "] )" << endl;
chrono.stop();
cout << "T" << A.rowdim() << "smithvalence(ZRing<Integer>):= "
<< chrono << endl;
}
return 0;
}
template<class I1, class Lp>
{
typename iterator_traits<I1>::value_type e;
size_t count = 0;
if (a != b) {e = *a; ++a; count = 1;}
else return;
while (a != b)
{ if (*a == e) ++count;
else
{ c.push_back(typename Lp::value_type(e, count));
e = *a; count = 1;
}
++a;
}
c.push_back(typename Lp::value_type(e, count));
return;
}
template <class I>
void display(I b, I e)
{ cout << "(";
for (I p = b; p != e; ++p) cout << '[' << p->first << "," << p->second << "] ";
cout << ")" << endl;
}
template<class Int_type, class Ring_type>
void runpoweroftworank(ifstream& input, const size_t exponent, size_t StPr) {
typedef std::vector<std::pair<size_t,Int_type> > Smith_t;
typedef Ring_type Ring;
typedef LinBox::SparseMatrix<Ring,
Smith_t local;
Ring R;
SparseMat A (ms);
input.close();
LinBox::GF2 F2;
Permutation<GF2> Q(F2,A.coldim());
cout << "A is " << A.rowdim() << " by " << A.coldim() << endl;
if (A.rowdim() <= 20 && A.coldim() <= 20) A.write(cout,Tag::FileFormat::Maple) << endl;
Givaro::Timer tim;
tim.clear(); tim.start();
if (StPr)
PGD(local, A, Q, exponent, StPr);
else
PGD(local, A, Q, exponent);
tim.stop();
R.write(std::cout << "Local Smith Form ") << " : " << std::endl << '(';
int num = A.rowdim();
for (auto p = local.begin(); p != local.end(); ++p) {
std::cout << '[' << p->second << ',' << p->first << "] ";
num -= p->first;
}
if (num > 0) std::cout << '[' << F2.zero << ',' << num << "] ";
std::cout << ')' << std::endl;
std::cerr << tim << std::endl;
}