In functions that appear in matrix arithmetic, use specific return values
on error, and propagate errors. This is *not* done in other parts of
MeatAxe (e.g., not for greased matrices or polynomials) and not for
standalone programs.
AUTHOR:
- Simon King, 2015-09-26
diff --git a/src/cfinfo.c b/src/cfinfo.c
index 293526b..9c1a004 100644
--- a/src/cfinfo.c
+++ b/src/cfinfo.c
@@ -215,7 +215,7 @@ int Lat_ReadInfo(Lat_Info *li, const char *basename)
}
for (i = 0; i < li->NCf; ++i)
{
- ReadWord(f,&(li->Cf[i].idword),&(li->Cf[i].idpol),fn);
+ if (!ReadWord(f,&(li->Cf[i].idword),&(li->Cf[i].idpol),fn)) return -1;
if (StfMatch(f,i < li->NCf - 1 ? "," : "];") != 0)
{
MTX_ERROR2("%s: %E",fn,MTX_ERR_FILEFMT);
@@ -232,7 +232,7 @@ int Lat_ReadInfo(Lat_Info *li, const char *basename)
}
for (i = 0; i < li->NCf; ++i)
{
- ReadWord(f,&(li->Cf[i].peakword),&(li->Cf[i].peakpol),fn);
+ if (!ReadWord(f,&(li->Cf[i].peakword),&(li->Cf[i].peakpol),fn)) return -1;
if (StfMatch(f,i < li->NCf - 1 ? "," : "];") != 0)
{
MTX_ERROR2("%s: %E",fn,MTX_ERR_FILEFMT);
diff --git a/src/chbasis.c b/src/chbasis.c
index 34cf886..f1ee2e8 100644
--- a/src/chbasis.c
+++ b/src/chbasis.c
@@ -61,7 +61,8 @@ int MrChangeBasis(MatRep_t *rep, const Matrix_t *trans)
/** Conjugate a list @em gen of @em ngen square matrices over the same
* field and of the same dimensions by a mattrix @em trans
* and write the result into @em newgen. If @em gen == @em newgen, then
- * the previous content of @em newgen will be overridden. **/
+ * the previous content of @em newgen will be overridden.
+ * Return -1 on error and 0 on success. **/
int ChangeBasis(const Matrix_t *trans, int ngen, const Matrix_t *gen[],
Matrix_t *newgen[])
@@ -83,18 +84,36 @@ int ChangeBasis(const Matrix_t *trans, int ngen, const Matrix_t *gen[],
}
Matrix_t *tmp = MatAlloc(trans->Field, trans->Nor, trans->Noc);
+ if (!tmp) return -1;
size_t tmpsize = FfCurrentRowSize*trans->Nor;
for (i = 0; i < ngen; ++i)
{
MTX_VERIFY(gen[i]->Nor==trans->Nor);
MTX_VERIFY(gen[i]->Noc==trans->Noc);
memset(tmp->Data, FF_ZERO, tmpsize);
- MatMulStrassen(tmp, trans, gen[i]);
+ if (!MatMulStrassen(tmp, trans, gen[i]))
+ {
+ MatFree(tmp);
+ return -1;
+ }
if ((const Matrix_t **)newgen == gen)
memset(newgen[i]->Data, FF_ZERO, tmpsize);
else
+ {
newgen[i] = MatAlloc(trans->Field, trans->Nor, trans->Noc);
- MatMulStrassen(newgen[i], tmp, bi);
+ if (!newgen[i])
+ {
+ MatFree(tmp);
+ MatFree(bi);
+ return -1;
+ }
+ }
+ if (!MatMulStrassen(newgen[i], tmp, bi))
+ {
+ MatFree(tmp);
+ MatFree(bi);
+ return -1;
+ }
}
MatFree(bi);
MatFree(tmp);
diff --git a/src/ffio.c b/src/ffio.c
index 92f9360..d2e3f1c 100644
--- a/src/ffio.c
+++ b/src/ffio.c
@@ -71,8 +71,11 @@ int FfReadRows(FILE *f, PTR buf, int n)
if (fread(b,FfTrueRowSize(FfNoc),1,f) != 1) break;
b += FfCurrentRowSize;
}
- if (ferror(f))
- MTX_ERROR("Read failed: %S");
+ if (ferror(f))
+ {
+ MTX_ERROR("Read failed: %S");
+ return -1;
+ }
return i;
}
@@ -106,8 +109,11 @@ int FfWriteRows(FILE *f, PTR buf, int n)
if (fwrite(b,FfTrueRowSize(FfNoc),1,f) != 1) break;
b += FfCurrentRowSize;
}
- if (ferror(f))
- MTX_ERROR("Write failed: %S");
+ if (ferror(f))
+ {
+ MTX_ERROR("Write failed: %S");
+ return -1;
+ }
return i;
}
diff --git a/src/kernel-0.c b/src/kernel-0.c
index 6ef2f72..431f01a 100644
--- a/src/kernel-0.c
+++ b/src/kernel-0.c
@@ -304,7 +304,10 @@ static FILE *OpenTableFile(int fl)
/* Create the table file.
---------------------- */
if (FfMakeTables(fl) != 0)
- MTX_ERROR("Unable to build arithmetic tables");
+ {
+ MTX_ERROR("Unable to build arithmetic tables");
+ return NULL;
+ }
fd = SysFopen(fn,FM_READ|FM_LIB);
return fd;
}
@@ -363,8 +366,7 @@ static int ReadTableFile(FILE *fd, int field)
return -1;
}
FfOrder = field;
- FfSetNoc(FfOrder);
- return 0;
+ return FfSetNoc(FfOrder);
}
@@ -471,7 +473,7 @@ size_t FfTrueRowSize(int noc)
** Embed a subfield.
** @param a Element of the subfield field.
** @param subfield Subfield order. Must be a divisor of the current field order.
- ** @return @em a, embedded into the current field.
+ ** @return @em a, embedded into the current field, or 255 on error.
**/
FEL FfEmbed(FEL a, int subfield)
@@ -482,7 +484,9 @@ FEL FfEmbed(FEL a, int subfield)
return a;
for (i = 0; mtx_embedord[i] != subfield && i < 4; ++i);
if (i >= 4)
- MTX_ERROR2("Cannot embed GF(%d) into GF(%d)",(int)subfield,(int)FfOrder);
+ { MTX_ERROR2("Cannot embed GF(%d) into GF(%d)",(int)subfield,(int)FfOrder);
+ return (FEL)255;
+ }
return mtx_embed[i][a];
}
@@ -498,6 +502,7 @@ FEL FfEmbed(FEL a, int subfield)
** FfSetField(subfield).
** @param a Element of the current field.
** @param subfield Subfield order. Must be a divisor of the current field order.
+ ** Return 255 on error.
**/
FEL FfRestrict(FEL a, int subfield)
@@ -511,6 +516,7 @@ FEL FfRestrict(FEL a, int subfield)
{
MTX_ERROR2("Cannot restrict GF(%d) to GF(%d)",(int)FfOrder,
(int)subfield);
+ return (FEL)255;
}
return mtx_restrict[i][a];
}
diff --git a/src/maddmul.c b/src/maddmul.c
index f5c171d..24ad3a5 100644
--- a/src/maddmul.c
+++ b/src/maddmul.c
@@ -59,7 +59,7 @@ Matrix_t *MatAddMul(Matrix_t *dest, const Matrix_t *src, FEL coeff)
------------ */
PTR dp = dest->Data, sp = src->Data;
int n;
- FfSetField(src->Field);
+ FfSetField(src->Field); /* No error checking */
FfSetNoc(src->Noc);
for (n = src->Nor; n > 0; --n)
{
diff --git a/src/maketabF.c b/src/maketabF.c
index d7af83e..0fa26fb 100644
--- a/src/maketabF.c
+++ b/src/maketabF.c
@@ -175,7 +175,7 @@ static void polymod(POLY a, POLY b)
testprim() - Test for primitivity.
----------------------------------------------------------------- */
-static void testprim()
+static int testprim()
{
int i, a[256];
@@ -187,7 +187,9 @@ static void testprim()
{
fprintf(stderr,"*** a[%d]=%d.",i,a[i]);
MTX_ERROR("Polynome is not primitive.");
+ return 1;
}
+ return 0;
}
@@ -195,7 +197,7 @@ static void testprim()
initarith() - Initialize index and zech logarithm tables.
----------------------------------------------------------------- */
-static void initarith()
+static int initarith()
{ int i,elem;
POLY a;
@@ -214,7 +216,7 @@ static void initarith()
polmultx(a);
polymod(a,irred);
}
- testprim();
+ if (testprim()) return 1;
/* Calculate zech logarithms
------------------------- */
@@ -222,6 +224,7 @@ static void initarith()
{ elem = (int)((i%P)==P-1 ? i+1-P : i+1); /* add 1 */
zech[indx[i]]=indx[elem]; /* Zech-table=result */
}
+ return 0;
}
@@ -314,7 +317,7 @@ static BYTE pack(BYTE a[8])
and initialize tables.
----------------------------------------------------------------- */
-static void writeheader()
+static int writeheader()
{
int i, j;
@@ -324,6 +327,7 @@ static void writeheader()
{
perror(filename);
MTX_ERROR("Cannot open table file");
+ return 1;
}
for (CPM=1,maxmem=Q; (long)maxmem * Q <= 256L; ++CPM, maxmem *= Q);
for (i = 0; irrednrs[i] != (int) Q && irrednrs[i] != 0; ++i);
@@ -333,7 +337,7 @@ static void writeheader()
for (j = 0; j <= MAXGRAD; j++)
irred[j] = irreducibles[i][MAXGRAD-j];
G = P; /* Generator is X */
- initarith(); /* Init index- and Zech-tables */
+ if (initarith()) return 1; /* Init index- and Zech-tables */
}
else
{
@@ -357,6 +361,7 @@ static void writeheader()
}
MESSAGE(1,("Generator : %ld\n",info[1]));
MESSAGE(1,("Packing : %ld/byte\n",info[3]));
+ return 0;
}
@@ -364,14 +369,14 @@ static void writeheader()
checkq() - Set Q and N. Verify that Q is a prime power.
----------------------------------------------------------------- */
-static void checkq(long l)
+static int checkq(long l)
{
long q, d;
if (l < 2 || l > 256)
{
- fprintf(stderr,"Field order out of range (2-256)\n");
- exit(EXIT_ERR);
+ MTX_ERROR1("Field order out of range (2-256): %E", MTX_ERR_RANGE);
+ return 1;
}
Q = l;
@@ -381,9 +386,10 @@ static void checkq(long l)
q /= d;
if (q != 1)
{
- fprintf(stderr,"Illegal Field order\n");
- exit(EXIT_ERR);
+ MTX_ERROR("Illegal Field order\n");
+ return 1;
}
+ return 0;
}
@@ -407,7 +413,7 @@ static void inittables()
mkembed() - Calculate embeddings of all subfields.
----------------------------------------------------------------- */
-static void mkembed()
+static int mkembed()
{
int n; /* Degree of subfield over Z_p */
long q; /* subfield order */
@@ -456,6 +462,7 @@ static void mkembed()
{
fprintf(stderr,"*** q=%ld, Q=%ld.",q,Q);
MTX_ERROR("Internal error.");
+ return 1;
}
/* Calculate a generator for the subfield
@@ -502,13 +509,13 @@ static void mkembed()
fflush(stdout);
}
}
+ return 0;
}
static int Init(int field)
{
- checkq(field);
- return 0;
+ return checkq(field);
}
/* -----------------------------------------------------------------
@@ -526,7 +533,7 @@ int FfMakeTables(int field)
---------- */
if (Init(field) != 0)
return 1;
- writeheader(); /* Open file and write header */
+ if (writeheader()) return 1; /* Open file and write header */
inittables();
/* Make insert table
@@ -618,7 +625,7 @@ int FfMakeTables(int field)
}
}
- mkembed();
+ if (mkembed()) return 1;
MESSAGE(1,("Writing tables to %s\n",filename));
if (
@@ -639,6 +646,7 @@ int FfMakeTables(int field)
{
perror(filename);
MTX_ERROR("Error writing table file");
+ return 1;
}
fclose(fd);
return(0);
diff --git a/src/matadd.c b/src/matadd.c
index 54dbcb1..2d86d86 100644
--- a/src/matadd.c
+++ b/src/matadd.c
@@ -48,7 +48,7 @@ Matrix_t *MatAdd(Matrix_t *dest, const Matrix_t *src)
------------------- */
dp = dest->Data;
sp = src->Data;
- FfSetField(src->Field);
+ FfSetField(src->Field); /* No error checking */
FfSetNoc(src->Noc);
for (n = src->Nor; n > 0; --n)
{
diff --git a/src/matclean.c b/src/matclean.c
index e7307bf..16f02d6 100644
--- a/src/matclean.c
+++ b/src/matclean.c
@@ -53,7 +53,7 @@ int MatClean(Matrix_t *mat, const Matrix_t *sub)
/* Clean
----- */
- FfSetNoc(mat->Noc);
+ FfSetNoc(mat->Noc); /* No error checking */
for (i = 0; i < mat->Nor; ++i)
{
PTR m = MatGetPtr(mat,i);
diff --git a/src/matcmp.c b/src/matcmp.c
index b778ec4..d503285 100644
--- a/src/matcmp.c
+++ b/src/matcmp.c
@@ -38,7 +38,7 @@ MTX_DEFINE_FILE_INFO
** not necessarily mean that an error has occured.
** @param a First matrix.
** @param b Second matrix.
- ** @return 0 if the matrices are equal, nonzero otherwise (see description).
+ ** @return 0 if the matrices are equal, nonzero otherwise (see description), -2 on error.
**/
int MatCompare(const Matrix_t *a, const Matrix_t *b)
@@ -50,7 +50,7 @@ int MatCompare(const Matrix_t *a, const Matrix_t *b)
if (!MatIsValid(a) || !MatIsValid(b))
{
MTX_ERROR1("%E",MTX_ERR_BADARG);
- return -1;
+ return -2;
}
/* Compare fields and dimensions
@@ -65,7 +65,7 @@ int MatCompare(const Matrix_t *a, const Matrix_t *b)
/* Compare the entries row by row. We do not use memcmp on the
whole matrix because we must ignore padding bytes.
----------------------------------------------------------- */
- FfSetField(a->Field);
+ FfSetField(a->Field); /* No error checking */
FfSetNoc(a->Noc);
for (i = 0; i < a->Nor; ++i)
{
diff --git a/src/matcopy.c b/src/matcopy.c
index 75852dd..c3e7850 100644
--- a/src/matcopy.c
+++ b/src/matcopy.c
@@ -105,7 +105,7 @@ int MatCopyRegion(Matrix_t *dest, int destrow, int destcol,
{
#ifdef PARANOID
FEL f;
- FfSetNoc(src->Noc);
+ FfSetNoc(src->Noc); /* No error checking */
f = FfExtract(s,k);
FfSetNoc(dest->Noc);
FfInsert(d,destcol+k-col1,f);
diff --git a/src/matcore.c b/src/matcore.c
index 1f27dfd..0dc9d92 100644
--- a/src/matcore.c
+++ b/src/matcore.c
@@ -131,7 +131,7 @@ Matrix_t *MatAlloc(int field, int nor, int noc)
SysFree(m);
return NULL;
}
- FfSetNoc(noc);
+ if (FfSetNoc(noc)) return NULL;
m->Magic = MAT_MAGIC;
m->Field = field;
m->Nor = nor;
diff --git a/src/matcut.c b/src/matcut.c
index fde0662..f274311 100644
--- a/src/matcut.c
+++ b/src/matcut.c
@@ -79,11 +79,12 @@ Matrix_t *MatCut(const Matrix_t *src, int row1, int col1, int nrows, int ncols)
/* Initialize pointers to the source and destination matrix
-------------------------------------------------------- */
s = MatGetPtr(src,row1);
+ if (!s) return NULL;
d = result->Data;
/* Copy the requested data
----------------------- */
- FfSetNoc(ncols);
+ if (FfSetNoc(ncols)) return NULL;
for (n = nrows; n > 0; --n)
{
if (col1 == 0)
@@ -95,9 +96,9 @@ Matrix_t *MatCut(const Matrix_t *src, int row1, int col1, int nrows, int ncols)
{
#ifdef PARANOID
FEL f;
- FfSetNoc(src->Noc);
+ FfSetNoc(src->Noc); /* No error checking */
f = FfExtract(s,col1+k);
- FfSetNoc(ncols);
+ FfSetNoc(ncols); /* error was checked above */
FfInsert(d,k,f);
#else
FfInsert(d,k,FfExtract(s,col1+k));
diff --git a/src/matech.c b/src/matech.c
index ed31cf4..ee52ebe 100644
--- a/src/matech.c
+++ b/src/matech.c
@@ -124,7 +124,7 @@ int MatEchelonize(Matrix_t *mat)
/* Build the pivot table
--------------------- */
- FfSetField(mat->Field);
+ FfSetField(mat->Field); /* No error checking */
FfSetNoc(mat->Noc);
rank = zmkechelon(mat->Data,mat->Nor,mat->Noc,mat->PivotTable,is_pivot);
@@ -163,13 +163,14 @@ long MatNullity(const Matrix_t *mat)
** This function calculates the dimension of the null-space of a matrix
** and deletes the matrix.
** @param mat Pointer to the matrix.
- ** @return Nullity of @em mat, or -$ on error.
+ ** @return Nullity of @em mat, or $-1$ on error.
**/
long MatNullity__(Matrix_t *mat)
{
long nul;
- MatEchelonize(mat);
+ if (!mat) return -1;
+ if (MatEchelonize(mat)==-1) return -1;
nul = mat->Noc - mat->Nor;
MatFree(mat);
return nul;
diff --git a/src/matins.c b/src/matins.c
index 45c31e4..50fe9c1 100644
--- a/src/matins.c
+++ b/src/matins.c
@@ -54,7 +54,7 @@ Matrix_t *MatInsert_(Matrix_t *mat, const Poly_t *pol)
return NULL;
}
- FfSetField(mat->Field);
+ FfSetField(mat->Field); /* No error checking */
FfSetNoc(nor);
/* Special case: p(x) = 0
@@ -81,7 +81,10 @@ Matrix_t *MatInsert_(Matrix_t *mat, const Poly_t *pol)
/* Evaluate p(A)
------------- */
if (pol->Degree > 1)
- x = MatDup(mat);
+ {
+ x = MatDup(mat);
+ if (!x) return NULL;
+ }
if ((f = pol->Data[pol->Degree]) != FF_ONE)
{
for (l = nor, v = mat->Data; l > 0; --l, FfStepPtr(&v))
@@ -147,6 +150,7 @@ Matrix_t *MatInsert(const Matrix_t *mat, const Poly_t *pol)
if (pol->Degree == 0)
{
x = MatAlloc(mat->Field,nor,nor);
+ if (!x) return NULL;
for (l = 0, v = x->Data; l < nor; ++l, FfStepPtr(&v))
FfInsert(v,l,pol->Data[0]);
return x;
@@ -155,6 +159,7 @@ Matrix_t *MatInsert(const Matrix_t *mat, const Poly_t *pol)
/* Evaluate p(A)
------------- */
x = MatDup(mat);
+ if (!x) return NULL;
if ((f = pol->Data[pol->Degree]) != FF_ONE)
{
for (l = nor, v = x->Data; l > 0; --l, FfStepPtr(&v))
diff --git a/src/matinv.c b/src/matinv.c
index 217eb0e..990cbe7 100644
--- a/src/matinv.c
+++ b/src/matinv.c
@@ -114,6 +114,7 @@ Matrix_t *MatInverse(const Matrix_t *mat)
/* Copy matrix into workspace
-------------------------- */
tmp = FfAlloc(mat->Nor);
+ if (!tmp) return NULL;
memcpy(tmp,mat->Data,FfCurrentRowSize * mat->Nor);
/* Inversion
diff --git a/src/matmul.c b/src/matmul.c
index 20f5e88..bed30fc 100644
--- a/src/matmul.c
+++ b/src/matmul.c
@@ -63,7 +63,7 @@ Matrix_t *MatMul(Matrix_t *dest, const Matrix_t *src)
/* Matrix multiplication
--------------------- */
- FfSetField(src->Field);
+ FfSetField(src->Field); /* no error checking, since the matrix *exists* */
FfSetNoc(src->Noc);
result = tmp = FfAlloc(dest->Nor);
if (result == NULL)
diff --git a/src/matnull.c b/src/matnull.c
index 4f28566..2550b96 100644
--- a/src/matnull.c
+++ b/src/matnull.c
@@ -27,6 +27,8 @@ MTX_DEFINE_FILE_INFO
- |piv| contains a pivot table for the null space.
If |flags| is nonzero, the null-space is not reduced to echelon form,
and the contents of |piv| are undefined.
+
+ Return -1 on error, the dimension of the null-space on success.
** @see
**/
@@ -40,7 +42,7 @@ static long znullsp(PTR matrix, long nor, int *piv, PTR nsp, int flags)
/* Make the identity matrix in .
---------------------------------- */
- FfSetNoc(nor);
+ if (FfSetNoc(nor)) return -1;
x = nsp;
for (i = 0; i < nor; ++i)
{
@@ -61,13 +63,12 @@ static long znullsp(PTR matrix, long nor, int *piv, PTR nsp, int flags)
for (k = 0; k < i; ++k)
{
- FfSetNoc(noc);
+ FfSetNoc(noc); /* No error checking, since noc used to be the previously assigned number of columns */
if ((p = piv[k]) >= 0 && (f = FfExtract(x,p)) != FF_ZERO)
{
f = FfNeg(FfDiv(f,FfExtract(xx,p)));
- FfSetNoc(noc);
FfAddMulRow(x,xx,f);
- FfSetNoc(nor);
+ FfSetNoc(nor); /* we have asserted above that it doesn't fail */
FfAddMulRow(y,yy,f);
}
FfSetNoc(noc);
@@ -151,11 +152,21 @@ Matrix_t *MatNullSpace_(Matrix_t *mat, int flags)
if (nsp == NULL)
return NULL;
nsp->PivotTable = NREALLOC(nsp->PivotTable,int,mat->Nor);
+ if (!nsp->PivotTable)
+ {
+ MatFree(nsp);
+ return NULL;
+ }
/* Calculate the null-space
------------------------ */
- FfSetNoc(mat->Noc);
+ FfSetNoc(mat->Noc); /* No error checking */
dim = znullsp(mat->Data,mat->Nor,nsp->PivotTable,nsp->Data,flags);
+ if (dim==-1)
+ {
+ MatFree(nsp);
+ return NULL;
+ }
if (flags)
{
SysFree(nsp->PivotTable);
diff --git a/src/matorder.c b/src/matorder.c
index 16aec74..24b31a3 100644
--- a/src/matorder.c
+++ b/src/matorder.c
@@ -32,7 +32,7 @@ MTX_DEFINE_FILE_INFO
** the order is greater than 1000000, or if the order on any cyclic
** subspace is greater than 1000.
** @param mat Pointer to the matrix.
- ** @return The order of @em mat, or 1 on error.
+ ** @return The order of @em mat, or -1 on error.
**/
int MatOrder(const Matrix_t *mat)
@@ -59,15 +59,29 @@ int MatOrder(const Matrix_t *mat)
FfSetNoc(mat->Noc);
nor = mat->Nor;
m1 = FfAlloc(nor);
+ if (!m1) return -1;
memcpy(m1,mat->Data,FfCurrentRowSize * nor);
bend = basis = FfAlloc(nor+1);
+ if (!bend)
+ {
+ SysFree(m1);
+ return -1;
+ }
piv = NALLOC(int,nor+1);
done = NALLOC(char,nor);
+ if (!piv || !done)
+ { SysFree(m1);
+ return -1;
+ }
memset(done,0,(size_t)nor);
v1 = FfAlloc(1);
v2 = FfAlloc(1);
v3 = FfAlloc(1);
+ if (!v1 || !v2 || !v3)
+ { SysFree(m1);
+ return -1;
+ }
tord = ord = 1;
dim = 0;
j1 = 1;
diff --git a/src/matpivot.c b/src/matpivot.c
index abe342a..c843282 100644
--- a/src/matpivot.c
+++ b/src/matpivot.c
@@ -71,7 +71,6 @@ static int zmkpivot(PTR matrix, int nor, int noc, int *piv, int *ispiv)
int MatPivotize(Matrix_t *mat)
{
- int rc;
int *newtab;
static int *is_pivot = NULL;
static int maxnoc = -1;
@@ -106,9 +105,7 @@ int MatPivotize(Matrix_t *mat)
--------------------- */
FfSetField(mat->Field);
FfSetNoc(mat->Noc);
- rc = zmkpivot(mat->Data,mat->Nor,mat->Noc,mat->PivotTable,is_pivot);
-
- return rc;
+ return zmkpivot(mat->Data,mat->Nor,mat->Noc,mat->PivotTable,is_pivot);
}
/**
diff --git a/src/matpwr.c b/src/matpwr.c
index cd66b5e..b06e5b2 100644
--- a/src/matpwr.c
+++ b/src/matpwr.c
@@ -119,8 +119,14 @@ Matrix_t *MatPower(const Matrix_t *mat, long n)
FfSetField(mat->Field);
FfSetNoc(mat->Noc);
tmp = FfAlloc(FfNoc);
+ if (!tmp) return NULL;
memcpy(tmp,mat->Data,FfCurrentRowSize * FfNoc);
tmp2 = FfAlloc(FfNoc);
+ if (!tmp2)
+ {
+ SysFree(tmp);
+ return NULL;
+ }
result = MatAlloc(mat->Field,mat->Nor,mat->Noc);
if (result != NULL)
matpwr_(n,tmp,result->Data,tmp2);
diff --git a/src/matread.c b/src/matread.c
index 031d100..06e6e6b 100644
--- a/src/matread.c
+++ b/src/matread.c
@@ -46,8 +46,9 @@ Matrix_t *MatRead(FILE *f)
return NULL;
if (FfReadRows(f,m->Data,m->Nor) != m->Nor)
{
- MatFree(m);
- return NULL;
+ MTX_ERROR("Number of given rows does not coincide with given row number");
+ MatFree(m);
+ return NULL;
}
return m;
}
diff --git a/src/mattrace.c b/src/mattrace.c
index f500248..772a6e4 100644
--- a/src/mattrace.c
+++ b/src/mattrace.c
@@ -21,7 +21,7 @@
** This function calculates the sum of all diagonal elements of a matrix.
** Note that the matrix need not be square.
** @param mat Pointer to the matrix.
- ** @return Trace of @a mat, @c FF_ZERO on error.
+ ** @return Trace of @a mat, @c 255 on error.
**/
FEL MatTrace(const Matrix_t *mat)
@@ -35,7 +35,7 @@ FEL MatTrace(const Matrix_t *mat)
------------------ */
#ifdef DEBUG
if (!MatIsValid(mat))
- return FF_ZERO;
+ return (FEL)255;
#endif
maxi = mat->Nor > mat->Noc ? mat->Noc : mat->Nor;
diff --git a/src/matwrite.c b/src/matwrite.c
index 1fb6af3..b364e80 100644
--- a/src/matwrite.c
+++ b/src/matwrite.c
@@ -44,7 +44,10 @@ int MatWrite(const Matrix_t *mat, FILE *f)
FfSetField(mat->Field);
FfSetNoc(mat->Noc);
if (FfWriteRows(f,mat->Data,mat->Nor) != mat->Nor)
- return -1;
+ {
+ MTX_ERROR("Cannot write rows");
+ return -1;
+ }
return 0;
}
@@ -75,7 +78,10 @@ int MatSave(const Matrix_t *mat, const char *fn)
i = MatWrite(mat,f);
fclose(f);
if (i != 0)
- MTX_ERROR1("Cannot write matrix to %s",fn);
+ {
+ MTX_ERROR1("Cannot write matrix to %s",fn);
+ return -1;
+ }
return i;
}
diff --git a/src/meataxe.h b/src/meataxe.h
index 368b37b..0efa7dd 100644
--- a/src/meataxe.h
+++ b/src/meataxe.h
@@ -135,8 +135,8 @@ PTR FfSubRowPartialReverse(PTR dest, PTR src, int first, int len);
PTR FfAlloc(int nor);
int FfCmpRows(PTR p1, PTR p2);
void FfCleanRow(PTR row, PTR matrix, int nor, const int *piv);
-void FfCleanRow2(PTR row, PTR matrix, int nor, const int *piv, PTR row2);
-void FfCleanRowAndRepeat(PTR row, PTR mat, int nor, const int *piv,
+int FfCleanRow2(PTR row, PTR matrix, int nor, const int *piv, PTR row2);
+int FfCleanRowAndRepeat(PTR row, PTR mat, int nor, const int *piv,
PTR row2, PTR mat2);
void FfCopyRow(PTR dest, PTR src);
FEL FfEmbed(FEL a, int subfield);
diff --git a/src/mmulscal.c b/src/mmulscal.c
index 281be16..9bff3ff 100644
--- a/src/mmulscal.c
+++ b/src/mmulscal.c
@@ -21,7 +21,7 @@
** Multiply a Matrix by a Constant.
** @param dest Pointer to the matrix.
** @param coeff Value to multiply with.
- ** @return The function returns @a dest.
+ ** @return The function returns @a dest, or NULL on error in debug mode only.
**/
Matrix_t *MatMulScalar(Matrix_t *dest, FEL coeff)
diff --git a/src/mtensor.c b/src/mtensor.c
index b2b9ac7..2fb90ca 100644
--- a/src/mtensor.c
+++ b/src/mtensor.c
@@ -85,6 +85,11 @@ Matrix_t *MatTensor(const Matrix_t *m1, const Matrix_t *m2)
---------------------------------------- */
x1 = m1->Data;
x3 = MatGetPtr(temat,i2);
+ if (!x3)
+ {
+ MatFree(temat);
+ return NULL;
+ }
FfSetNoc(temat->Noc);
/* Loop through all rows of
diff --git a/src/quotient.c b/src/quotient.c
index f44b556..eea0754 100644
--- a/src/quotient.c
+++ b/src/quotient.c
@@ -82,16 +82,23 @@ Matrix_t *QProjection(const Matrix_t *subspace, const Matrix_t *vectors)
sdim = subspace->Nor;
qdim = subspace->Noc - sdim;
result = MatAlloc(subspace->Field,vectors->Nor,qdim);
+ if (!result) return NULL;
/* Calculate the projection
------------------------ */
FfSetNoc(subspace->Noc);
tmp = FfAlloc(1);
+ if (!tmp) return NULL;
non_piv = subspace->PivotTable + subspace->Nor;
for (i = 0; i < vectors->Nor; ++i)
{
int k;
PTR q = MatGetPtr(result,i);
+ if (!q)
+ {
+ SysFree(tmp);
+ return NULL;
+ }
FfCopyRow(tmp,MatGetPtr(vectors,i));
FfCleanRow(tmp,subspace->Data,sdim,subspace->PivotTable);
for (k = 0; k < qdim; ++k)
@@ -158,14 +165,20 @@ Matrix_t *QAction(const Matrix_t *subspace, const Matrix_t *gen)
/* Calculate the action on the quotient
------------------------------------ */
- FfSetNoc(dim);
+ FfSetNoc(dim); /* No error checking, since dim is the ->Noc of an existing matrix */
tmp = FfAlloc(1);
+ if (!tmp) return NULL;
piv = subspace->PivotTable;
non_piv = piv + subspace->Nor;
for (k = 0; k < qdim; ++k)
{
int l;
PTR qx = MatGetPtr(action,k);
+ if (!qx)
+ {
+ SysFree(tmp);
+ return NULL;
+ }
FfCopyRow(tmp,MatGetPtr(gen,non_piv[k]));
FfCleanRow(tmp,subspace->Data,sdim,piv);
for (l = 0; l < qdim; ++l)
diff --git a/src/saction.c b/src/saction.c
index adae3cf..0aba44d 100644
--- a/src/saction.c
+++ b/src/saction.c
@@ -68,8 +68,14 @@ Matrix_t *SAction(const Matrix_t *subspace, const Matrix_t *gen)
sdim = subspace->Nor;
FfSetField(subspace->Field);
action = MatAlloc(FfOrder,sdim,sdim);
- FfSetNoc(dim);
+ if (!action) return NULL;
+ FfSetNoc(dim); /* No error checking, since dim is the ->Noc of an existing matrix */
tmp = FfAlloc(1);
+ if (!tmp)
+ {
+ MatFree(action);
+ return NULL;
+ }
/* Calaculate the action.
---------------------- */
@@ -77,6 +83,12 @@ Matrix_t *SAction(const Matrix_t *subspace, const Matrix_t *gen)
{
PTR xi = MatGetPtr(subspace,i);
PTR yi = MatGetPtr(action,i);
+ if (!xi || !yi)
+ {
+ MatFree(action);
+ SysFree(tmp);
+ return NULL;
+ }
FEL f;
/* Calculate the image of the -th row of .
@@ -85,10 +97,20 @@ Matrix_t *SAction(const Matrix_t *subspace, const Matrix_t *gen)
/* Clean the image with the subspace and store coefficients.
--------------------------------------------------------- */
- FfCleanRow2(tmp,subspace->Data,sdim,subspace->PivotTable,yi);
+ if (FfCleanRow2(tmp,subspace->Data,sdim,subspace->PivotTable,yi))
+ {
+ MatFree(action);
+ SysFree(tmp);
+ return NULL;
+ }
if (FfFindPivot(tmp,&f) >= 0)
- MTX_ERROR("Split(): Subspace not invariant");
+ {
+ MatFree(action);
+ SysFree(tmp);
+ MTX_ERROR("Split(): Subspace not invariant");
+ return NULL;
}
+ }
/* Clean up and return the result.
------------------------------- */
diff --git a/src/stabpwr.c b/src/stabpwr.c
index ff33bc6..01282ab 100644
--- a/src/stabpwr.c
+++ b/src/stabpwr.c
@@ -68,15 +68,18 @@ int StablePower_(Matrix_t *mat, int *pwr, Matrix_t **ker)
--------------------------- */
p = 1;
k1 = MatNullSpace(mat);
- MatMul(mat,mat);
+ if (!k1) return -1;
+ if (!MatMul(mat,mat)) return -1;
k2 = MatNullSpace(mat);
+ if (!k2) return -1;
while (k2->Nor > k1->Nor)
{
p *= 2;
MatFree(k1);
k1 = k2;
- MatMul(mat,mat);
+ if (!MatMul(mat,mat)) return -1;
k2 = MatNullSpace(mat);
+ if (!k2) return -1;
}
MatFree(k2);
diff --git a/src/sumint.c b/src/sumint.c
index 278acd8..905fa79 100644
--- a/src/sumint.c
+++ b/src/sumint.c
@@ -77,7 +77,7 @@ int FfSumAndIntersection(PTR wrk1, int *nor1, int *nor2, PTR wrk2, int *piv)
{
FEL f;
int p;
- FfCleanRowAndRepeat(x1,wrk1,k,piv,x2,wrk2);
+ if (FfCleanRowAndRepeat(x1,wrk1,k,piv,x2,wrk2)) return -1;
if ((p = FfFindPivot(x1,&f)) < 0)
continue; /* Null row - ignore */
if (k < i)
diff --git a/src/temap.c b/src/temap.c
index 7ba445a..4c2d493 100644
--- a/src/temap.c
+++ b/src/temap.c
@@ -74,17 +74,21 @@ Matrix_t *TensorMap(Matrix_t *vec, const Matrix_t *a, const Matrix_t *b)
for (i = 0; i < vec->Nor; ++i)
{
Matrix_t *tmp = MatTransposed(a);
+ if (!tmp) return NULL;
Matrix_t *v = VectorToMatrix(vec,i,b->Nor);
if (v == NULL)
{
MTX_ERROR("Conversion failed");
- break;
+ return NULL;
}
- MatMul(tmp,v);
+ if (!MatMul(tmp,v)) return NULL;
MatFree(v);
- MatMul(tmp,b);
+ if (!MatMul(tmp,b)) return NULL;
if (MatrixToVector(tmp,result,i))
- MTX_ERROR("Conversion failed");
+ {
+ MTX_ERROR("Conversion failed");
+ return NULL;
+ }
MatFree(tmp);
}
return result;
diff --git a/src/vec2mat.c b/src/vec2mat.c
index 1047805..e76ad88 100644
--- a/src/vec2mat.c
+++ b/src/vec2mat.c
@@ -63,8 +63,11 @@ Matrix_t *VectorToMatrix(Matrix_t *vecs, int n, int noc)
return NULL;
for (i = 0; i < result->Nor; ++i)
{
- if (MatCopyRegion(result,i,0, vecs,n,i*noc,1,noc) != 0)
- MTX_ERROR("Copy failed");
+ if (MatCopyRegion(result,i,0, vecs,n,i*noc,1,noc) != 0)
+ {
+ MTX_ERROR("Copy failed");
+ return NULL;
+ }
}
return result;
}
diff --git a/src/window.c b/src/window.c
index 9c87694..fbeb943 100644
--- a/src/window.c
+++ b/src/window.c
@@ -69,7 +69,11 @@ MatrixWindow_t *WindowAlloc(int fl, int nor, size_t rowsize)
MTX_ERROR1("%E",MTX_ERR_NOMEM);
return NULL;
}
- FfSetField(fl);
+ if (FfSetField(fl))
+ {
+ free(out);
+ return NULL;
+ }
out->Matrix = MatAlloc(fl, nor, rowsize*sizeof(long)*MPB);
if (out->Matrix == NULL)
{
@@ -266,7 +270,8 @@ __asm__(" popl %ebx\n"
/** dest := left+right
left and right must be distinct, but one of them may coincide with dest -- under the assumption
- that, in that case, the ambient matrices coincide as well. **/
+ that, in that case, the ambient matrices coincide as well.
+ Return dest, or NULL on error (the only error may occur in a compatibility check). **/
MatrixWindow_t *WindowSum(MatrixWindow_t *dest, MatrixWindow_t *left, MatrixWindow_t *right)
{
PTR x, result, tmp;
@@ -335,6 +340,7 @@ MatrixWindow_t *WindowSum(MatrixWindow_t *dest, MatrixWindow_t *left, MatrixWind
/** dest := left-right
left and right must be distinct, but one of them may coincide with dest -- under the assumption
that, in that case, the ambient matrices coincide as well.
+ Return dest, or NULL on error (the only error may occur in a compatibility check).
**/
MatrixWindow_t *WindowDif(MatrixWindow_t *dest, MatrixWindow_t *left, MatrixWindow_t *right)
{
@@ -407,7 +413,7 @@ MatrixWindow_t *WindowDif(MatrixWindow_t *dest, MatrixWindow_t *left, MatrixWind
can write the result into it. Moreover, the chunk of memory pointed at by dest MUST be disjoint
from the chunks for left and right!
- Dimensions are not tested!
+ Dimensions are not tested, always dest will be returned (no error value).
**/
MatrixWindow_t *WindowAddMul(MatrixWindow_t *dest, MatrixWindow_t *left, MatrixWindow_t *right)
{
@@ -617,7 +623,7 @@ int StrassenStep(MatrixWindow_t *dest_win, MatrixWindow_t *A_win, MatrixWindow_t
S2->RowSize = A_sub_rowsize;
S2->Matrix = X->Matrix;
S2->ULCorner = X->ULCorner;
- WindowDif(S2, A00, A10);
+ WindowDif(S2, A00, A10); /* No error checking, as we know that the windows are compatible */
/*
printf("1. S2 = A00-A10 in X\n");
WindowShow(X);
@@ -653,7 +659,7 @@ int StrassenStep(MatrixWindow_t *dest_win, MatrixWindow_t *A_win, MatrixWindow_t
S0->RowSize = A_sub_rowsize;
S0->Matrix = X->Matrix;
S0->ULCorner = X->ULCorner;
- WindowSum(S0, A10, A11);
+ WindowSum(S0, A10, A11); /* no error checking here and below, as we know the dimensions of the windows */
/*
printf("4. S0 = A10+A11 in X\n");
WindowShow(X);
diff --git a/src/zcleanrow.c b/src/zcleanrow.c
index b4dcb30..d36a165 100644
--- a/src/zcleanrow.c
+++ b/src/zcleanrow.c
@@ -63,10 +63,10 @@ void FfCleanRow(PTR row, PTR matrix, int nor, const int *piv)
** @param nor Number of rows.
** @param piv Pivot table for @em matrix.
** @param row2 Pointer to row where the operations are recorded.
- ** @return Always 0.
+ ** @return 0, or 1 on error.
**/
-void FfCleanRow2(PTR row, PTR mat, int nor, const int *piv, PTR row2)
+int FfCleanRow2(PTR row, PTR mat, int nor, const int *piv, PTR row2)
{
int i;
PTR x;
@@ -74,7 +74,7 @@ void FfCleanRow2(PTR row, PTR mat, int nor, const int *piv, PTR row2)
if (row2 == NULL || piv == NULL)
{
MTX_ERROR1("%E",MTX_ERR_BADARG);
- return;
+ return 1;
}
for (i = 0, x = mat; i < nor; ++i, FfStepPtr(&x))
{
@@ -86,6 +86,7 @@ void FfCleanRow2(PTR row, PTR mat, int nor, const int *piv, PTR row2)
FfInsert(row2,i,f);
}
}
+ return 0;
}
@@ -100,10 +101,10 @@ void FfCleanRow2(PTR row, PTR mat, int nor, const int *piv, PTR row2)
** @param piv Pivot table for @em mat.
** @param row2 Pointer to the second row to be cleaned.
** @param mat2 Matrix to the second matrix.
- ** @return Always 0.
+ ** @return 0, or 1 on error.
**/
-void FfCleanRowAndRepeat(PTR row, PTR mat, int nor, const int *piv, PTR row2, PTR mat2)
+int FfCleanRowAndRepeat(PTR row, PTR mat, int nor, const int *piv, PTR row2, PTR mat2)
{
int i;
PTR x, x2;
@@ -112,7 +113,7 @@ void FfCleanRowAndRepeat(PTR row, PTR mat, int nor, const int *piv, PTR row2, PT
if (row2 == NULL || piv == NULL || row2 == NULL || mat2 == NULL)
{
MTX_ERROR1("%E",MTX_ERR_BADARG);
- return;
+ return 1;
}
#endif
for (i = 0, x = mat, x2 = mat2; i < nor; ++i, FfStepPtr(&x), FfStepPtr(&x2))
@@ -125,6 +126,7 @@ void FfCleanRowAndRepeat(PTR row, PTR mat, int nor, const int *piv, PTR row2, PT
FfAddMulRow(row2,x2,f);
}
}
+ return 0;
}