Index: trunk/psLib/src/dataIO/psLookupTable.c
===================================================================
--- trunk/psLib/src/dataIO/psLookupTable.c	(revision 4031)
+++ trunk/psLib/src/dataIO/psLookupTable.c	(revision 4050)
@@ -7,8 +7,8 @@
 *  @author Ross Harman, MHPCC
 *
-*  @version $Revision: 1.14 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2005-05-25 22:46:47 $
+*  @version $Revision: 1.15 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2005-05-31 21:46:56 $
 *
-*  Copyright 2004-5 Maui High Performance Computing Center, University of Hawaii
+*  Copyright 2004-2005 Maui High Performance Computing Center, Univ. of Hawaii
 */
 #include <stdio.h>
@@ -64,11 +64,5 @@
 static char *cleanString(char *inString, int sLen);
 static char* getToken(char **inString, char *delimiter, psParseErrorType *status);
-static psU8 parseU8(char *inString, psParseErrorType *status);
-static psS8 parseS8(char *inString, psParseErrorType *status);
-static psU16 parseU16(char *inString, psParseErrorType *status);
-static psS16 parseS16(char *inString, psParseErrorType *status);
-static psU32 parseU32(char *inString, psParseErrorType *status);
 static psS32 parseS32(char *inString, psParseErrorType *status);
-static psU64 parseU64(char *inString, psParseErrorType *status);
 static psS64 parseS64(char *inString, psParseErrorType *status);
 static psF32 parseF32(char *inString, psParseErrorType *status);
@@ -87,5 +81,4 @@
         inString++;
     }
-
     return true;
 }
@@ -100,13 +93,12 @@
     char *cleaned = NULL;
 
-
     ptrB = inString;
 
-    /* Skip over leading # or whitespace */
+    // Skip over leading # or whitespace
     while (isspace(*ptrB) || *ptrB=='#') {
         ptrB++;
     }
 
-    /* Skip over trailing whitespace, null terminators, and # characters */
+    // Skip over trailing whitespace, null terminators, and # characters
     ptrE = inString + sLen;
     while(isspace(*ptrE) || *ptrE=='\0' || *ptrE=='#') {
@@ -130,5 +122,4 @@
     char *cleanToken = NULL;
     int sLen = 0;
-
 
     // Skip over leading whitespace
@@ -151,89 +142,4 @@
 
     return cleanToken;
-}
-
-/** Returns single parsed value as a psU8. The input string must be cleaned and null terminated. */
-static psU8 parseU8(char *inString, psParseErrorType *status)
-{
-    char *end = NULL;
-    psU8 value = 0.0;
-
-
-    value = (psU8)strtoul(inString, &end, 0);
-    if(*end != '\0') {
-        *status = PS_PARSE_ERROR_VALUE;
-    } else if(inString==end) {
-        *status = PS_PARSE_ERROR_VALUE;
-    }
-
-    return value;
-}
-
-/** Returns single parsed value as a psS8. The input string must be cleaned and null terminated. */
-static psS8 parseS8(char *inString, psParseErrorType *status)
-{
-    char *end = NULL;
-    psS8 value = 0.0;
-
-
-    value = (psS8)strtol(inString, &end, 0);
-    if(*end != '\0') {
-        *status = PS_PARSE_ERROR_VALUE;
-    } else if(inString==end) {
-        *status = PS_PARSE_ERROR_VALUE;
-    }
-
-    return value;
-}
-
-/** Returns single parsed value as a psU16. The input string must be cleaned and null terminated. */
-static psU16 parseU16(char *inString, psParseErrorType *status)
-{
-    char *end = NULL;
-    psU16 value = 0.0;
-
-
-    value = (psU16)strtoul(inString, &end, 0);
-    if(*end != '\0') {
-        *status = PS_PARSE_ERROR_VALUE;
-    } else if(inString==end) {
-        *status = PS_PARSE_ERROR_VALUE;
-    }
-
-    return value;
-}
-
-/** Returns single parsed value as a psS16. The input string must be cleaned and null terminated. */
-static psS16 parseS16(char *inString, psParseErrorType *status)
-{
-    char *end = NULL;
-    psS16 value = 0.0;
-
-
-    value = (psS16)strtol(inString, &end, 0);
-    if(*end != '\0') {
-        *status = PS_PARSE_ERROR_VALUE;
-    } else if(inString==end) {
-        *status = PS_PARSE_ERROR_VALUE;
-    }
-
-    return value;
-}
-
-/** Returns single parsed value as a psU32. The input string must be cleaned and null terminated. */
-static psU32 parseU32(char *inString, psParseErrorType *status)
-{
-    char *end = NULL;
-    psU32 value = 0.0;
-
-
-    value = (psU32)strtoul(inString, &end, 0);
-    if(*end != '\0') {
-        *status = PS_PARSE_ERROR_VALUE;
-    } else if(inString==end) {
-        *status = PS_PARSE_ERROR_VALUE;
-    }
-
-    return value;
 }
 
@@ -255,21 +161,4 @@
 }
 
-/** Returns single parsed value as a psU64. The input string must be cleaned and null terminated. */
-static psU64 parseU64(char *inString, psParseErrorType *status)
-{
-    char *end = NULL;
-    psU64 value = 0.0;
-
-
-    value = (psU64)strtoull(inString, &end, 0);
-    if(*end != '\0') {
-        *status = PS_PARSE_ERROR_VALUE;
-    } else if(inString==end) {
-        *status = PS_PARSE_ERROR_VALUE;
-    }
-
-    return value;
-}
-
 /** Returns single parsed value as a psS64. The input string must be cleaned and null terminated. */
 static psS64 parseS64(char *inString, psParseErrorType *status)
