Skip to content

Commit

Permalink
* Implement MatrixReader::detectFormat and helpers
Browse files Browse the repository at this point in the history
* Rename FORMAT_GUILLAUME to FORMAT_DUMAS
* Add function row-echelon-form to guess output-format based on extension of matrix-filename
  • Loading branch information
hovinen committed Jun 22, 2011
1 parent f6df476 commit 3aec33b
Show file tree
Hide file tree
Showing 7 changed files with 202 additions and 25 deletions.
9 changes: 9 additions & 0 deletions linbox/matrix/io-png.tcc
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@ bool MatrixReader<Ring>::isPNG (std::istream &is) const
return png_sig_cmp (pngsig, 0, _png_sig_size) == 0;
}

template <class Ring>
bool MatrixReader<Ring>::isPNG (char *buf, std::streamsize n) const
{
if (n < (std::streamsize) _png_sig_size)
return false;

return png_sig_cmp ((png_byte *) buf, 0, _png_sig_size) == 0;
}

template <class Ring>
void MatrixReader<Ring>::PNGReadData (png_structp png_ptr, png_bytep data, png_size_t length)
{
Expand Down
17 changes: 13 additions & 4 deletions linbox/matrix/io.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ namespace LinBox

/// File-formats for matrix-output
enum FileFormatTag {
FORMAT_DETECT, FORMAT_UNKNOWN, FORMAT_TURNER, FORMAT_ONE_BASED, FORMAT_GUILLAUME, FORMAT_MAPLE, FORMAT_MATLAB, FORMAT_SAGE, FORMAT_PRETTY,
FORMAT_DETECT, FORMAT_UNKNOWN, FORMAT_TURNER, FORMAT_ONE_BASED, FORMAT_DUMAS, FORMAT_MAPLE, FORMAT_MATLAB, FORMAT_SAGE, FORMAT_PRETTY,
#ifdef __LINBOX_HAVE_LIBPNG
FORMAT_PNG
#endif // __LINBOX_HAVE_LIBPNG
Expand Down Expand Up @@ -63,7 +63,7 @@ class MatrixReader {
std::istream &readOneBased (std::istream &is, Matrix &A) const;

template <class Matrix>
std::istream &readGuillaume (std::istream &is, Matrix &A) const;
std::istream &readDumas (std::istream &is, Matrix &A) const;

template <class Matrix>
std::istream &readMaple (std::istream &is, Matrix &A) const;
Expand All @@ -77,11 +77,20 @@ class MatrixReader {
template <class Matrix>
std::istream &readPretty (std::istream &is, Matrix &A) const;

bool isDumas (char *buf, std::streamsize n) const;
bool isTurner (char *buf, std::streamsize n) const;
bool isMaple (char *buf, std::streamsize n) const;
bool isMatlab (char *buf, std::streamsize n) const;
bool isSage (char *buf, std::streamsize n) const;
bool isPretty (char *buf, std::streamsize n) const;

#ifdef __LINBOX_HAVE_LIBPNG
static const unsigned _png_sig_size = 8;

bool isPNG (std::istream &is) const;

bool isPNG (char *buf, std::streamsize n) const;

static void PNGReadData (png_structp pngPtr, png_bytep data, png_size_t length);

template <class Vector>
Expand Down Expand Up @@ -168,7 +177,7 @@ class MatrixWriter {
std::ostream &writeOneBased (std::ostream &os, const Matrix &A) const;

template <class Matrix>
std::ostream &writeGuillaume (std::ostream &os, const Matrix &A) const;
std::ostream &writeDumas (std::ostream &os, const Matrix &A) const;

template <class Matrix>
std::ostream &writeMaple (std::ostream &os, const Matrix &A) const;
Expand Down Expand Up @@ -221,7 +230,7 @@ class MatrixWriter {
template <class Matrix>
std::ostream &writePNG (std::ostream &is, const Matrix &A) const
{ return writePNGSpecialised (is, A, typename MatrixTraits<Matrix>::MatrixCategory ()); }
#endif // __LINBOX_HAVE_LIBPNG
#endif // __LINBOX_HAVE_LIBPNG
};

} // namespace LinBox
Expand Down
121 changes: 112 additions & 9 deletions linbox/matrix/io.tcc
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,15 @@

#include <sstream>
#include <cmath>
#include <cctype>

#include <regex.h>

#include "linbox/linbox-config.h"
#include "linbox/util/commentator.h"
#include "linbox/matrix/io.h"

#define BUF_SIZE 80
#define BUF_SIZE 32

namespace LinBox
{
Expand All @@ -39,8 +43,8 @@ std::istream &MatrixReader<Ring>::read (std::istream &is, Matrix &A, FileFormatT
return readOneBased (is, A);
break;

case FORMAT_GUILLAUME:
return readGuillaume (is, A);
case FORMAT_DUMAS:
return readDumas (is, A);
break;

case FORMAT_MAPLE:
Expand Down Expand Up @@ -70,10 +74,109 @@ std::istream &MatrixReader<Ring>::read (std::istream &is, Matrix &A, FileFormatT
}
}

template <class Ring>
bool MatrixReader<Ring>::isDumas (char *buf, std::streamsize n) const
{
regex_t re;

if (regcomp (&re, "^[:digit:]+ [:digit:]+ M$", REG_EXTENDED) != 0)
throw LinboxError ("regcomp failure (isDumas)");

return regexec (&re, buf, 0, NULL, 0) == 0;
}

template <class Ring>
bool MatrixReader<Ring>::isTurner (char *buf, std::streamsize n) const
{
regex_t re;

if (regcomp (&re, "^[:digit:]+ [:digit:]+ [:digit:]+$", REG_EXTENDED) != 0)
throw LinboxError ("regcomp failure (isTurner)");

return regexec (&re, buf, 0, NULL, 0) == 0;
}

template <class Ring>
bool MatrixReader<Ring>::isMaple (char *buf, std::streamsize n) const
{
regex_t re;

if (regcomp (&re, "(\\[[:space:]+\\])|(\\[[:space:]+\\[[:space:]+([:digit:]+[:space:]+,[:space:]+)*[:digit:]+)", REG_EXTENDED) != 0)
throw LinboxError ("regcomp failure (isMaple)");

return regexec (&re, buf, 0, NULL, 0) == 0;
}

template <class Ring>
bool MatrixReader<Ring>::isMatlab (char *buf, std::streamsize n) const
{
regex_t re;

if (regcomp (&re, "(\\[[:space:]+\\])|(\\[[:space:]+([:digit:]+[:space:]+,[:space:]+)*[:digit:]+)", REG_EXTENDED) != 0)
throw LinboxError ("regcomp failure (isMatlab)");

return regexec (&re, buf, 0, NULL, 0) == 0;
}

template <class Ring>
bool MatrixReader<Ring>::isSage (char *buf, std::streamsize n) const
{
regex_t re;

if (regcomp (&re, "matrix\\((GF\\([:digit:]+\\),|ZZ|QQ)?[ \t\n]+\\[[ \t\n]+\\[[:space:]+([:digit:]+[:space:]+,[:space:]+)*[:digit:]+", REG_EXTENDED) != 0)
throw LinboxError ("regcomp failure (isSage)");

return regexec (&re, buf, 0, NULL, 0) == 0;
}

template <class Ring>
bool MatrixReader<Ring>::isPretty (char *buf, std::streamsize n) const
{
regex_t re;

if (regcomp (&re, "((\\[[:space:]+\\])|(\\[[:space:]+((\\.|[:digit:]+)[:space:]+)*(\\.|[:digit:]+)))", REG_EXTENDED) != 0)
throw LinboxError ("regcomp failure (isPretty)");

return regexec (&re, buf, 0, NULL, 0) == 0;
}

template <class Ring>
FileFormatTag MatrixReader<Ring>::detectFormat (std::istream &is) const
{
throw NotImplemented ();
FileFormatTag format = FORMAT_UNKNOWN;

char line[BUF_SIZE];

is.get (line, BUF_SIZE);

if (isDumas (line, BUF_SIZE))
format = FORMAT_DUMAS;
else if (isTurner (line, BUF_SIZE))
format = FORMAT_TURNER;
else if (isMaple (line, BUF_SIZE))
format = FORMAT_MAPLE;
else if (isMatlab (line, BUF_SIZE))
format = FORMAT_MATLAB;
else if (isSage (line, BUF_SIZE))
format = FORMAT_SAGE;
else if (isPretty (line, BUF_SIZE))
format = FORMAT_PRETTY;
#ifdef __LINBOX_HAVE_LIBPNG
else {
std::streamsize s = is.gcount ();
while (s-- != 0)
is.unget ();

if (isPNG (is))
format = FORMAT_PNG;
}
#endif // __LINBOX_HAVE_LIBPNG

std::streamsize s = is.gcount ();
while (s-- != 0)
is.unget ();

return format;
}

template <class Ring>
Expand All @@ -86,7 +189,7 @@ std::istream &MatrixReader<Ring>::readTurner (std::istream &is, Matrix &A) const

char buf[BUF_SIZE];

is.getline (buf, 80);
is.getline (buf, BUF_SIZE);

do {
std::istringstream str (buf);
Expand All @@ -110,7 +213,7 @@ std::istream &MatrixReader<Ring>::readTurner (std::istream &is, Matrix &A) const

template <class Ring>
template <class Matrix>
std::istream &MatrixReader<Ring>::readGuillaume (std::istream &is, Matrix &A) const
std::istream &MatrixReader<Ring>::readDumas (std::istream &is, Matrix &A) const
{
size_t m, n, i, j;
char c;
Expand Down Expand Up @@ -312,8 +415,8 @@ std::ostream &MatrixWriter<Ring>::write (std::ostream &os, const Matrix &A, File
return writeOneBased (os, A);
break;

case FORMAT_GUILLAUME:
return writeGuillaume (os, A);
case FORMAT_DUMAS:
return writeDumas (os, A);
break;

case FORMAT_MAPLE:
Expand Down Expand Up @@ -383,7 +486,7 @@ std::ostream &MatrixWriter<Ring>::writeOneBased (std::ostream &os, const Matrix

template <class Ring>
template <class Matrix>
std::ostream &MatrixWriter<Ring>::writeGuillaume (std::ostream &os, const Matrix &A) const
std::ostream &MatrixWriter<Ring>::writeDumas (std::ostream &os, const Matrix &A) const
{
os << A.rowdim () << ' ' << A.coldim () << " M" << std::endl;
writeOneBased (os, A);
Expand Down
8 changes: 4 additions & 4 deletions tests/test-matrix-domain.h
Original file line number Diff line number Diff line change
Expand Up @@ -1352,7 +1352,7 @@ template <class Field, class Modules, class Matrix>
bool testReadWriteFormat (Context<Field, Modules> &ctx, const char *text, const Matrix &M, FileFormatTag format)
{
static const char *format_names[] =
{ "detect", "unknown", "Turner", "one-based", "Guillaume", "Maple", "Matlab", "Sage", "pretty", "PNG" };
{ "detect", "unknown", "Turner", "one-based", "Dumas", "Maple", "Matlab", "Sage", "pretty", "PNG" };

ostringstream str;
str << "Testing " << text << " read/write (format " << format_names[format] << ")" << std::ends;
Expand Down Expand Up @@ -1422,7 +1422,7 @@ bool testReadWrite (Context<Field, Modules> &ctx, const char *text, const Matrix
report << "Input matrix M:" << std::endl;
BLAS3::write (ctx, report, M);

FileFormatTag formats[] = { FORMAT_TURNER, FORMAT_GUILLAUME, FORMAT_MATLAB, FORMAT_PRETTY };
FileFormatTag formats[] = { FORMAT_TURNER, FORMAT_DUMAS, FORMAT_MATLAB, FORMAT_PRETTY };

for (size_t i = 0; i < sizeof (formats) / sizeof (FileFormatTag); ++i)
pass = testReadWriteFormat (ctx, text, M, formats[i]) && pass;
Expand All @@ -1446,9 +1446,9 @@ bool testReadWrite (Context<GF2, Modules> &ctx, const char *text, const Matrix &
BLAS3::write (ctx, report, M);

#ifdef __LINBOX_HAVE_LIBPNG
FileFormatTag formats[] = { FORMAT_TURNER, FORMAT_GUILLAUME, FORMAT_MATLAB, FORMAT_PRETTY, FORMAT_PNG };
FileFormatTag formats[] = { FORMAT_TURNER, FORMAT_DUMAS, FORMAT_MATLAB, FORMAT_PRETTY, FORMAT_PNG };
#else // !__LINBOX_HAVE_LIBPNG
FileFormatTag formats[] = { FORMAT_TURNER, FORMAT_GUILLAUME, FORMAT_MATLAB, FORMAT_PRETTY };
FileFormatTag formats[] = { FORMAT_TURNER, FORMAT_DUMAS, FORMAT_MATLAB, FORMAT_PRETTY };
#endif // __LINBOX_HAVE_LIBPNG

for (size_t i = 0; i < sizeof (formats) / sizeof (FileFormatTag); ++i)
Expand Down
14 changes: 14 additions & 0 deletions util/equal.C
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,13 @@ int check_equal (const Ring &R, const char *input1, FileFormatTag input1_format,
commentator.stop ("error");
return -1;
}
catch (UnrecognisedFormat) {
commentator.report (Commentator::LEVEL_IMPORTANT, INTERNAL_ERROR)
<< "Unable to determine format of first input-file" << std::endl;
commentator.stop ("error");
commentator.stop ("error");
return -1;
}

commentator.stop (MSG_DONE);

Expand All @@ -76,6 +83,13 @@ int check_equal (const Ring &R, const char *input1, FileFormatTag input1_format,
commentator.stop ("error");
return -1;
}
catch (UnrecognisedFormat) {
commentator.report (Commentator::LEVEL_IMPORTANT, INTERNAL_ERROR)
<< "Unable to determine format of second input-file" << std::endl;
commentator.stop ("error");
commentator.stop ("error");
return -1;
}

commentator.stop (MSG_DONE);

Expand Down
36 changes: 29 additions & 7 deletions util/row-echelon-form.C
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,25 @@ template <class Ring, class Matrix>
int row_echelon_form (const Ring &R, const char *input, FileFormatTag input_format, const char *output, FileFormatTag output_format,
typename EchelonForm<Ring>::Method method, bool reduced)
{
static const char *format_names[] =
{ "detect", "unknown", "Turner", "one-based", "Dumas", "Maple", "Matlab", "Sage", "pretty", "PNG" };

Context<Ring> ctx (R);

commentator.start ("Converting matrix to row-echelon-form", __FUNCTION__);

if (output_format == FORMAT_DETECT) {
output_format = guess_format_tag (output);

if (output_format == FORMAT_UNKNOWN) {
commentator.report (Commentator::LEVEL_IMPORTANT, INTERNAL_ERROR)
<< "Could not guess output file-format" << std::endl;
commentator.stop ("error");
} else
commentator.report (Commentator::LEVEL_IMPORTANT, INTERNAL_DESCRIPTION)
<< "Writing output in " << format_names[output_format] << " format" << std::endl;
}

Matrix A;

commentator.start ("Reading input-matrix");
Expand All @@ -52,6 +67,13 @@ int row_echelon_form (const Ring &R, const char *input, FileFormatTag input_form
commentator.stop ("error");
return -1;
}
catch (UnrecognisedFormat) {
commentator.report (Commentator::LEVEL_IMPORTANT, INTERNAL_ERROR)
<< "Unable to determine format of input-file" << std::endl;
commentator.stop ("error");
commentator.stop ("error");
return -1;
}

commentator.stop (MSG_DONE);

Expand Down Expand Up @@ -191,7 +213,7 @@ int main (int argc, char **argv)
static bool floatingPoint = false;
static const char *methodString = "f4";
static const char *inputFileFormat = "guess";
static const char *outputFileFormat = "dumas";
static const char *outputFileFormat = "guess";
static const char *matrixType = "dense";
static char *input = NULL;
static char *output = NULL;
Expand All @@ -202,8 +224,8 @@ int main (int argc, char **argv)
{ 'p', "-p", "Modulus of ring, when ring is 'modular'", TYPE_INT, &p },
{ 'f', "-f", "Compute using floating point, when ring is 'modular'", TYPE_NONE, &floatingPoint },
{ 'm', "-m", "Method to be used ('standard', 'afast', 'm4ri', or 'f4')", TYPE_STRING, &methodString },
{ 'i', "-i", "Input file format ('guess', 'dumas', 'turner', 'maple', 'matlab', 'sage', 'png')", TYPE_STRING, &inputFileFormat },
{ 'o', "-o", "Output file format ('dumas', 'turner', 'maple', 'matlab', 'sage', 'png', 'pretty')", TYPE_STRING, &outputFileFormat },
{ 'i', "-i", "Input file format ('guess', 'dumas', 'turner', 'maple', 'matlab', 'sage', 'png', 'pretty')", TYPE_STRING, &inputFileFormat },
{ 'o', "-o", "Output file format ('guess', 'dumas', 'turner', 'maple', 'matlab', 'sage', 'png', 'pretty')", TYPE_STRING, &outputFileFormat },
{ 't', "-t", "Type to use for matrix ('dense', 'sparse', 'hybrid')", TYPE_STRING, &matrixType },
{ '\0' }
};
Expand All @@ -220,13 +242,13 @@ int main (int argc, char **argv)
FileFormatTag input_format = get_format_tag (inputFileFormat);
FileFormatTag output_format = get_format_tag (outputFileFormat);

if (input_format == FORMAT_UNKNOWN || input_format == FORMAT_PRETTY) {
std::cerr << "Invalid input-file-format (use 'guess', 'dumas', 'turner', 'maple', 'matlab', 'sage', or 'png')" << std::endl;
if (input_format == FORMAT_UNKNOWN) {
std::cerr << "Invalid input-file-format (use 'guess', 'dumas', 'turner', 'maple', 'matlab', 'sage', 'png', or 'pretty')" << std::endl;
return -1;
}

if (output_format == FORMAT_UNKNOWN || output_format == FORMAT_DETECT) {
std::cerr << "Invalid output-file-format (use 'dumas', 'turner', 'maple', 'matlab', 'sage', 'png', or 'pretty')" << std::endl;
if (output_format == FORMAT_UNKNOWN) {
std::cerr << "Invalid output-file-format (use 'guess', 'dumas', 'turner', 'maple', 'matlab', 'sage', 'png', or 'pretty')" << std::endl;
return -1;
}

Expand Down
Loading

0 comments on commit 3aec33b

Please sign in to comment.