SPNBOX Support Files

Deallocation Functions (deallocation.c)

deallocation.c implements a series of functions the purpose of which is to deallocate the various structures returned by the SPNBOX functions. It has been made as safe as possible - that is, it checks before attempting to free arrays to ensure that the array pointers are not null and before attempting to deallocate matrices to make sure that they have been allocated. This last check is implemented by examing the matrix type - a nonzero type is taken to be an indicator of a valid matrix. Thus, result structures should always be zeroed after they are created so that, if the structure should be passed to a deallocation function before it is filled by an SPNBOX function, the deallocation function will not attempt free some random piece of memory.

Extended Matrix Manipulation (extendedmatrix.c)

The extended matrix manipulation functions provide functionality above and beyond that of mere matrix arithmatic. The general parameter format is to take pointers to the operand matrices followed by any row and column numbers, possibly followed by an integer describing the mode. Most of the functions are such that their return value is a single matrix. The mode integer changes the behavior of the functions. Modes between 1 and 3 request that the returned matrix be a newly-allocated matrix of the given type and that the operands be left unaltered. A mode of 0 requests that the returned matrix be a newly-allocated matrix of the default type assigned by AllocateMatrix and the operands be left unaltered. A negative mode requests that the operand matrix (or the primary operand if there are several) be altered by the function and returned.

Some of the functions, when in a negative mode, attempt to employ an optimization based on the internal nature of the matrix type. When the operation involves the addition, movement, or deletion of rows or columns, a type-2 matrix is of particular interest. The type-2 matrix stores its data as an array of arrays, that is, a pointer to an array of pointers, each of which is a pointer to an array of matrix elements. For an untransposed matrix (trans = 0), the sub-arrays are rows. For a transposed matrix (trans = 1) the sub-arrays are columns. Thus, if the operation in question deals with rows and the operand matrix or matrices are type-2 untransposed, the pointers to arrays can be manipulated rather than having to copy or reallocate areas of memory. Simililarly, if the operation deals with columns and the matrices are type-2 transposed, the pointers to arrays can be manipulated rather than having to reallocate or copy areas of memory. Note that these attempts at optimization are carried out internally and should be totally transparent to the calling function except where speed is concerned.

For specific function descriptions see the header file, extendedmatrix.h.

LP Solve Library (liblpsolve55.a)

This is a third-party mixed integer linear programming solver used by SPNBOX. The SPNBOX functions all interface to it via ipsolve.c, which itself interfaces to the MILP library via ipslv.c. This library file is the result of the linux-targeted makefile in the third-party/lp_solve_5.5 directory. The makefile is called by the SPNBOX makefile, which then copies the final library file liblpsolve55.a from its default location in the directory /third-party/lp_solve_5.5/lpsolve55/ to the /spnbox directory.

Matrix Arithmetic (matrixmath.c)

The matrix arithmetic functions, as well as a few utility functions such as transposition and a friendly display function, are contained in the matrixmath.h and .c files. The general format of these functions is to take as parameters pointers to the operand matrices, any integer operands, and finally a pointer to a matrix in which the result will be stored. The result is assumed to have already been allocated. The result matrix will typically also be returned by the arithmetic function. However, if the pointer to the destination matrix is replaced by an integer between 0 and 3, a new matrix of the correct size will be allocated, filled with the result, and returned. If the integer is set to 0 the default allocation type will be used. Otherwise the specified type will be used.

Dynamic Memory Management (memorymanager.c)

The memory management files define two structures as aids in memory management and the functions to work with them. MemoryManager.h maintains a self-growing list of memory allocations and matrix allocations so that all the memory can be freed at once. Its accompanying functions are wrappers for the allocation functions, mcalloc and MAllocateMatrixType, which take as their first argument a pointer to a MemoryManager struct. They will allocate the new memory or matrix as requested and add a pointer to it to the appropriate lists. MemoryManagers hold separate lists, one for matrices and one for ordinary memory. The other functions are ManageMatrix and ManageMemory, which add to the lists matrices or pieces of memory that were not created through the wrapper functions but should be deallocated with the rest of the memory in the manager's lists. FreeMemory takes a pointer to a memory manager and will free all the memory and all the matrices. Note that, internally, it frees matrices first and then normal memory. MemoryManager keeps its lists in dynamically-allocated memory, which is reallocated in blocks and not reallocated again until the next entire block has been filled. The block size for the memory and matrix lists can be set separately via the function that creates Memory Managers, but if the relevant parameters are less than some minimum it will raise them to the minimum, which is blocks of 5.

The other structure provided by MemoryManager.h is a MemoryGrower. This keeps track of a fixed number of pieces of memory, the number determined during creation by a parameter passed to CreateMemoryGrower. It allows these pieces of memory to be increased in size efficiently by allocating them in multiples of some block size, also determined during creation, and not actually reallocating until some amount of memory greater than the current actual capacity is requested. It does this by wrapping the allocation functions with its own, growMalloc and growCalloc, that take one additional parameter, a pointer to the MemoryGrower structure. They are used like variants of realloc, in that if the memory had been previously allocated they ensure that the previous contents remain. Note that MemoryGrower keeps track of capacity based on the value of the pointer associated with the memory. Thus an external change to this pointer value will cause a fatal error when MemoryGrower is unable to locate the new pointer in its record of managed pointers.