@@ -277,5 +166,4 @@
     char *end = NULL;
     psS64 value = 0.0;
-
 
     value = (psS64)strtoll(inString, &end, 0);
@@ -295,5 +183,4 @@
     psF32 value = 0.0;
 
-
     value = (psF32)strtof(inString, &end);
     if(*end != '\0') {
@@ -312,5 +199,4 @@
     psF64 value = 0.0;
 
-
     value = (psF64)strtod(inString, &end);
     if(*end != '\0') {
@@ -338,24 +224,6 @@
 
     switch(type) {
-    case PS_TYPE_U8:
-        vec->data.U8[index] = parseU8(strValue, status);
-        break;
-    case PS_TYPE_S8:
-        vec->data.S8[index] = parseS8(strValue, status);
-        break;
-    case PS_TYPE_U16:
-        vec->data.U16[index] = parseU16(strValue, status);
-        break;
-    case PS_TYPE_S16:
-        vec->data.S16[index] = parseS16(strValue, status);
-        break;
-    case PS_TYPE_U32:
-        vec->data.U32[index] = parseU32(strValue, status);
-        break;
     case PS_TYPE_S32:
         vec->data.S32[index] = parseS32(strValue, status);
-        break;
-    case PS_TYPE_U64:
-        vec->data.U64[index] = parseU64(strValue, status);
         break;
     case PS_TYPE_S64:
@@ -375,23 +243,4 @@
 }
 
-static psParseErrorType printError(psU64 lineCount, char* badText, psParseErrorType status)
-{
-    switch(status) {
-    case PS_PARSE_ERROR_VALUE:
-        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_PARSE_VALUE, badText, lineCount);
-        break;
-    case PS_PARSE_ERROR_TYPE:
-        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_PARSE_TYPE, badText, lineCount);
-        break;
-    case PS_PARSE_ERROR_GENERAL:
-        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_PARSE_GENERAL, badText, lineCount);
-        break;
-    default:
-        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_INVALID_TYPE, badText, lineCount);
-    }
-
-    return PS_LOOKUP_SUCCESS;
-}
-
 static void lookupTableFree(psLookupTable* table)
 {
@@ -401,6 +250,6 @@
 
     psFree(table->values);
-    psFree(table->index);
-    psFree((char*)table->fileName);
+    psFree((char*)table->filename);
+    psFree((char*)table->format);
 }
 
@@ -409,12 +258,14 @@
 /*****************************************************************************/
 
-psLookupTable* psLookupTableAlloc(const char *fileName, psF64 validFrom, psF64 validTo)
+psLookupTable* psLookupTableAlloc(const char *fileName, const char *format, int indexCol)
 {
     psLookupTable *outTable = NULL;
-
 
     // Can't read table if you don't know its name
     PS_ASSERT_PTR_NON_NULL(fileName,NULL);
 
+    // Can't read table if you don't know its format
+    PS_ASSERT_PTR_NON_NULL(format,NULL);
+
     // Allocate lookup table
     outTable = (psLookupTable*)psAlloc(sizeof(psLookupTable));
@@ -423,14 +274,12 @@
     psMemSetDeallocator(outTable, (psFreeFcn)lookupTableFree);
 
-    // Allocate and set metadata item comment
-    outTable->fileName = psStringCopy(fileName);
-
-    // Number of table rows and columns. Automatically resized by table read.
-    outTable->numRows = 0;
-    outTable->numCols = 0;
+    // Allocate and set file name and format strings
+    outTable->filename = psStringCopy(fileName);
+    outTable->format = psStringCopy(format);
 
     // Valid ranges. Automatically set by table read if both zero.
-    outTable->validFrom = validFrom;
-    outTable->validTo = validTo;
+    outTable->validFrom = 0;
+    outTable->validTo = 0;
+    outTable->indexCol = indexCol;
 
     // Vector of independent index values. Filled by table read.
@@ -447,41 +296,41 @@
 case PS_TYPE_U8:                                                                \
     TABLE->validFrom = (psF64)TABLE->index->data.U8[0];                         \
-    TABLE->validTo   = (psF64)TABLE->index->data.U8[TABLE->index->nalloc-1];    \
+    TABLE->validTo   = (psF64)TABLE->index->data.U8[TABLE->index->n-1];         \
     break;                                                                      \
 case PS_TYPE_S8:                                                                \
     TABLE->validFrom = (psF64)TABLE->index->data.S8[0];                         \
-    TABLE->validTo   = (psF64)TABLE->index->data.S8[TABLE->index->nalloc-1];    \
+    TABLE->validTo   = (psF64)TABLE->index->data.S8[TABLE->index->n-1];         \
     break;                                                                      \
 case PS_TYPE_U16:                                                               \
     TABLE->validFrom = (psF64)TABLE->index->data.U16[0];                        \
-    TABLE->validTo   = (psF64)TABLE->index->data.U16[TABLE->index->nalloc-1];   \
+    TABLE->validTo   = (psF64)TABLE->index->data.U16[TABLE->index->n-1];        \
     break;                                                                      \
 case PS_TYPE_S16:                                                               \
     TABLE->validFrom = (psF64)TABLE->index->data.S16[0];                        \
-    TABLE->validTo   = (psF64)TABLE->index->data.S16[TABLE->index->nalloc-1];   \
+    TABLE->validTo   = (psF64)TABLE->index->data.S16[TABLE->index->n-1];        \
     break;                                                                      \
 case PS_TYPE_U32:                                                               \
     TABLE->validFrom = (psF64)TABLE->index->data.U32[0];                        \
-    TABLE->validTo   = (psF64)TABLE->index->data.U32[TABLE->index->nalloc-1];   \
+    TABLE->validTo   = (psF64)TABLE->index->data.U32[TABLE->index->n-1];        \
     break;                                                                      \
 case PS_TYPE_S32:                                                               \
     TABLE->validFrom = (psF64)TABLE->index->data.S32[0];                        \
-    TABLE->validTo   = (psF64)TABLE->index->data.S32[TABLE->index->nalloc-1];   \
+    TABLE->validTo   = (psF64)TABLE->index->data.S32[TABLE->index->n-1];        \
     break;                                                                      \
 case PS_TYPE_U64:                                                               \
     TABLE->validFrom = (psF64)TABLE->index->data.U64[0];                        \
-    TABLE->validTo   = (psF64)TABLE->index->data.U64[TABLE->index->nalloc-1];   \
+    TABLE->validTo   = (psF64)TABLE->index->data.U64[TABLE->index->n-1];        \
     break;                                                                      \
 case PS_TYPE_S64:                                                               \
     TABLE->validFrom = (psF64)TABLE->index->data.S64[0];                        \
-    TABLE->validTo   = (psF64)TABLE->index->data.S64[TABLE->index->nalloc-1];   \
+    TABLE->validTo   = (psF64)TABLE->index->data.S64[TABLE->index->n-1];        \
     break;                                                                      \
 case PS_TYPE_F32:                                                               \
     TABLE->validFrom = (psF64)TABLE->index->data.F32[0];                        \
-    TABLE->validTo   = (psF64)TABLE->index->data.F32[TABLE->index->nalloc-1];   \
+    TABLE->validTo   = (psF64)TABLE->index->data.F32[TABLE->index->n-1];        \
     break;                                                                      \
 case PS_TYPE_F64:                                                               \
     TABLE->validFrom = (psF64)TABLE->index->data.F64[0];                        \
-    TABLE->validTo   = (psF64)TABLE->index->data.F64[TABLE->index->nalloc-1];   \
+    TABLE->validTo   = (psF64)TABLE->index->data.F64[TABLE->index->n-1];        \
     break;                                                                      \
 default:                                                                        \
@@ -513,13 +362,37 @@
 case PS_TYPE_S32:                                                                          \
     ((psVector*)VEC_OUT)->data.S32[INDEX_OUT] = ((psVector*)VEC_IN)->data.S32[INDEX_IN];   \
+    if(INDEX_OUT == 0) {                                                                   \
+        validFrom = ((psVector*)VEC_OUT)->data.S32[INDEX_OUT];                             \
+    }                                                                                      \
+    if(INDEX_OUT == ((psVector*)VEC_OUT)->n-1 ) {                                          \
+        validTo = ((psVector*)VEC_OUT)->data.S32[INDEX_OUT];                               \
+    }                                                                                      \
     break;                                                                                 \
 case PS_TYPE_S64:                                                                          \
     ((psVector*)VEC_OUT)->data.S64[INDEX_OUT] = ((psVector*)VEC_IN)->data.S64[INDEX_IN];   \
+    if(INDEX_OUT == 0) {                                                                   \
+        validFrom = ((psVector*)VEC_OUT)->data.S64[INDEX_OUT];                             \
+    }                                                                                      \
+    if(INDEX_OUT == ((psVector*)VEC_OUT)->n-1 ) {                                          \
+        validTo = ((psVector*)VEC_OUT)->data.S64[INDEX_OUT];                               \
+    }                                                                                      \
     break;                                                                                 \
 case PS_TYPE_F32:                                                                          \
     ((psVector*)VEC_OUT)->data.F32[INDEX_OUT] = ((psVector*)VEC_IN)->data.F32[INDEX_IN];   \
+    if(INDEX_OUT == 0) {                                                                   \
+        validFrom = ((psVector*)VEC_OUT)->data.F32[INDEX_OUT];                             \
+    }                                                                                      \
+    if(INDEX_OUT == ((psVector*)VEC_OUT)->n-1 ) {                                          \
+        validTo = ((psVector*)VEC_OUT)->data.F32[INDEX_OUT];                               \
+    }                                                                                      \
     break;                                                                                 \
 case PS_TYPE_F64:                                                                          \
     ((psVector*)VEC_OUT)->data.F64[INDEX_OUT] = ((psVector*)VEC_IN)->data.F64[INDEX_IN];   \
+    if(INDEX_OUT == 0) {                                                                   \
+        validFrom = ((psVector*)VEC_OUT)->data.F64[INDEX_OUT];                             \
+    }                                                                                      \
+    if(INDEX_OUT == ((psVector*)VEC_OUT)->n-1 ) {                                          \
+        validTo = ((psVector*)VEC_OUT)->data.F64[INDEX_OUT];                               \
+    }                                                                                      \
     break;                                                                                 \
 default:                                                                                   \
@@ -527,194 +400,269 @@
 }
 
-
-psLookupTable* psLookupTableRead(psLookupTable *table)
-{
-    bool typeLine = true;
-    char *line = NULL;
-    char *strType = NULL;
-    char *strValue = NULL;
-    char *linePtr = NULL;
-    psParseErrorType status = PS_PARSE_SUCCESS;
-    psParseErrorType lineStatus = PS_PARSE_SUCCESS;
-    psU64 lineCount = 0;
-    psU64 numRows = 0;
-    psU64 numCols = 0;
-    psU64 failedLines = 0;
-    FILE *fp = NULL;
-    psElemType elemType;
-    psVector *indexVec = NULL;
-    psVector *valuesVec = NULL;
-    psArray *values = NULL;
-    psBool sortIndex = false;
+psArray *psVectorsReadFromFile(const char *filename, const char *format)
+{
+    psArray*          outputArray = NULL;
+    psVector*         colVector   = NULL;
+    char*             strValue    = NULL;
+    char*             strNum      = NULL;
+    char*             line        = NULL;
+    char*             linePtr     = NULL;
+    int               numCols     = 0;
+    int               numRows     = 0;
+    FILE*             fp          = NULL;
+    const char*       tempFormat  = NULL;
+    psParseErrorType  parseStatus = PS_PARSE_SUCCESS;
+
+    // Check for nul file name
+    PS_ASSERT_PTR_NON_NULL(filename,NULL);
+
+    // Parse format string for valid string
+    PS_ASSERT_PTR_NON_NULL(format,NULL);
+
+    // Create temp pointer which can then be used several times
+    tempFormat = format;
+
+    // Create output array and set array elements to zero
+    outputArray = psArrayAlloc(10);
+    outputArray->n = 0;
+
+    // Parse the format string to determine how many vectors
+    // and whether the format string is valid
+    while((strValue=getToken((char**)&tempFormat," ",&parseStatus))) {
+
+        // Check for %d format sub string
+        if(strcmp(strValue,"\%d") == 0 ) {
+            numCols++;
+            colVector = psVectorAlloc(1,PS_TYPE_S32);
+            outputArray = psArrayAdd(outputArray,1,colVector);
+            psFree(colVector);
+        } else if (strcmp(strValue,"\%ld") == 0) {
+            numCols++;
+            colVector = psVectorAlloc(1,PS_TYPE_S64);
+            outputArray = psArrayAdd(outputArray,1,colVector);
+            psFree(colVector);
+        } else if (strcmp(strValue,"\%f") == 0) {
+            numCols++;
+            colVector = psVectorAlloc(1,PS_TYPE_F32);
+            outputArray = psArrayAdd(outputArray,1,colVector);
+            psFree(colVector);
+        } else if (strcmp(strValue,"\%lf") == 0) {
+            numCols++;
+            colVector = psVectorAlloc(1,PS_TYPE_F64);
+            outputArray = psArrayAdd(outputArray,1,colVector);
+            psFree(colVector);
+        } else if (strstr(strValue,"\%*") != 0) {
+            // Don't increase number of columns
+        } else {
+            psError(PS_ERR_BAD_PARAMETER_VALUE,true,"Invalid format specifier");
+            psFree(strValue);
+            numCols = 0;
+            break;
+        }
+        psFree(strValue);
+    }
+
+    // If the format string was parsed successfully and return numCols the
+    // prepare to open file and read values
+    if(numCols > 0) {
+
+        // Open specified file
+        if((fp=fopen(filename, "r")) == NULL) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_FILE_NOT_FOUND,
+                    filename);
+            psFree(outputArray);
+            return NULL;
+        } else {
+            // Initialize array index
+            int arrayIndex = 0;
+
+            // Create reusable line for continuous read
+            line = (char*)psAlloc(MAX_STRING_LENGTH*sizeof(char));
+
+            // Loop through file to get numRows, numCols, and column data types
+            while((fgets(line, MAX_STRING_LENGTH, fp) != NULL) && (parseStatus == PS_PARSE_SUCCESS)) {
+
+                // Copy pointer to line for parsing
+                linePtr = line;
+
+                // If line is not a comment or blank, then extract data
+                if(!ignoreLine(linePtr)) {
+                    numRows++;
+
+                    // Copy format pointer for parsing
+                    tempFormat = format;
+                    arrayIndex = 0;
+                    parseStatus = PS_PARSE_SUCCESS;
+
+                    // Loop through format and line strings to get values in text table file
+                    while((strValue=getToken((char**)&tempFormat," ",&parseStatus)) &&
+                            (strNum=getToken((char**)&linePtr," ",&parseStatus)) ) {
+
+                        // Set column vector
+                        colVector = outputArray->data[arrayIndex];
+
+                        // Set column entries based on format string defining the type
+                        if(strcmp(strValue,"\%d") == 0 ) {
+                            colVector = psVectorRecycle(colVector, numRows, colVector->type.type);
+                            parseValue(colVector,numRows-1,strNum,&parseStatus);
+                            arrayIndex++;
+                        } else if (strcmp(strValue,"\%ld") == 0) {
+                            colVector = psVectorRecycle(colVector, numRows, colVector->type.type);
+                            parseValue(colVector,numRows-1,strNum,&parseStatus);
+                            arrayIndex++;
+                        } else if (strcmp(strValue,"\%f") == 0) {
+                            colVector = psVectorRecycle(colVector, numRows, colVector->type.type);
+                            parseValue(colVector,numRows-1,strNum,&parseStatus);
+                            arrayIndex++;
+                        } else if (strcmp(strValue,"\%lf") == 0) {
+                            colVector = psVectorRecycle(colVector, numRows, colVector->type.type);
+                            parseValue(colVector,numRows-1,strNum,&parseStatus);
+                            arrayIndex++;
+                        } else if (strstr(strValue,"\%*") != 0) {
+                            // Don't increase number of columns
+                        }
+                        psFree(strValue);
+                        psFree(strNum);
+
+                        // If the file line was not parsed successful report error and return NULL
+                        if(parseStatus != PS_PARSE_SUCCESS) {
+                            psError(PS_ERR_UNKNOWN,true,"Parsing text file failed.");
+                            fclose(fp);
+                            psFree(outputArray);
+                            psFree(line);
+                            return NULL;
+                        }
+                    }
+                }  // ignore line
+            }
+
+            // Read on the lines in the file - close file pointer
+            fclose(fp);
+            psFree(line);
+        }
+    } else {
+        // Format string parse error detected
+        psError(PS_ERR_UNKNOWN,true,"Format string was not parsed sucessfully");
+        psFree(outputArray);
+        return NULL;
+    }
+
+    // Return populated array
+    return outputArray;
+}
+
+psLookupTable *psLookupTableImport(psLookupTable *table, const psArray *vectors, int indexCol)
+{
+    psLookupTable* outputTable = NULL;
+    psBool         sortNeeded  = false;
+    psF64          validTo     = 0;
+    psF64          validFrom   = 0;
 
     // Check for NULL input table
     PS_ASSERT_PTR_NON_NULL(table,NULL);
 
-    // Check for input table with NULL file name
-    PS_ASSERT_PTR_NON_NULL(table->fileName,NULL);
-
-    // Open table file specified by table->fileName
-    if((fp=fopen(table->fileName, "r")) == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_FILE_NOT_FOUND,
-                table->fileName);
-        return table;
-    }
-
-    // Initialize vector pointers
-    indexVec = table->index;
-    values = table->values = psArrayAlloc(10);
-    values->n = 0;
-
-    // Create reusable line for continuous read
-    line = (char*)psAlloc(MAX_STRING_LENGTH*sizeof(char));
-
-    // Loop through file to get numRows, numCols, and column data types
-    while((fgets(line, MAX_STRING_LENGTH, fp) != NULL) && (lineStatus == PS_PARSE_SUCCESS)) {
-
-        // Initialize variables for new line
-        linePtr = line;
-        lineCount++;
-
-        // If line is not a comment or blank, then extract data
-        if(!ignoreLine(linePtr)) {
-
-            if(typeLine == true) {
-
-                // Determine column types from first line in data file after comments
-                while((strType=getToken(&linePtr," ",&status))) {
-                    numCols++;
-                    typeLine = false;
-                    if(!strncmp(strType, "psU8", 4)) {
-                        elemType = PS_TYPE_U8;
-                    } else if(!strncmp(strType, "psS8", 4)) {
-                        elemType = PS_TYPE_S8;
-                    } else if(!strncmp(strType, "psU16", 5)) {
-                        elemType = PS_TYPE_U16;
-                    } else if(!strncmp(strType, "psS16", 5)) {
-                        elemType = PS_TYPE_S16;
-                    } else if(!strncmp(strType, "psU32", 5)) {
-                        elemType = PS_TYPE_U32;
-                    } else if(!strncmp(strType, "psS32", 5)) {
-                        elemType = PS_TYPE_S32;
-                    } else if(!strncmp(strType, "psU64", 5)) {
-                        elemType = PS_TYPE_U64;
-                    } else if(!strncmp(strType, "psS64", 5)) {
-                        elemType = PS_TYPE_S64;
-                    } else if(!strncmp(strType, "psF32", 5)) {
-                        elemType = PS_TYPE_F32;
-                    } else if(!strncmp(strType, "psF64", 5)) {
-                        elemType = PS_TYPE_F64;
-                    } else {
-                        status = PS_PARSE_ERROR_TYPE;
-                    }
-
-                    // Realloc number of columns as you go
-                    psVector* vec = psVectorAlloc(0, elemType);
-                    if(numCols == 1) {
-                        indexVec = vec;
-                    } else {
-                        psArrayAdd(values,0,vec);
-                        psFree(vec);
-                    }
-
-                    if(status) {
-                        printError(lineCount, strValue, status);
-                        failedLines++;
-                        lineStatus = status;
-                        status = PS_PARSE_SUCCESS;
-                    }
-                    psFree(strType);
-                }
-            } else {
-                // Parse and add values to all columns
-                numRows++;
-                numCols = 0;
-                while((strValue=getToken(&linePtr," ",&status))) {
-                    numCols++;
-
-                    // Realloc number of rows as you go
-                    if(numCols == 1) {
-                        sortIndex = false;
-                        indexVec = psVectorRecycle(indexVec, numRows, indexVec->type.type);
-                        parseValue(indexVec, numRows-1, strValue, &status);
-                    } else {
-                        valuesVec = values->data[numCols-2];
-                        valuesVec = psVectorRecycle(valuesVec, numRows, valuesVec->type.type);
-                        parseValue(valuesVec, numRows-1, strValue, &status);
-                    }
-
-                    if(status) {
-                        printError(lineCount, strValue, status);
-                        failedLines++;
-                        lineStatus = status;
-                        status = PS_PARSE_SUCCESS;
-                    }
-                    psFree(strValue);
-                } // end while
-            } // end else
-        } // if ignoreLine
-    } // end while
-
-    psFree(line);
-
-    // Set table for return
-    table->numRows = numRows;
-    table->numCols = numCols-1;
-    table->index = indexVec;
-    table->values = values;
-
-    // Set table values to indicate error detected during the read
-    if(lineStatus) {
-        table->numRows = 0;
-        table->numCols = 0;
-        table->validFrom = 0;
-        table->validTo = 0;
-        psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psLookupTable_TABLE_INVALID);
-    } else {
-        // Check if index vector needs to be sorted
-        psVector* sortedIndex = psVectorAlloc(table->numRows,PS_TYPE_U32);
-        sortedIndex = psVectorSortIndex(sortedIndex,table->index);
-        for(psS32 i = 0; i < numRows; i++ ) {
-            if(sortedIndex->data.U32[i] != i) {
-                sortIndex = true;
-                break;
+    // Check for NULL vectors
+    PS_ASSERT_PTR_NON_NULL(vectors,NULL);
+
+    // Check for invalid index column
+    if(indexCol < 0 ) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE,true,"Index column cannot be less than zero");
+        return NULL;
+    }
+
+    psVector* indexColumnVector = vectors->data[indexCol];
+    psS32  numRows = indexColumnVector->n;
+    psS32  numCols = vectors->n;
+
+    // Check if array is sorted on the index column
+    psVector* sortedIndex = psVectorAlloc(numRows,PS_TYPE_U32);
+    sortedIndex = psVectorSortIndex(sortedIndex,indexColumnVector);
+    for(psS32 i = 0; i < numRows; i++ ) {
+        if(sortedIndex->data.U32[i] != i) {
+            sortNeeded = true;
+            break;
+        }
+    }
+
+    // Check if it is necessary to sort value vectors
+    if(sortNeeded) {
+        // Allocate new array to contain sorted vectors
+        psArray* newValueArray = psArrayAlloc(numCols);
+        for(psS32 j = 0; j < numCols; j++) {
+            psS32 type = ((psVector*)(vectors->data[j]))->type.type;
+            newValueArray->data[j] = psVectorAlloc(numRows,type);
+        }
+
+        // Populate new array/vectors with sorted values
+        for(psS32 i = 0; i < numRows; i++) {
+            // Populate new index vector
+            psU32 sortIndex = sortedIndex->data.U32[i];
+            // For every column populate new value vectors
+            for(psS32 j=0; j < numCols; j++) {
+                COPY_VECTOR_VALUES(newValueArray->data[j],i,vectors->data[j], sortIndex)
             }
         }
-        // Check if it is necessary to sort value vectors
-        if(sortIndex) {
-            // Allocate new index vector
-            psVector* newIndexVector = psVectorAlloc(numRows,indexVec->type.type);
-            // Allocate new value vectors
-            psArray* newValueArray = psArrayAlloc(numCols-1);
-            for(psS32 j = 0; j < numCols-1; j++) {
-                psS32 type = ((psVector*)(table->values->data[j]))->type.type;
-                newValueArray->data[j] = psVectorAlloc(numRows,type);
-            }
-            for(psS32 i = 0; i < numRows; i++) {
-                // Populate new index vector
-                psU32 sortIndex = sortedIndex->data.U32[i];
-                COPY_VECTOR_VALUES(newIndexVector,i, indexVec,sortIndex)
-                // For every column populate new value vectors
-                for(psS32 j=0; j < numCols-1; j++) {
-                    COPY_VECTOR_VALUES(newValueArray->data[j],i,table->values->data[j], sortIndex)
-                }
-            }
-            // Free old index vector
-            psFree(table->index);
-            // Free old value vectors
-            psFree(table->values);
-            // Assign new vector value to table
-            table->index = newIndexVector;
-            // Assign new value vectors to table array
-            table->values = newValueArray;
+        // Assign new vector value to table
+        table->index = newValueArray->data[indexCol];
+        // Assign new value vectors to table array
+        table->values = newValueArray;
+        // Assign indexCol
+        table->indexCol = indexCol;
+        // Assign validTo and validFrom values
+        UPDATE_VALID_TO_FROM(table)
+
+        // Set return value
+        outputTable = table;
+
+    } else {
+        // Index vector is already sorted
+        // Assign array vector specified by indexCol to table index vector and increment memory ref
+        table->index = vectors->data[indexCol];
+        table->values = (psArray*)vectors;
+        psMemIncrRefCounter((psArray*)vectors);
+
+        // Assign indexCol
+        table->indexCol = indexCol;
+        // Assign validTo and validFrom values
+        UPDATE_VALID_TO_FROM(table);
+
+        // Set return value
+        outputTable = table;
+    }
+
+    // Free sort vector
+    psFree(sortedIndex);
+
+    return outputTable;
+}
+
+psS32 psLookupTableRead(psLookupTable* table)
+{
+    psS32           numRows  = 0;
+    psArray*        vectors  = NULL;
+    psLookupTable*  outTable = NULL;
+
+    // Check if the input table is NULL then return 0
+    PS_ASSERT_PTR_NON_NULL(table,0);
+
+    // Read vectors from file specified in table
+    vectors = psVectorsReadFromFile(table->filename, table->format);
+
+    // Check for valid array after reading from file
+    if(vectors != NULL) {
+
+        // Import vector into table
+        outTable = psLookupTableImport(table, vectors, table->indexCol);
+
+        psFree(vectors);
+
+        // Update the number of rows read if outTable is not NULL
+        if(outTable != NULL) {
+            numRows = table->index->n;
         }
-        psFree(sortedIndex);
-        // Update the validTo and validFrom
-        UPDATE_VALID_TO_FROM(table)
-    }
-
-    fclose(fp);
-
-    return table;
+    }
+
+    // Return the number of lines read
+    return numRows;
 }
 
@@ -756,102 +704,44 @@
 }
 
-
-#define CHECK_LOWER_UPPER_BOUND(TABLE,INDEX,COLUMN)                                \
-switch (TABLE->index->type.type) {                                                 \
-case PS_TYPE_U8:                                                                   \
-    if( (psU8)index < TABLE->index->data.U8[0] ) {                                 \
-        *status = PS_LOOKUP_PAST_TOP;                                              \
-    }                                                                              \
-    if( (psU8)index > TABLE->index->data.U8[numRows-1]) {                          \
-        *status = PS_LOOKUP_PAST_BOTTOM;                                           \
-    }                                                                              \
-    break;                                                                         \
-case PS_TYPE_U16:                                                                  \
-    if( (psU16)index < TABLE->index->data.U16[0] ) {                               \
-        *status = PS_LOOKUP_PAST_TOP;                                              \
-    }                                                                              \
-    if( (psU16)index > TABLE->index->data.U16[numRows-1] ) {                       \
-        *status = PS_LOOKUP_PAST_BOTTOM;                                           \
-    }                                                                              \
-    break;                                                                         \
-case PS_TYPE_U32:                                                                  \
-    if( (psU32)index < TABLE->index->data.U32[0]) {                                \
-        *status = PS_LOOKUP_PAST_TOP;                                              \
-    }                                                                              \
-    if ( (psU32)index > TABLE->index->data.U32[numRows-1] ) {                      \
-        *status = PS_LOOKUP_PAST_BOTTOM;                                           \
-    }                                                                              \
-    break;                                                                         \
-case PS_TYPE_U64:                                                                  \
-    if( (psU64)index < TABLE->index->data.U64[0] ) {                               \
-        *status = PS_LOOKUP_PAST_TOP;                                              \
-    }                                                                              \
-    if( (psU64)index > TABLE->index->data.U64[numRows-1] ) {                       \
-        *status = PS_LOOKUP_PAST_BOTTOM;                                           \
-    }                                                                              \
-    break;                                                                         \
-case PS_TYPE_S8:                                                                   \
-    if( (psS8)index < TABLE->index->data.S8[0] ) {                                 \
-        *status = PS_LOOKUP_PAST_TOP;                                              \
-    }                                                                              \
-    if( (psS8)index > TABLE->index->data.S8[numRows-1] ) {                         \
-        *status = PS_LOOKUP_PAST_BOTTOM;                                           \
-    }                                                                              \
-    break;                                                                         \
-case PS_TYPE_S16:                                                                  \
-    if( (psS16)index < TABLE->index->data.S16[0] ) {                               \
-        *status = PS_LOOKUP_PAST_TOP;                                              \
-    }                                                                              \
-    if( (psS16)index > TABLE->index->data.S16[numRows-1] ) {                       \
-        *status = PS_LOOKUP_PAST_BOTTOM;                                           \
-    }                                                                              \
-    break;                                                                         \
-case PS_TYPE_S32:                                                                  \
-    if( (psS32)index < TABLE->index->data.S32[0] ) {                               \
-        *status = PS_LOOKUP_PAST_TOP;                                              \
-    }                                                                              \
-    if( (psS32)index > TABLE->index->data.S32[numRows-1] ) {                       \
-        *status = PS_LOOKUP_PAST_BOTTOM;                                           \
-    }                                                                              \
-    break;                                                                         \
-case PS_TYPE_S64:                                                                  \
-    if( (psS64)index < TABLE->index->data.S64[0] ) {                               \
-        *status = PS_LOOKUP_PAST_TOP;                                              \
-    }                                                                              \
-    if( (psS64)index > TABLE->index->data.S64[numRows-1] ) {                       \
-        *status = PS_LOOKUP_PAST_BOTTOM;                                           \
-    }                                                                              \
-    break;                                                                         \
-case PS_TYPE_F32:                                                                  \
-    if( (psF32)index < TABLE->index->data.F32[0] ) {                               \
-        *status = PS_LOOKUP_PAST_TOP;                                              \
-    }                                                                              \
-    if( (psF32)index > TABLE->index->data.F32[numRows-1] ) {                       \
-        *status = PS_LOOKUP_PAST_BOTTOM;                                           \
-    }                                                                              \
-    break;                                                                         \
-case PS_TYPE_F64:                                                                  \
-    if( index < TABLE->index->data.F64[0] ) {                                      \
-        *status = PS_LOOKUP_PAST_TOP;                                              \
-    }                                                                              \
-    if( index > TABLE->index->data.F64[numRows-1] ) {                              \
-        *status = PS_LOOKUP_PAST_BOTTOM;                                           \
-    }                                                                              \
-    break;                                                                         \
-default:                                                                           \
-    *status = PS_LOOKUP_ERROR;                                                     \
-    return NAN;                                                                    \
-    break;                                                                         \
-}                                                                                  \
-if(*status == PS_LOOKUP_PAST_TOP) {                                                \
-    CONVERT_VALUE_TO_F64(((psVector*)(TABLE->values->data[COLUMN])),0,out)         \
-    return out;                                                                    \
-} else if (*status == PS_LOOKUP_PAST_BOTTOM) {                                     \
-    CONVERT_VALUE_TO_F64(((psVector*)(TABLE->values->data[COLUMN])),numRows-1,out) \
-    return out;                                                                    \
-}
-
-
-psF64 psLookupTableInterpolate(psLookupTable *table, psF64 index, psU64 column, psLookupStatusType *status)
+#define CHECK_LOWER_UPPER_BOUND(TABLE,INDEX,COLUMN)                     \
+switch (TABLE->index->type.type) {                                      \
+case PS_TYPE_S32:                                                       \
+    if( (psS32)index < TABLE->index->data.S32[0] ) {                    \
+        return NAN;                                                     \
+    }                                                                   \
+    if( (psS32)index > TABLE->index->data.S32[numRows-1] ) {            \
+        return NAN;                                                     \
+    }                                                                   \
+    break;                                                              \
+case PS_TYPE_S64:                                                       \
+    if( (psS64)index < TABLE->index->data.S64[0] ) {                    \
+        return NAN;                                                     \
+    }                                                                   \
+    if( (psS64)index > TABLE->index->data.S64[numRows-1] ) {            \
+        return NAN;                                                     \
+    }                                                                   \
+    break;                                                              \
+case PS_TYPE_F32:                                                       \
+    if( (psF32)index < TABLE->index->data.F32[0] ) {                    \
+        return NAN;                                                     \
+    }                                                                   \
+    if( (psF32)index > TABLE->index->data.F32[numRows-1] ) {            \
+        return NAN;                                                     \
+    }                                                                   \
+    break;                                                              \
+case PS_TYPE_F64:                                                       \
+    if( index < TABLE->index->data.F64[0] ) {                           \
+        return NAN;                                                     \
+    }                                                                   \
+    if( index > TABLE->index->data.F64[numRows-1] ) {                   \
+        return NAN;                                                     \
+    }                                                                   \
+    break;                                                              \
+default:                                                                \
+    return NAN;                                                         \
+    break;                                                              \
+}
+
+psF64 psLookupTableInterpolate(const psLookupTable *table, psF64 index, psS32 column)
 {
     psU64 hiIdx = 0;
@@ -867,13 +757,11 @@
     psArray *values = NULL;
 
-    // Error checks
-    // Set status to error prior to check since if checks fails it will immediately return
-    PS_ASSERT_PTR_NON_NULL(status,NAN);
-    *status = PS_LOOKUP_ERROR;
+    // Check for NULL table
     PS_ASSERT_PTR_NON_NULL(table,NAN);
+
     indexVec = table->index;
     values = table->values;
-    numRows = table->numRows;
-    numCols = table->numCols;
+    numRows = table->index->n;
+    numCols = table->values->n;
     PS_ASSERT_PTR_NON_NULL(indexVec,NAN);
     PS_ASSERT_PTR_NON_NULL(values,NAN);
@@ -884,7 +772,4 @@
     valuesVec = (psVector*)values->data[column];
     PS_ASSERT_PTR_NON_NULL(indexVec,NAN);
-
-    // Set status to success since it passed all parameter checks
-    *status = PS_LOOKUP_SUCCESS;
 
     // Verify the index is within the bounds of the table
@@ -898,5 +783,4 @@
             psError(PS_ERR_BAD_PARAMETER_VALUE, true,
                     PS_ERRORTEXT_psLookupTable_INTERPOLATE_HIGH, hiIdx);
-            *status = PS_LOOKUP_ERROR;
             return NAN;
         }
