IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 4050


Ignore:
Timestamp:
May 31, 2005, 11:46:56 AM (21 years ago)
Author:
evanalst
Message:

SDR-14 updates to functions.

Location:
trunk/psLib/src
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/psLib/src/dataIO/psLookupTable.c

    r4031 r4050  
    77*  @author Ross Harman, MHPCC
    88*
    9 *  @version $Revision: 1.14 $ $Name: not supported by cvs2svn $
    10 *  @date $Date: 2005-05-25 22:46:47 $
     9*  @version $Revision: 1.15 $ $Name: not supported by cvs2svn $
     10*  @date $Date: 2005-05-31 21:46:56 $
    1111*
    12 *  Copyright 2004-5 Maui High Performance Computing Center, University of Hawaii
     12*  Copyright 2004-2005 Maui High Performance Computing Center, Univ. of Hawaii
    1313*/
    1414#include <stdio.h>
     
    6464static char *cleanString(char *inString, int sLen);
    6565static char* getToken(char **inString, char *delimiter, psParseErrorType *status);
    66 static psU8 parseU8(char *inString, psParseErrorType *status);
    67 static psS8 parseS8(char *inString, psParseErrorType *status);
    68 static psU16 parseU16(char *inString, psParseErrorType *status);
    69 static psS16 parseS16(char *inString, psParseErrorType *status);
    70 static psU32 parseU32(char *inString, psParseErrorType *status);
    7166static psS32 parseS32(char *inString, psParseErrorType *status);
    72 static psU64 parseU64(char *inString, psParseErrorType *status);
    7367static psS64 parseS64(char *inString, psParseErrorType *status);
    7468static psF32 parseF32(char *inString, psParseErrorType *status);
     
    8781        inString++;
    8882    }
    89 
    9083    return true;
    9184}
     
    10093    char *cleaned = NULL;
    10194
    102 
    10395    ptrB = inString;
    10496
    105     /* Skip over leading # or whitespace */
     97    // Skip over leading # or whitespace
    10698    while (isspace(*ptrB) || *ptrB=='#') {
    10799        ptrB++;
    108100    }
    109101
    110     /* Skip over trailing whitespace, null terminators, and # characters */
     102    // Skip over trailing whitespace, null terminators, and # characters
    111103    ptrE = inString + sLen;
    112104    while(isspace(*ptrE) || *ptrE=='\0' || *ptrE=='#') {
     
    130122    char *cleanToken = NULL;
    131123    int sLen = 0;
    132 
    133124
    134125    // Skip over leading whitespace
     
    151142
    152143    return cleanToken;
    153 }
    154 
    155 /** Returns single parsed value as a psU8. The input string must be cleaned and null terminated. */
    156 static psU8 parseU8(char *inString, psParseErrorType *status)
    157 {
    158     char *end = NULL;
    159     psU8 value = 0.0;
    160 
    161 
    162     value = (psU8)strtoul(inString, &end, 0);
    163     if(*end != '\0') {
    164         *status = PS_PARSE_ERROR_VALUE;
    165     } else if(inString==end) {
    166         *status = PS_PARSE_ERROR_VALUE;
    167     }
    168 
    169     return value;
    170 }
    171 
    172 /** Returns single parsed value as a psS8. The input string must be cleaned and null terminated. */
    173 static psS8 parseS8(char *inString, psParseErrorType *status)
    174 {
    175     char *end = NULL;
    176     psS8 value = 0.0;
    177 
    178 
    179     value = (psS8)strtol(inString, &end, 0);
    180     if(*end != '\0') {
    181         *status = PS_PARSE_ERROR_VALUE;
    182     } else if(inString==end) {
    183         *status = PS_PARSE_ERROR_VALUE;
    184     }
    185 
    186     return value;
    187 }
    188 
    189 /** Returns single parsed value as a psU16. The input string must be cleaned and null terminated. */
    190 static psU16 parseU16(char *inString, psParseErrorType *status)
    191 {
    192     char *end = NULL;
    193     psU16 value = 0.0;
    194 
    195 
    196     value = (psU16)strtoul(inString, &end, 0);
    197     if(*end != '\0') {
    198         *status = PS_PARSE_ERROR_VALUE;
    199     } else if(inString==end) {
    200         *status = PS_PARSE_ERROR_VALUE;
    201     }
    202 
    203     return value;
    204 }
    205 
    206 /** Returns single parsed value as a psS16. The input string must be cleaned and null terminated. */
    207 static psS16 parseS16(char *inString, psParseErrorType *status)
    208 {
    209     char *end = NULL;
    210     psS16 value = 0.0;
    211 
    212 
    213     value = (psS16)strtol(inString, &end, 0);
    214     if(*end != '\0') {
    215         *status = PS_PARSE_ERROR_VALUE;
    216     } else if(inString==end) {
    217         *status = PS_PARSE_ERROR_VALUE;
    218     }
    219 
    220     return value;
    221 }
    222 
    223 /** Returns single parsed value as a psU32. The input string must be cleaned and null terminated. */
    224 static psU32 parseU32(char *inString, psParseErrorType *status)
    225 {
    226     char *end = NULL;
    227     psU32 value = 0.0;
    228 
    229 
    230     value = (psU32)strtoul(inString, &end, 0);
    231     if(*end != '\0') {
    232         *status = PS_PARSE_ERROR_VALUE;
    233     } else if(inString==end) {
    234         *status = PS_PARSE_ERROR_VALUE;
    235     }
    236 
    237     return value;
    238144}
    239145
     
    255161}
    256162
    257 /** Returns single parsed value as a psU64. The input string must be cleaned and null terminated. */
    258 static psU64 parseU64(char *inString, psParseErrorType *status)
    259 {
    260     char *end = NULL;
    261     psU64 value = 0.0;
    262 
    263 
    264     value = (psU64)strtoull(inString, &end, 0);
    265     if(*end != '\0') {
    266         *status = PS_PARSE_ERROR_VALUE;
    267     } else if(inString==end) {
    268         *status = PS_PARSE_ERROR_VALUE;
    269     }
    270 
    271     return value;
    272 }
    273 
    274163/** Returns single parsed value as a psS64. The input string must be cleaned and null terminated. */
    275164static psS64 parseS64(char *inString, psParseErrorType *status)
     
    277166    char *end = NULL;
    278167    psS64 value = 0.0;
    279 
    280168
    281169    value = (psS64)strtoll(inString, &end, 0);
     
    295183    psF32 value = 0.0;
    296184
    297 
    298185    value = (psF32)strtof(inString, &end);
    299186    if(*end != '\0') {
     
    312199    psF64 value = 0.0;
    313200
    314 
    315201    value = (psF64)strtod(inString, &end);
    316202    if(*end != '\0') {
     
    338224
    339225    switch(type) {
    340     case PS_TYPE_U8:
    341         vec->data.U8[index] = parseU8(strValue, status);
    342         break;
    343     case PS_TYPE_S8:
    344         vec->data.S8[index] = parseS8(strValue, status);
    345         break;
    346     case PS_TYPE_U16:
    347         vec->data.U16[index] = parseU16(strValue, status);
    348         break;
    349     case PS_TYPE_S16:
    350         vec->data.S16[index] = parseS16(strValue, status);
    351         break;
    352     case PS_TYPE_U32:
    353         vec->data.U32[index] = parseU32(strValue, status);
    354         break;
    355226    case PS_TYPE_S32:
    356227        vec->data.S32[index] = parseS32(strValue, status);
    357         break;
    358     case PS_TYPE_U64:
    359         vec->data.U64[index] = parseU64(strValue, status);
    360228        break;
    361229    case PS_TYPE_S64:
     
    375243}
    376244
    377 static psParseErrorType printError(psU64 lineCount, char* badText, psParseErrorType status)
    378 {
    379     switch(status) {
    380     case PS_PARSE_ERROR_VALUE:
    381         psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_PARSE_VALUE, badText, lineCount);
    382         break;
    383     case PS_PARSE_ERROR_TYPE:
    384         psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_PARSE_TYPE, badText, lineCount);
    385         break;
    386     case PS_PARSE_ERROR_GENERAL:
    387         psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_PARSE_GENERAL, badText, lineCount);
    388         break;
    389     default:
    390         psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_INVALID_TYPE, badText, lineCount);
    391     }
    392 
    393     return PS_LOOKUP_SUCCESS;
    394 }
    395 
    396245static void lookupTableFree(psLookupTable* table)
    397246{
     
    401250
    402251    psFree(table->values);
    403     psFree(table->index);
    404     psFree((char*)table->fileName);
     252    psFree((char*)table->filename);
     253    psFree((char*)table->format);
    405254}
    406255
     
    409258/*****************************************************************************/
    410259
    411 psLookupTable* psLookupTableAlloc(const char *fileName, psF64 validFrom, psF64 validTo)
     260psLookupTable* psLookupTableAlloc(const char *fileName, const char *format, int indexCol)
    412261{
    413262    psLookupTable *outTable = NULL;
    414 
    415263
    416264    // Can't read table if you don't know its name
    417265    PS_ASSERT_PTR_NON_NULL(fileName,NULL);
    418266
     267    // Can't read table if you don't know its format
     268    PS_ASSERT_PTR_NON_NULL(format,NULL);
     269
    419270    // Allocate lookup table
    420271    outTable = (psLookupTable*)psAlloc(sizeof(psLookupTable));
     
    423274    psMemSetDeallocator(outTable, (psFreeFcn)lookupTableFree);
    424275
    425     // Allocate and set metadata item comment
    426     outTable->fileName = psStringCopy(fileName);
    427 
    428     // Number of table rows and columns. Automatically resized by table read.
    429     outTable->numRows = 0;
    430     outTable->numCols = 0;
     276    // Allocate and set file name and format strings
     277    outTable->filename = psStringCopy(fileName);
     278    outTable->format = psStringCopy(format);
    431279
    432280    // Valid ranges. Automatically set by table read if both zero.
    433     outTable->validFrom = validFrom;
    434     outTable->validTo = validTo;
     281    outTable->validFrom = 0;
     282    outTable->validTo = 0;
     283    outTable->indexCol = indexCol;
    435284
    436285    // Vector of independent index values. Filled by table read.
     
    447296case PS_TYPE_U8:                                                                \
    448297    TABLE->validFrom = (psF64)TABLE->index->data.U8[0];                         \
    449     TABLE->validTo   = (psF64)TABLE->index->data.U8[TABLE->index->nalloc-1];    \
     298    TABLE->validTo   = (psF64)TABLE->index->data.U8[TABLE->index->n-1];         \
    450299    break;                                                                      \
    451300case PS_TYPE_S8:                                                                \
    452301    TABLE->validFrom = (psF64)TABLE->index->data.S8[0];                         \
    453     TABLE->validTo   = (psF64)TABLE->index->data.S8[TABLE->index->nalloc-1];    \
     302    TABLE->validTo   = (psF64)TABLE->index->data.S8[TABLE->index->n-1];         \
    454303    break;                                                                      \
    455304case PS_TYPE_U16:                                                               \
    456305    TABLE->validFrom = (psF64)TABLE->index->data.U16[0];                        \
    457     TABLE->validTo   = (psF64)TABLE->index->data.U16[TABLE->index->nalloc-1];   \
     306    TABLE->validTo   = (psF64)TABLE->index->data.U16[TABLE->index->n-1];        \
    458307    break;                                                                      \
    459308case PS_TYPE_S16:                                                               \
    460309    TABLE->validFrom = (psF64)TABLE->index->data.S16[0];                        \
    461     TABLE->validTo   = (psF64)TABLE->index->data.S16[TABLE->index->nalloc-1];   \
     310    TABLE->validTo   = (psF64)TABLE->index->data.S16[TABLE->index->n-1];        \
    462311    break;                                                                      \
    463312case PS_TYPE_U32:                                                               \
    464313    TABLE->validFrom = (psF64)TABLE->index->data.U32[0];                        \
    465     TABLE->validTo   = (psF64)TABLE->index->data.U32[TABLE->index->nalloc-1];   \
     314    TABLE->validTo   = (psF64)TABLE->index->data.U32[TABLE->index->n-1];        \
    466315    break;                                                                      \
    467316case PS_TYPE_S32:                                                               \
    468317    TABLE->validFrom = (psF64)TABLE->index->data.S32[0];                        \
    469     TABLE->validTo   = (psF64)TABLE->index->data.S32[TABLE->index->nalloc-1];   \
     318    TABLE->validTo   = (psF64)TABLE->index->data.S32[TABLE->index->n-1];        \
    470319    break;                                                                      \
    471320case PS_TYPE_U64:                                                               \
    472321    TABLE->validFrom = (psF64)TABLE->index->data.U64[0];                        \
    473     TABLE->validTo   = (psF64)TABLE->index->data.U64[TABLE->index->nalloc-1];   \
     322    TABLE->validTo   = (psF64)TABLE->index->data.U64[TABLE->index->n-1];        \
    474323    break;                                                                      \
    475324case PS_TYPE_S64:                                                               \
    476325    TABLE->validFrom = (psF64)TABLE->index->data.S64[0];                        \
    477     TABLE->validTo   = (psF64)TABLE->index->data.S64[TABLE->index->nalloc-1];   \
     326    TABLE->validTo   = (psF64)TABLE->index->data.S64[TABLE->index->n-1];        \
    478327    break;                                                                      \
    479328case PS_TYPE_F32:                                                               \
    480329    TABLE->validFrom = (psF64)TABLE->index->data.F32[0];                        \
    481     TABLE->validTo   = (psF64)TABLE->index->data.F32[TABLE->index->nalloc-1];   \
     330    TABLE->validTo   = (psF64)TABLE->index->data.F32[TABLE->index->n-1];        \
    482331    break;                                                                      \
    483332case PS_TYPE_F64:                                                               \
    484333    TABLE->validFrom = (psF64)TABLE->index->data.F64[0];                        \
    485     TABLE->validTo   = (psF64)TABLE->index->data.F64[TABLE->index->nalloc-1];   \
     334    TABLE->validTo   = (psF64)TABLE->index->data.F64[TABLE->index->n-1];        \
    486335    break;                                                                      \
    487336default:                                                                        \
     
    513362case PS_TYPE_S32:                                                                          \
    514363    ((psVector*)VEC_OUT)->data.S32[INDEX_OUT] = ((psVector*)VEC_IN)->data.S32[INDEX_IN];   \
     364    if(INDEX_OUT == 0) {                                                                   \
     365        validFrom = ((psVector*)VEC_OUT)->data.S32[INDEX_OUT];                             \
     366    }                                                                                      \
     367    if(INDEX_OUT == ((psVector*)VEC_OUT)->n-1 ) {                                          \
     368        validTo = ((psVector*)VEC_OUT)->data.S32[INDEX_OUT];                               \
     369    }                                                                                      \
    515370    break;                                                                                 \
    516371case PS_TYPE_S64:                                                                          \
    517372    ((psVector*)VEC_OUT)->data.S64[INDEX_OUT] = ((psVector*)VEC_IN)->data.S64[INDEX_IN];   \
     373    if(INDEX_OUT == 0) {                                                                   \
     374        validFrom = ((psVector*)VEC_OUT)->data.S64[INDEX_OUT];                             \
     375    }                                                                                      \
     376    if(INDEX_OUT == ((psVector*)VEC_OUT)->n-1 ) {                                          \
     377        validTo = ((psVector*)VEC_OUT)->data.S64[INDEX_OUT];                               \
     378    }                                                                                      \
    518379    break;                                                                                 \
    519380case PS_TYPE_F32:                                                                          \
    520381    ((psVector*)VEC_OUT)->data.F32[INDEX_OUT] = ((psVector*)VEC_IN)->data.F32[INDEX_IN];   \
     382    if(INDEX_OUT == 0) {                                                                   \
     383        validFrom = ((psVector*)VEC_OUT)->data.F32[INDEX_OUT];                             \
     384    }                                                                                      \
     385    if(INDEX_OUT == ((psVector*)VEC_OUT)->n-1 ) {                                          \
     386        validTo = ((psVector*)VEC_OUT)->data.F32[INDEX_OUT];                               \
     387    }                                                                                      \
    521388    break;                                                                                 \
    522389case PS_TYPE_F64:                                                                          \
    523390    ((psVector*)VEC_OUT)->data.F64[INDEX_OUT] = ((psVector*)VEC_IN)->data.F64[INDEX_IN];   \
     391    if(INDEX_OUT == 0) {                                                                   \
     392        validFrom = ((psVector*)VEC_OUT)->data.F64[INDEX_OUT];                             \
     393    }                                                                                      \
     394    if(INDEX_OUT == ((psVector*)VEC_OUT)->n-1 ) {                                          \
     395        validTo = ((psVector*)VEC_OUT)->data.F64[INDEX_OUT];                               \
     396    }                                                                                      \
    524397    break;                                                                                 \
    525398default:                                                                                   \
     
    527400}
    528401
    529 
    530 psLookupTable* psLookupTableRead(psLookupTable *table)
    531 {
    532     bool typeLine = true;
    533     char *line = NULL;
    534     char *strType = NULL;
    535     char *strValue = NULL;
    536     char *linePtr = NULL;
    537     psParseErrorType status = PS_PARSE_SUCCESS;
    538     psParseErrorType lineStatus = PS_PARSE_SUCCESS;
    539     psU64 lineCount = 0;
    540     psU64 numRows = 0;
    541     psU64 numCols = 0;
    542     psU64 failedLines = 0;
    543     FILE *fp = NULL;
    544     psElemType elemType;
    545     psVector *indexVec = NULL;
    546     psVector *valuesVec = NULL;
    547     psArray *values = NULL;
    548     psBool sortIndex = false;
     402psArray *psVectorsReadFromFile(const char *filename, const char *format)
     403{
     404    psArray*          outputArray = NULL;
     405    psVector*         colVector   = NULL;
     406    char*             strValue    = NULL;
     407    char*             strNum      = NULL;
     408    char*             line        = NULL;
     409    char*             linePtr     = NULL;
     410    int               numCols     = 0;
     411    int               numRows     = 0;
     412    FILE*             fp          = NULL;
     413    const char*       tempFormat  = NULL;
     414    psParseErrorType  parseStatus = PS_PARSE_SUCCESS;
     415
     416    // Check for nul file name
     417    PS_ASSERT_PTR_NON_NULL(filename,NULL);
     418
     419    // Parse format string for valid string
     420    PS_ASSERT_PTR_NON_NULL(format,NULL);
     421
     422    // Create temp pointer which can then be used several times
     423    tempFormat = format;
     424
     425    // Create output array and set array elements to zero
     426    outputArray = psArrayAlloc(10);
     427    outputArray->n = 0;
     428
     429    // Parse the format string to determine how many vectors
     430    // and whether the format string is valid
     431    while((strValue=getToken((char**)&tempFormat," ",&parseStatus))) {
     432
     433        // Check for %d format sub string
     434        if(strcmp(strValue,"\%d") == 0 ) {
     435            numCols++;
     436            colVector = psVectorAlloc(1,PS_TYPE_S32);
     437            outputArray = psArrayAdd(outputArray,1,colVector);
     438            psFree(colVector);
     439        } else if (strcmp(strValue,"\%ld") == 0) {
     440            numCols++;
     441            colVector = psVectorAlloc(1,PS_TYPE_S64);
     442            outputArray = psArrayAdd(outputArray,1,colVector);
     443            psFree(colVector);
     444        } else if (strcmp(strValue,"\%f") == 0) {
     445            numCols++;
     446            colVector = psVectorAlloc(1,PS_TYPE_F32);
     447            outputArray = psArrayAdd(outputArray,1,colVector);
     448            psFree(colVector);
     449        } else if (strcmp(strValue,"\%lf") == 0) {
     450            numCols++;
     451            colVector = psVectorAlloc(1,PS_TYPE_F64);
     452            outputArray = psArrayAdd(outputArray,1,colVector);
     453            psFree(colVector);
     454        } else if (strstr(strValue,"\%*") != 0) {
     455            // Don't increase number of columns
     456        } else {
     457            psError(PS_ERR_BAD_PARAMETER_VALUE,true,"Invalid format specifier");
     458            psFree(strValue);
     459            numCols = 0;
     460            break;
     461        }
     462        psFree(strValue);
     463    }
     464
     465    // If the format string was parsed successfully and return numCols the
     466    // prepare to open file and read values
     467    if(numCols > 0) {
     468
     469        // Open specified file
     470        if((fp=fopen(filename, "r")) == NULL) {
     471            psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_FILE_NOT_FOUND,
     472                    filename);
     473            psFree(outputArray);
     474            return NULL;
     475        } else {
     476            // Initialize array index
     477            int arrayIndex = 0;
     478
     479            // Create reusable line for continuous read
     480            line = (char*)psAlloc(MAX_STRING_LENGTH*sizeof(char));
     481
     482            // Loop through file to get numRows, numCols, and column data types
     483            while((fgets(line, MAX_STRING_LENGTH, fp) != NULL) && (parseStatus == PS_PARSE_SUCCESS)) {
     484
     485                // Copy pointer to line for parsing
     486                linePtr = line;
     487
     488                // If line is not a comment or blank, then extract data
     489                if(!ignoreLine(linePtr)) {
     490                    numRows++;
     491
     492                    // Copy format pointer for parsing
     493                    tempFormat = format;
     494                    arrayIndex = 0;
     495                    parseStatus = PS_PARSE_SUCCESS;
     496
     497                    // Loop through format and line strings to get values in text table file
     498                    while((strValue=getToken((char**)&tempFormat," ",&parseStatus)) &&
     499                            (strNum=getToken((char**)&linePtr," ",&parseStatus)) ) {
     500
     501                        // Set column vector
     502                        colVector = outputArray->data[arrayIndex];
     503
     504                        // Set column entries based on format string defining the type
     505                        if(strcmp(strValue,"\%d") == 0 ) {
     506                            colVector = psVectorRecycle(colVector, numRows, colVector->type.type);
     507                            parseValue(colVector,numRows-1,strNum,&parseStatus);
     508                            arrayIndex++;
     509                        } else if (strcmp(strValue,"\%ld") == 0) {
     510                            colVector = psVectorRecycle(colVector, numRows, colVector->type.type);
     511                            parseValue(colVector,numRows-1,strNum,&parseStatus);
     512                            arrayIndex++;
     513                        } else if (strcmp(strValue,"\%f") == 0) {
     514                            colVector = psVectorRecycle(colVector, numRows, colVector->type.type);
     515                            parseValue(colVector,numRows-1,strNum,&parseStatus);
     516                            arrayIndex++;
     517                        } else if (strcmp(strValue,"\%lf") == 0) {
     518                            colVector = psVectorRecycle(colVector, numRows, colVector->type.type);
     519                            parseValue(colVector,numRows-1,strNum,&parseStatus);
     520                            arrayIndex++;
     521                        } else if (strstr(strValue,"\%*") != 0) {
     522                            // Don't increase number of columns
     523                        }
     524                        psFree(strValue);
     525                        psFree(strNum);
     526
     527                        // If the file line was not parsed successful report error and return NULL
     528                        if(parseStatus != PS_PARSE_SUCCESS) {
     529                            psError(PS_ERR_UNKNOWN,true,"Parsing text file failed.");
     530                            fclose(fp);
     531                            psFree(outputArray);
     532                            psFree(line);
     533                            return NULL;
     534                        }
     535                    }
     536                }  // ignore line
     537            }
     538
     539            // Read on the lines in the file - close file pointer
     540            fclose(fp);
     541            psFree(line);
     542        }
     543    } else {
     544        // Format string parse error detected
     545        psError(PS_ERR_UNKNOWN,true,"Format string was not parsed sucessfully");
     546        psFree(outputArray);
     547        return NULL;
     548    }
     549
     550    // Return populated array
     551    return outputArray;
     552}
     553
     554psLookupTable *psLookupTableImport(psLookupTable *table, const psArray *vectors, int indexCol)
     555{
     556    psLookupTable* outputTable = NULL;
     557    psBool         sortNeeded  = false;
     558    psF64          validTo     = 0;
     559    psF64          validFrom   = 0;
    549560
    550561    // Check for NULL input table
    551562    PS_ASSERT_PTR_NON_NULL(table,NULL);
    552563
    553     // Check for input table with NULL file name
    554     PS_ASSERT_PTR_NON_NULL(table->fileName,NULL);
    555 
    556     // Open table file specified by table->fileName
    557     if((fp=fopen(table->fileName, "r")) == NULL) {
    558         psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_FILE_NOT_FOUND,
    559                 table->fileName);
    560         return table;
    561     }
    562 
    563     // Initialize vector pointers
    564     indexVec = table->index;
    565     values = table->values = psArrayAlloc(10);
    566     values->n = 0;
    567 
    568     // Create reusable line for continuous read
    569     line = (char*)psAlloc(MAX_STRING_LENGTH*sizeof(char));
    570 
    571     // Loop through file to get numRows, numCols, and column data types
    572     while((fgets(line, MAX_STRING_LENGTH, fp) != NULL) && (lineStatus == PS_PARSE_SUCCESS)) {
    573 
    574         // Initialize variables for new line
    575         linePtr = line;
    576         lineCount++;
    577 
    578         // If line is not a comment or blank, then extract data
    579         if(!ignoreLine(linePtr)) {
    580 
    581             if(typeLine == true) {
    582 
    583                 // Determine column types from first line in data file after comments
    584                 while((strType=getToken(&linePtr," ",&status))) {
    585                     numCols++;
    586                     typeLine = false;
    587                     if(!strncmp(strType, "psU8", 4)) {
    588                         elemType = PS_TYPE_U8;
    589                     } else if(!strncmp(strType, "psS8", 4)) {
    590                         elemType = PS_TYPE_S8;
    591                     } else if(!strncmp(strType, "psU16", 5)) {
    592                         elemType = PS_TYPE_U16;
    593                     } else if(!strncmp(strType, "psS16", 5)) {
    594                         elemType = PS_TYPE_S16;
    595                     } else if(!strncmp(strType, "psU32", 5)) {
    596                         elemType = PS_TYPE_U32;
    597                     } else if(!strncmp(strType, "psS32", 5)) {
    598                         elemType = PS_TYPE_S32;
    599                     } else if(!strncmp(strType, "psU64", 5)) {
    600                         elemType = PS_TYPE_U64;
    601                     } else if(!strncmp(strType, "psS64", 5)) {
    602                         elemType = PS_TYPE_S64;
    603                     } else if(!strncmp(strType, "psF32", 5)) {
    604                         elemType = PS_TYPE_F32;
    605                     } else if(!strncmp(strType, "psF64", 5)) {
    606                         elemType = PS_TYPE_F64;
    607                     } else {
    608                         status = PS_PARSE_ERROR_TYPE;
    609                     }
    610 
    611                     // Realloc number of columns as you go
    612                     psVector* vec = psVectorAlloc(0, elemType);
    613                     if(numCols == 1) {
    614                         indexVec = vec;
    615                     } else {
    616                         psArrayAdd(values,0,vec);
    617                         psFree(vec);
    618                     }
    619 
    620                     if(status) {
    621                         printError(lineCount, strValue, status);
    622                         failedLines++;
    623                         lineStatus = status;
    624                         status = PS_PARSE_SUCCESS;
    625                     }
    626                     psFree(strType);
    627                 }
    628             } else {
    629                 // Parse and add values to all columns
    630                 numRows++;
    631                 numCols = 0;
    632                 while((strValue=getToken(&linePtr," ",&status))) {
    633                     numCols++;
    634 
    635                     // Realloc number of rows as you go
    636                     if(numCols == 1) {
    637                         sortIndex = false;
    638                         indexVec = psVectorRecycle(indexVec, numRows, indexVec->type.type);
    639                         parseValue(indexVec, numRows-1, strValue, &status);
    640                     } else {
    641                         valuesVec = values->data[numCols-2];
    642                         valuesVec = psVectorRecycle(valuesVec, numRows, valuesVec->type.type);
    643                         parseValue(valuesVec, numRows-1, strValue, &status);
    644                     }
    645 
    646                     if(status) {
    647                         printError(lineCount, strValue, status);
    648                         failedLines++;
    649                         lineStatus = status;
    650                         status = PS_PARSE_SUCCESS;
    651                     }
    652                     psFree(strValue);
    653                 } // end while
    654             } // end else
    655         } // if ignoreLine
    656     } // end while
    657 
    658     psFree(line);
    659 
    660     // Set table for return
    661     table->numRows = numRows;
    662     table->numCols = numCols-1;
    663     table->index = indexVec;
    664     table->values = values;
    665 
    666     // Set table values to indicate error detected during the read
    667     if(lineStatus) {
    668         table->numRows = 0;
    669         table->numCols = 0;
    670         table->validFrom = 0;
    671         table->validTo = 0;
    672         psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psLookupTable_TABLE_INVALID);
    673     } else {
    674         // Check if index vector needs to be sorted
    675         psVector* sortedIndex = psVectorAlloc(table->numRows,PS_TYPE_U32);
    676         sortedIndex = psVectorSortIndex(sortedIndex,table->index);
    677         for(psS32 i = 0; i < numRows; i++ ) {
    678             if(sortedIndex->data.U32[i] != i) {
    679                 sortIndex = true;
    680                 break;
     564    // Check for NULL vectors
     565    PS_ASSERT_PTR_NON_NULL(vectors,NULL);
     566
     567    // Check for invalid index column
     568    if(indexCol < 0 ) {
     569        psError(PS_ERR_BAD_PARAMETER_VALUE,true,"Index column cannot be less than zero");
     570        return NULL;
     571    }
     572
     573    psVector* indexColumnVector = vectors->data[indexCol];
     574    psS32  numRows = indexColumnVector->n;
     575    psS32  numCols = vectors->n;
     576
     577    // Check if array is sorted on the index column
     578    psVector* sortedIndex = psVectorAlloc(numRows,PS_TYPE_U32);
     579    sortedIndex = psVectorSortIndex(sortedIndex,indexColumnVector);
     580    for(psS32 i = 0; i < numRows; i++ ) {
     581        if(sortedIndex->data.U32[i] != i) {
     582            sortNeeded = true;
     583            break;
     584        }
     585    }
     586
     587    // Check if it is necessary to sort value vectors
     588    if(sortNeeded) {
     589        // Allocate new array to contain sorted vectors
     590        psArray* newValueArray = psArrayAlloc(numCols);
     591        for(psS32 j = 0; j < numCols; j++) {
     592            psS32 type = ((psVector*)(vectors->data[j]))->type.type;
     593            newValueArray->data[j] = psVectorAlloc(numRows,type);
     594        }
     595
     596        // Populate new array/vectors with sorted values
     597        for(psS32 i = 0; i < numRows; i++) {
     598            // Populate new index vector
     599            psU32 sortIndex = sortedIndex->data.U32[i];
     600            // For every column populate new value vectors
     601            for(psS32 j=0; j < numCols; j++) {
     602                COPY_VECTOR_VALUES(newValueArray->data[j],i,vectors->data[j], sortIndex)
    681603            }
    682604        }
    683         // Check if it is necessary to sort value vectors
    684         if(sortIndex) {
    685             // Allocate new index vector
    686             psVector* newIndexVector = psVectorAlloc(numRows,indexVec->type.type);
    687             // Allocate new value vectors
    688             psArray* newValueArray = psArrayAlloc(numCols-1);
    689             for(psS32 j = 0; j < numCols-1; j++) {
    690                 psS32 type = ((psVector*)(table->values->data[j]))->type.type;
    691                 newValueArray->data[j] = psVectorAlloc(numRows,type);
    692             }
    693             for(psS32 i = 0; i < numRows; i++) {
    694                 // Populate new index vector
    695                 psU32 sortIndex = sortedIndex->data.U32[i];
    696                 COPY_VECTOR_VALUES(newIndexVector,i, indexVec,sortIndex)
    697                 // For every column populate new value vectors
    698                 for(psS32 j=0; j < numCols-1; j++) {
    699                     COPY_VECTOR_VALUES(newValueArray->data[j],i,table->values->data[j], sortIndex)
    700                 }
    701             }
    702             // Free old index vector
    703             psFree(table->index);
    704             // Free old value vectors
    705             psFree(table->values);
    706             // Assign new vector value to table
    707             table->index = newIndexVector;
    708             // Assign new value vectors to table array
    709             table->values = newValueArray;
     605        // Assign new vector value to table
     606        table->index = newValueArray->data[indexCol];
     607        // Assign new value vectors to table array
     608        table->values = newValueArray;
     609        // Assign indexCol
     610        table->indexCol = indexCol;
     611        // Assign validTo and validFrom values
     612        UPDATE_VALID_TO_FROM(table)
     613
     614        // Set return value
     615        outputTable = table;
     616
     617    } else {
     618        // Index vector is already sorted
     619        // Assign array vector specified by indexCol to table index vector and increment memory ref
     620        table->index = vectors->data[indexCol];
     621        table->values = (psArray*)vectors;
     622        psMemIncrRefCounter((psArray*)vectors);
     623
     624        // Assign indexCol
     625        table->indexCol = indexCol;
     626        // Assign validTo and validFrom values
     627        UPDATE_VALID_TO_FROM(table);
     628
     629        // Set return value
     630        outputTable = table;
     631    }
     632
     633    // Free sort vector
     634    psFree(sortedIndex);
     635
     636    return outputTable;
     637}
     638
     639psS32 psLookupTableRead(psLookupTable* table)
     640{
     641    psS32           numRows  = 0;
     642    psArray*        vectors  = NULL;
     643    psLookupTable*  outTable = NULL;
     644
     645    // Check if the input table is NULL then return 0
     646    PS_ASSERT_PTR_NON_NULL(table,0);
     647
     648    // Read vectors from file specified in table
     649    vectors = psVectorsReadFromFile(table->filename, table->format);
     650
     651    // Check for valid array after reading from file
     652    if(vectors != NULL) {
     653
     654        // Import vector into table
     655        outTable = psLookupTableImport(table, vectors, table->indexCol);
     656
     657        psFree(vectors);
     658
     659        // Update the number of rows read if outTable is not NULL
     660        if(outTable != NULL) {
     661            numRows = table->index->n;
    710662        }
    711         psFree(sortedIndex);
    712         // Update the validTo and validFrom
    713         UPDATE_VALID_TO_FROM(table)
    714     }
    715 
    716     fclose(fp);
    717 
    718     return table;
     663    }
     664
     665    // Return the number of lines read
     666    return numRows;
    719667}
    720668
     
    756704}
    757705
    758 
    759 #define CHECK_LOWER_UPPER_BOUND(TABLE,INDEX,COLUMN)                                \
    760 switch (TABLE->index->type.type) {                                                 \
    761 case PS_TYPE_U8:                                                                   \
    762     if( (psU8)index < TABLE->index->data.U8[0] ) {                                 \
    763         *status = PS_LOOKUP_PAST_TOP;                                              \
    764     }                                                                              \
    765     if( (psU8)index > TABLE->index->data.U8[numRows-1]) {                          \
    766         *status = PS_LOOKUP_PAST_BOTTOM;                                           \
    767     }                                                                              \
    768     break;                                                                         \
    769 case PS_TYPE_U16:                                                                  \
    770     if( (psU16)index < TABLE->index->data.U16[0] ) {                               \
    771         *status = PS_LOOKUP_PAST_TOP;                                              \
    772     }                                                                              \
    773     if( (psU16)index > TABLE->index->data.U16[numRows-1] ) {                       \
    774         *status = PS_LOOKUP_PAST_BOTTOM;                                           \
    775     }                                                                              \
    776     break;                                                                         \
    777 case PS_TYPE_U32:                                                                  \
    778     if( (psU32)index < TABLE->index->data.U32[0]) {                                \
    779         *status = PS_LOOKUP_PAST_TOP;                                              \
    780     }                                                                              \
    781     if ( (psU32)index > TABLE->index->data.U32[numRows-1] ) {                      \
    782         *status = PS_LOOKUP_PAST_BOTTOM;                                           \
    783     }                                                                              \
    784     break;                                                                         \
    785 case PS_TYPE_U64:                                                                  \
    786     if( (psU64)index < TABLE->index->data.U64[0] ) {                               \
    787         *status = PS_LOOKUP_PAST_TOP;                                              \
    788     }                                                                              \
    789     if( (psU64)index > TABLE->index->data.U64[numRows-1] ) {                       \
    790         *status = PS_LOOKUP_PAST_BOTTOM;                                           \
    791     }                                                                              \
    792     break;                                                                         \
    793 case PS_TYPE_S8:                                                                   \
    794     if( (psS8)index < TABLE->index->data.S8[0] ) {                                 \
    795         *status = PS_LOOKUP_PAST_TOP;                                              \
    796     }                                                                              \
    797     if( (psS8)index > TABLE->index->data.S8[numRows-1] ) {                         \
    798         *status = PS_LOOKUP_PAST_BOTTOM;                                           \
    799     }                                                                              \
    800     break;                                                                         \
    801 case PS_TYPE_S16:                                                                  \
    802     if( (psS16)index < TABLE->index->data.S16[0] ) {                               \
    803         *status = PS_LOOKUP_PAST_TOP;                                              \
    804     }                                                                              \
    805     if( (psS16)index > TABLE->index->data.S16[numRows-1] ) {                       \
    806         *status = PS_LOOKUP_PAST_BOTTOM;                                           \
    807     }                                                                              \
    808     break;                                                                         \
    809 case PS_TYPE_S32:                                                                  \
    810     if( (psS32)index < TABLE->index->data.S32[0] ) {                               \
    811         *status = PS_LOOKUP_PAST_TOP;                                              \
    812     }                                                                              \
    813     if( (psS32)index > TABLE->index->data.S32[numRows-1] ) {                       \
    814         *status = PS_LOOKUP_PAST_BOTTOM;                                           \
    815     }                                                                              \
    816     break;                                                                         \
    817 case PS_TYPE_S64:                                                                  \
    818     if( (psS64)index < TABLE->index->data.S64[0] ) {                               \
    819         *status = PS_LOOKUP_PAST_TOP;                                              \
    820     }                                                                              \
    821     if( (psS64)index > TABLE->index->data.S64[numRows-1] ) {                       \
    822         *status = PS_LOOKUP_PAST_BOTTOM;                                           \
    823     }                                                                              \
    824     break;                                                                         \
    825 case PS_TYPE_F32:                                                                  \
    826     if( (psF32)index < TABLE->index->data.F32[0] ) {                               \
    827         *status = PS_LOOKUP_PAST_TOP;                                              \
    828     }                                                                              \
    829     if( (psF32)index > TABLE->index->data.F32[numRows-1] ) {                       \
    830         *status = PS_LOOKUP_PAST_BOTTOM;                                           \
    831     }                                                                              \
    832     break;                                                                         \
    833 case PS_TYPE_F64:                                                                  \
    834     if( index < TABLE->index->data.F64[0] ) {                                      \
    835         *status = PS_LOOKUP_PAST_TOP;                                              \
    836     }                                                                              \
    837     if( index > TABLE->index->data.F64[numRows-1] ) {                              \
    838         *status = PS_LOOKUP_PAST_BOTTOM;                                           \
    839     }                                                                              \
    840     break;                                                                         \
    841 default:                                                                           \
    842     *status = PS_LOOKUP_ERROR;                                                     \
    843     return NAN;                                                                    \
    844     break;                                                                         \
    845 }                                                                                  \
    846 if(*status == PS_LOOKUP_PAST_TOP) {                                                \
    847     CONVERT_VALUE_TO_F64(((psVector*)(TABLE->values->data[COLUMN])),0,out)         \
    848     return out;                                                                    \
    849 } else if (*status == PS_LOOKUP_PAST_BOTTOM) {                                     \
    850     CONVERT_VALUE_TO_F64(((psVector*)(TABLE->values->data[COLUMN])),numRows-1,out) \
    851     return out;                                                                    \
    852 }
    853 
    854 
    855 psF64 psLookupTableInterpolate(psLookupTable *table, psF64 index, psU64 column, psLookupStatusType *status)
     706#define CHECK_LOWER_UPPER_BOUND(TABLE,INDEX,COLUMN)                     \
     707switch (TABLE->index->type.type) {                                      \
     708case PS_TYPE_S32:                                                       \
     709    if( (psS32)index < TABLE->index->data.S32[0] ) {                    \
     710        return NAN;                                                     \
     711    }                                                                   \
     712    if( (psS32)index > TABLE->index->data.S32[numRows-1] ) {            \
     713        return NAN;                                                     \
     714    }                                                                   \
     715    break;                                                              \
     716case PS_TYPE_S64:                                                       \
     717    if( (psS64)index < TABLE->index->data.S64[0] ) {                    \
     718        return NAN;                                                     \
     719    }                                                                   \
     720    if( (psS64)index > TABLE->index->data.S64[numRows-1] ) {            \
     721        return NAN;                                                     \
     722    }                                                                   \
     723    break;                                                              \
     724case PS_TYPE_F32:                                                       \
     725    if( (psF32)index < TABLE->index->data.F32[0] ) {                    \
     726        return NAN;                                                     \
     727    }                                                                   \
     728    if( (psF32)index > TABLE->index->data.F32[numRows-1] ) {            \
     729        return NAN;                                                     \
     730    }                                                                   \
     731    break;                                                              \
     732case PS_TYPE_F64:                                                       \
     733    if( index < TABLE->index->data.F64[0] ) {                           \
     734        return NAN;                                                     \
     735    }                                                                   \
     736    if( index > TABLE->index->data.F64[numRows-1] ) {                   \
     737        return NAN;                                                     \
     738    }                                                                   \
     739    break;                                                              \
     740default:                                                                \
     741    return NAN;                                                         \
     742    break;                                                              \
     743}
     744
     745psF64 psLookupTableInterpolate(const psLookupTable *table, psF64 index, psS32 column)
    856746{
    857747    psU64 hiIdx = 0;
     
    867757    psArray *values = NULL;
    868758
    869     // Error checks
    870     // Set status to error prior to check since if checks fails it will immediately return
    871     PS_ASSERT_PTR_NON_NULL(status,NAN);
    872     *status = PS_LOOKUP_ERROR;
     759    // Check for NULL table
    873760    PS_ASSERT_PTR_NON_NULL(table,NAN);
     761
    874762    indexVec = table->index;
    875763    values = table->values;
    876     numRows = table->numRows;
    877     numCols = table->numCols;
     764    numRows = table->index->n;
     765    numCols = table->values->n;
    878766    PS_ASSERT_PTR_NON_NULL(indexVec,NAN);
    879767    PS_ASSERT_PTR_NON_NULL(values,NAN);
     
    884772    valuesVec = (psVector*)values->data[column];
    885773    PS_ASSERT_PTR_NON_NULL(indexVec,NAN);
    886 
    887     // Set status to success since it passed all parameter checks
    888     *status = PS_LOOKUP_SUCCESS;
    889774
    890775    // Verify the index is within the bounds of the table
     
    898783            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
    899784                    PS_ERRORTEXT_psLookupTable_INTERPOLATE_HIGH, hiIdx);
    900             *status = PS_LOOKUP_ERROR;
    901785            return NAN;
    902786        }
     
    909793        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
    910794                PS_ERRORTEXT_psLookupTable_INTERPOLATE_LOW, loIdx);
    911         *status = PS_LOOKUP_ERROR;
    912795        return NAN;
    913796    }
     
    919802    if(fabs(denom) < FLT_EPSILON) {
    920803        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_DIVIDE_BY_ZERO);
    921         *status = PS_LOOKUP_ERROR;
    922804        return NAN;
    923805    } else {
     
    934816}
    935817
    936 psVector* psLookupTableInterpolateAll(psLookupTable *table, psF64 index, psVector *stats)
    937 {
    938     psU64 i = 0;
     818psVector* psLookupTableInterpolateAll(psLookupTable *table, psF64 index)
     819{
    939820    psU64 numCols = 0;
    940821    psVector *outVector = NULL;
    941     psLookupStatusType status = PS_LOOKUP_SUCCESS;
    942822
    943823    // Error checks
    944824    PS_ASSERT_PTR_NON_NULL(table,NULL);
    945     PS_ASSERT_PTR_NON_NULL(stats,NULL);
    946     numCols = table->numCols;
     825    numCols = table->values->n;
    947826    PS_ASSERT_INT_UNEQUAL(numCols, 0,NULL);
    948827
    949     outVector = psVectorAlloc(numCols+1, PS_TYPE_F64);
     828    // Create output vector
     829    outVector = psVectorAlloc(numCols, PS_TYPE_F64);
    950830
    951831    // Fill vectors with results and status of results
    952     for(i=0; i<numCols; i++) {
    953         outVector->data.F64[i] = psLookupTableInterpolate(table, index, i, &status);
    954         stats->data.U32[i] = status;
     832    for(psU64 i=0; i<numCols; i++) {
     833        outVector->data.F64[i] = psLookupTableInterpolate(table, index, i);
     834        if(isnan(outVector->data.F64[i])) {
     835            // Free allocated vector
     836            psFree(outVector);
     837            outVector = NULL;
     838            // Break out of loop since error detected
     839            break;
     840        }
    955841    }
    956842
  • trunk/psLib/src/dataIO/psLookupTable.h

    r3684 r4050  
    77*  @author Ross Harman, MHPCC
    88*
    9 *  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
    10 *  @date $Date: 2005-04-08 17:58:57 $
     9*  @version $Revision: 1.6 $ $Name: not supported by cvs2svn $
     10*  @date $Date: 2005-05-31 21:46:56 $
    1111*
    1212*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    2828typedef struct
    2929{
    30     const char *fileName;              ///< Name of file with table
    31     psU64 numRows;                     ///< Number of table rows
    32     psU64 numCols;                     ///< Number of table columns
     30    const char *filename;              ///< Name of file with table
     31    const char *format;                ///< scanf-like format string for file
     32    unsigned int indexCol;             ///< Column of the index vector (starting at zero)
     33    psVector *index;                   ///< Vector of independent index values
     34    psArray *values;                   ///< Array of dependent table values corresponding to index values
    3335    psF64 validFrom;                   ///< Lower bound for rable read
    3436    psF64 validTo;                     ///< Upper bound for table read
    35     psVector *index;                   ///< Vector of independent index values
    36     psArray *values;                   ///< Array of dependent table values corresponding to index values
    3737}
    3838psLookupTable;
     
    6969psLookupTable* psLookupTableAlloc(
    7070    const char *fileName,           ///< Name of file to read
    71     psF64 validFrom,                ///< Lower bound for rable read
    72     psF64 validTo                   ///< Upper bound for table read
     71    const char *format,             ///< scanf-like format string
     72    int indexCol                    ///< Column of the index vector (starting at zero)
     73);
     74
     75/** Read vectors from file
     76 *
     77 *  Read numeric vectors from ASCII text file
     78 *
     79 *  @return psArray*  New array of psVectors corresponding to the columns of the table
     80 */
     81psArray *psVectorsReadFromFile(
     82    const char* filename,            ///< File to be read
     83    const char* format               ///< scanf-like format string
     84);
     85
     86/** Import arrays of vectors into a table
     87 *
     88 *  Import array of vectors read from text file into a table structure
     89 *
     90 *  @return psLookupTable*  Lookup table structure with array vector data
     91 */
     92psLookupTable *psLookupTableImport(
     93    psLookupTable *table,            ///< Lookup table into which to import
     94    const psArray *vectors,          ///< Array of vectors
     95    int indexCol                     ///< Index of the index vector in the array of vectors
    7396);
    7497
     
    77100 *  Reads a lookup table and fills corresponding psLookupTable struct.
    78101 *
    79  *  @return psLookupTable*     New psLookupTable struct.
     102 *  @return psS32     Number of valid lines read
    80103 */
    81 psLookupTable* psLookupTableRead(
     104psS32 psLookupTableRead(
    82105    psLookupTable *table            ///< Table to read
    83106);
     
    91114 */
    92115psF64 psLookupTableInterpolate(
    93     psLookupTable *table,           ///< Table with data
     116    const psLookupTable *table,     ///< Table with data
    94117    psF64 index,                    ///< Value to be interpolated
    95     psU64 column,                   ///< Column in table to be interpolated
    96     psLookupStatusType *status      ///< Status of lookup
     118    psS32 column                    ///< Column in table to be interpolated
    97119);
    98120
     
    106128psVector* psLookupTableInterpolateAll(
    107129    psLookupTable *table,           ///< Table with data
    108     psF64 index,                    ///< Value to be interpolated
    109     psVector *stats                 ///< Vector of status for each lookup
     130    psF64 index                     ///< Value to be interpolated
    110131);
    111132
  • trunk/psLib/src/types/psLookupTable.c

    r4031 r4050  
    77*  @author Ross Harman, MHPCC
    88*
    9 *  @version $Revision: 1.14 $ $Name: not supported by cvs2svn $
    10 *  @date $Date: 2005-05-25 22:46:47 $
     9*  @version $Revision: 1.15 $ $Name: not supported by cvs2svn $
     10*  @date $Date: 2005-05-31 21:46:56 $
    1111*
    12 *  Copyright 2004-5 Maui High Performance Computing Center, University of Hawaii
     12*  Copyright 2004-2005 Maui High Performance Computing Center, Univ. of Hawaii
    1313*/
    1414#include <stdio.h>
     
    6464static char *cleanString(char *inString, int sLen);
    6565static char* getToken(char **inString, char *delimiter, psParseErrorType *status);
    66 static psU8 parseU8(char *inString, psParseErrorType *status);
    67 static psS8 parseS8(char *inString, psParseErrorType *status);
    68 static psU16 parseU16(char *inString, psParseErrorType *status);
    69 static psS16 parseS16(char *inString, psParseErrorType *status);
    70 static psU32 parseU32(char *inString, psParseErrorType *status);
    7166static psS32 parseS32(char *inString, psParseErrorType *status);
    72 static psU64 parseU64(char *inString, psParseErrorType *status);
    7367static psS64 parseS64(char *inString, psParseErrorType *status);
    7468static psF32 parseF32(char *inString, psParseErrorType *status);
     
    8781        inString++;
    8882    }
    89 
    9083    return true;
    9184}
     
    10093    char *cleaned = NULL;
    10194
    102 
    10395    ptrB = inString;
    10496
    105     /* Skip over leading # or whitespace */
     97    // Skip over leading # or whitespace
    10698    while (isspace(*ptrB) || *ptrB=='#') {
    10799        ptrB++;
    108100    }
    109101
    110     /* Skip over trailing whitespace, null terminators, and # characters */
     102    // Skip over trailing whitespace, null terminators, and # characters
    111103    ptrE = inString + sLen;
    112104    while(isspace(*ptrE) || *ptrE=='\0' || *ptrE=='#') {
     
    130122    char *cleanToken = NULL;
    131123    int sLen = 0;
    132 
    133124
    134125    // Skip over leading whitespace
     
    151142
    152143    return cleanToken;
    153 }
    154 
    155 /** Returns single parsed value as a psU8. The input string must be cleaned and null terminated. */
    156 static psU8 parseU8(char *inString, psParseErrorType *status)
    157 {
    158     char *end = NULL;
    159     psU8 value = 0.0;
    160 
    161 
    162     value = (psU8)strtoul(inString, &end, 0);
    163     if(*end != '\0') {
    164         *status = PS_PARSE_ERROR_VALUE;
    165     } else if(inString==end) {
    166         *status = PS_PARSE_ERROR_VALUE;
    167     }
    168 
    169     return value;
    170 }
    171 
    172 /** Returns single parsed value as a psS8. The input string must be cleaned and null terminated. */
    173 static psS8 parseS8(char *inString, psParseErrorType *status)
    174 {
    175     char *end = NULL;
    176     psS8 value = 0.0;
    177 
    178 
    179     value = (psS8)strtol(inString, &end, 0);
    180     if(*end != '\0') {
    181         *status = PS_PARSE_ERROR_VALUE;
    182     } else if(inString==end) {
    183         *status = PS_PARSE_ERROR_VALUE;
    184     }
    185 
    186     return value;
    187 }
    188 
    189 /** Returns single parsed value as a psU16. The input string must be cleaned and null terminated. */
    190 static psU16 parseU16(char *inString, psParseErrorType *status)
    191 {
    192     char *end = NULL;
    193     psU16 value = 0.0;
    194 
    195 
    196     value = (psU16)strtoul(inString, &end, 0);
    197     if(*end != '\0') {
    198         *status = PS_PARSE_ERROR_VALUE;
    199     } else if(inString==end) {
    200         *status = PS_PARSE_ERROR_VALUE;
    201     }
    202 
    203     return value;
    204 }
    205 
    206 /** Returns single parsed value as a psS16. The input string must be cleaned and null terminated. */
    207 static psS16 parseS16(char *inString, psParseErrorType *status)
    208 {
    209     char *end = NULL;
    210     psS16 value = 0.0;
    211 
    212 
    213     value = (psS16)strtol(inString, &end, 0);
    214     if(*end != '\0') {
    215         *status = PS_PARSE_ERROR_VALUE;
    216     } else if(inString==end) {
    217         *status = PS_PARSE_ERROR_VALUE;
    218     }
    219 
    220     return value;
    221 }
    222 
    223 /** Returns single parsed value as a psU32. The input string must be cleaned and null terminated. */
    224 static psU32 parseU32(char *inString, psParseErrorType *status)
    225 {
    226     char *end = NULL;
    227     psU32 value = 0.0;
    228 
    229 
    230     value = (psU32)strtoul(inString, &end, 0);
    231     if(*end != '\0') {
    232         *status = PS_PARSE_ERROR_VALUE;
    233     } else if(inString==end) {
    234         *status = PS_PARSE_ERROR_VALUE;
    235     }
    236 
    237     return value;
    238144}
    239145
     
    255161}
    256162
    257 /** Returns single parsed value as a psU64. The input string must be cleaned and null terminated. */
    258 static psU64 parseU64(char *inString, psParseErrorType *status)
    259 {
    260     char *end = NULL;
    261     psU64 value = 0.0;
    262 
    263 
    264     value = (psU64)strtoull(inString, &end, 0);
    265     if(*end != '\0') {
    266         *status = PS_PARSE_ERROR_VALUE;
    267     } else if(inString==end) {
    268         *status = PS_PARSE_ERROR_VALUE;
    269     }
    270 
    271     return value;
    272 }
    273 
    274163/** Returns single parsed value as a psS64. The input string must be cleaned and null terminated. */
    275164static psS64 parseS64(char *inString, psParseErrorType *status)
     
    277166    char *end = NULL;
    278167    psS64 value = 0.0;
    279 
    280168
    281169    value = (psS64)strtoll(inString, &end, 0);
     
    295183    psF32 value = 0.0;
    296184
    297 
    298185    value = (psF32)strtof(inString, &end);
    299186    if(*end != '\0') {
     
    312199    psF64 value = 0.0;
    313200
    314 
    315201    value = (psF64)strtod(inString, &end);
    316202    if(*end != '\0') {
     
    338224
    339225    switch(type) {
    340     case PS_TYPE_U8:
    341         vec->data.U8[index] = parseU8(strValue, status);
    342         break;
    343     case PS_TYPE_S8:
    344         vec->data.S8[index] = parseS8(strValue, status);
    345         break;
    346     case PS_TYPE_U16:
    347         vec->data.U16[index] = parseU16(strValue, status);
    348         break;
    349     case PS_TYPE_S16:
    350         vec->data.S16[index] = parseS16(strValue, status);
    351         break;
    352     case PS_TYPE_U32:
    353         vec->data.U32[index] = parseU32(strValue, status);
    354         break;
    355226    case PS_TYPE_S32:
    356227        vec->data.S32[index] = parseS32(strValue, status);
    357         break;
    358     case PS_TYPE_U64:
    359         vec->data.U64[index] = parseU64(strValue, status);
    360228        break;
    361229    case PS_TYPE_S64:
     
    375243}
    376244
    377 static psParseErrorType printError(psU64 lineCount, char* badText, psParseErrorType status)
    378 {
    379     switch(status) {
    380     case PS_PARSE_ERROR_VALUE:
    381         psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_PARSE_VALUE, badText, lineCount);
    382         break;
    383     case PS_PARSE_ERROR_TYPE:
    384         psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_PARSE_TYPE, badText, lineCount);
    385         break;
    386     case PS_PARSE_ERROR_GENERAL:
    387         psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_PARSE_GENERAL, badText, lineCount);
    388         break;
    389     default:
    390         psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_INVALID_TYPE, badText, lineCount);
    391     }
    392 
    393     return PS_LOOKUP_SUCCESS;
    394 }
    395 
    396245static void lookupTableFree(psLookupTable* table)
    397246{
     
    401250
    402251    psFree(table->values);
    403     psFree(table->index);
    404     psFree((char*)table->fileName);
     252    psFree((char*)table->filename);
     253    psFree((char*)table->format);
    405254}
    406255
     
    409258/*****************************************************************************/
    410259
    411 psLookupTable* psLookupTableAlloc(const char *fileName, psF64 validFrom, psF64 validTo)
     260psLookupTable* psLookupTableAlloc(const char *fileName, const char *format, int indexCol)
    412261{
    413262    psLookupTable *outTable = NULL;
    414 
    415263
    416264    // Can't read table if you don't know its name
    417265    PS_ASSERT_PTR_NON_NULL(fileName,NULL);
    418266
     267    // Can't read table if you don't know its format
     268    PS_ASSERT_PTR_NON_NULL(format,NULL);
     269
    419270    // Allocate lookup table
    420271    outTable = (psLookupTable*)psAlloc(sizeof(psLookupTable));
     
    423274    psMemSetDeallocator(outTable, (psFreeFcn)lookupTableFree);
    424275
    425     // Allocate and set metadata item comment
    426     outTable->fileName = psStringCopy(fileName);
    427 
    428     // Number of table rows and columns. Automatically resized by table read.
    429     outTable->numRows = 0;
    430     outTable->numCols = 0;
     276    // Allocate and set file name and format strings
     277    outTable->filename = psStringCopy(fileName);
     278    outTable->format = psStringCopy(format);
    431279
    432280    // Valid ranges. Automatically set by table read if both zero.
    433     outTable->validFrom = validFrom;
    434     outTable->validTo = validTo;
     281    outTable->validFrom = 0;
     282    outTable->validTo = 0;
     283    outTable->indexCol = indexCol;
    435284
    436285    // Vector of independent index values. Filled by table read.
     
    447296case PS_TYPE_U8:                                                                \
    448297    TABLE->validFrom = (psF64)TABLE->index->data.U8[0];                         \
    449     TABLE->validTo   = (psF64)TABLE->index->data.U8[TABLE->index->nalloc-1];    \
     298    TABLE->validTo   = (psF64)TABLE->index->data.U8[TABLE->index->n-1];         \
    450299    break;                                                                      \
    451300case PS_TYPE_S8:                                                                \
    452301    TABLE->validFrom = (psF64)TABLE->index->data.S8[0];                         \
    453     TABLE->validTo   = (psF64)TABLE->index->data.S8[TABLE->index->nalloc-1];    \
     302    TABLE->validTo   = (psF64)TABLE->index->data.S8[TABLE->index->n-1];         \
    454303    break;                                                                      \
    455304case PS_TYPE_U16:                                                               \
    456305    TABLE->validFrom = (psF64)TABLE->index->data.U16[0];                        \
    457     TABLE->validTo   = (psF64)TABLE->index->data.U16[TABLE->index->nalloc-1];   \
     306    TABLE->validTo   = (psF64)TABLE->index->data.U16[TABLE->index->n-1];        \
    458307    break;                                                                      \
    459308case PS_TYPE_S16:                                                               \
    460309    TABLE->validFrom = (psF64)TABLE->index->data.S16[0];                        \
    461     TABLE->validTo   = (psF64)TABLE->index->data.S16[TABLE->index->nalloc-1];   \
     310    TABLE->validTo   = (psF64)TABLE->index->data.S16[TABLE->index->n-1];        \
    462311    break;                                                                      \
    463312case PS_TYPE_U32:                                                               \
    464313    TABLE->validFrom = (psF64)TABLE->index->data.U32[0];                        \
    465     TABLE->validTo   = (psF64)TABLE->index->data.U32[TABLE->index->nalloc-1];   \
     314    TABLE->validTo   = (psF64)TABLE->index->data.U32[TABLE->index->n-1];        \
    466315    break;                                                                      \
    467316case PS_TYPE_S32:                                                               \
    468317    TABLE->validFrom = (psF64)TABLE->index->data.S32[0];                        \
    469     TABLE->validTo   = (psF64)TABLE->index->data.S32[TABLE->index->nalloc-1];   \
     318    TABLE->validTo   = (psF64)TABLE->index->data.S32[TABLE->index->n-1];        \
    470319    break;                                                                      \
    471320case PS_TYPE_U64:                                                               \
    472321    TABLE->validFrom = (psF64)TABLE->index->data.U64[0];                        \
    473     TABLE->validTo   = (psF64)TABLE->index->data.U64[TABLE->index->nalloc-1];   \
     322    TABLE->validTo   = (psF64)TABLE->index->data.U64[TABLE->index->n-1];        \
    474323    break;                                                                      \
    475324case PS_TYPE_S64:                                                               \
    476325    TABLE->validFrom = (psF64)TABLE->index->data.S64[0];                        \
    477     TABLE->validTo   = (psF64)TABLE->index->data.S64[TABLE->index->nalloc-1];   \
     326    TABLE->validTo   = (psF64)TABLE->index->data.S64[TABLE->index->n-1];        \
    478327    break;                                                                      \
    479328case PS_TYPE_F32:                                                               \
    480329    TABLE->validFrom = (psF64)TABLE->index->data.F32[0];                        \
    481     TABLE->validTo   = (psF64)TABLE->index->data.F32[TABLE->index->nalloc-1];   \
     330    TABLE->validTo   = (psF64)TABLE->index->data.F32[TABLE->index->n-1];        \
    482331    break;                                                                      \
    483332case PS_TYPE_F64:                                                               \
    484333    TABLE->validFrom = (psF64)TABLE->index->data.F64[0];                        \
    485     TABLE->validTo   = (psF64)TABLE->index->data.F64[TABLE->index->nalloc-1];   \
     334    TABLE->validTo   = (psF64)TABLE->index->data.F64[TABLE->index->n-1];        \
    486335    break;                                                                      \
    487336default:                                                                        \
     
    513362case PS_TYPE_S32:                                                                          \
    514363    ((psVector*)VEC_OUT)->data.S32[INDEX_OUT] = ((psVector*)VEC_IN)->data.S32[INDEX_IN];   \
     364    if(INDEX_OUT == 0) {                                                                   \
     365        validFrom = ((psVector*)VEC_OUT)->data.S32[INDEX_OUT];                             \
     366    }                                                                                      \
     367    if(INDEX_OUT == ((psVector*)VEC_OUT)->n-1 ) {                                          \
     368        validTo = ((psVector*)VEC_OUT)->data.S32[INDEX_OUT];                               \
     369    }                                                                                      \
    515370    break;                                                                                 \
    516371case PS_TYPE_S64:                                                                          \
    517372    ((psVector*)VEC_OUT)->data.S64[INDEX_OUT] = ((psVector*)VEC_IN)->data.S64[INDEX_IN];   \
     373    if(INDEX_OUT == 0) {                                                                   \
     374        validFrom = ((psVector*)VEC_OUT)->data.S64[INDEX_OUT];                             \
     375    }                                                                                      \
     376    if(INDEX_OUT == ((psVector*)VEC_OUT)->n-1 ) {                                          \
     377        validTo = ((psVector*)VEC_OUT)->data.S64[INDEX_OUT];                               \
     378    }                                                                                      \
    518379    break;                                                                                 \
    519380case PS_TYPE_F32:                                                                          \
    520381    ((psVector*)VEC_OUT)->data.F32[INDEX_OUT] = ((psVector*)VEC_IN)->data.F32[INDEX_IN];   \
     382    if(INDEX_OUT == 0) {                                                                   \
     383        validFrom = ((psVector*)VEC_OUT)->data.F32[INDEX_OUT];                             \
     384    }                                                                                      \
     385    if(INDEX_OUT == ((psVector*)VEC_OUT)->n-1 ) {                                          \
     386        validTo = ((psVector*)VEC_OUT)->data.F32[INDEX_OUT];                               \
     387    }                                                                                      \
    521388    break;                                                                                 \
    522389case PS_TYPE_F64:                                                                          \
    523390    ((psVector*)VEC_OUT)->data.F64[INDEX_OUT] = ((psVector*)VEC_IN)->data.F64[INDEX_IN];   \
     391    if(INDEX_OUT == 0) {                                                                   \
     392        validFrom = ((psVector*)VEC_OUT)->data.F64[INDEX_OUT];                             \
     393    }                                                                                      \
     394    if(INDEX_OUT == ((psVector*)VEC_OUT)->n-1 ) {                                          \
     395        validTo = ((psVector*)VEC_OUT)->data.F64[INDEX_OUT];                               \
     396    }                                                                                      \
    524397    break;                                                                                 \
    525398default:                                                                                   \
     
    527400}
    528401
    529 
    530 psLookupTable* psLookupTableRead(psLookupTable *table)
    531 {
    532     bool typeLine = true;
    533     char *line = NULL;
    534     char *strType = NULL;
    535     char *strValue = NULL;
    536     char *linePtr = NULL;
    537     psParseErrorType status = PS_PARSE_SUCCESS;
    538     psParseErrorType lineStatus = PS_PARSE_SUCCESS;
    539     psU64 lineCount = 0;
    540     psU64 numRows = 0;
    541     psU64 numCols = 0;
    542     psU64 failedLines = 0;
    543     FILE *fp = NULL;
    544     psElemType elemType;
    545     psVector *indexVec = NULL;
    546     psVector *valuesVec = NULL;
    547     psArray *values = NULL;
    548     psBool sortIndex = false;
     402psArray *psVectorsReadFromFile(const char *filename, const char *format)
     403{
     404    psArray*          outputArray = NULL;
     405    psVector*         colVector   = NULL;
     406    char*             strValue    = NULL;
     407    char*             strNum      = NULL;
     408    char*             line        = NULL;
     409    char*             linePtr     = NULL;
     410    int               numCols     = 0;
     411    int               numRows     = 0;
     412    FILE*             fp          = NULL;
     413    const char*       tempFormat  = NULL;
     414    psParseErrorType  parseStatus = PS_PARSE_SUCCESS;
     415
     416    // Check for nul file name
     417    PS_ASSERT_PTR_NON_NULL(filename,NULL);
     418
     419    // Parse format string for valid string
     420    PS_ASSERT_PTR_NON_NULL(format,NULL);
     421
     422    // Create temp pointer which can then be used several times
     423    tempFormat = format;
     424
     425    // Create output array and set array elements to zero
     426    outputArray = psArrayAlloc(10);
     427    outputArray->n = 0;
     428
     429    // Parse the format string to determine how many vectors
     430    // and whether the format string is valid
     431    while((strValue=getToken((char**)&tempFormat," ",&parseStatus))) {
     432
     433        // Check for %d format sub string
     434        if(strcmp(strValue,"\%d") == 0 ) {
     435            numCols++;
     436            colVector = psVectorAlloc(1,PS_TYPE_S32);
     437            outputArray = psArrayAdd(outputArray,1,colVector);
     438            psFree(colVector);
     439        } else if (strcmp(strValue,"\%ld") == 0) {
     440            numCols++;
     441            colVector = psVectorAlloc(1,PS_TYPE_S64);
     442            outputArray = psArrayAdd(outputArray,1,colVector);
     443            psFree(colVector);
     444        } else if (strcmp(strValue,"\%f") == 0) {
     445            numCols++;
     446            colVector = psVectorAlloc(1,PS_TYPE_F32);
     447            outputArray = psArrayAdd(outputArray,1,colVector);
     448            psFree(colVector);
     449        } else if (strcmp(strValue,"\%lf") == 0) {
     450            numCols++;
     451            colVector = psVectorAlloc(1,PS_TYPE_F64);
     452            outputArray = psArrayAdd(outputArray,1,colVector);
     453            psFree(colVector);
     454        } else if (strstr(strValue,"\%*") != 0) {
     455            // Don't increase number of columns
     456        } else {
     457            psError(PS_ERR_BAD_PARAMETER_VALUE,true,"Invalid format specifier");
     458            psFree(strValue);
     459            numCols = 0;
     460            break;
     461        }
     462        psFree(strValue);
     463    }
     464
     465    // If the format string was parsed successfully and return numCols the
     466    // prepare to open file and read values
     467    if(numCols > 0) {
     468
     469        // Open specified file
     470        if((fp=fopen(filename, "r")) == NULL) {
     471            psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_FILE_NOT_FOUND,
     472                    filename);
     473            psFree(outputArray);
     474            return NULL;
     475        } else {
     476            // Initialize array index
     477            int arrayIndex = 0;
     478
     479            // Create reusable line for continuous read
     480            line = (char*)psAlloc(MAX_STRING_LENGTH*sizeof(char));
     481
     482            // Loop through file to get numRows, numCols, and column data types
     483            while((fgets(line, MAX_STRING_LENGTH, fp) != NULL) && (parseStatus == PS_PARSE_SUCCESS)) {
     484
     485                // Copy pointer to line for parsing
     486                linePtr = line;
     487
     488                // If line is not a comment or blank, then extract data
     489                if(!ignoreLine(linePtr)) {
     490                    numRows++;
     491
     492                    // Copy format pointer for parsing
     493                    tempFormat = format;
     494                    arrayIndex = 0;
     495                    parseStatus = PS_PARSE_SUCCESS;
     496
     497                    // Loop through format and line strings to get values in text table file
     498                    while((strValue=getToken((char**)&tempFormat," ",&parseStatus)) &&
     499                            (strNum=getToken((char**)&linePtr," ",&parseStatus)) ) {
     500
     501                        // Set column vector
     502                        colVector = outputArray->data[arrayIndex];
     503
     504                        // Set column entries based on format string defining the type
     505                        if(strcmp(strValue,"\%d") == 0 ) {
     506                            colVector = psVectorRecycle(colVector, numRows, colVector->type.type);
     507                            parseValue(colVector,numRows-1,strNum,&parseStatus);
     508                            arrayIndex++;
     509                        } else if (strcmp(strValue,"\%ld") == 0) {
     510                            colVector = psVectorRecycle(colVector, numRows, colVector->type.type);
     511                            parseValue(colVector,numRows-1,strNum,&parseStatus);
     512                            arrayIndex++;
     513                        } else if (strcmp(strValue,"\%f") == 0) {
     514                            colVector = psVectorRecycle(colVector, numRows, colVector->type.type);
     515                            parseValue(colVector,numRows-1,strNum,&parseStatus);
     516                            arrayIndex++;
     517                        } else if (strcmp(strValue,"\%lf") == 0) {
     518                            colVector = psVectorRecycle(colVector, numRows, colVector->type.type);
     519                            parseValue(colVector,numRows-1,strNum,&parseStatus);
     520                            arrayIndex++;
     521                        } else if (strstr(strValue,"\%*") != 0) {
     522                            // Don't increase number of columns
     523                        }
     524                        psFree(strValue);
     525                        psFree(strNum);
     526
     527                        // If the file line was not parsed successful report error and return NULL
     528                        if(parseStatus != PS_PARSE_SUCCESS) {
     529                            psError(PS_ERR_UNKNOWN,true,"Parsing text file failed.");
     530                            fclose(fp);
     531                            psFree(outputArray);
     532                            psFree(line);
     533                            return NULL;
     534                        }
     535                    }
     536                }  // ignore line
     537            }
     538
     539            // Read on the lines in the file - close file pointer
     540            fclose(fp);
     541            psFree(line);
     542        }
     543    } else {
     544        // Format string parse error detected
     545        psError(PS_ERR_UNKNOWN,true,"Format string was not parsed sucessfully");
     546        psFree(outputArray);
     547        return NULL;
     548    }
     549
     550    // Return populated array
     551    return outputArray;
     552}
     553
     554psLookupTable *psLookupTableImport(psLookupTable *table, const psArray *vectors, int indexCol)
     555{
     556    psLookupTable* outputTable = NULL;
     557    psBool         sortNeeded  = false;
     558    psF64          validTo     = 0;
     559    psF64          validFrom   = 0;
    549560
    550561    // Check for NULL input table
    551562    PS_ASSERT_PTR_NON_NULL(table,NULL);
    552563
    553     // Check for input table with NULL file name
    554     PS_ASSERT_PTR_NON_NULL(table->fileName,NULL);
    555 
    556     // Open table file specified by table->fileName
    557     if((fp=fopen(table->fileName, "r")) == NULL) {
    558         psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_FILE_NOT_FOUND,
    559                 table->fileName);
    560         return table;
    561     }
    562 
    563     // Initialize vector pointers
    564     indexVec = table->index;
    565     values = table->values = psArrayAlloc(10);
    566     values->n = 0;
    567 
    568     // Create reusable line for continuous read
    569     line = (char*)psAlloc(MAX_STRING_LENGTH*sizeof(char));
    570 
    571     // Loop through file to get numRows, numCols, and column data types
    572     while((fgets(line, MAX_STRING_LENGTH, fp) != NULL) && (lineStatus == PS_PARSE_SUCCESS)) {
    573 
    574         // Initialize variables for new line
    575         linePtr = line;
    576         lineCount++;
    577 
    578         // If line is not a comment or blank, then extract data
    579         if(!ignoreLine(linePtr)) {
    580 
    581             if(typeLine == true) {
    582 
    583                 // Determine column types from first line in data file after comments
    584                 while((strType=getToken(&linePtr," ",&status))) {
    585                     numCols++;
    586                     typeLine = false;
    587                     if(!strncmp(strType, "psU8", 4)) {
    588                         elemType = PS_TYPE_U8;
    589                     } else if(!strncmp(strType, "psS8", 4)) {
    590                         elemType = PS_TYPE_S8;
    591                     } else if(!strncmp(strType, "psU16", 5)) {
    592                         elemType = PS_TYPE_U16;
    593                     } else if(!strncmp(strType, "psS16", 5)) {
    594                         elemType = PS_TYPE_S16;
    595                     } else if(!strncmp(strType, "psU32", 5)) {
    596                         elemType = PS_TYPE_U32;
    597                     } else if(!strncmp(strType, "psS32", 5)) {
    598                         elemType = PS_TYPE_S32;
    599                     } else if(!strncmp(strType, "psU64", 5)) {
    600                         elemType = PS_TYPE_U64;
    601                     } else if(!strncmp(strType, "psS64", 5)) {
    602                         elemType = PS_TYPE_S64;
    603                     } else if(!strncmp(strType, "psF32", 5)) {
    604                         elemType = PS_TYPE_F32;
    605                     } else if(!strncmp(strType, "psF64", 5)) {
    606                         elemType = PS_TYPE_F64;
    607                     } else {
    608                         status = PS_PARSE_ERROR_TYPE;
    609                     }
    610 
    611                     // Realloc number of columns as you go
    612                     psVector* vec = psVectorAlloc(0, elemType);
    613                     if(numCols == 1) {
    614                         indexVec = vec;
    615                     } else {
    616                         psArrayAdd(values,0,vec);
    617                         psFree(vec);
    618                     }
    619 
    620                     if(status) {
    621                         printError(lineCount, strValue, status);
    622                         failedLines++;
    623                         lineStatus = status;
    624                         status = PS_PARSE_SUCCESS;
    625                     }
    626                     psFree(strType);
    627                 }
    628             } else {
    629                 // Parse and add values to all columns
    630                 numRows++;
    631                 numCols = 0;
    632                 while((strValue=getToken(&linePtr," ",&status))) {
    633                     numCols++;
    634 
    635                     // Realloc number of rows as you go
    636                     if(numCols == 1) {
    637                         sortIndex = false;
    638                         indexVec = psVectorRecycle(indexVec, numRows, indexVec->type.type);
    639                         parseValue(indexVec, numRows-1, strValue, &status);
    640                     } else {
    641                         valuesVec = values->data[numCols-2];
    642                         valuesVec = psVectorRecycle(valuesVec, numRows, valuesVec->type.type);
    643                         parseValue(valuesVec, numRows-1, strValue, &status);
    644                     }
    645 
    646                     if(status) {
    647                         printError(lineCount, strValue, status);
    648                         failedLines++;
    649                         lineStatus = status;
    650                         status = PS_PARSE_SUCCESS;
    651                     }
    652                     psFree(strValue);
    653                 } // end while
    654             } // end else
    655         } // if ignoreLine
    656     } // end while
    657 
    658     psFree(line);
    659 
    660     // Set table for return
    661     table->numRows = numRows;
    662     table->numCols = numCols-1;
    663     table->index = indexVec;
    664     table->values = values;
    665 
    666     // Set table values to indicate error detected during the read
    667     if(lineStatus) {
    668         table->numRows = 0;
    669         table->numCols = 0;
    670         table->validFrom = 0;
    671         table->validTo = 0;
    672         psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psLookupTable_TABLE_INVALID);
    673     } else {
    674         // Check if index vector needs to be sorted
    675         psVector* sortedIndex = psVectorAlloc(table->numRows,PS_TYPE_U32);
    676         sortedIndex = psVectorSortIndex(sortedIndex,table->index);
    677         for(psS32 i = 0; i < numRows; i++ ) {
    678             if(sortedIndex->data.U32[i] != i) {
    679                 sortIndex = true;
    680                 break;
     564    // Check for NULL vectors
     565    PS_ASSERT_PTR_NON_NULL(vectors,NULL);
     566
     567    // Check for invalid index column
     568    if(indexCol < 0 ) {
     569        psError(PS_ERR_BAD_PARAMETER_VALUE,true,"Index column cannot be less than zero");
     570        return NULL;
     571    }
     572
     573    psVector* indexColumnVector = vectors->data[indexCol];
     574    psS32  numRows = indexColumnVector->n;
     575    psS32  numCols = vectors->n;
     576
     577    // Check if array is sorted on the index column
     578    psVector* sortedIndex = psVectorAlloc(numRows,PS_TYPE_U32);
     579    sortedIndex = psVectorSortIndex(sortedIndex,indexColumnVector);
     580    for(psS32 i = 0; i < numRows; i++ ) {
     581        if(sortedIndex->data.U32[i] != i) {
     582            sortNeeded = true;
     583            break;
     584        }
     585    }
     586
     587    // Check if it is necessary to sort value vectors
     588    if(sortNeeded) {
     589        // Allocate new array to contain sorted vectors
     590        psArray* newValueArray = psArrayAlloc(numCols);
     591        for(psS32 j = 0; j < numCols; j++) {
     592            psS32 type = ((psVector*)(vectors->data[j]))->type.type;
     593            newValueArray->data[j] = psVectorAlloc(numRows,type);
     594        }
     595
     596        // Populate new array/vectors with sorted values
     597        for(psS32 i = 0; i < numRows; i++) {
     598            // Populate new index vector
     599            psU32 sortIndex = sortedIndex->data.U32[i];
     600            // For every column populate new value vectors
     601            for(psS32 j=0; j < numCols; j++) {
     602                COPY_VECTOR_VALUES(newValueArray->data[j],i,vectors->data[j], sortIndex)
    681603            }
    682604        }
    683         // Check if it is necessary to sort value vectors
    684         if(sortIndex) {
    685             // Allocate new index vector
    686             psVector* newIndexVector = psVectorAlloc(numRows,indexVec->type.type);
    687             // Allocate new value vectors
    688             psArray* newValueArray = psArrayAlloc(numCols-1);
    689             for(psS32 j = 0; j < numCols-1; j++) {
    690                 psS32 type = ((psVector*)(table->values->data[j]))->type.type;
    691                 newValueArray->data[j] = psVectorAlloc(numRows,type);
    692             }
    693             for(psS32 i = 0; i < numRows; i++) {
    694                 // Populate new index vector
    695                 psU32 sortIndex = sortedIndex->data.U32[i];
    696                 COPY_VECTOR_VALUES(newIndexVector,i, indexVec,sortIndex)
    697                 // For every column populate new value vectors
    698                 for(psS32 j=0; j < numCols-1; j++) {
    699                     COPY_VECTOR_VALUES(newValueArray->data[j],i,table->values->data[j], sortIndex)
    700                 }
    701             }
    702             // Free old index vector
    703             psFree(table->index);
    704             // Free old value vectors
    705             psFree(table->values);
    706             // Assign new vector value to table
    707             table->index = newIndexVector;
    708             // Assign new value vectors to table array
    709             table->values = newValueArray;
     605        // Assign new vector value to table
     606        table->index = newValueArray->data[indexCol];
     607        // Assign new value vectors to table array
     608        table->values = newValueArray;
     609        // Assign indexCol
     610        table->indexCol = indexCol;
     611        // Assign validTo and validFrom values
     612        UPDATE_VALID_TO_FROM(table)
     613
     614        // Set return value
     615        outputTable = table;
     616
     617    } else {
     618        // Index vector is already sorted
     619        // Assign array vector specified by indexCol to table index vector and increment memory ref
     620        table->index = vectors->data[indexCol];
     621        table->values = (psArray*)vectors;
     622        psMemIncrRefCounter((psArray*)vectors);
     623
     624        // Assign indexCol
     625        table->indexCol = indexCol;
     626        // Assign validTo and validFrom values
     627        UPDATE_VALID_TO_FROM(table);
     628
     629        // Set return value
     630        outputTable = table;
     631    }
     632
     633    // Free sort vector
     634    psFree(sortedIndex);
     635
     636    return outputTable;
     637}
     638
     639psS32 psLookupTableRead(psLookupTable* table)
     640{
     641    psS32           numRows  = 0;
     642    psArray*        vectors  = NULL;
     643    psLookupTable*  outTable = NULL;
     644
     645    // Check if the input table is NULL then return 0
     646    PS_ASSERT_PTR_NON_NULL(table,0);
     647
     648    // Read vectors from file specified in table
     649    vectors = psVectorsReadFromFile(table->filename, table->format);
     650
     651    // Check for valid array after reading from file
     652    if(vectors != NULL) {
     653
     654        // Import vector into table
     655        outTable = psLookupTableImport(table, vectors, table->indexCol);
     656
     657        psFree(vectors);
     658
     659        // Update the number of rows read if outTable is not NULL
     660        if(outTable != NULL) {
     661            numRows = table->index->n;
    710662        }
    711         psFree(sortedIndex);
    712         // Update the validTo and validFrom
    713         UPDATE_VALID_TO_FROM(table)
    714     }
    715 
    716     fclose(fp);
    717 
    718     return table;
     663    }
     664
     665    // Return the number of lines read
     666    return numRows;
    719667}
    720668
     
    756704}
    757705
    758 
    759 #define CHECK_LOWER_UPPER_BOUND(TABLE,INDEX,COLUMN)                                \
    760 switch (TABLE->index->type.type) {                                                 \
    761 case PS_TYPE_U8:                                                                   \
    762     if( (psU8)index < TABLE->index->data.U8[0] ) {                                 \
    763         *status = PS_LOOKUP_PAST_TOP;                                              \
    764     }                                                                              \
    765     if( (psU8)index > TABLE->index->data.U8[numRows-1]) {                          \
    766         *status = PS_LOOKUP_PAST_BOTTOM;                                           \
    767     }                                                                              \
    768     break;                                                                         \
    769 case PS_TYPE_U16:                                                                  \
    770     if( (psU16)index < TABLE->index->data.U16[0] ) {                               \
    771         *status = PS_LOOKUP_PAST_TOP;                                              \
    772     }                                                                              \
    773     if( (psU16)index > TABLE->index->data.U16[numRows-1] ) {                       \
    774         *status = PS_LOOKUP_PAST_BOTTOM;                                           \
    775     }                                                                              \
    776     break;                                                                         \
    777 case PS_TYPE_U32:                                                                  \
    778     if( (psU32)index < TABLE->index->data.U32[0]) {                                \
    779         *status = PS_LOOKUP_PAST_TOP;                                              \
    780     }                                                                              \
    781     if ( (psU32)index > TABLE->index->data.U32[numRows-1] ) {                      \
    782         *status = PS_LOOKUP_PAST_BOTTOM;                                           \
    783     }                                                                              \
    784     break;                                                                         \
    785 case PS_TYPE_U64:                                                                  \
    786     if( (psU64)index < TABLE->index->data.U64[0] ) {                               \
    787         *status = PS_LOOKUP_PAST_TOP;                                              \
    788     }                                                                              \
    789     if( (psU64)index > TABLE->index->data.U64[numRows-1] ) {                       \
    790         *status = PS_LOOKUP_PAST_BOTTOM;                                           \
    791     }                                                                              \
    792     break;                                                                         \
    793 case PS_TYPE_S8:                                                                   \
    794     if( (psS8)index < TABLE->index->data.S8[0] ) {                                 \
    795         *status = PS_LOOKUP_PAST_TOP;                                              \
    796     }                                                                              \
    797     if( (psS8)index > TABLE->index->data.S8[numRows-1] ) {                         \
    798         *status = PS_LOOKUP_PAST_BOTTOM;                                           \
    799     }                                                                              \
    800     break;                                                                         \
    801 case PS_TYPE_S16:                                                                  \
    802     if( (psS16)index < TABLE->index->data.S16[0] ) {                               \
    803         *status = PS_LOOKUP_PAST_TOP;                                              \
    804     }                                                                              \
    805     if( (psS16)index > TABLE->index->data.S16[numRows-1] ) {                       \
    806         *status = PS_LOOKUP_PAST_BOTTOM;                                           \
    807     }                                                                              \
    808     break;                                                                         \
    809 case PS_TYPE_S32:                                                                  \
    810     if( (psS32)index < TABLE->index->data.S32[0] ) {                               \
    811         *status = PS_LOOKUP_PAST_TOP;                                              \
    812     }                                                                              \
    813     if( (psS32)index > TABLE->index->data.S32[numRows-1] ) {                       \
    814         *status = PS_LOOKUP_PAST_BOTTOM;                                           \
    815     }                                                                              \
    816     break;                                                                         \
    817 case PS_TYPE_S64:                                                                  \
    818     if( (psS64)index < TABLE->index->data.S64[0] ) {                               \
    819         *status = PS_LOOKUP_PAST_TOP;                                              \
    820     }                                                                              \
    821     if( (psS64)index > TABLE->index->data.S64[numRows-1] ) {                       \
    822         *status = PS_LOOKUP_PAST_BOTTOM;                                           \
    823     }                                                                              \
    824     break;                                                                         \
    825 case PS_TYPE_F32:                                                                  \
    826     if( (psF32)index < TABLE->index->data.F32[0] ) {                               \
    827         *status = PS_LOOKUP_PAST_TOP;                                              \
    828     }                                                                              \
    829     if( (psF32)index > TABLE->index->data.F32[numRows-1] ) {                       \
    830         *status = PS_LOOKUP_PAST_BOTTOM;                                           \
    831     }                                                                              \
    832     break;                                                                         \
    833 case PS_TYPE_F64:                                                                  \
    834     if( index < TABLE->index->data.F64[0] ) {                                      \
    835         *status = PS_LOOKUP_PAST_TOP;                                              \
    836     }                                                                              \
    837     if( index > TABLE->index->data.F64[numRows-1] ) {                              \
    838         *status = PS_LOOKUP_PAST_BOTTOM;                                           \
    839     }                                                                              \
    840     break;                                                                         \
    841 default:                                                                           \
    842     *status = PS_LOOKUP_ERROR;                                                     \
    843     return NAN;                                                                    \
    844     break;                                                                         \
    845 }                                                                                  \
    846 if(*status == PS_LOOKUP_PAST_TOP) {                                                \
    847     CONVERT_VALUE_TO_F64(((psVector*)(TABLE->values->data[COLUMN])),0,out)         \
    848     return out;                                                                    \
    849 } else if (*status == PS_LOOKUP_PAST_BOTTOM) {                                     \
    850     CONVERT_VALUE_TO_F64(((psVector*)(TABLE->values->data[COLUMN])),numRows-1,out) \
    851     return out;                                                                    \
    852 }
    853 
    854 
    855 psF64 psLookupTableInterpolate(psLookupTable *table, psF64 index, psU64 column, psLookupStatusType *status)
     706#define CHECK_LOWER_UPPER_BOUND(TABLE,INDEX,COLUMN)                     \
     707switch (TABLE->index->type.type) {                                      \
     708case PS_TYPE_S32:                                                       \
     709    if( (psS32)index < TABLE->index->data.S32[0] ) {                    \
     710        return NAN;                                                     \
     711    }                                                                   \
     712    if( (psS32)index > TABLE->index->data.S32[numRows-1] ) {            \
     713        return NAN;                                                     \
     714    }                                                                   \
     715    break;                                                              \
     716case PS_TYPE_S64:                                                       \
     717    if( (psS64)index < TABLE->index->data.S64[0] ) {                    \
     718        return NAN;                                                     \
     719    }                                                                   \
     720    if( (psS64)index > TABLE->index->data.S64[numRows-1] ) {            \
     721        return NAN;                                                     \
     722    }                                                                   \
     723    break;                                                              \
     724case PS_TYPE_F32:                                                       \
     725    if( (psF32)index < TABLE->index->data.F32[0] ) {                    \
     726        return NAN;                                                     \
     727    }                                                                   \
     728    if( (psF32)index > TABLE->index->data.F32[numRows-1] ) {            \
     729        return NAN;                                                     \
     730    }                                                                   \
     731    break;                                                              \
     732case PS_TYPE_F64:                                                       \
     733    if( index < TABLE->index->data.F64[0] ) {                           \
     734        return NAN;                                                     \
     735    }                                                                   \
     736    if( index > TABLE->index->data.F64[numRows-1] ) {                   \
     737        return NAN;                                                     \
     738    }                                                                   \
     739    break;                                                              \
     740default:                                                                \
     741    return NAN;                                                         \
     742    break;                                                              \
     743}
     744
     745psF64 psLookupTableInterpolate(const psLookupTable *table, psF64 index, psS32 column)
    856746{
    857747    psU64 hiIdx = 0;
     
    867757    psArray *values = NULL;
    868758
    869     // Error checks
    870     // Set status to error prior to check since if checks fails it will immediately return
    871     PS_ASSERT_PTR_NON_NULL(status,NAN);
    872     *status = PS_LOOKUP_ERROR;
     759    // Check for NULL table
    873760    PS_ASSERT_PTR_NON_NULL(table,NAN);
     761
    874762    indexVec = table->index;
    875763    values = table->values;
    876     numRows = table->numRows;
    877     numCols = table->numCols;
     764    numRows = table->index->n;
     765    numCols = table->values->n;
    878766    PS_ASSERT_PTR_NON_NULL(indexVec,NAN);
    879767    PS_ASSERT_PTR_NON_NULL(values,NAN);
     
    884772    valuesVec = (psVector*)values->data[column];
    885773    PS_ASSERT_PTR_NON_NULL(indexVec,NAN);
    886 
    887     // Set status to success since it passed all parameter checks
    888     *status = PS_LOOKUP_SUCCESS;
    889774
    890775    // Verify the index is within the bounds of the table
     
    898783            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
    899784                    PS_ERRORTEXT_psLookupTable_INTERPOLATE_HIGH, hiIdx);
    900             *status = PS_LOOKUP_ERROR;
    901785            return NAN;
    902786        }
     
    909793        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
    910794                PS_ERRORTEXT_psLookupTable_INTERPOLATE_LOW, loIdx);
    911         *status = PS_LOOKUP_ERROR;
    912795        return NAN;
    913796    }
     
    919802    if(fabs(denom) < FLT_EPSILON) {
    920803        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_DIVIDE_BY_ZERO);
    921         *status = PS_LOOKUP_ERROR;
    922804        return NAN;
    923805    } else {
     
    934816}
    935817
    936 psVector* psLookupTableInterpolateAll(psLookupTable *table, psF64 index, psVector *stats)
    937 {
    938     psU64 i = 0;
     818psVector* psLookupTableInterpolateAll(psLookupTable *table, psF64 index)
     819{
    939820    psU64 numCols = 0;
    940821    psVector *outVector = NULL;
    941     psLookupStatusType status = PS_LOOKUP_SUCCESS;
    942822
    943823    // Error checks
    944824    PS_ASSERT_PTR_NON_NULL(table,NULL);
    945     PS_ASSERT_PTR_NON_NULL(stats,NULL);
    946     numCols = table->numCols;
     825    numCols = table->values->n;
    947826    PS_ASSERT_INT_UNEQUAL(numCols, 0,NULL);
    948827
    949     outVector = psVectorAlloc(numCols+1, PS_TYPE_F64);
     828    // Create output vector
     829    outVector = psVectorAlloc(numCols, PS_TYPE_F64);
    950830
    951831    // Fill vectors with results and status of results
    952     for(i=0; i<numCols; i++) {
    953         outVector->data.F64[i] = psLookupTableInterpolate(table, index, i, &status);
    954         stats->data.U32[i] = status;
     832    for(psU64 i=0; i<numCols; i++) {
     833        outVector->data.F64[i] = psLookupTableInterpolate(table, index, i);
     834        if(isnan(outVector->data.F64[i])) {
     835            // Free allocated vector
     836            psFree(outVector);
     837            outVector = NULL;
     838            // Break out of loop since error detected
     839            break;
     840        }
    955841    }
    956842
  • trunk/psLib/src/types/psLookupTable.h

    r3684 r4050  
    77*  @author Ross Harman, MHPCC
    88*
    9 *  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
    10 *  @date $Date: 2005-04-08 17:58:57 $
     9*  @version $Revision: 1.6 $ $Name: not supported by cvs2svn $
     10*  @date $Date: 2005-05-31 21:46:56 $
    1111*
    1212*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    2828typedef struct
    2929{
    30     const char *fileName;              ///< Name of file with table
    31     psU64 numRows;                     ///< Number of table rows
    32     psU64 numCols;                     ///< Number of table columns
     30    const char *filename;              ///< Name of file with table
     31    const char *format;                ///< scanf-like format string for file
     32    unsigned int indexCol;             ///< Column of the index vector (starting at zero)
     33    psVector *index;                   ///< Vector of independent index values
     34    psArray *values;                   ///< Array of dependent table values corresponding to index values
    3335    psF64 validFrom;                   ///< Lower bound for rable read
    3436    psF64 validTo;                     ///< Upper bound for table read
    35     psVector *index;                   ///< Vector of independent index values
    36     psArray *values;                   ///< Array of dependent table values corresponding to index values
    3737}
    3838psLookupTable;
     
    6969psLookupTable* psLookupTableAlloc(
    7070    const char *fileName,           ///< Name of file to read
    71     psF64 validFrom,                ///< Lower bound for rable read
    72     psF64 validTo                   ///< Upper bound for table read
     71    const char *format,             ///< scanf-like format string
     72    int indexCol                    ///< Column of the index vector (starting at zero)
     73);
     74
     75/** Read vectors from file
     76 *
     77 *  Read numeric vectors from ASCII text file
     78 *
     79 *  @return psArray*  New array of psVectors corresponding to the columns of the table
     80 */
     81psArray *psVectorsReadFromFile(
     82    const char* filename,            ///< File to be read
     83    const char* format               ///< scanf-like format string
     84);
     85
     86/** Import arrays of vectors into a table
     87 *
     88 *  Import array of vectors read from text file into a table structure
     89 *
     90 *  @return psLookupTable*  Lookup table structure with array vector data
     91 */
     92psLookupTable *psLookupTableImport(
     93    psLookupTable *table,            ///< Lookup table into which to import
     94    const psArray *vectors,          ///< Array of vectors
     95    int indexCol                     ///< Index of the index vector in the array of vectors
    7396);
    7497
     
    77100 *  Reads a lookup table and fills corresponding psLookupTable struct.
    78101 *
    79  *  @return psLookupTable*     New psLookupTable struct.
     102 *  @return psS32     Number of valid lines read
    80103 */
    81 psLookupTable* psLookupTableRead(
     104psS32 psLookupTableRead(
    82105    psLookupTable *table            ///< Table to read
    83106);
     
    91114 */
    92115psF64 psLookupTableInterpolate(
    93     psLookupTable *table,           ///< Table with data
     116    const psLookupTable *table,     ///< Table with data
    94117    psF64 index,                    ///< Value to be interpolated
    95     psU64 column,                   ///< Column in table to be interpolated
    96     psLookupStatusType *status      ///< Status of lookup
     118    psS32 column                    ///< Column in table to be interpolated
    97119);
    98120
     
    106128psVector* psLookupTableInterpolateAll(
    107129    psLookupTable *table,           ///< Table with data
    108     psF64 index,                    ///< Value to be interpolated
    109     psVector *stats                 ///< Vector of status for each lookup
     130    psF64 index                     ///< Value to be interpolated
    110131);
    111132
Note: See TracChangeset for help on using the changeset viewer.