[Pntool-developers] SF.net SVN: pntool:[196] spnbox
Brought to you by:
compaqdrew,
miordache
From: <Ste...@us...> - 2009-07-14 15:31:45
|
Revision: 196 http://pntool.svn.sourceforge.net/pntool/?rev=196&view=rev Author: StephenCamp Date: 2009-07-14 15:31:42 +0000 (Tue, 14 Jul 2009) Log Message: ----------- Split the functions in matrixmath.c into two files: Matrix mathematics remain in matrixmath.c. Manipulation functions such as row insertion and removal have been moved to extendedmatrix.c. The test routines and makefiles have been updated appropriately. The manipulation functions have been updated to have a more consistent interface. Each function now takes a "mode" parameter that determines whether it is to allocate space for and return a completely new matrix and leave the operands untouched or modify the operands directly. supervis.c has been updated to use the new function definition. Updated the readme. Modified Paths: -------------- spnbox/Makefile spnbox/README.txt spnbox/matrixmath.c spnbox/matrixmath.h spnbox/supervis.c spnbox/tests/Makefile spnbox/tests/test-matrixmath.c spnbox/tests/test-matrixmath.txt Added Paths: ----------- spnbox/extendedmatrix.c spnbox/extendedmatrix.h spnbox/tests/test-extendedmatrix.c spnbox/tests/test-extendedmatrix.txt Modified: spnbox/Makefile =================================================================== --- spnbox/Makefile 2009-07-13 18:01:14 UTC (rev 195) +++ spnbox/Makefile 2009-07-14 15:31:42 UTC (rev 196) @@ -3,7 +3,7 @@ COMPILER=gcc -g -all: actn.o chkcons.o ilpadm.o ipslv.o ipsolve.o isadm.o issiph.o linenf.o matrixmath.o MemoryManager.o msplit.o nltrans.o pn2acpn.o pn2eacpn.o supervis.o liblpsolve55.a +all: actn.o chkcons.o extendedmatrix.o ilpadm.o ipslv.o ipsolve.o isadm.o issiph.o linenf.o matrixmath.o MemoryManager.o msplit.o nltrans.o pn2acpn.o pn2eacpn.o supervis.o liblpsolve55.a actn.o: actn.c spnbox.h MemoryManager.h matrixmath.h ../pnheaders/general.h ../pnheaders/matrix.h $(COMPILER) -c actn.c @@ -11,6 +11,9 @@ chkcons.o: chkcons.c spnbox.h MemoryManager.h matrixmath.h ../pnheaders/general.h ../pnheaders/matrix.h ../pnheaders/pns.h $(COMPILER) -c chkcons.c +extendedmatrix.o: extendedmatrix.c extendedmatrix.h ../pnheaders/general.h ../pnheaders/matrix.h + $(COMPILER) -c extendedmatrix.c + ilpadm.o: ilpadm.c spnbox.h MemoryManager.h matrixmath.h ../pnheaders/general.h ../pnheaders/matrix.h ../pnheaders/pns.h $(COMPILER) -c ilpadm.c @@ -62,3 +65,7 @@ clean: rm -f *.o *.a cd ../third-party/lp_solve_5.5; make -f Makefile.Linux clean + +clean-partial: + rm -f *.o + Modified: spnbox/README.txt =================================================================== --- spnbox/README.txt 2009-07-13 18:01:14 UTC (rev 195) +++ spnbox/README.txt 2009-07-14 15:31:42 UTC (rev 196) @@ -12,7 +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. +To test the various functions in the matrixmath.c file, use make matrixmath. To test the functions in the extendedmatrix.c file, use make extendedmatrix. 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. @@ -35,11 +35,11 @@ - deallocation.c: This implements functions to deallocate the structures returned by SPNBOX functions. - Makefile: This is the main makefile. When used without a target it builds - object files that implement all SPNBOX functionality. It can take as a target - the command "clean", upon reciept of which it removes all object files, all - library (*.a) files, moves to the third-party/lp_solve_5.5/ directory, and - executes the linux-targeted makefile to clean the lpsolve libraries and - intermediate files. + object files that implement all SPNBOX functionality. + Use "make clean" to remove all object files, all library (*.a) files, and + execute the clean command for the lpsolve library in the third-party/lp_solve_5.5 + directory. + Use "make clean-partial" to remove all object files. - Each of the other files corresponds to a single SPNBOX function. tests subdirectory: Added: spnbox/extendedmatrix.c =================================================================== --- spnbox/extendedmatrix.c (rev 0) +++ spnbox/extendedmatrix.c 2009-07-14 15:31:42 UTC (rev 196) @@ -0,0 +1,341 @@ +#include "../pnheaders/general.h" +#include "../pnheaders/matrix.h" +#include "matrixmath.h" +#include "extendedmatrix.h" + +static matrix InsertRowsCopy(matrix* outer, matrix* inner, int start, int mode); +static matrix InsertRowsOrig(matrix* outer, matrix* inner, int start); +static matrix RemoveRowsCopy(matrix* m, int row, int rows, int mode); +static matrix RemoveRowsOrig(matrix* m, int row, int rows); +static matrix InsertNullRowsCopy(matrix *m, int row, int rows, int mode); +static matrix InsertNullRowsOrig(matrix *m, int row, int rows); + +matrix InsertRows(matrix* outer, matrix* inner, int start, int mode) +{ + matrix null; + + /*Check parameters. None of the pointers can be null.*/ + if(! (outer && inner)) + { + merror(0, "InsertRows/Columns: One of the operands is a null pointer"); + AllocateMatrix(&null, 0, 0); + return null; + } + /*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"); + AllocateMatrix(&null, 0, 0); + return null; + } + + /*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, "InsertRows/Columns: The index of the first inserted row/column is out of range"); + AllocateMatrix(&null, 0, 0); + return null; + } + + /*If mode is 0 or positive, we are writing to a copy.*/ + if (mode >= 0) + { + return InsertRowsCopy(outer, inner, start, mode); + } + /*Otherwise, we want to actually merge the matrices.*/ + else + { + return InsertRowsOrig(outer, inner, start); + } +} + +matrix InsertColumns(matrix* outer, matrix* inner, int start, int mode) +{ + /*This is the column analogue of InsertRows. Transpose the operands and call + InsertRows.*/ + matrix result; + TransposeMatrix(outer); + TransposeMatrix(inner); + result = InsertRows(outer, inner, start, mode); + TransposeMatrix(outer); + if (mode >= 0) TransposeMatrix(inner); + TransposeMatrix(&result); + return result; +} + +matrix InsertNullRows(matrix* m, int start, int rowsToAdd, int mode) +{ + matrix null; + if (! m) + { + merror(0, "InsertNewRows/COLUMNS: Null matrix pointer"); + AllocateMatrix(&null, 0, 0); + return null; + } + /*Make sure the starting point is valid. Start will be the index of the first + of the new rows added. If index < 0, default to adding at the end of the + matrix.*/ + if (start < 0) start = NumberOfRows(*m); + if (start > NumberOfRows(*m)) + { + merror(0, "InsertNewRows/COLUMNS: First new index is out of range"); + AllocateMatrix(&null, 0, 0); + return null; + } + /*Make sure the rowsToAdd is valid. Cannot be less than 1.*/ + if (rowsToAdd < 1) + { + merror(0, "InsertNewRows/COLUMNS: Rows/Columns to add is negative or zero"); + AllocateMatrix(&null, 0, 0); + return null; + } + if (mode >= 0) + { + return InsertNullRowsCopy(m, start, rowsToAdd, mode); + } + else + { + return InsertNullRowsOrig(m, start, rowsToAdd); + } +} + +matrix InsertNullColumns(matrix* m, int start, int colsToAdd, int mode) +{ + matrix result; + /*This is the column analogue of InsertNewRows. Transpose the matrix and call + InsertNewRows.*/ + TransposeMatrix(m); + result = InsertNullRows(m, start, colsToAdd, mode); + TransposeMatrix(&result); + TransposeMatrix(m); + return result; +} + +matrix RemoveRows(matrix* m, int start, int rowsToRemove, int mode) +{ + /*Matrix pointer cannot be null.*/ + matrix null; + if (! m) + { + merror(0, "REMOVEROWS/COLUMNS: Null matrix pointer"); + AllocateMatrix(&null, 0, 0); + return null; + } + /*Start has to be the index of the first row to remove.*/ + if (start < 0 || start >= NumberOfRows(*m)) + { + merror(0, "REMOVEROWS/COLUMNS: Index of first row/column to remove is out of range"); + AllocateMatrix(&null, 0, 0); + return null; + } + /*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/COLUMNS: Number of rows/columns to remove is out of range"); + AllocateMatrix(&null, 0, 0); + return null; + } + if (mode >= 0) + { + return RemoveRowsCopy(m, start, rowsToRemove, mode); + } + else + { + return RemoveRowsOrig(m, start, rowsToRemove); + } +} + +matrix RemoveColumns(matrix* m, int start, int colsToRemove, int Mode) +{ + matrix result; + /*This is the column analogue of RemoveRows. Transpose the matrix and call + RemoveRows.*/ + TransposeMatrix(m); + result = RemoveRows(m, start, colsToRemove, Mode); + TransposeMatrix(&result); + TransposeMatrix(m); + return result; +} + +matrix InsertRowsCopy(matrix* outer, matrix* inner, int start, int mode) +{ + matrix result; + /*Insert null rows.*/ + result = InsertNullRowsCopy(outer, start, NumberOfRows(*inner), mode); + /*Copy the inner matrix.*/ + CopyBlock(NumberOfRows(*inner), NumberOfColumns(*inner), inner, 0, 0, &result, start, 0); + return result; +} + +matrix InsertRowsOrig(matrix* outer, matrix* inner, int start) +{ + int i; + mtype **newAr; + /*If the outer and inner matrices are both type 2 untransposed, we can combine + memory directly. Otherwise we'll want to insert new blank rows into outer + and copy the contents of inner.*/ + if (outer->type == 2 && inner->type == 2 && !(outer->trans || inner->trans)) + { + /*Combine row memory directly.*/ + newAr = tcalloc(outer->nr + inner->nr, sizeof(mtype*)); + outer->nr += inner->nr; + for (i = 0; i < outer->nr; i++) + { + 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)); + } + else + { + /*Otherwise insert the new null rows and copy.*/ + InsertNullRowsOrig(outer, start, NumberOfRows(*inner)); + CopyBlock(NumberOfRows(*inner), NumberOfColumns(*inner), inner, 0, 0, outer, start, 0); + DeallocateMatrix(inner); + memset(inner, 0, sizeof(matrix)); + } + return *outer; +} + +matrix RemoveRowsCopy(matrix* m, int row, int rows, int mode) +{ + matrix result; + + /*Prepare the result matrix.*/ + if (mode) + { + AllocateMatrixType(mode, &result, NumberOfRows(*m) - rows, NumberOfColumns(*m)); + } + else + { + AllocateMatrix(&result, NumberOfRows(*m) - rows, NumberOfColumns(*m)); + } + /*Copy the first-half block.*/ + if (row) + { + CopyBlock(row, NumberOfColumns(*m), m, 0, 0, &result, 0, 0); + } + /*Copy the second-half block.*/ + if (NumberOfRows(*m) - row - rows) + { + CopyBlock(NumberOfRows(*m) - row - rows, NumberOfColumns(*m), m, row + rows, 0, &result, row, 0); + } + return result; +} + +matrix RemoveRowsOrig(matrix* m, int row, int rows) +{ + mtype** newAr; + int i; + /*Check to see if the remove can be optimized.*/ + if (m->type == 2 && (! m->trans)) + { + newAr = tcalloc(m->nr, sizeof(mtype*)); + for (i = 0; i < m->nr; i++) + { + if (i < row) + { + newAr[i] = m->ar[i]; + } + else if (i < row + rows) + { + free(m->ar[i]); + } + else + { + newAr[i - rows] = m->ar[i]; + } + } + free(m->ar); + m->ar = newAr; + m->nr -= rows; + } + else + { + /*If not, do a slow remove. This has to create a complete copy of the + matrix. Preserve matrix type.*/ + matrix old = *m; + *m = RemoveRowsCopy(m, row, rows, m->type); + DeallocateMatrix(&old); + } + return *m; +} + +matrix InsertNullRowsCopy(matrix *m, int row, int rows, int mode) +{ + matrix result; + /*Allocate the result matrix.*/ + if (mode) + { + AllocateMatrixType(mode, &result, NumberOfRows(*m) + rows, NumberOfColumns(*m)); + } + else + { + AllocateMatrix(&result, NumberOfRows(*m) + rows, NumberOfColumns(*m)); + } + /*Copy the first-half block.*/ + if (row) + { + CopyBlock(row, NumberOfColumns(*m), m, 0, 0, &result, 0, 0); + } + /*Copy the second-half block.*/ + if (NumberOfRows(*m) - row) + { + CopyBlock(NumberOfRows(*m) - row, NumberOfColumns(*m), m, row, 0, &result, row + rows, 0); + } + return result; +} + +matrix InsertNullRowsOrig(matrix *m, int row, int rows) +{ + mtype **newAr; + int i; + /*See if the insertion can be optimized.*/ + if (m->type == 2 && (! m->trans)) + { + m->nr += rows; + newAr = tcalloc(m->nr, sizeof(mtype*)); + for (i = 0; i < m->nr; i++) + { + if (i < row) + { + newAr[i] = m->ar[i]; + } + else if (i < row + rows) + { + newAr[i] = tcalloc(NumberOfColumns(*m), sizeof(mtype)); + } + else + { + newAr[i] = m->ar[i - rows]; + } + } + free(m->ar); + m->ar = newAr; + } + else + { + /*To insert blank rows we'll need to do a complete copy anyway.*/ + matrix old; + old = *m; + *m = InsertNullRowsCopy(m, row, rows, m->type); + DeallocateMatrix(&old); + } + return *m; +} Added: spnbox/extendedmatrix.h =================================================================== --- spnbox/extendedmatrix.h (rev 0) +++ spnbox/extendedmatrix.h 2009-07-14 15:31:42 UTC (rev 196) @@ -0,0 +1,86 @@ +#ifndef EXTENDEDMATRIX +#define EXTENDEDMATRIX + +matrix InsertRows(matrix* outer, matrix* inner, int start, int mode); +/*InsertRows inserts the rows of the matrix inner into the matrix outer in such +a way that the index of the first new row is start. If start is negative, the +new rows are added to the end of outer. +If mode is 0 or greater, InsertRows allocates a new matrix to hold the results +and leaves the operands unchanged. The type of the new matrix will be default +if mode is 0 or greater than 3, or the value of mode itself otherwise. +If mode is negative, then the matrix pointed to by outer is actually changed. +All the memory of inner is given to outer. Note that this means that inner +should not ever be deallocated; to deallocate it will deallocate part of the +memory used by the modified outer. +If in modification mode, InsertRows can optimize the operation if both matrices +are type 2 untransposed. The optimization reduces computational complexity by +a factor at least equal to the number of columns in the matrices.*/ + +matrix InsertColumns(matrix* outer, matrix* inner, int start, int mode); +/*InsertColumns inserts the columns of the matrix inner into the matrix outer in +such a way that the index of the first new column is start. If start is negative, +the new columns are added to the end of outer. +If mode is 0 or greater, InsertColumns allocates a new matrix to hold the results +and leaves the operands unchanged. The type of the new matrix will be default +if mode is 0 or greater than 3, or the value of mode itself otherwise. +If mode is negative, then the matrix pointed to by outer is actually changed. +All the memory of inner is given to outer. Note that this means that inner +should not ever be deallocated; to deallocate it will deallocate part of the +memory used by the modified outer. +If in modification mode, InsertColumns can optimize the operation if both +matrices are type 2 transposed. The optimization reduces computational +complexity by a factor at least equal to the number of rows in the matrices.*/ + +matrix InsertNullRows(matrix* m, int start, int rowsToAdd, int mode); +/*InsertNewRows adds one or more new null (all-zero) rows into the given matrix. +start The index of the first of the new rows. If it is set to a negative + 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. +mode If mode is 0 or greater than 3, a new matrix of the default type + will be allocated to hold the results and the operand will remain + unchanged. If mode is 1, 2, or 3, the new matrix will be of type + 1, 2, or 3. If mode is less than zero, the new rows will be + inserted into the original matrix pointed to by m. +The return value is the result matrix. +Note that in modification mode, 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.*/ + +matrix InsertNullColumns(matrix* m, int start, int colsToAdd, int mode); +/*InsertNewColumns adds one or more new (all-zero) rows into the given matrix. +See InsertNewRows; the parameters of InsertNewColumns are the column analogues of +InsertNewRows' parameters. The return value is the new matrix. InsertNewColumns +can apply the same type of optimization, except that it will work only for +transposed type-2 matrices and the factor of optimization is at least equal to +number of rows in the matrices.*/ + +matrix RemoveRows(matrix* m, int start, int rowsToRemove, int mode); +/*RemoveRows removes one or more contiguous rows from the given matrix. +start The index of the first row to remove. If it is out of range the + function will fail with an error message. +rowsToRemove The number of rows to remove. If the number is less than 1 or + large enough that it would attempt to remove nonexistant rows, + the function fails with an error message and terminates execution. +mode If mode is 0 or greater than 3, a new matrix of the default type + will be allocated to hold the results and the operand will remain + unchanged. If mode is 1, 2, or 3, the new matrix will be of type + 1, 2, or 3. If mode is less than zero, the rows will be removed + from the original matrix pointed to by m. +The return value is the new matrix. +If RemoveRows is passed a type-2 untransposed matrix in modification mode ( +modifying the original matrix), it employs optimization that reduces the +computational complexity of the operation by at approximately a factor +corresponding to the number of columns in the matrix.*/ + +matrix RemoveColumns(matrix* m, int start, int colsToRemove, int mode); +/*RemoveColumns removes one or more contiguous columns from the given matrix. +See RemoveRows; the parameters of RemoveColumns are the column analogues of +RemoveRows. The return value is the new matrix. +RemoveColumns is able to employ the same type of optimization as RemoveRows +(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.*/ +#endif Modified: spnbox/matrixmath.c =================================================================== --- spnbox/matrixmath.c 2009-07-13 18:01:14 UTC (rev 195) +++ spnbox/matrixmath.c 2009-07-14 15:31:42 UTC (rev 196) @@ -2,12 +2,50 @@ matrixmath.c Written in 2009 by Stephen Camp Updated 19 May 2009 +Updated 13 July 2009 ****************************************************************************/ #include "../pnheaders/general.h" #include "../pnheaders/matrix.h" #include "matrixmath.h" +/*This function is an internal function used by many of the matrixmath functions. +It examines the dst pointer to determine if it points to a valid destination +or if it requests a destination be allocated. +If the former, the function checks to make sure the destination is of the +correct size. If the latter, it does the allocation..*/ +static int CheckDestination(matrix** dst, int dstRows, int dstCols, matrix* local) +{ + /*If *dst > 3 it is a valid pointer. Check to make sure the destination has + the requested size.*/ + if ((long) *dst > 3) + { + if (NumberOfRows(**dst) != dstRows || NumberOfColumns(**dst) != dstCols) + { + return 0; + } + else + { + /*Return 1. This will indicate success with no allocation.*/ + return 1; + } + } + /*If a specific type of allocation is is requested...*/ + else if (*dst) + { + AllocateMatrixType((int) *dst, local, dstRows, dstCols); + *dst = local; + } + /*Otherwise, use the default allocated type.*/ + else + { + AllocateMatrix(local, dstRows, dstCols); + *dst = local; + } + /*Return -1. This will indicate success with allocation.*/ + return -1; +} + /*This function transposes the matrix passed in Matrix. Currently, this operation is very fast as it consists only of changing an internal flag in the matrix structure.*/ @@ -23,18 +61,15 @@ int i, j, rows, cols; /*This will hold an empty matrix for error return or be allocated to be the destination matrix.*/ - matrix destinationMatrix; - //This will point to the final destination matrix. - matrix *destination; - + matrix local; //Zero the destination matrix to use as an error return value. - AllocateMatrix(&destinationMatrix, 0, 0); + AllocateMatrix(&local, 0, 0); //Check to make sure none of the parameters are null. if(! (addA && addB)) { merror(0, "AddMatrix: One of the parameters is a null pointer"); - return destinationMatrix; + return local; } //Check to make sure the matrices are of the same dimension. rows = NumberOfRows(*addA); @@ -43,45 +78,25 @@ if (rows != NumberOfRows(*addB) || cols != NumberOfColumns(*addB)) { merror(0, "AddMatrix: The operands do not have the same dimensions"); - return destinationMatrix; + return local; } //Arrange the destination matrix. - if (! dst) + if (! CheckDestination(&dst, rows, cols, &local)) { - //If dst is a null pointer, allocate a new matrix of the default type. - AllocateMatrix(&destinationMatrix, rows, cols); - destination = &destinationMatrix; + merror(0, "AddMatrix: The destination matrix is the wrong size"); + return local; } - else if ((int) dst < 4) - { - /*If dst is between 1 and 3, treat it as the type number of a new matrix of - a specific type to hold the destination.*/ - AllocateMatrixType((int) dst, &destinationMatrix, rows, cols); - destination = &destinationMatrix; - } - else - { - /*Otherwise assume dst is a valid pointer to a pre-allocated matrix. Make - sure the dimensions are right. Make sure the destination matrix has the - right dimensions.*/ - if (rows != NumberOfRows(*dst) || cols != NumberOfColumns(*dst)) - { - merror(0, "AddMatrix: The destination matrix has the wrong dimensions"); - return destinationMatrix; - } - destination = dst; - } //Add the matrices for (i = 0; i < rows; i++) { for (j = 0; j < cols; j++) { - SetMatrixEl(destination, i, j, GetMatrixEl(addA, i, j) + GetMatrixEl(addB, i, j)); + SetMatrixEl(dst, i, j, GetMatrixEl(addA, i, j) + GetMatrixEl(addB, i, j)); } } - return *destination; + return *dst; } /* SubtractMatrix does an element-by-element subtraction. The elements of the @@ -92,17 +107,15 @@ int i, j, rows, cols; /*This will hold an empty matrix for error return or be allocated to be the destination matrix.*/ - matrix destinationMatrix; - /*This will point to the final destination matrix.*/ - matrix *destination; + matrix local; //Zero the destination matrix to use as an error return value. - AllocateMatrix(&destinationMatrix, 0, 0); + AllocateMatrix(&local, 0, 0); if(! (add && sub)) { merror(0, "SubtractMatrix: One of the operands is a null pointer"); - return; + return local; } //Check to make sure the matrices are of the same dimension. rows = NumberOfRows(*add); @@ -111,43 +124,23 @@ if (rows != NumberOfRows(*sub) || cols != NumberOfColumns(*sub)) { merror(0, "SubtractMatrix: The operands do not have the same dimensions"); - return; + return local; } //Arrange the destination matrix. - if (! dst) + if (! CheckDestination(&dst, rows, cols, &local)) { - //If dst is a null pointer, allocate a new matrix of the default type. - AllocateMatrix(&destinationMatrix, rows, cols); - destination = &destinationMatrix; + merror(0, "SubtractMatrix: The destination matrix has the wrong dimensions"); + return local; } - else if ((int) dst < 4) - { - /*If dst is between 1 and 3, treat it as the type number of a new matrix of - a specific type to hold the destination.*/ - AllocateMatrixType((int) dst, &destinationMatrix, rows, cols); - destination = &destinationMatrix; - } - else - { - /*Otherwise assume dst is a valid pointer to a pre-allocated matrix. Make - sure the dimensions are right.*/ - //Make sure the destination matrix has the right dimensions. - if (rows != NumberOfRows(*dst) || cols != NumberOfColumns(*dst)) - { - merror(0, "SubtractMatrix: The destination matrix has the wrong dimensions"); - return destinationMatrix; - } - destination = dst; - } //Subtract the matrices for (i = 0; i < rows; i++) { for (j = 0; j < cols; j++) { - SetMatrixEl(destination, i, j, GetMatrixEl(add, i, j) - GetMatrixEl(sub, i, j)); + SetMatrixEl(dst, i, j, GetMatrixEl(add, i, j) - GetMatrixEl(sub, i, j)); } } - return *destination; + return *dst; } /*MultiplyMatrix does a matrix multiplication of the matrices pointed to by @@ -157,12 +150,10 @@ int i, j, k, rows, cols, inner, currentsum; /*This will hold an empty matrix for error return or be allocated to be the destination matrix.*/ - matrix destinationMatrix; - //This will point to the final destination matrix. - matrix *destination; + matrix local; //Zero the destination matrix to use as an error return value. - AllocateMatrix(&destinationMatrix, 0, 0); + AllocateMatrix(&local, 0, 0); //Check to make sure none of the operands are null. if(! (left && right)) @@ -183,35 +174,15 @@ if (inner != NumberOfRows(*right)) { merror(0, "MultiplyMatrix: The matrices do not have matching inner dimensions"); - return; + return local; } //Arrange the destination matrix. - if (! dst) + if (! CheckDestination(&dst, rows, cols, &local)) { - //If dst is a null pointer, allocate a new matrix of the default type. - AllocateMatrix(&destinationMatrix, rows, cols); - destination = &destinationMatrix; + merror(0, "MultiplyMatrix: The destination matrix has the wrong dimensions"); + return local; } - else if ((int) dst < 4) - { - /*If dst is between 1 and 3, treat it as the type number of a new matrix of - a specific type to hold the destination.*/ - AllocateMatrixType((int) dst, &destinationMatrix, rows, cols); - destination = &destinationMatrix; - } - else - { - /*Otherwise assume dst is a valid pointer to a pre-allocated matrix. Make - sure the dimensions are right. Make sure the destination matrix has the - right dimensions.*/ - if (rows != NumberOfRows(*dst) || cols != NumberOfColumns(*dst)) - { - merror(0, "MultiplyMatrix: The destination matrix has the wrong dimensions"); - return destinationMatrix; - } - destination = dst; - } /*Now, take the matrix product. Each element of the destination is the sum of corresponding elements of *left by row and *right by column.*/ @@ -224,15 +195,20 @@ { currentsum += (GetMatrixEl(left, i, k) * GetMatrixEl(right, k, j)); } - SetMatrixEl(destination, i, j, currentsum); + SetMatrixEl(dst, i, j, currentsum); } } - return *destination; + return *dst; } void ShowMatrix(const matrix* m, const char* title) { int i, j; + if (! m) + { + printf ("Matrix $s (null pointer).\n", title); + return; + } printf("Matrix %s (%d x %d of type %d):\n", title, NumberOfRows(*m), NumberOfColumns(*m), m->type); for (i = 0; i < NumberOfRows(*m); i++) { @@ -244,98 +220,6 @@ } } -matrix InsertRows(matrix* outer, matrix* inner, int start, matrix* dst) -{ - 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(! (outer && inner)) - { - 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; - } - - /*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, "InsertRows/Columns: The index of the first inserted row/column is out of range"); - return destinationMatrix; - } - - /*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, 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, NumberOfRows(*inner) + NumberOfRows(*outer), NumberOfColumns(*inner)); - destination = &destinationMatrix; - } - else - { - /*Assume dst is a valid address. Check to make sure it has the right - dimensions.*/ - destination = dst; - if (! (NumberOfRows(*inner) + NumberOfRows(*outer) == NumberOfRows(*dst) && NumberOfColumns(*inner) == NumberOfColumns(*dst))) - { - merror(0, "InsertRows/Columns: The destination matrix does not have the proper dimensions."); - return destinationMatrix; - } - } - - /*Copy the beforehand part of the outer matrix.*/ - if (start) - { - CopyBlock(start, NumberOfColumns(*outer), outer, 0, 0, destination, 0, 0); - } - - /*Copy the inner matrix.*/ - CopyBlock(NumberOfRows(*inner), NumberOfColumns(*inner), inner, 0, 0, destination, start, 0); - - /*Copy the final part of the outer matrix.*/ - if (NumberOfRows(*outer) - start) - { - CopyBlock(NumberOfRows(*outer) - start, NumberOfColumns(*outer), outer, start, 0, destination, start + NumberOfRows(*inner), 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, the pointer to the corresponding matrix is interpreted as a pointer to an array @@ -410,309 +294,3 @@ } return 1; } - -/*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.*/ -static void AddRowsFast(matrix* m, int start, int rowsToAdd) -{ - int i; - mtype** NewAr; - m->nr += rowsToAdd; - NewAr = tcalloc(m->nr, sizeof(mtype*)); - for (i = 0; i < m->nr; i++) - { - /*If we have not yet reached the insertion point, copy addresses directly.*/ - if (i < start) - { - NewAr[i] = m->ar[i]; - } - /*At the insertion point, allocate space for a new row.*/ - else if (i < start + rowsToAdd) - { - NewAr[i] = tcalloc(m->nc, sizeof(mtype)); - } - /*After the insertion point, each new array element should get the value - of the previous element in the original array.*/ - else - { - NewAr[i] = m->ar[i - rowsToAdd]; - } - } - /*Free and reassign memory.*/ - free(m->ar); - m->ar = NewAr; -} - -/*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) -{ - int i; - matrix NewM; - - /*Preserve the transpose state of the matrix.*/ - if (m->trans) - { - AllocateMatrixType(m->type, &NewM, NumberOfColumns(*m), NumberOfRows(*m) + rowsToAdd); - TransposeMatrix(&NewM); - } - else - { - AllocateMatrixType(m->type, &NewM, NumberOfRows(*m) + rowsToAdd, NumberOfColumns(*m)); - } - - for (i = 0; i < NumberOfRows(NewM); i++) - { - if (i < start) - { - CopyBlock(1, NumberOfColumns(NewM), m, i, 0, &NewM, i, 0); - } - else if (i >= start + rowsToAdd) - { - CopyBlock(1, NumberOfColumns(NewM), m, i - rowsToAdd, 0, &NewM, i, 0); - } - } - DeallocateMatrix(m); - (*m) = NewM; -} - -/*This function is called by RemoveRow and RemoveCol when they detect that the -matrix is properly formatted for an optimized row/column removal. It assumes -that basic parameter checking has been done by AddRow and AddCol. It is a -private function internal to this file.*/ -static void RemoveRowsFast(matrix* m, int start, int rowsToAdd) -{ - int i; - mtype** NewAr; - NewAr = tcalloc(m->nr, sizeof(mtype*)); - for (i = 0; i < m->nr; i++) - { - if (i < start) - { - NewAr[i] = m->ar[i]; - } - else if (i < start + rowsToAdd) - { - free(m->ar[i]); - } - else - { - NewAr[i - rowsToAdd] = m->ar[i]; - } - } - free(m->ar); - m->ar = NewAr; - m->nr -= rowsToAdd; -} - -/*This function is called by RemoveRows and RemoveColumns when they detect that -a matrix is not properly formatted for fast row removal. It is a private -function internal to this file.*/ -static int RemoveRowsSlow(matrix *m, int start, int rowsToRemove) -{ - int i; - matrix NewM; - /*Preserve the transpose state of the matrix.*/ - if (m->trans) - { - AllocateMatrixType(m->type, &NewM, NumberOfColumns(*m), NumberOfRows(*m) - rowsToRemove); - TransposeMatrix(&NewM); - } - else - { - AllocateMatrixType(m->type, &NewM, NumberOfRows(*m) - rowsToRemove, NumberOfColumns(*m)); - } - for (i = 0; i < NumberOfRows(NewM); i++) - { - if (i < start) - { - CopyBlock(1, NumberOfColumns(NewM), m, i, 0, &NewM, i, 0); - } - else - { - CopyBlock(1, NumberOfColumns(NewM), m, i + rowsToRemove, 0, &NewM, i, 0); - } - } - DeallocateMatrix(m); - *m = NewM; -} - -int InsertNewRows(matrix* m, int start, int rowsToAdd) -{ - int i; - matrix NewM; - if (! m) - { - merror(0, "InsertNewRows/COLUMNS: Null matrix pointer"); - return 0; - } - /*Make sure the starting point is valid. Start will be the index of the first - of the new rows added. If index < 0, default to adding at the end of the - matrix.*/ - if (start < 0) start = NumberOfRows(*m); - if (start > NumberOfRows(*m)) - { - 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, "InsertNewRows/COLUMNS: Rows/Columns to add is negative or zero"); - return 0; - } - - if (m->type == 2 && (! m->trans)) - { - /*If matrix is an untransposed type 2, the row add can be heavily - optimized.*/ - AddRowsFast(m, start, rowsToAdd); - } - else - { - AddRowsSlow(m, start, rowsToAdd); - return 1; - } -} - -int InsertNewColumns(matrix* m, int start, int colsToAdd) -{ - 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) -{ - /*Matrix pointer cannot be null.*/ - if (! m) - { - 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/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/COLUMNS: Number of rows/columns to remove is out of range"); - return 0; - } - /*See if we can optimize the removal.*/ - if (m->type == 2 && ! m->trans) - { - RemoveRowsFast(m, start, rowsToRemove); - } - else - { - RemoveRowsSlow(m, start, rowsToRemove); - } - return 1; -} - -int RemoveColumns(matrix* m, int start, int colsToRemove) -{ - 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++) - { - 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; - } - /*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, "MERGEROWS/COLUMNS: Start index is out of range"); - return 0; - } - /*The matrices must have the same number of columns.*/ - if (NumberOfColumns(*outer) != NumberOfColumns(*inner)) - { - merror(0, "MERGEROWS/COLUMNS: The outer and inner matrices do not have the same number of columns"); - return 0; - } - /*Attempt to optimize.*/ - if (outer->type == 2 && inner->type == 2 && ! (outer->trans || inner->trans)) - { - MergeRowsFast(outer, inner, start); - } - else - { - /*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-13 18:01:14 UTC (rev 195) +++ spnbox/matrixmath.h 2009-07-14 15:31:42 UTC (rev 196) @@ -42,25 +42,6 @@ /*ShowMatrix is a debugging function that dumps the contents of a matrix to the screen in a human-readable format.*/ -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 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); /*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, @@ -72,70 +53,6 @@ /*MatrixEqualMatrix tests the equality of matrices A and B. It returns nonzero if the matrices are equal and zero if they are different.*/ -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, 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, 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 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. -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.*/ - -int RemoveRows(matrix* m, int start, int rowsToRemove); -/*RemoveRows removes one or more contiguous rows from the given matrix. -start The index of the first row to remove. If it is out of range the - function will fail with an error message. -rowsToRemove The number of rows to remove. If the number is less than 1 or - large enough that it would attempt to remove nonexistant rows, - 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 approximately a -factor corresponding to the number of columns in the matrix.*/ - -int RemoveColumns(matrix* m, int start, int colsToRemove); -/*RemoveColumns removes one or more contiguous columns from the given matrix. -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 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-13 18:01:14 UTC (rev 195) +++ spnbox/supervis.c 2009-07-14 15:31:42 UTC (rev 196) @@ -1,6 +1,7 @@ #include "spnbox.h" #include "../pnheaders/matrix.h" #include "matrixmath.h" +#include "extendedmatrix.h" supervis_r supervis(matrix* PlantIn, matrix* PlantOut, matrix* L) { @@ -91,11 +92,11 @@ /*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); + toReturn.Dfm = InsertRows(PlantOut, &supervisorDm, -1, 2); /*Concatenate the columns of the input matrices. The result should be stored in a type-2 matrix.*/ - toReturn.Dfp = InsertRows(PlantIn, &supervisorDp, -1, (matrix*) 2); + toReturn.Dfp = InsertRows(PlantIn, &supervisorDp, -1, 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-13 18:01:14 UTC (rev 195) +++ spnbox/tests/Makefile 2009-07-14 15:31:42 UTC (rev 196) @@ -10,13 +10,14 @@ COMMON=StructuredIO.o test.o MemoryManager.o general.o pns.o matrix.o matrixmath.o deallocation.o #These symbols define the dependencies of various test executables. +EXTENDEDMATRIX=extendedmatrix.o IPSLV=ipslv.o ../liblpsolve55.a IPSOLVE=ipsolve.o $(IPSLV) ISADM=isadm.o ISSIPH=issiph.o MSPLIT=msplit.o PN2ACPN=pn2acpn.o -SUPERVIS=supervis.o +SUPERVIS=supervis.o $(EXTENDEDMATRIX.O) ACTN=actn.o $(NLTRANS) ILPADM=ilpadm.o $(IPSOLVE) LINENF=linenf.o $(ILPADM) @@ -29,7 +30,9 @@ COMMONHEADER=../spnbox.h test.h ../../pnheaders/pns.h ../../pnheaders/matrix.h ../matrixmath.h ../MemoryManager.h StructuredIO.h #Targets -all: ipslv ipsolve isadm issiph msplit pn2acpn supervis actn ilpadm linenf nltrans pn2eacpn reduce tactn +all: extendedmatrix ipslv ipsolve isadm issiph msplit matrixmath pn2acpn supervis actn ilpadm linenf nltrans pn2eacpn reduce tactn +extendedmatrix: test-extendedmatrix.o $(EXTENDEDMATRIX) $(COMMON) + $(COMPILER) -o extendedmatrix.exe test-extendedmatrix.o $(EXTENDEDMATRIX) $(COMMON) ipslv: test-ipslv.o $(IPSLV) $(COMPILER) -o ipslv.exe test-ipslv.o $(IPSLV) ipsolve: test-ipsolve.o $(COMMON) $(IPSOLVE) @@ -44,8 +47,8 @@ $(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) - $(COMPILER) -o supervis.exe test-supervis.o $(COMMON) $(SUPERVIS) +supervis: test-supervis.o $(COMMON) $(EXTENDEDMATRIX) $(SUPERVIS) + $(COMPILER) -o supervis.exe test-supervis.o $(COMMON) $(EXTENDEDMATRIX) $(SUPERVIS) actn: test-actn.o $(COMMON) $(ACTN) $(COMPILER) -o actn.exe test-actn.o $(COMMON) $(ACTN) ilpadm: test-ilpadm.o $(COMMON) $(ILPADM) @@ -72,6 +75,8 @@ $(COMPILER) -c ../chkcons.c deallocation.o: ../deallocation.c ../spnbox.h $(COMPILER) -c ../deallocation.c +extendedmatrix.o: ../extendedmatrix.c ../extendedmatrix.h ../../pnheaders/matrix.h ../../pnheaders/general.h + $(COMPILER) -c ../extendedmatrix.c general.o: ../../pnheaders/general.c ../../pnheaders/general.h $(COMPILER) -c ../../pnheaders/general.c ilpadm.o: ../spnbox.h ../matrixmath.h ../../pnheaders/general.h ../../pnheaders/matrix.h ../MemoryManager.h ../ilpadm.c @@ -104,7 +109,7 @@ $(COMPILER) -c ../../pnheaders/pns.c reduce.o: ../spnbox.h ../../pnheaders/matrix.h ../reduce.c $(COMPILER) -c ../reduce.c -supervis.o: ../spnbox.h ../matrixmath.h ../../pnheaders/general.h ../../pnheaders/ ../../pnheaders/matrix.h ../supervis.c +supervis.o: ../spnbox.h ../matrixmath.h ../../pnheaders/general.h ../../pnheaders/ ../../pnheaders/matrix.h ../supervis.c ../extendedmatrix.h $(COMPILER) -c ../supervis.c StructuredIO.o: ../MemoryManager.h ../../pnheaders/matrix.h StructuredIO.h StructuredIO.c $(COMPILER) -c StructuredIO.c @@ -116,6 +121,8 @@ #Rules for making the test executable object files. test-actn.o: test-actn.c $(COMMONHEADER) $(COMPILER) -c test-actn.c +test-extendedmatrix.o: test-extendedmatrix.c $(COMMONHEADER) + $(COMPILER) -c test-extendedmatrix.c test-ilpadm.o: test-ilpadm.c $(COMMONHEADER) $(COMPILER) -c test-ilpadm.c test-ipslv.o: test-ipslv.c Added: spnbox/tests/test-extendedmatrix.c =================================================================== --- spnbox/tests/test-extendedmatrix.c (rev 0) +++ spnbox/tests/test-extendedmatrix.c 2009-07-14 15:31:42 UTC (rev 196) @@ -0,0 +1,494 @@ +#include <time.h> +#include "test.h" +#include "../extendedmatrix.h" + +#define FF_OPTIMIZATION 0 +#define FF_OPERATION 1 +#define FF_MODE 2 +#define FF_A 3 +#define FF_B 4 +#define FF_ROW 5 +#define FF_COL 6 +#define FF_ROWS 7 +#define FF_COLS 8 +#define FF_REPS 9 +#define FF_SIZE 10 +#define FF_SPEEDTEST 11 + +static void SInsertR(int Size, int Reps, int Row, int Rows, int Optimized); +static void SInsertC(int Size, int Reps, int Col, int Cols, int Optimized); +static void TInsertR(matrix *A, matrix *B, int Row, int Mode, int Optimized); +static void TInsertC(matrix *A, matrix *B, int Col, int Mode, int Optimized); +static void SRemoveR(int Size, int Reps, int Row, int Rows, int Optimized); +static void SRemoveC(int Size, int Reps, int Col, int Cols, int Optimized); +static void TRemoveR(matrix *A, int Row, int Rows, int Mode, int Optimized); +static void TRemoveC(matrix *A, int Col, int Cols, int Mode, int Optimized); +static void SInsertNullR(int Size, int Reps, int Row, int Rows, int Optimized); +static void SInsertNullC(int Size, int Reps, int Col, int Cols, int Optimized); +static void TInsertNullR(matrix *A, int Row, int Rows, int Mode, int Optimized); +static void TInsertNullC(matrix *A, int Col, int Cols, int Mode, int Optimized); + +static void PrintPercent(int num, int denom); +static matrix* AllocateMatrices(int rows, int cols, int Reps, int Transpose); +static void DeallocateMatrices(int reps, matrix *m); +void SetDefaults(char* optimization, char* Operation, int *Mode, matrix *A, matrix *B, int *Row, int *Column, int* Rows, int *Columns, int *Reps, int *Size, char *speedtest); + +int main(int argc, char* argv[]) +{ + FILE* input; + + if (! (input = GetInput(argc, argv))) + { + return 1; + } + + char Desc[] = "string optimization, string operation, int mode, matrix A, matrix B, int row, int column, int rows, int columns, int repetitions, int size, string speedtest"; + char Operation[128], optimization[128], speedtest[128]; + matrix A, B; + int *Filled; + int Mode, Row, Column, Rows, Columns, Reps, Size, Optimized, SpeedTest; + MemoryManager mem; + + mem = CreateMemoryManager(5, 2, 0, 0); + SetDefaults(optimization, Operation, &Mode, &A, &B, &Row, &Column, &Rows, &Columns, &Reps, &Size, speedtest); + while (ParseStructure(input, Desc, &Filled, &mem, optimization, Operation, &Mode, &A, &B, &Row, &Column, &Rows, &Columns, &Reps, &Size)) + { + Optimized = ! strcmp(optimization, "yes"); + if (Optimized) Mode = -1; + SpeedTest = ! strcmp(speedtest, "yes"); + if (! Filled[FF_OPERATION]) + { + printf("Warning: No operation code specified. Skipping problem.\n"); + } + else if (! strcmp(Operation, "InsertRows")) + { + if (SpeedTest) + { + SInsertR(Size, Reps, Row, Rows, Optimized); + } + else + { + TInsertR(&A, &B, Row, Mode, Optimized); + } + } + else if (! strcmp(Operation, "InsertColumns")) + { + if (SpeedTest) + { + SInsertC(Size, Reps, Column, Columns, Optimized); + } + else + { + TInsertC(&A, &B, Column, Mode, Optimized); + } + } + else if (! strcmp(Operation, "InsertNullRows")) + { + if (SpeedTest) + { + SInsertNullR(Size, Reps, Row, Rows, Optimized); + } + else + { + TInsertNullR(&A, Row, Rows, Mode, Optimized); + } + } + else if (! strcmp(Operation, "InsertNullColumns")) + { + if (SpeedTest) + { + SInsertNullC(Size, Reps, Column, Columns, Optimized); + } + else + { + TInsertNullC(&A, Column, Columns, Mode, Optimized); + } + } + else if (! strcmp(Operation, "RemoveRows")) + { + if (SpeedTest) + { + SRemoveR(Size, Reps, Row, Rows, Optimized); + } + else + { + TRemoveR(&A, Row, Rows, Mode, Optimized); + } + } + else if (! strcmp(Operation, "RemoveColumns")) + { + if (SpeedTest) + { + SRemoveC(Size, Reps, Column, Columns, Optimized); + } + else + { + TRemoveC(&A, Column, Columns, Mode, Optimized); + } + } + else + { + printf("Warning: Unrecognized operation '%s'.\n", Operation); + } + printf("-------------------------------------------------------------------------------\n"); + FreeMemory(&mem); + mem = CreateMemoryManager(10, 2, 0, 0); + SetDefaults(optimization, Operation, &Mode, &A, &B, &Row, &Column, &Rows, &Columns, &Reps, &Size, speedtest); + } + FreeMemory(&mem); + return 0; +} + +void SInsertR(int Size, int Reps, int Row, int Rows, int Optimized) +{ + printf("Speed-testing row insertion (%s).\n", Optimized ? "optimized" : "unoptimized"); + printf("Inserting %d rows into a square matrix of size %d, %d times...\n", Rows, Size, Reps); + + matrix *outer = AllocateMatrices(Size, Size, Reps, ! Optimized); + matrix *inner = AllocateMatrices(Rows, Size, Reps, ! Optimized); + ShowMatrix(outer, "Sample Matrix Before"); + clock_t t0 = clock(); + int i; + for (i = 0; i < Reps; i++) + { + InsertRows(outer + i, inner + i, Row, -1); + } + double time = ((double) (clock() - t0)) / ((double) CLOCKS_PER_SEC); + ShowMatrix(outer, "Sample Matrix After"); + printf("Time: %.2f ms", time / 1000.0); + DeallocateMatrices(Reps, outer); +} + +void SInsertC(int Size, int Reps, int Col, int Cols, int Optimized) +{ + printf("Speed-testing column insertion (%s).\n", Optimized ? "optimized" : "unoptimized"); + printf("Inserting %d columns into a square matrix of size %d, %d times...\n", Cols, Size, Reps); + + matrix *outer = AllocateMatrices(Size, Size, Reps, Optimized); + matrix *inner = AllocateMatrices(Size, Cols, Reps, Optimized); + ShowMatrix(outer, "Sample Matrix Before"); + clock_t t0 = clock(); + int i; + for (i = 0; i < Reps; i++) + { + InsertColumns(outer + i, inner + i, Col, -1); + } + double time = ((double) (clock() - t0)) / ((double) CLOCKS_PER_SEC); + ShowMatrix(outer, "Sample Matrix After"); + printf("Time: %.2f ms", time / 1000.0); + DeallocateMatrices(Reps, outer); +} + +void TInsertR(matrix *A, matrix *B, int Row, int Mode, int Optimized) +{ + printf("Testing row insertion: B -> A at row %d...\n", Row); + printf("Mode: %d. Optimization: %s.\n", Mode, Optimized ? "Yes" : "No"); + matrix A1, B1; + if (Optimized) + { + AllocateMatrixType(2, &A1, NumberOfRows(*A), NumberOfColumns(*A)); + CopyMatrix(A, &A1); + AllocateMatrixType(2, &B1, NumberOfRows(*B), NumberOfColumns(*B)); + CopyMatrix(B, &B1); + } + else + { + AllocateMatrixType(2, &A1, NumberOfColumns(*A), NumberOfRows(*A)); + TransposeMatrix(&A1); + CopyMatrix(A, &A1); + AllocateMatrixType(2, &B1, NumberOfColumns(*B), NumberOfRows(*B)); + TransposeMatrix(&B1); + CopyMatrix(B, &B1); + } + + ShowMatrix(&A1, "A"); + ShowMatrix(&B1, "B"); + matrix result; + result = InsertRows(&A1, &B1, Row, Mode); + ShowMatrix(Mode < 0 ? &A1 : &result, "result"); + + DeallocateMatrix(&A1); + if (B1.type) DeallocateMatrix(&B1); + if (Mode >= 0) DeallocateMatrix(&result); +} + +void TInsertC(matrix *A, matrix *B, int Col, int Mode, int Optimized) +{ + printf("Testing column insertion: B -> A at column %d...\n", Col); + printf("Mode: %d. Optimization: %s.\n", Mode, Optimized ? "Yes" : "No"); + matrix A1, B1; + if (! Optimized) + { + AllocateMatrixType(2, &A1, NumberOfRows(*A), NumberOfColumns(*A)); + CopyMatrix(A, &A1); + AllocateMatrixType(2, &B1, NumberOfRows(*B), NumberOfColumns(*B)); + CopyMatrix(B, &B1); + } + else + { + AllocateMatrixType(2, &A1, NumberOfColumns(*A), NumberOfRows(*A)); + TransposeMatrix(&A1); + CopyMatrix(A, &A1); + AllocateMatrixType(2, &B1, NumberOfColumns(*B), NumberOfRows(*B)); + TransposeMatrix(&B1); + CopyMatrix(B, &B1); + } + + ShowMatrix(&A1, "A"); + ShowMatrix(&B1, "B"); + matrix result; + result = InsertColumns(&A1, &B1, Col, Mode); + ShowMatrix(Mode < 0 ? &A1 : &result, "result"); + + DeallocateMatrix(&A1); + if (B1.type) DeallocateMatrix(&B1); + if (Mode >= 0) DeallocateMatrix(&result); +} + +void SRemoveR(int Size, int Reps, int Row, int Rows, int Optimized) +{ + printf("Speed-testing row removal (%s).\n", Optimized ? "optimized" : "unoptimized"); + printf("Removing %d rows from a square matrix of size %d, %d times...\n", Rows, Size, Reps); + + matrix *m = AllocateMatrices(Size, Size, Reps, ! Optimized); + + ShowMatrix(m, "Sample Matrix Before"); + clock_t t0 = clock(); + int i; + for (i = 0; i < Reps; i++) + { + RemoveRows(m + i, Row, Rows, -1); + } + double time = ((double) (clock() - t0)) / ((double) CLOCKS_PER_SEC); + ShowMatrix(m, "Sample Matrix After"); + printf("Time: %.2f ms", time / 1000.0); + DeallocateMatrices(Reps, m); +} + +void SRemoveC(int Size, int Reps, int Col, int Cols, int Optimized) +{ + printf("Speed-testing column removal (%s).\n", Optimized ? "optimized" : "unoptimized"); + printf("Removing %d columns from a square matrix of size %d, %d times...\n", Cols, Size, Reps); + + matrix *m = AllocateMatrices(Size, Size, Reps, Optimized); + + ShowMatrix(m, "Sample Matrix Before"); + clock_t t0 = clock(); + int i; + for (i = 0; i < Reps; i++) + { + RemoveColumns(m + i, Col, Cols, -1); + } + double time = ((double) (clock() - t0)) / ((double) CLOCKS_PER_SEC); + ShowMatrix(m, "Sample Matrix After"); + printf("Time: %.2f ms", time / 1000.0); + DeallocateMatrices(Reps, m); +} + +void TRemoveR(matrix *A, int Row, int Rows, int Mode, int Optimized) +{ + printf("Testing row removal: %d rows from A at row %d.\n", Rows, Row); + printf("Mode: %d. Optimization: %s.\n", Mode, Optimized ? "Yes" : "No"); + matrix A1; + if (Optimized) + { + AllocateMatrixType(2, &A1, NumberOfRows(*A), NumberOfColumns(*A)); + CopyMatrix(A, &A1); + } + else + { + AllocateMatrixType(2, &A1, NumberOfColumns(*A), NumberOfRows(*A)); + TransposeMatrix(&A1); + CopyMatrix(A, &A1); + } + + ShowMatrix(&A1, "A Before"); + matrix result; + result = RemoveRows(&A1, Row, Rows, Mode); + ShowMatrix(Mode < 0 ? &A1 : &result, "A After"); + + DeallocateMatrix(&A1); + if (Mode >= 0) DeallocateMatrix(&result); +} + +void TRemoveC(matrix *A, int Col, int Cols, int Mode, int Optimized) +{ + printf("Testing column removal: %d columns from A at column %d.\n", Cols, Col); + printf("Mode: %d. Optimization: %s.\n", Mode, Optimized ? "Yes" : "No");... [truncated message content] |