@@ -909,5 +793,4 @@
         psError(PS_ERR_BAD_PARAMETER_VALUE, true,
                 PS_ERRORTEXT_psLookupTable_INTERPOLATE_LOW, loIdx);
-        *status = PS_LOOKUP_ERROR;
         return NAN;
     }
@@ -919,5 +802,4 @@
     if(fabs(denom) < FLT_EPSILON) {
         psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_DIVIDE_BY_ZERO);
-        *status = PS_LOOKUP_ERROR;
         return NAN;
     } else {
@@ -934,23 +816,27 @@
 }
 
-psVector* psLookupTableInterpolateAll(psLookupTable *table, psF64 index, psVector *stats)
-{
-    psU64 i = 0;
+psVector* psLookupTableInterpolateAll(psLookupTable *table, psF64 index)
+{
     psU64 numCols = 0;
     psVector *outVector = NULL;
-    psLookupStatusType status = PS_LOOKUP_SUCCESS;
 
     // Error checks
     PS_ASSERT_PTR_NON_NULL(table,NULL);
-    PS_ASSERT_PTR_NON_NULL(stats,NULL);
-    numCols = table->numCols;
+    numCols = table->values->n;
     PS_ASSERT_INT_UNEQUAL(numCols, 0,NULL);
 
-    outVector = psVectorAlloc(numCols+1, PS_TYPE_F64);
+    // Create output vector
+    outVector = psVectorAlloc(numCols, PS_TYPE_F64);
 
     // Fill vectors with results and status of results
-    for(i=0; i<numCols; i++) {
-        outVector->data.F64[i] = psLookupTableInterpolate(table, index, i, &status);
-        stats->data.U32[i] = status;
+    for(psU64 i=0; i<numCols; i++) {
+        outVector->data.F64[i] = psLookupTableInterpolate(table, index, i);
+        if(isnan(outVector->data.F64[i])) {
+            // Free allocated vector
+            psFree(outVector);
+            outVector = NULL;
+            // Break out of loop since error detected
+            break;
+        }
     }
 
