#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.*/

void SwapRows(matrix* a, matrix* b, int rowA, int rowB);
/*SwapRows exchanges the contents of the rowA'th row of A with the rowB'th row of
B. If both matrices are type-2 untransposed, the function employs an optimization
that reduces computational complexity by a factor equal to the number of columns
in the matrices.
a and b can point to the same matrix.*/

void SwapColumns(matrix *a, matrix* b, int colA, int colB);
/*SwapColumns exchanges the contents of the colA'th column of A with the colB'th
column of B. If both matrices are type-2 transposed, the function employs an
optimization that reduces computational complexity by a factor equal to the
number of rows in the matrices.
a and b can point to the same matrix.*/

void OptimizeRows(matrix *m);
/*OptimizeRows modifies the matrix passed to it so that its use with the row-
manipulation functions will be optimized for speed.*/

void OptimizeColumns(matrix *m);
/*OptimizeColumns modifies the matrix passed to it so that its use with the 
column-manipulation functions will be optimized for speed.*/
#endif
