[Pntool-developers] SF.net SVN: pntool:[195] spnbox
Brought to you by:
compaqdrew,
miordache
From: <Ste...@us...> - 2009-07-13 18:01:17
|
Revision: 195 http://pntool.svn.sourceforge.net/pntool/?rev=195&view=rev Author: StephenCamp Date: 2009-07-13 18:01:14 +0000 (Mon, 13 Jul 2009) Log Message: ----------- Changed functions available in matrixmath.c/h: * Replaced Concatenation functions with InsertRows & InsertColumns, which function the same way but allow for the new rows or columns to be placed anywhere, not just at the end of the matrix. * Changed some names. To create a new matrix that is a copy of an old matrix with new blank rows or columns for later filling, use InsertNewRows or InsertNewColumns. These optimize when possible (type 2 matrices of appropriate transpose state) * Added MergeRows and MergeColumns. These actually combine the allocated memory for two matrices (so the "inner" matrix should not be deallocated later - this will cause a memory error when the "outer" matrix is deallocated or vice versa). Again, these optimize when possible (type 2 matrices of appropriate transpose state) Wrote new test routines and scripts for the matrixmath functions. Updated the readme. Modified test library StructuredIO (now trims leading/trailing whitespace when reading a string) Modified Paths: -------------- spnbox/README.txt spnbox/matrixmath.c spnbox/matrixmath.h spnbox/supervis.c spnbox/tests/Makefile spnbox/tests/StructuredIO.c Added Paths: ----------- spnbox/tests/test-matrixmath.c spnbox/tests/test-matrixmath.txt Modified: spnbox/README.txt =================================================================== --- spnbox/README.txt 2009-07-10 04:46:45 UTC (rev 194) +++ spnbox/README.txt 2009-07-13 18:01:14 UTC (rev 195) @@ -12,6 +12,7 @@ make <functionname> This will generate an executable called <functionname>.exe. make all will generate test executables for all spnbox functions. +To test the various functions in the matrixmath.c file, use make matrixmath. For all with such test programs except that ipslv, the test program is implemented as a program that will read from an input stream containing text in a human-readable format, interpret the text as parameters to the function, make a function call, and display the results. For format specifications, see the comments in StructuredIO.c/h. Modified: spnbox/matrixmath.c =================================================================== --- spnbox/matrixmath.c 2009-07-10 04:46:45 UTC (rev 194) +++ spnbox/matrixmath.c 2009-07-13 18:01:14 UTC (rev 195) @@ -244,34 +244,32 @@ } } -matrix ConcatenateMatrixRows(const matrix* left, const matrix* right, matrix* dst) +matrix InsertRows(matrix* outer, matrix* inner, int start, matrix* dst) { - /*rows will store the number of rows to fill, leftcols the number of columns - in left and rightcols the number of columns in right. destination is a pointer - to the final destination matrix and destinationmatrix is a blank matrix that - will be allocated if dst is not allocated.*/ - int rows, leftcols, rightcols; matrix* destination; matrix destinationMatrix; /*Zero destinationMatrix so that it can be used as an error return value.*/ AllocateMatrix(&destinationMatrix, 0, 0); /*Check parameters. None of the pointers can be null except dst.*/ - if(! (left && right)) + if(! (outer && inner)) { - merror(0, "ConcatenateMatrixRows: One of the operands is a null pointer"); + merror(0, "InsertRows/Columns: One of the operands is a null pointer"); return destinationMatrix; + } + /*inner and outer must have the same number of columns.*/ + if (NumberOfColumns(*inner) != NumberOfColumns(*outer)) + { + merror(0, "InsertRows/Columns: The operands do not have the same number of columns/rows"); + return destinationMatrix; } - /*Get the number of rows and columns of the destination.*/ - rows = NumberOfRows(*left); - leftcols = NumberOfColumns(*left); - rightcols = NumberOfColumns(*right); - - /*left and right must have the same number of columns.*/ - if (rows != NumberOfRows(*right)) + /*If start is negative, default to adding to the end.*/ + if (start < 0) start = NumberOfRows(*outer); + /*start cannot point to a row farther out than the first possible new row*/ + if (start > NumberOfRows(*outer)) { - merror(0, "ConcatenateMatrixRows: The operands do not have the same number of rows"); + merror(0, "InsertRows/Columns: The index of the first inserted row/column is out of range"); return destinationMatrix; } @@ -281,14 +279,14 @@ { /*If the dst pointer is null, allocate a new matrix of the default type and use this as the destination matrix.*/ - AllocateMatrix(&destinationMatrix, rows, leftcols + rightcols); + AllocateMatrix(&destinationMatrix, NumberOfRows(*inner) + NumberOfRows(*outer), NumberOfColumns(*inner)); destination = &destinationMatrix; } else if((int) dst < 4) { /*If the dst pointer is between 1 and 3, treat it like an integer describing the type of the desired destination matrix.*/ - AllocateMatrixType((int) dst, &destinationMatrix, rows, leftcols + rightcols); + AllocateMatrixType((int) dst, &destinationMatrix, NumberOfRows(*inner) + NumberOfRows(*outer), NumberOfColumns(*inner)); destination = &destinationMatrix; } else @@ -296,93 +294,47 @@ /*Assume dst is a valid address. Check to make sure it has the right dimensions.*/ destination = dst; - if (! (rows == NumberOfRows(*dst) && leftcols + rightcols == NumberOfColumns(*dst))) + if (! (NumberOfRows(*inner) + NumberOfRows(*outer) == NumberOfRows(*dst) && NumberOfColumns(*inner) == NumberOfColumns(*dst))) { - merror(0, "ConcatenateMatrixRows: The destination matrix does not have the proper dimensions."); + merror(0, "InsertRows/Columns: The destination matrix does not have the proper dimensions."); return destinationMatrix; } } - /*Copy the left matrix into columns 0-NumberOfColumns(*left) - 1.*/ - CopyBlock(rows, leftcols, left, 0, 0, destination, 0, 0); - - /*Copy the right matrix into columns NumberOfColumns(*left) -> (total number - of columns)*/ - CopyBlock(rows, rightcols, right, 0, 0, destination, 0, leftcols); - - /*Return the final result.*/ - return (*destination); -} - -matrix ConcatenateMatrixCols(const matrix* top, const matrix* bottom, matrix* dst) -{ - /*cols will store the number of columns to fill, toprows the number of rows in - top and bottomrows the number of rows in bottom. destination is a pointer to - the final destination matrix and destinationmatrix is a blank matrix that will - be allocated if dst is not allocated.*/ - int cols, toprows, bottomrows; - matrix* destination; - matrix destinationMatrix; - /*Zero destinationMatrix so that it can be used as an error return value.*/ - AllocateMatrix(&destinationMatrix, 0, 0); - - /*Check parameters. None of the pointers can be null except dst.*/ - if(! (top && bottom)) + /*Copy the beforehand part of the outer matrix.*/ + if (start) { - merror(0, "ConcatenateMatrixCols: One of the operands is a null pointer"); - return destinationMatrix; + CopyBlock(start, NumberOfColumns(*outer), outer, 0, 0, destination, 0, 0); } - /*Get the number of columns and columns of the destination.*/ - cols = NumberOfColumns(*top); - bottomrows = NumberOfRows(*bottom); - toprows = NumberOfRows(*top); + /*Copy the inner matrix.*/ + CopyBlock(NumberOfRows(*inner), NumberOfColumns(*inner), inner, 0, 0, destination, start, 0); - /*left and right must have the same number of columns.*/ - if (cols != NumberOfColumns(*bottom)) + /*Copy the final part of the outer matrix.*/ + if (NumberOfRows(*outer) - start) { - merror(0, "ConcatenateMatrixCols: The operands do not have the same number of columns"); - return destinationMatrix; + CopyBlock(NumberOfRows(*outer) - start, NumberOfColumns(*outer), outer, start, 0, destination, start + NumberOfRows(*inner), 0); } - /*Check to see if dst has been allocated or is a number indicated the matrix - type the user wants allocated for the result.*/ - if (! dst) - { - /*If the dst pointer is null, allocate a new matrix of the default type and - use this as the destination matrix.*/ - AllocateMatrix(&destinationMatrix, toprows + bottomrows, cols); - destination = &destinationMatrix; - } - else if((int) dst < 4) - { - /*If the dst pointer is between 1 and 3, treat it like an integer describing - the type of the desired destination matrix.*/ - AllocateMatrixType((int) dst, &destinationMatrix, toprows + bottomrows, cols); - destination = &destinationMatrix; - } - else - { - /*Assume dst is a valid address. Check to make sure it has the right - dimensions.*/ - destination = dst; - if (! (cols == NumberOfColumns(*dst) && toprows + bottomrows == NumberOfRows(*dst))) - { - merror(0, "ConcatenateMatrixCols: The destination matrix does not have the proper dimensions."); - return destinationMatrix; - } - } - - /*Copy the left matrix into columns 0-NumberOfColumns(*left) - 1.*/ - CopyBlock(toprows, cols, top, 0, 0, destination, 0, 0); - - /*Copy the right matrix into columns NumberOfColumns(*left) -> (total number - of columns)*/ - CopyBlock(bottomrows, cols, bottom, 0, 0, destination, toprows, 0); - /*Return the final result.*/ return (*destination); } + +matrix InsertColumns(matrix* outer, matrix* inner, int start, matrix* dst) +{ + /*This is the column analogue of InsertRows. Transpose the operands and call + InsertRows.*/ + matrix result; + TransposeMatrix(outer); + TransposeMatrix(inner); + if ((int) dst > 3) TransposeMatrix(dst); + result = InsertRows(outer, inner, start, dst); + TransposeMatrix(outer); + TransposeMatrix(inner); + TransposeMatrix(&result); + if ((int) dst > 3) TransposeMatrix(dst); + return result; +} /*This function multiplies a particular row of the left matrix by a particular column of the right matrix. If the row or column index is a negative constaint, @@ -459,7 +411,7 @@ return 1; } -/*This function is called by AddRows and AddColumns when they detect that the +/*This function is called by InsertNewRows and InsertNewColumns when they detect that the matrix is properly formatted for optimized row/column add. It assumes that basic parameter checking has been done by AddRow and AddCol. It is a private function internal to this file.*/ @@ -493,7 +445,7 @@ m->ar = NewAr; } -/*This function is called by AddRows and AddColumns when they detect that a +/*This function is called by InsertNewRows and InsertNewColumns when they detect that a matrix is not properly formatted for fast row add. It is a private function internal to this file.*/ static void AddRowsSlow(matrix* m, int start, int rowsToAdd) @@ -588,13 +540,13 @@ *m = NewM; } -int AddRows(matrix* m, int start, int rowsToAdd) +int InsertNewRows(matrix* m, int start, int rowsToAdd) { int i; matrix NewM; if (! m) { - merror(0, "ADDROWS: Null matrix pointer"); + merror(0, "InsertNewRows/COLUMNS: Null matrix pointer"); return 0; } /*Make sure the starting point is valid. Start will be the index of the first @@ -603,13 +555,13 @@ if (start < 0) start = NumberOfRows(*m); if (start > NumberOfRows(*m)) { - merror(0, "ADDROWS: First new row index is out of range"); + merror(0, "InsertNewRows/COLUMNS: First new index is out of range"); return 0; } /*Make sure the rowsToAdd is valid. Cannot be less than 1.*/ if (rowsToAdd < 1) { - merror(0, "ADDROWS: Rows to add is negative or zero"); + merror(0, "InsertNewRows/COLUMNS: Rows/Columns to add is negative or zero"); return 0; } @@ -626,44 +578,15 @@ } } -int AddColumns(matrix* m, int start, int colsToAdd) +int InsertNewColumns(matrix* m, int start, int colsToAdd) { - if (! m) - { - merror(0, "ADDCOLUMNS: Null matrix pointer"); - return 0; - } - /*Make sure the starting point is valid. Start will be the index of the first - of the new columns added. If index < 0, default to adding at the end of the - matrix.*/ - if (start < 0) start = NumberOfColumns(*m); - if (start > NumberOfColumns(*m)) - { - merror(0, "ADDCOLUMNS: First new row index is out of range"); - return 0; - } - /*Make sure the colsToAdd is valid. Cannot be less than 1.*/ - if (colsToAdd < 1) - { - merror(0, "ADDCOLUMNS: cols to add is negative or zero"); - return 0; - } - - if (m->type == 2 && m->trans) - { - /*If matrix is a transposed type 2, the column add can be heavily - optimized.*/ - AddRowsFast(m, start, colsToAdd); - } - else - { - /*AddRowsSlow just adds rows. Transpose the matrix to do the add, then - untranspose when we're done.*/ - TransposeMatrix(m); - AddRowsSlow(m, start, colsToAdd); - TransposeMatrix(m); - } - return 1; + int result; + /*This is the column analogue of InsertNewRows. Transpose the matrix and call + InsertNewRows.*/ + TransposeMatrix(m); + result = InsertNewRows(m, start, colsToAdd); + TransposeMatrix(m); + return result; } int RemoveRows(matrix* m, int start, int rowsToRemove) @@ -671,20 +594,20 @@ /*Matrix pointer cannot be null.*/ if (! m) { - merror(0, "REMOVEROWS: Null matrix pointer"); + merror(0, "REMOVEROWS/COLUMNS: Null matrix pointer"); return 0; } /*Start has to be the index of the first row to remove.*/ if (start < 0 || start >= NumberOfRows(*m)) { - merror(0, "REMOVEROWS: Index of first row to remove is out of range"); + merror(0, "REMOVEROWS/COLUMNS: Index of first row/column to remove is out of range"); return 0; } /*The row count cannot be less than 1, nor can it be so great that it requires the removal of rows that do not exist.*/ if (rowsToRemove < 1 || start + rowsToRemove > NumberOfRows(*m)) { - merror(0, "REMOVEROWS: Number of rows to remove is out of range"); + merror(0, "REMOVEROWS/COLUMNS: Number of rows/columns to remove is out of range"); return 0; } /*See if we can optimize the removal.*/ @@ -701,38 +624,95 @@ int RemoveColumns(matrix* m, int start, int colsToRemove) { - /*Matrix pointer cannot be null.*/ - if (! m) + int result; + /*This is the column analogue of RemoveRows. Transpose the matrix and call + RemoveRows.*/ + TransposeMatrix(m); + result = RemoveRows(m, start, colsToRemove); + TransposeMatrix(m); + return result; +} + +static void MergeRowsFast(matrix *outer, matrix *inner, int start) +{ + int i; + mtype **newAr; + + newAr = tcalloc(outer->nr + inner->nr, sizeof(mtype*)); + outer->nr += inner->nr; + for (i = 0; i < outer->nr; i++) { - merror(0, "REMOVECOLUMNS: Null matrix pointer"); + if (i < start) + { + newAr[i] = outer->ar[i]; + } + else if (i < start + inner->nr) + { + newAr[i] = inner->ar[i - start]; + } + else + { + newAr[i] = outer->ar[i - inner->nr]; + } + } + free(outer->ar); + free(inner->ar); + outer->ar = newAr; + memset(inner, 0, sizeof(matrix)); +} + +int MergeRows(matrix *outer, matrix *inner, int start) +{ + /*Neither of the matrices can be null pointers.*/ + if (! (inner && outer)) + { + merror(0, "MERGEROWS/COLUMNS: Null matrix pointer"); return 0; } - /*Start has to be the index of the first column to remove.*/ - if (start < 0 || start >= NumberOfColumns(*m)) + /*If start is negative, default to adding rows at the end.*/ + if (start < 0) start = NumberOfRows(*outer); + /*We cannot add rows any farther out than the end.*/ + if (start > NumberOfRows(*outer)) { - merror(0, "REMOVECOLUMNS: Index of first column to remove is out of range"); + merror(0, "MERGEROWS/COLUMNS: Start index is out of range"); return 0; } - /*The column count cannot be less than 1, nor can it be so great that it - requires the removal of columns that do not exist.*/ - if (colsToRemove < 1 || start + colsToRemove > NumberOfColumns(*m)) + /*The matrices must have the same number of columns.*/ + if (NumberOfColumns(*outer) != NumberOfColumns(*inner)) { - merror(0, "REMOVECOLUMNS: Number of columns to remove is out of range"); + merror(0, "MERGEROWS/COLUMNS: The outer and inner matrices do not have the same number of columns"); return 0; } - /*See if we can optimize the removal.*/ - if (m->type == 2 && m->trans) + /*Attempt to optimize.*/ + if (outer->type == 2 && inner->type == 2 && ! (outer->trans || inner->trans)) { - RemoveRowsFast(m, start, colsToRemove); + MergeRowsFast(outer, inner, start); } else { - /*If not, transpose the matrix so we can use the row removal function. - Untranspose when done.*/ - TransposeMatrix(m); - RemoveRowsSlow(m, start, colsToRemove); - TransposeMatrix(m); + /*Otherwise, do a slow add and copy.*/ + InsertNewRows(outer, start, NumberOfRows(*inner)); + CopyBlock(NumberOfRows(*inner), NumberOfColumns(*inner), inner, 0, 0, outer, start, 0); + /*For consistencies' sake (with Fast Row Merge), deallocate the inner matrix + and zero it.*/ + DeallocateMatrix(inner); + memset(inner, 0, sizeof(matrix)); } return 1; } +int MergeColumns(matrix *outer, matrix *inner, int start) +{ + /*This is the column analogue of MergeRows. Simply transpose the operands and + call MergeRows.*/ + int result; + TransposeMatrix(outer); + TransposeMatrix(inner); + result = MergeRows(outer, inner, start); + TransposeMatrix(outer); + TransposeMatrix(inner); + return result; +} + + + Modified: spnbox/matrixmath.h =================================================================== --- spnbox/matrixmath.h 2009-07-10 04:46:45 UTC (rev 194) +++ spnbox/matrixmath.h 2009-07-13 18:01:14 UTC (rev 195) @@ -42,20 +42,23 @@ /*ShowMatrix is a debugging function that dumps the contents of a matrix to the screen in a human-readable format.*/ -matrix ConcatenateMatrixRows(const matrix* left, const matrix* right, matrix* dst); -/*ConcatenateMatrixRows returns a matrix each row of which consists of the -corresponding row of left followed to the right by the corresponding row of -right. If dst is a valid pointer the matrix to which it points is used as the -destination. If dst is null, the function allocates a new matrix of the type -determined by AllocateMatrix. If dst is an integer between 1 and 3 inclusive, +matrix InsertRows(matrix* outer, matrix* inner, int start, matrix* dst); +/*InsertRows returns a matrix that is a copy of outer with the rows of inner +inserted in such a way that the first of the inserted rows has index start. If +start is negative, the inserted rows are added at the end of the matrix. +If dst is a valid pointer the matrix to which it points is used as the +destination. If dst is null, the function allocates a new matrix of the type +determined by AllocateMatrix. If dst is an integer between 1 and 3 inclusive, the function allocates a new matrix of that type number.*/ -matrix ConcatenateMatrixCols(const matrix* top, const matrix* bottom, matrix* dst); -/*ConcatenateMatrixCols returns a matrix each column of which consists of the -corresponding column of top followed below by the corresponding column of -bottom. If dst is a valid pointer the matrix to which it points is used as the -destination. If dst is null, the function allocates a new matrix of the type -determined by AllocateMatrix. If dst is an integer between 1 and 3 inclusive, +matrix InsertColumns(matrix* outer, matrix* inner, int start, matrix* dst); +/*InsertColumns returns a matrix that is a copy of outer with the columns of +inner inserted in such a way that the first of the inserted columns has index +start. If start is negative, the inserted columns are added at the end of the +matrix. +If dst is a valid pointer the matrix to which it points is used as the +destination. If dst is null, the function allocates a new matrix of the type +determined by AllocateMatrix. If dst is an integer between 1 and 3 inclusive, the function allocates a new matrix of that type number.*/ int MultiplyVector(matrix* left, matrix* right, int Row, int Col, int Length); @@ -69,25 +72,25 @@ /*MatrixEqualMatrix tests the equality of matrices A and B. It returns nonzero if the matrices are equal and zero if they are different.*/ -int AddRows(matrix* m, int start, int rowsToAdd); -/*AddRows adds one or more contiguous rows to the given matrix. +int InsertNewRows(matrix* m, int start, int rowsToAdd); +/*InsertNewRows adds one or more contiguous rows to the given matrix. start The index of the first of the new rows. If it is set to a negative - number, AddRows adds the block of rows to the bottom of the matrix. + number, InsertNewRows adds the block of rows to the bottom of the matrix. If it is too high the function will show an error message and terminate execution. rowsToAdd The number of rows to add to the matrix. Rows will be added in a contiguous block. Return value is nonzero on success and zero on failure. -Note that if the matrix is a type-2 un-transposed, AddRows is able to invoke +Note that if the matrix is a type-2 un-transposed, InsertNewRows is able to invoke a special highly-optimized algorithm that reduces the computational complexity of the operation by at least a factor corresponding to the number of columns in the matrix.*/ -int AddColumns(matrix* m, int start, int colsToAdd); -/*AddColumns adds one or more contiguous columns to the given matrix. See -AddRows; the parameters of AddColumns are the column analogues of AddRows' +int InsertNewColumns(matrix* m, int start, int colsToAdd); +/*InsertNewColumns adds one or more contiguous columns to the given matrix. See +InsertNewRows; the parameters of InsertNewColumns are the column analogues of InsertNewRows' parameters. The return value is nonzero on success and zero on failure. -AddColumns is able to employ the same type of optimization as AddRows (decreasing +InsertNewColumns is able to employ the same type of optimization as InsertNewRows (decreasing computational complexity by a factor at least equal to the number of rows in the matrix) if and only if the matrix is a type-2 transposed.*/ @@ -100,7 +103,7 @@ the function fails with an error message and terminates execution. The return value is nonzero on success and zero on failure. If RemoveRows is passed a type-2 untransposed matrix, it employs optimization -that reduces the computational complexity of the operation by at least a +that reduces the computational complexity of the operation by at approximately a factor corresponding to the number of columns in the matrix.*/ int RemoveColumns(matrix* m, int start, int colsToRemove); @@ -108,9 +111,31 @@ See RemoveRows; the parameters of RemoveColumns are the column analogues of RemoveRows. The return value is nonzero on success and zero on failure. RemoveColumns is able to employ the same type of optimization as RemoveRows -(reducing computational copmlexity by a factor at least equal to the number of +(reducing computational complexity by a factor at least equal to the number of rows in the matrix) if and only if the matrix is a type-2 transposed.*/ +int MergeRows(matrix *outer, matrix *inner, int start); +/*MergeRows inserts the rows of the inner matrix into the outer matrix +in such a way that the first of the inserted rows has the specified start index. +Note that the function actually modifies both of the operands; it modifies the +contents of the matrix pointed to by outer by inserting the new rows, and after +inserted deallocates and zeroes the matrix pointed to by inner. The return value +is nonzero on success and zero on failure. +If both the operand matrices are type 2 untransposed, MergeRows will will employ +an optimization that will decrease computational complexity by a factor at least +equal to the number of columns in the matrices.*/ + +int MergeColumns(matrix *outer, matrix *inner, int start); +/*MergeColumns inserts the columns of the inner matrix into the outer matrix +in such a way that the first of the inserted columns has the specified start +index. Note that the function actually modifies both of the operands; it +modifies the contents of the matrix pointed to by outer by inserting the new +columns, and after inserted deallocates and zeroes the matrix pointed to by +inner. The return value is nonzero on success and zero on failure. +If both the operand matrices are type 2 transposed, MergeColumns will will +employ an optimization that will decrease computational complexity by a factor +at least equal to the number of rows in the matrices.*/ + #endif Modified: spnbox/supervis.c =================================================================== --- spnbox/supervis.c 2009-07-10 04:46:45 UTC (rev 194) +++ spnbox/supervis.c 2009-07-13 18:01:14 UTC (rev 195) @@ -89,13 +89,13 @@ AllocateMatrixType(2, &supervisorDp, k, n); d2dd(&supervisorD, &supervisorDm, &supervisorDp); - /*Concatenate the columns of the output matrices. The result should be stored - in a type-2 matrix.*/ - toReturn.Dfm = ConcatenateMatrixCols(PlantOut, &supervisorDm, (matrix*) 2); + /*Add the rows of the supervisor to the end of the net matrices. The result + should be stored in a type-2 matrix.*/ + toReturn.Dfm = InsertRows(PlantOut, &supervisorDm, -1, (matrix*) 2); /*Concatenate the columns of the input matrices. The result should be stored in a type-2 matrix.*/ - toReturn.Dfp = ConcatenateMatrixCols(PlantIn, &supervisorDp, (matrix*) 2); + toReturn.Dfp = InsertRows(PlantIn, &supervisorDp, -1, (matrix*) 2); /*Free any memory that was allocated. If we allocated new space for constraints, then a new matrix was allocated for it*/ Modified: spnbox/tests/Makefile =================================================================== --- spnbox/tests/Makefile 2009-07-10 04:46:45 UTC (rev 194) +++ spnbox/tests/Makefile 2009-07-13 18:01:14 UTC (rev 195) @@ -38,8 +38,10 @@ $(COMPILER) -o isadm.exe test-isadm.o $(COMMON) $(ISADM) issiph: test-issiph.o $(COMMON) $(ISSIPH) $(COMPILER) -o issiph.exe test-issiph.o $(COMMON) $(ISSIPH) -msplit: test-msplit.o $(MSPLIT) +msplit: test-msplit.o $(COMMON) $(MSPLIT) $(COMPILER) -o msplit.exe test-msplit.o $(COMMON) $(MSPLIT) +matrixmath: test-matrixmath.o $(COMMON) + $(COMPILER) -o matrixmath.exe test-matrixmath.o $(COMMON) pn2acpn: test-pn2acpn.o $(COMMON) $(PN2ACPN) $(COMPILER) -o pn2acpn.exe test-pn2acpn.o $(COMMON) $(PN2ACPN) supervis: test-supervis.o $(COMMON) $(SUPERVIS) @@ -124,6 +126,8 @@ $(COMPILER) -c test-isadm.c test-linenf.o: test-linenf.c $(COMMONHEADER) $(COMPILER) -c test-linenf.c +test-matrixmath.o: test-matrixmath.c $(COMMONHEADER) + $(COMPILER) -c test-matrixmath.c test-msplit.o: test-msplit.c $(COMMONHEADER) $(COMPILER) -c test-msplit.c test-nltrans.o: test-nltrans.c $(COMMONHEADER) Modified: spnbox/tests/StructuredIO.c =================================================================== --- spnbox/tests/StructuredIO.c 2009-07-10 04:46:45 UTC (rev 194) +++ spnbox/tests/StructuredIO.c 2009-07-13 18:01:14 UTC (rev 195) @@ -15,9 +15,11 @@ int An integer. double A double. string A pointer to characters. Reads a single line. - -Output descriptor string syntax is the same as for the input descriptor except that non-count array types are invalid and there is one additional type, indexarrayc, which is stored like an arrayic but displayed -as a row of X's, one in each tab-separated column corresponding to an index stored in the array. + +Output descriptor string syntax is the same as for the input descriptor except +that non-count array types are invalid and there is one additional type, +indexarrayc, which is stored like an arrayic but displayed as a row of X's, one +in each tab-separated column corresponding to an index stored in the array. */ typedef struct Parameter @@ -27,11 +29,12 @@ int Start; } Parameter; -int ParseDescription(MemoryManager* memory, char* DataDescription, Parameter** Param, int* Items); -int FindParameter(char* Name, Parameter* Param, int ParamCount); -matrix ReadMatrix(FILE* file); -double* ReadDblArray(FILE* file, int* length); -int* ReadIntArray(FILE* file, int* length); +static int ParseDescription(MemoryManager* memory, char* DataDescription, Parameter** Param, int* Items); +static int FindParameter(char* Name, Parameter* Param, int ParamCount); +static matrix ReadMatrix(FILE* file); +static double* ReadDblArray(FILE* file, int* length); +static int* ReadIntArray(FILE* file, int* length); +static void TrimWhitespace(char* string); int ParseStructure(FILE *file, char* DataDescription, int** FilledMask, MemoryManager* Memory, ...) { @@ -188,6 +191,8 @@ else if (! strcmp(Param[PID].Type, "string")) { fgets(((char*) Data[Param[PID].Start]), 128, file); + /*Trim leading and trailing whitespace.*/ + TrimWhitespace((char*) Data[Param[PID].Start]); } else { @@ -522,7 +527,7 @@ { /*If it has, empty the list and fail.*/ free(*Param); - merror(0, "READER: Data description containts duplicate item names"); + merror(0, "PARSE/DISPLAYSTRUCTURE: Data description containts duplicate item names"); return 0; } /*Add a new element to the array of parameter description structures @@ -544,7 +549,7 @@ { /*If we get here the parameter type was not recognized. Fail.*/ free(*Param); - merror(0, "READER: Bad data description type"); + merror(0, "PARSE/DISPLAYSTRUCTURE: Bad data description type"); return 0; } } @@ -555,7 +560,7 @@ Fail.*/ free(*Param); printf("Warning: Bad Data Description Group '%s %s'.\n", Type, Name); - merror(0, "READER: Bad data description group"); + merror(0, "PARSE/DISPLAYSTRUCTURE: Bad data description group"); return 0; } } while (Token = strtok(0, ",")); @@ -605,3 +610,29 @@ } return 1; } + +void TrimWhitespace(char* string) +{ + int test, flag = 0; + /*Remove leading whitespace.*/ + for (test = 0; test <= strlen(string); test++) + { + if (! (flag || isspace(string[test]))) + { + flag = test; + } + if (flag) + { + string[test - flag] = string[test]; + } + } + /*Remove trailing whitespace.*/ + for (test = strlen(string) - 1; test >= 0; test--) + { + if (! isspace(string[test])) + { + break; + } + } + string[test + 1] = '\0'; +} \ No newline at end of file Added: spnbox/tests/test-matrixmath.c =================================================================== --- spnbox/tests/test-matrixmath.c (rev 0) +++ spnbox/tests/test-matrixmath.c 2009-07-13 18:01:14 UTC (rev 195) @@ -0,0 +1,726 @@ +#include <time.h> +#include "test.h" + +#define FF_OPTION 0 +#define FF_OPERATION 1 +#define FF_A 2 +#define FF_B 3 +#define FF_C 4 +#define FF_D 5 +#define FF_ROW 6 +#define FF_COL 7 +#define FF_ROWS 8 +#define FF_COLS 9 +#define FF_REPS 10 +#define FF_SIZE 11 + +static void TestAdd(matrix *A, matrix *B, char *Option, int *Filled); +static void TestSubtract(matrix *A, matrix *B, char *Option, int *Filled); +static void TestMultiply(matrix *A, matrix *B, char *Option, int *Filled); +static void TestInsertRows(matrix *A, matrix *B, int Row, char *Option, int *Filled); +static void TestInsertColumns(matrix *A, matrix *B, int Column, char *Option, int *Filled); +static void TestMultiplyVector(matrix *A, matrix *B, int* C, int *D, int Row, int Column, int Size, int *Filled); +static void TestMatrixEqualMatrix(matrix *A, matrix *B, int* Filled); +static void TestInsertNewRows(matrix *A, int Row, int Rows, int Reps, int Size, char* Option, int *Filled); +static void TestInsertNewColumns(matrix *A, int Column, int Columns, int Reps, int Size, char* Option, int *Filled); +static void TestRemoveRows(matrix *A, int row, int rows, int Reps, int Size, char* Option, int *Filled); +static void TestRemoveColumns(matrix *A, int column, int columns, int Reps, int Size, char* Option, int *Filled); +static void TestMergeRows(matrix *A, matrix *B, int row, int Reps, int Size, char* Option, int *Filled); +static void TestMergeColumns(matrix *A, matrix *B, int column, int Reps, int Size, char* Option, int *Filled); +static int ReadAllocationOption(char* Option, int* Filled); +static void SetPointers(matrix **A, matrix **B, int **C, int **D, int* Filled); +static void PrintPercent(int num, int denom); +static void AllocateMatrices(int reps, int size, matrix **m, int Transpose); +static void DeallocateMatrices(int reps, matrix *m); +static void ShowArray(int *array, int Count, char* name); +static void SetDefaults(int* Filled, int* Row, int* Col, int* Rows, int* Cols, int* Reps, int* Size); + +int main(int argc, char* argv[]) +{ + FILE* input; + + input = GetInput(argc, argv); + + char Desc[] = "string option, string operation, matrix A, matrix B, arrayi C, arrayi D, int row, int column, int rows, int columns, int repetitions, int size"; + char Operation[128], Option[128]; + matrix A, B; + int *C, *D, *Filled; + int CCount, DCount, Row, Column, Rows, Columns, Reps, Size; + MemoryManager mem; + + mem = CreateMemoryManager(5, 2, 0, 0); + + while (ParseStructure(input, Desc, &Filled, &mem, Option, Operation, &A, &B, &C, &CCount, &D, &DCount, &Row, &Column, &Rows, &Columns, &Reps, &Size)) + { + SetDefaults(Filled, &Row, &Column, &Rows, &Columns, &Reps, &Size); + if (! Filled[FF_OPERATION]) + { + printf("Warning: No operation code specified. Skipping problem.\n"); + } + else if (! strcmp(Operation, "AddMatrix")) + { + TestAdd(&A, &B, Option, Filled); + } + else if (! strcmp(Operation, "SubtractMatrix")) + { + TestSubtract(&A, &B, Option, Filled); + } + else if (! strcmp(Operation, "MultiplyMatrix")) + { + TestMultiply(&A, &B, Option, Filled); + } + else if (! strcmp(Operation, "InsertRows")) + { + TestInsertRows(&A, &B, Row, Option, Filled); + } + else if (! strcmp(Operation, "InsertColumns")) + { + TestInsertColumns(&A, &B, Column, Option, Filled); + } + else if (! strcmp(Operation, "MultiplyVector")) + { + TestMultiplyVector(&A, &B, C, D, Row, Column, Size, Filled); + } + else if (! strcmp(Operation, "MatrixEqualMatrix")) + { + TestMatrixEqualMatrix(&A, &B, Filled); + } + else if (! strcmp(Operation, "InsertNewRows")) + { + TestInsertNewRows(&A, Row, Rows, Reps, Size, Option, Filled); + } + else if (! strcmp(Operation, "InsertNewColumns")) + { + TestInsertNewColumns(&A, Column, Columns, Reps, Size, Option, Filled); + } + else if (! strcmp(Operation, "RemoveRows")) + { + TestRemoveRows(&A, Row, Rows, Reps, Size, Option, Filled); + } + else if (! strcmp(Operation, "RemoveColumns")) + { + TestRemoveColumns(&A, Column, Columns, Reps, Size, Option, Filled); + } + else if (! strcmp(Operation, "MergeRows")) + { + TestMergeRows(&A, &B, Row, Reps, Size, Option, Filled); + } + else if (! strcmp(Operation, "MergeColumns")) + { + TestMergeColumns(&A, &B, Column, Reps, Size, Option, Filled); + } + else + { + printf("Warning: Unrecognized operation '%s'.\n", Operation); + } + printf("-------------------------------------------------------------------------------\n"); + FreeMemory(&mem); + mem = CreateMemoryManager(10, 2, 0, 0); + } + FreeMemory(&mem); + return 0; +} + +void TestAdd(matrix *A, matrix *B, char *Option, int *Filled) +{ + int Alloc; + matrix Destination; + printf("Testing addition A + B...\n"); + SetPointers(&A, &B, 0, 0, Filled); + ShowMatrix(A, "A"); + ShowMatrix(B, "B"); + Alloc = ReadAllocationOption(Option, Filled); + + if (Alloc < 0) + { + AllocateMatrix(&Destination, NumberOfRows(*A), NumberOfColumns(*A)); + AddMatrix(A, B, &Destination); + } + else + { + Destination = AddMatrix(A, B, (matrix*) Alloc); + } + ShowMatrix(&Destination, "Result"); + DeallocateMatrix(&Destination); +} + +void TestSubtract(matrix *A, matrix *B, char *Option, int *Filled) +{ + int Alloc; + matrix Destination; + printf("Testing subtraction A - B...\n"); + SetPointers(&A, &B, 0, 0, Filled); + ShowMatrix(A, "A"); + ShowMatrix(B, "B"); + Alloc = ReadAllocationOption(Option, Filled); + if (Alloc < 0) + { + AllocateMatrix(&Destination, NumberOfRows(*A), NumberOfColumns(*A)); + SubtractMatrix(A, B, &Destination); + } + else + { + Destination = SubtractMatrix(A, B, (matrix*) Alloc); + } + ShowMatrix(&Destination, "Result"); + DeallocateMatrix(&Destination); +} + +void TestMultiply(matrix *A, matrix *B, char *Option, int *Filled) +{ + int Alloc; + matrix Destination; + printf("Testing matrix multiplication A * B...\n"); + SetPointers(&A, &B, 0, 0, Filled); + ShowMatrix(A, "A"); + ShowMatrix(B, "B"); + Alloc = ReadAllocationOption(Option, Filled); + if (Alloc < 0) + { + AllocateMatrix(&Destination, NumberOfRows(*A), NumberOfColumns(*B)); + MultiplyMatrix(A, B, &Destination); + } + else + { + Destination = MultiplyMatrix(A, B, (matrix*) Alloc); + } + ShowMatrix(&Destination, "Result"); + DeallocateMatrix(&Destination); +} + +void TestInsertRows(matrix *A, matrix *B, int Row, char *Option, int *Filled) +{ + int Alloc; + matrix Destination; + printf("Testing row insertion B -> A at row %d.\n", Row); + SetPointers(&A, &B, 0, 0, Filled); + ShowMatrix(A, "A"); + ShowMatrix(B, "B"); + Alloc = ReadAllocationOption(Option, Filled); + if (Alloc < 0) + { + AllocateMatrix(&Destination, NumberOfRows(*A) + NumberOfRows(*B), NumberOfColumns(*A)); + InsertRows(A, B, Row, &Destination); + } + else + { + Destination = InsertRows(A, B, Row, (matrix*) Alloc); + } + ShowMatrix(&Destination, "Result"); + DeallocateMatrix(&Destination); +} + +void TestInsertColumns(matrix *A, matrix *B, int Column, char *Option, int *Filled) +{ + int Alloc; + matrix Destination; + printf("Testing column insertion B -> A at column %d.\n", Column); + SetPointers(&A, &B, 0, 0, Filled); + ShowMatrix(A, "A"); + ShowMatrix(B, "B"); + Alloc = ReadAllocationOption(Option, Filled); + if (Alloc < 0) + { + AllocateMatrix(&Destination, NumberOfRows(*A), NumberOfColumns(*A) + NumberOfColumns(*B)); + InsertColumns(A, B, Column, &Destination); + } + else + { + Destination = InsertColumns(A, B, Column, (matrix*) Alloc); + } + ShowMatrix(&Destination, "Result"); + DeallocateMatrix(&Destination); +} + +void TestMultiplyVector(matrix *A, matrix *B, int* C, int *D, int Row, int Column, int Size, int *Filled) +{ + SetPointers(&A, &B, &C, &D, Filled); + char *message; + /*Determine the multiplication mode based on what is and isn't filled in.*/ + int Mode = 0, ModeSet = 0; + if (Filled[FF_A] && Filled[FF_B]) + { + printf("Testing vector multiplication A(%d,:) * B(:,%d)...\n", Row, Column); + ShowMatrix(A, "A"); + ShowMatrix(B, "B"); + printf("Result: %d\n", MultiplyVector(A, B, Row, Column, 0)); + } + else if (Filled[FF_A]) + { + if (! Filled[FF_C]) C = D; + printf("Testing vector multiplication A(%d,:) * V...\n", Row); + ShowMatrix(A, "A"); + ShowArray(C, NumberOfColumns(*A), "V"); + printf("Result: %d\n", MultiplyVector(A, (matrix*) C, Row, MULTIPLYVECTOR_ARRAY, 0)); + } + else if (Filled[FF_B]) + { + if (! Filled[FF_C]) C = D; + printf("Testing vector multiplication V * B(:,%d)...\n", Column); + ShowArray(C, NumberOfColumns(*B), "V"); + ShowMatrix(B, "B"); + printf("Result: %d\n", MultiplyVector((matrix*) C, B, MULTIPLYVECTOR_ARRAY, Column, 0)); + } + else + { + + printf("Testing vector multiplication V1 * V2...\n"); + ShowArray(C, Size, "V1"); + ShowArray(D, Size, "V2"); + printf("Result: %d\n", MultiplyVector((matrix*) C, (matrix*) D, MULTIPLYVECTOR_ARRAY, MULTIPLYVECTOR_ARRAY, Size)); + } +} + +void TestMatrixEqualMatrix(matrix *A, matrix *B, int* Filled) +{ + SetPointers(&A, &B, 0, 0, Filled); + printf("Testing equality test A = B...\n"); + ShowMatrix(A, "A"); + ShowMatrix(B, "B"); + printf("Result: %d\n", MatrixEqualMatrix(A, B)); +} + +void TestInsertNewRows(matrix *A, int Row, int Rows, int Reps, int Size, char* Option, int *Filled) +{ + /*There are two possible options: speedtest-optimized and speedtest-unoptimized. No option means normal test.*/ + matrix *m; + clock_t t0; + double time; + int i; + if (Filled[FF_OPTION] && (! strcmp(Option, "speedtest-optimized"))) + { + printf("Speed-testing optimized new row insertion by inserting %d rows into square matrices of size %d, %d times...\n", Rows, Size, Reps); + /*Allocate type-2 untransposed matrices.*/ + AllocateMatrices(Reps, Size, &m, 0); + ShowMatrix(m, "Sample Before"); + printf("Running test...\n"); + t0 = clock(); + for (i = 0; i < Reps; i++) + { + InsertNewRows(m + i, Row, Rows); + } + time = ((double) (clock() - t0)) / (double) CLOCKS_PER_SEC; + ShowMatrix(m, "Sample After"); + printf("Time: %.2f ms\n", time * 1000.0); + DeallocateMatrices(Reps, m); + } + else if (Filled[FF_OPTION] && (! strcmp(Option, "speedtest-unoptimized"))) + { + printf("Speed-testing unoptimized new row insertion by inserting %d rows into square matrices of size %d, %d times...\n", Rows, Size, Reps); + /*Allocate type-2 transposed matrices.*/ + AllocateMatrices(Reps, Size, &m, 1); + ShowMatrix(m, "Sample Before"); + printf("Running test...\n"); + t0 = clock(); + for (i = 0; i < Reps; i++) + { + InsertNewRows(m + i, Row, Rows); + } + time = ((double) (clock() - t0)) / (double) CLOCKS_PER_SEC; + ShowMatrix(m, "Sample After"); + printf("Time: %.2f ms\n", time * 1000.0); + DeallocateMatrices(Reps, m); + } + else + { + if (! Filled[FF_A]) A = 0; + + printf("Testing new row insertion of %d rows starting at row %d...\n", Rows, Row); + ShowMatrix(A, "A Before"); + InsertNewRows(A, Row, Rows); + ShowMatrix(A, "A After"); + } +} + +void TestInsertNewColumns(matrix *A, int Column, int Columns, int Reps, int Size, char* Option, int *Filled) +{ + /*There are two possible options: speedtest-optimized and speedtest-unoptimized. No option means normal test.*/ + matrix *m; + clock_t t0; + double time; + int i; + if (Filled[FF_OPTION] && (! strcmp(Option, "speedtest-optimized"))) + { + printf("Speed-testing optimized new column insertion by inserting %d columns into square matrices of size %d, %d times...\n", Columns, Size, Reps); + /*Allocate type-2 transposed matrices.*/ + AllocateMatrices(Reps, Size, &m, 1); + ShowMatrix(m, "Sample Before"); + printf("Running test...\n"); + t0 = clock(); + for (i = 0; i < Reps; i++) + { + InsertNewColumns(m + i, Column, Columns); + } + time = ((double) (clock() - t0)) / (double) CLOCKS_PER_SEC; + ShowMatrix(m, "Sample After"); + printf("Time: %.2f ms\n", time * 1000.0); + DeallocateMatrices(Reps, m); + } + else if (Filled[FF_OPTION] && (! strcmp(Option, "speedtest-unoptimized"))) + { + printf("Speed-testing unoptimized new column insertion by inserting %d columns into square matrices of size %d, %d times...\n", Columns, Size, Reps); + /*Allocate type-2 untransposed matrices.*/ + AllocateMatrices(Reps, Size, &m, 0); + ShowMatrix(m, "Sample Before"); + printf("Running test...\n"); + t0 = clock(); + for (i = 0; i < Reps; i++) + { + InsertNewColumns(m + i, Column, Columns); + } + time = ((double) (clock() - t0)) / (double) CLOCKS_PER_SEC; + ShowMatrix(m, "Sample After"); + printf("Time: %.2f ms\n", time * 1000.0); + DeallocateMatrices(Reps, m); + } + else + { + if (! Filled[FF_A]) A = 0; + + printf("Testing new column insertion of %d rows starting at column %d...\n", Columns, Column); + ShowMatrix(A, "A Before"); + InsertNewColumns(A, Column, Columns); + ShowMatrix(A, "A After"); + } +} + +void TestRemoveRows(matrix *A, int row, int rows, int Reps, int Size, char* Option, int *Filled) +{ + /*There are two possible options: speedtest-optimized and speedtest-unoptimized. No option means normal test.*/ + matrix *m; + clock_t t0; + double time; + int i; + if (Filled[FF_OPTION] && (! strcmp(Option, "speedtest-optimized"))) + { + printf("Speed-testing optimized row removal by removing %d rows from square matrices of size %d, %d times...\n", rows, Size, Reps); + /*Allocate type-2 untransposed matrices.*/ + AllocateMatrices(Reps, Size, &m, 0); + ShowMatrix(m, "Sample Before"); + printf("Running test...\n"); + t0 = clock(); + for (i = 0; i < Reps; i++) + { + RemoveRows(m + i, row, rows); + } + time = ((double) (clock() - t0)) / (double) CLOCKS_PER_SEC; + ShowMatrix(m, "Sample After"); + printf("Time: %.2f ms\n", time * 1000.0); + DeallocateMatrices(Reps, m); + } + else if (Filled[FF_OPTION] && (! strcmp(Option, "speedtest-unoptimized"))) + { + printf("Speed-testing unoptimized row removal by removing %d rows from square matrices of size %d, %d times...\n", rows, Size, Reps); + /*Allocate type-2 transposed matrices.*/ + AllocateMatrices(Reps, Size, &m, 1); + ShowMatrix(m, "Sample Before"); + printf("Running test...\n"); + t0 = clock(); + for (i = 0; i < Reps; i++) + { + RemoveRows(m + i, row, rows); + } + time = ((double) (clock() - t0)) / (double) CLOCKS_PER_SEC; + ShowMatrix(m, "Sample After"); + printf("Time: %.2f ms\n", time * 1000.0); + DeallocateMatrices(Reps, m); + } + else + { + if (! Filled[FF_A]) A = 0; + + printf("Testing new row insertion of %d rows starting at row %d...\n", rows, row); + ShowMatrix(A, "A Before"); + RemoveRows(A, row, rows); + ShowMatrix(A, "A After"); + } +} + +void TestRemoveColumns(matrix *A, int column, int columns, int Reps, int Size, char* Option, int *Filled) +{ + /*There are two possible options: speedtest-optimized and speedtest-unoptimized. No option means normal test.*/ + matrix *m; + clock_t t0; + double time; + int i; + if (Filled[FF_OPTION] && (! strcmp(Option, "speedtest-optimized"))) + { + printf("Speed-testing optimized column removal by removing %d columns from square matrices of size %d, %d times...\n", columns, Size, Reps); + /*Allocate type-2 transposed matrices.*/ + AllocateMatrices(Reps, Size, &m, 1); + ShowMatrix(m, "Sample Before"); + printf("Running test...\n"); + t0 = clock(); + for (i = 0; i < Reps; i++) + { + RemoveColumns(m + i, column, columns); + } + time = ((double) (clock() - t0)) / (double) CLOCKS_PER_SEC; + ShowMatrix(m, "Sample After"); + printf("Time: %.2f ms\n", time * 1000.0); + DeallocateMatrices(Reps, m); + } + else if (Filled[FF_OPTION] && (! strcmp(Option, "speedtest-unoptimized"))) + { + printf("Speed-testing unoptimized column removal by removing %d columns from square matrices of size %d, %d times...\n", columns, Size, Reps); + /*Allocate type-2 untransposed matrices.*/ + AllocateMatrices(Reps, Size, &m, 0); + ShowMatrix(m, "Sample Before"); + printf("Running test...\n"); + t0 = clock(); + for (i = 0; i < Reps; i++) + { + RemoveColumns(m + i, column, columns); + } + time = ((double) (clock() - t0)) / (double) CLOCKS_PER_SEC; + ShowMatrix(m, "Sample After"); + printf("Time: %.2f ms\n", time * 1000.0); + DeallocateMatrices(Reps, m); + } + else + { + if (! Filled[FF_A]) A = 0; + + printf("Testing new column insertion of %d columns starting at column %d...\n", columns, column); + ShowMatrix(A, "A Before"); + RemoveColumns(A, column, columns); + ShowMatrix(A, "A After"); + } +} + +void TestMergeRows(matrix *A, matrix *B, int row, int Reps, int Size, char* Option, int *Filled) +{ + /*There are two possible options: speedtest-optimized and speedtest-unoptimized. No option means normal test.*/ + matrix *m1, *m2; + clock_t t0; + double time; + int i; + if (Filled[FF_OPTION] && (! strcmp(Option, "speedtest-optimized"))) + { + printf("Speed-testing optimized row merge by merging by row two square matrices of size %d, %d times...\n", Size, Reps); + /*Allocate type-2 untransposed matrices.*/ + AllocateMatrices(Reps, Size, &m1, 0); + AllocateMatrices(Reps, Size, &m2, 0); + ShowMatrix(m1, "Sample Before"); + printf("Running test...\n"); + t0 = clock(); + for (i = 0; i < Reps; i++) + { + MergeRows(m1 + i, m2 + i, row); + } + time = ((double) (clock() - t0)) / (double) CLOCKS_PER_SEC; + ShowMatrix(m1, "Sample After"); + printf("Time: %.2f ms\n", time * 1000.0); + DeallocateMatrices(Reps, m1); + } + else if (Filled[FF_OPTION] && (! strcmp(Option, "speedtest-unoptimized"))) + { + printf("Speed-testing unoptimized row merge by merging by row two square matrices of size %d, %d times...\n", Size, Reps); + /*Allocate type-2 transposed matrices.*/ + AllocateMatrices(Reps, Size, &m1, 1); + AllocateMatrices(Reps, Size, &m2, 1); + ShowMatrix(m1, "Sample Before"); + printf("Running test...\n"); + t0 = clock(); + for (i = 0; i < Reps; i++) + { + MergeRows(m1 + i, m2 + i, row); + } + time = ((double) (clock() - t0)) / (double) CLOCKS_PER_SEC; + ShowMatrix(m1, "Sample After"); + printf("Time: %.2f ms\n", time * 1000.0); + DeallocateMatrices(Reps, m1); + } + else + { + if (! Filled[FF_A]) A = 0; + /*Build a new copy of B - we cannot do a merge with the old one because + it will be deallocated by the merge and then the final deallocation will + fail.*/ + matrix New; + AllocateMatrixType(1, &New, NumberOfRows(*B), NumberOfColumns(*B)); + CopyMatrix(B, &New); + printf("Testing row merge B -> A starting at row %d...", row); + ShowMatrix(A, "A Before"); + ShowMatrix(&New, "B"); + MergeRows(A, &New, row); + ShowMatrix(A, "A After"); + } +} + +void TestMergeColumns(matrix *A, matrix *B, int column, int Reps, int Size, char* Option, int *Filled) +{ + /*There are two possible options: speedtest-optimized and speedtest-unoptimized. No option means normal test.*/ + matrix *m1, *m2; + clock_t t0; + double time; + int i; + if (Filled[FF_OPTION] && (! strcmp(Option, "speedtest-optimized"))) + { + printf("Speed-testing optimized column merge by merging by column two square matrices of size %d, %d times...\n", Size, Reps); + /*Allocate type-2 transposed matrices.*/ + AllocateMatrices(Reps, Size, &m1, 1); + AllocateMatrices(Reps, Size, &m2, 1); + ShowMatrix(m1, "Sample Before"); + printf("Running test...\n"); + t0 = clock(); + for (i = 0; i < Reps; i++) + { + MergeColumns(m1 + i, m2 + i, column); + } + time = ((double) (clock() - t0)) / (double) CLOCKS_PER_SEC; + ShowMatrix(m1, "Sample After"); + printf("Time: %.2f ms\n", time * 1000.0); + DeallocateMatrices(Reps, m1); + } + else if (Filled[FF_OPTION] && (! strcmp(Option, "speedtest-unoptimized"))) + { + printf("Speed-testing unoptimized column merge by merging by column two square matrices of size %d, %d times...\n", Size, Reps); + /*Allocate type-2 untransposed matrices.*/ + AllocateMatrices(Reps, Size, &m1, 0); + AllocateMatrices(Reps, Size, &m2, 0); + ShowMatrix(m1, "Sample Before"); + printf("Running test...\n"); + t0 = clock(); + for (i = 0; i < Reps; i++) + { + MergeColumns(m1 + i, m2 + i, column); + } + time = ((double) (clock() - t0)) / (double) CLOCKS_PER_SEC; + ShowMatrix(m1, "Sample After"); + printf("Time: %.2f ms\n", time * 1000.0); + DeallocateMatrices(Reps, m1); + } + else + { + if (! Filled[FF_A]) A = 0; + /*Build a new copy of B - we cannot do a merge with the old one because + it will be deallocated by the merge and then the final deallocation will + fail.*/ + matrix New; + AllocateMatrixType(1, &New, NumberOfRows(*B), NumberOfColumns(*B)); + CopyMatrix(B, &New); + printf("Testing column merge B -> A starting at column %d...", column); + ShowMatrix(A, "A Before"); + ShowMatrix(&New, "B"); + MergeColumns(A, &New, column); + ShowMatrix(A, "A After"); + } +} + +/*Interpret the how-to-allocate option for an operation that can either use +pre-allocated result storage, allocate its own, or allocate its own of a +specified type.*/ +int ReadAllocationOption(char* Option, int* Filled) +{ + if (! Filled[FF_OPTION]) return -1; + if (! strcmp(Option, "preallocate")) + { + return -1; + } + else if (! strcmp(Option, "allocate")) + { + return 0; + } + else if (! strcmp(Option, "type1")) + { + return 1; + } + else if (! strcmp(Option, "type2")) + { + return 2; + } + else if (! strcmp(Option, "type3")) + { + return 3; + } + else + { + printf("Warning: Unrecognized allocation option '%s'. Preallocating.\n", Option); + return -1; + } +} + +/*Make sure that pointers to matrices and arrays are null if the arrays and +matrices were not given in the problem data.*/ +void SetPointers(matrix **A, matrix **B, int **C, int **D, int* Filled) +{ + if ((! Filled[FF_A]) && A) *A = 0; + if ((! Filled[FF_B]) && B) *B = 0; + if ((! Filled[FF_C]) && C) *C = 0; + if ((! Filled[FF_D]) && D) *D = 0; +} + +/*Display a progress percentage that changes with time instead of being left +in the output buffer.*/ +void PrintPercent(int num, int denom) +{ + static int lastPercent = -1; + int percent; + percent = (num * 100) / denom; + if (percent != lastPercent) + { + lastPercent = percent; + if (percent) printf("\b\b\b\b"); + printf("%3d%%", percent); + fflush(stdout); + } +} + +/*Allocate an array of matrices to be used for a speed test.*/ +void AllocateMatrices(int reps, int size, matrix **m, int Transpose) +{ + int i; + *m = tcalloc(reps, sizeof(matrix)); + printf("Allocating test matrices..."); + PrintPercent(0, 1); + for (i = 0; i < reps; i++) + { + AllocateMatrixType(2, (*m) + i, size, size); + if (Transpose) TransposeMatrix((*m) + i); + PrintPercent(i + 1, reps); + } + printf("\n"); +} + +/*Deallocate an array of matrices that have been allocated for a speed test.*/ +void DeallocateMatrices(int reps, matrix *m) +{ + int i; + printf("Deallocating test matrices..."); + PrintPercent(0, 1); + for (i = 0; i < reps; i++) + { + DeallocateMatrix(m + i); + PrintPercent(i + 1, reps); + } + printf("\n"); + free(m); +} + +/*Used by TestMultiplyVector to show array-type vectors.*/ +void ShowArray(int *array, int Count, char* name) +{ + int i; + if (! array) + { + printf("ShowArray: Null array pointer"); + return; + } + printf("%s\t", name); + for (i = 0; i < Count; i++) + { + printf("%d\t", array[i]); + } + printf("\n"); +} + +void SetDefaults(int* Filled, int* Row, int* Col, int* Rows, int* Cols, int* Reps, int* Size) +{ + if (! Filled[FF_ROW]) *Row = -1; + if (! Filled[FF_COL]) *Col = -1; + if (! Filled[FF_ROWS]) *Rows = 0; + if (! Filled[FF_COLS]) *Cols = 0; + if (! Filled[FF_REPS]) *Reps = 1; + if (! Filled[FF_SIZE]) *Size = 0; +} \ No newline at end of file Added: spnbox/tests/test-matrixmath.txt =================================================================== --- spnbox/tests/test-matrixmath.txt (rev 0) +++ spnbox/tests/test-matrixmath.txt 2009-07-13 18:01:14 UTC (rev 195) @@ -0,0 +1,348 @@ +rem string option, string operation, matrix A, matrix B, arrayi C, arrayi D, +rem int row, int column, int rows, int columns, int repetitions, int size +rem Operation Operands Options +rem AddMatrix A, B preallocate, allocate, type1, type2, type3 +rem SubtractMatrix A, B preallocate, allocate, type1, type2, type3 +rem MultiplyMatrix A, B preallocate, allocate, type1, type2, type3 +rem InsertRows A, B, Row preallocate, allocate, type1, type2, type3 +rem InsertColumns A, B, Column preallocate, allocate, type1, type2, type3 +rem MultiplyVector (A, B) or (A, C or D) +rem or (B, C or D) +rem MatrixEqualMatrix A, B +rem InsertNewRows [A], Row, Rows +rem [Repetitions, Size] speedtest-optimized, speedtest-unoptimized +rem InsertNewColumns [A], Column, Columns +rem [Repetitions, Size] speedtest-optimized, speedtest-unoptimized +rem RemoveRows [A], Row, Rows +rem [Repetitions, Size] speedtest-optimized, speedtest-unoptimized +rem RemoveColumns [A], Column, Columns +rem [Repetitions, Size] speedtest-optimized, speedtest-unoptimized +rem MergeRows [A, B,] Row, +rem [Repetitions, Size] speedtest-optimized, speedtest-unoptimized +rem MergeColumns [A, B,] Column, +rem [Repetitions, Size] speedtest-optimized, speedtest-unoptimized + +echo Problem 1. Addition Test with preallocated result space. +operation AddMatrix +A 3 3 +1 2 3 +4 5 6 +7 8 9 + +B 3 3 +9 8 7 +6 5 4 +3 2 1 + +done + +echo Problem 2. Addition test with self-allocated result space. +operation AddMatrix +option allocate +A 2 2 +1 2 +3 4 + +B 2 2 +3 4 +2 1 + +done + +echo Problem 3. Subtraction test with specific type self-allocated result space. +operation SubtractMatrix +option type1 +A 3 3 +9 9 9 +9 9 9 +9 9 9 + +B 3 3 +9 8 7 +6 5 4 +3 2 1 + +done + +echo Problem 4. Multiplication test with explicit preallocated result space. +operation MultiplyMatrix +option preallocate +A 2 3 +1 2 1 +2 1 2 + +B 3 1 +1 2 3 + +done + +echo Problem 5. Inserted rows from one matrix into another matrix. +operation InsertRows +A 2 3 +1 2 3 +7 8 9 + +B 1 3 +4 5 6 + +row 1 +done + +echo Problem 6. Inserting columns from one matrix into another matrix. +operation InsertColumns +A 3 2 +1 7 +2 8 +3 9 + +B 3 1 +4 +5 +6 + +column 1 +done + +echo Problem 7. MultiplyVector with integer arrays. +echo The answer should be 19. +operation MultiplyVector +C 3 +1 2 3 + +D 3 +3 5 2 + +size 3 +done + +echo Problem 7. MultiplyVector with one matrix and one integer array. +echo The answer should be 19. +operation MultiplyVector +A 3 3 +0 0 0 +1 2 3 +0 0 0 + +C 3 +3 5 2 + +row 1 +done + +echo Problem 8. MultiplyVector with one integer array and one matrix. +echo The answer should be 19. +operation MultiplyVector +D 3 +3 5 2 + +B 3 3 +0 1 0 +0 2 0 +0 3 0 + +column 1 +done + +echo Problem 9. MultiplyVector with two matrices. +echo The answer should be 19. +operation MultiplyVector +A 3 3 +0 0 0 +0 0 0 +3 5 2 + +B 3 3 +1 0 0 +2 0 0 +3 0 0 + +column 0 +row 2 +done + +echo Problem 10. Matrix equality test with equal matrices. +operation MatrixEqualMatrix +A 2 2 +1 2 +3 4 + +B 2 2 +1 2 +3 4 + +done + +echo Problem 11. Matrix equality test with unequal matrices. +operation MatrixEqualMatrix +A 2 2 +1 2 +3 4 + +B 2 2 +1 2 +3 1 + +done +echo Problem 12. Matrix equality test with matrices of different sizes. +operation MatrixEqualMatrix +A 2 2 +1 1 +1 1 + +B 1 1 +1 +done + +echo Problem 13. New row insertion. +operation InsertNewRows +A 2 3 +1 2 3 +2 4 6 + +row 1 +rows 2 +done + +echo Problem 14. New column insertion. +operation InsertNewColumns +A 2 2 +1 2 +1 2 + +columns 3 +done + +echo Problem 15. Row removal. +operation RemoveRows +A 4 2 +1 1 +0 0 +2 2 +3 3 + +row 1 +rows 2 +done + +echo Problem 16. Column removal. +operation RemoveColumns +A 2 4 +1 1 2 3 +1 4 5 6 + +column 0 +columns 1 +done + +echo Problem 16. Row merge. +operation MergeRows +A 2 3 +1 2 3 +7 8 9 + +B 1 3 +4 5 6 +row 1 + +done + +echo Problem 17. Column merge. +operation MergeColumns +A 3 2 +1 7 +2 8 +3 9 + +B 3 1 +4 +5 +6 + +column 1 +done + +echo Speed Test: InsertNewRows, unoptimized +operation InsertNewRows +size 10 +rows 1 +repetitions 40000 +option speedtest-unoptimized +done + +echo Speed Test: InsertNewRows, optimized +operation InsertNewRows +size 10 +rows 1 +repetitions 40000 +option speedtest-optimized +done + +echo Speed Test: RemoveRows, unoptimized +operation RemoveRows +size 10 +row 4 +rows 1 +repetitions 40000 +option speedtest-unoptimized +done + +echo Speed Test: RemoveRows, optimized +operation RemoveRows +size 10 +row 4 +rows 1 +repetitions 40000 +option speedtest-optimized +done + +echo Speed Test: RemoveColumns, unoptimized +operation RemoveColumns +size 10 +column 4 +columns 1 +repetitions 40000 +option speedtest-unoptimized +done + +echo Speed Test: RemoveColumns, optimized +operation RemoveColumns +size 10 +column 4 +columns 1 +repetitions 40000 +option speedtest-optimized +done + +echo Speed Test: MergeRows, unoptimized +operation MergeRows +size 10 +row 2 +repetitions 20000 +option speedtest-unoptimized +done + +echo Speed Test: MergeRows, optimized +operation MergeRows +size 10 +row 2 +repetitions 20000 +option speedtest-optimized +done + +echo Speed Test: MergeColumns, unoptimized +operation MergeColumns +size 10 +column 5 +repetitions 20000 +option speedtest-unoptimized +done + +echo Speed Test: MergeColumns, optimized +operation MergeColumns +size 10 +column 5 +repetitions 20000 +option speedtest-optimized + +done +quit This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |