IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 2302


Ignore:
Timestamp:
Nov 8, 2004, 2:38:14 PM (22 years ago)
Author:
harman
Message:

Added psLookupTable code

Location:
trunk/psLib/src
Files:
6 added
6 edited

Legend:

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

    r2195 r2302  
    88*  @author Ross Harman, MHPCC
    99*
    10 *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
    11 *  @date $Date: 2004-10-26 00:36:50 $
     10*  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
     11*  @date $Date: 2004-11-09 00:38:14 $
    1212*
    1313*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
    1414*/
    15 
    16 #include "psLookupTable.c"
    17 
    18 
    19 psLookupTable* psLookupTableAlloc(psU64 numRows, psU64 numCols)
    20 {
    21 }
    22 
    23 psLookupTable* psLookupTableRead(char *fileName)
    24 {
    25 }
    26 
    27 psF64 psLookupTableInterpolate(psLookupTable *table, psF64 index, psMaskType *status)
    28 {
    29 }
    30 
    31 psVector* psLookupTableInterpolate(psLookupTable *table, psF64 index, psMaskType *status)
    32 {
    33 }
    34 
    35 #endif
     15#include <stdio.h>
     16#include <string.h>
     17#include <ctype.h>
     18#include <stdlib.h>
     19#include <math.h>
     20
     21#include "psMemory.h"
     22#include "psString.h"
     23#include "psError.h"
     24#include "psLookupTable.h"
     25#include "psFileUtilsErrors.h"
     26#include "psConstants.h"
     27
     28/******************************************************************************/
     29/*  DEFINE STATEMENTS                                                         */
     30/******************************************************************************/
     31
     32/** Maximum size of a string */
     33#define MAX_STRING_LENGTH 256
     34
     35/******************************************************************************/
     36/*  TYPE DEFINITIONS                                                          */
     37/******************************************************************************/
     38
     39// None
     40
     41/*****************************************************************************/
     42/*  GLOBAL VARIABLES                                                         */
     43/*****************************************************************************/
     44
     45// None
     46
     47/*****************************************************************************/
     48/*  FILE STATIC VARIABLES                                                    */
     49/*****************************************************************************/
     50
     51// None
     52
     53/*****************************************************************************/
     54/*  FUNCTION IMPLEMENTATION - LOCAL                                          */
     55/*****************************************************************************/
     56
     57static bool ignoreLine(char *inString);
     58static char *cleanString(char *inString, int sLen);
     59static char* getToken(char **inString, char *delimiter, psParseErrorType *status);
     60static psU8 parseU8(char *inString, psParseErrorType *status);
     61static psS8 parseS8(char *inString, psParseErrorType *status);
     62static psU16 parseU16(char *inString, psParseErrorType *status);
     63static psS16 parseS16(char *inString, psParseErrorType *status);
     64static psU32 parseU32(char *inString, psParseErrorType *status);
     65static psS32 parseS32(char *inString, psParseErrorType *status);
     66static psU64 parseU64(char *inString, psParseErrorType *status);
     67static psS64 parseS64(char *inString, psParseErrorType *status);
     68static psF32 parseF32(char *inString, psParseErrorType *status);
     69static psF64 parseF64(char *inString, psParseErrorType *status);
     70static void parseValue(psVector *vec, psU64 index, char* strValue, psParseErrorType *status);
     71static void lookupTableFree(psLookupTable* table);
     72
     73/** Determines if a line is blank (whitespace only) or a commentline. It returns true if so. The input string
     74 *  must be null terminated. */
     75static bool ignoreLine(char *inString)
     76{
     77    while(*inString!='\0' && *inString!='#') {
     78        if(!isspace(*inString)) {
     79            return false;
     80        }
     81        inString++;
     82    }
     83
     84    return true;
     85}
     86
     87
     88/** Removes leading and trailing whitespace and # characters from a string. The cleaned string is a new null
     89 *  terminated copy of the original input string. */
     90static char *cleanString(char *inString, int sLen)
     91{
     92    char *ptrB = NULL;
     93    char *ptrE = NULL;
     94    char *cleaned = NULL;
     95
     96
     97    ptrB = inString;
     98
     99    /* Skip over leading # or whitespace */
     100    while (isspace(*ptrB) || *ptrB=='#') {
     101        ptrB++;
     102    }
     103
     104    /* Skip over trailing whitespace, null terminators, and # characters */
     105    ptrE = inString + sLen;
     106    while(isspace(*ptrE) || *ptrE=='\0' || *ptrE=='#') {
     107        ptrE--;
     108    }
     109
     110    // Length, sLen, does not include '\0'
     111    sLen = ptrE - ptrB + 1;
     112
     113    // Adds '\0' to end of string and +1 to sLen
     114    cleaned = psStringNCopy(ptrB, sLen);
     115
     116    return cleaned;
     117}
     118
     119
     120/** Returns cleaned token based on delimiter, but not including delimiter. Also changes the pointer location
     121 * the beginning of the string. Tokens are newly allocated null terminated strings. */
     122static char* getToken(char **inString, char *delimiter, psParseErrorType *status)
     123{
     124    char *cleanToken = NULL;
     125    int sLen = 0;
     126
     127
     128    // Skip over leading whitespace
     129    while(isspace(**inString)) {
     130        (*inString)++;
     131    }
     132
     133    // Length of token, not including delimiter
     134    sLen = strcspn(*inString, delimiter);
     135    if(sLen) {
     136
     137        // Create new, cleaned, and null terminated token
     138        cleanToken = cleanString(*inString, sLen);
     139
     140        // Move to end of token
     141        (*inString) += sLen;
     142    } else if(**inString!='\0' && sLen==0) {
     143        *status = PS_PARSE_ERROR_GENERAL;
     144    }
     145
     146    return cleanToken;
     147}
     148
     149/** Returns single parsed value as a psU8. The input string must be cleaned and null terminated. */
     150static psU8 parseU8(char *inString, psParseErrorType *status)
     151{
     152    char *end = NULL;
     153    psU8 value = 0.0;
     154
     155
     156    value = (psU8)strtoul(inString, &end, 0);
     157    if(*end != '\0') {
     158        *status = PS_PARSE_ERROR_VALUE;
     159    } else if(inString==end) {
     160        *status = PS_PARSE_ERROR_VALUE;
     161    }
     162
     163    return value;
     164}
     165
     166/** Returns single parsed value as a psS8. The input string must be cleaned and null terminated. */
     167static psS8 parseS8(char *inString, psParseErrorType *status)
     168{
     169    char *end = NULL;
     170    psS8 value = 0.0;
     171
     172
     173    value = (psS8)strtol(inString, &end, 0);
     174    if(*end != '\0') {
     175        *status = PS_PARSE_ERROR_VALUE;
     176    } else if(inString==end) {
     177        *status = PS_PARSE_ERROR_VALUE;
     178    }
     179
     180    return value;
     181}
     182
     183/** Returns single parsed value as a psU16. The input string must be cleaned and null terminated. */
     184static psU16 parseU16(char *inString, psParseErrorType *status)
     185{
     186    char *end = NULL;
     187    psU16 value = 0.0;
     188
     189
     190    value = (psU16)strtoul(inString, &end, 0);
     191    if(*end != '\0') {
     192        *status = PS_PARSE_ERROR_VALUE;
     193    } else if(inString==end) {
     194        *status = PS_PARSE_ERROR_VALUE;
     195    }
     196
     197    return value;
     198}
     199
     200/** Returns single parsed value as a psS16. The input string must be cleaned and null terminated. */
     201static psS16 parseS16(char *inString, psParseErrorType *status)
     202{
     203    char *end = NULL;
     204    psS16 value = 0.0;
     205
     206
     207    value = (psS16)strtol(inString, &end, 0);
     208    if(*end != '\0') {
     209        *status = PS_PARSE_ERROR_VALUE;
     210    } else if(inString==end) {
     211        *status = PS_PARSE_ERROR_VALUE;
     212    }
     213
     214    return value;
     215}
     216
     217/** Returns single parsed value as a psU32. The input string must be cleaned and null terminated. */
     218static psU32 parseU32(char *inString, psParseErrorType *status)
     219{
     220    char *end = NULL;
     221    psU32 value = 0.0;
     222
     223
     224    value = (psU32)strtoul(inString, &end, 0);
     225    if(*end != '\0') {
     226        *status = PS_PARSE_ERROR_VALUE;
     227    } else if(inString==end) {
     228        *status = PS_PARSE_ERROR_VALUE;
     229    }
     230
     231    return value;
     232}
     233
     234/** Returns single parsed value as a psS32. The input string must be cleaned and null terminated. */
     235static psS32 parseS32(char *inString, psParseErrorType *status)
     236{
     237    char *end = NULL;
     238    psS32 value = 0.0;
     239
     240
     241    value = (psS32)strtol(inString, &end, 0);
     242    if(*end != '\0') {
     243        *status = PS_PARSE_ERROR_VALUE;
     244    } else if(inString==end) {
     245        *status = PS_PARSE_ERROR_VALUE;
     246    }
     247
     248    return value;
     249}
     250
     251/** Returns single parsed value as a psU64. The input string must be cleaned and null terminated. */
     252static psU64 parseU64(char *inString, psParseErrorType *status)
     253{
     254    char *end = NULL;
     255    psU64 value = 0.0;
     256
     257
     258    value = (psU64)strtoull(inString, &end, 0);
     259    if(*end != '\0') {
     260        *status = PS_PARSE_ERROR_VALUE;
     261    } else if(inString==end) {
     262        *status = PS_PARSE_ERROR_VALUE;
     263    }
     264
     265    return value;
     266}
     267
     268/** Returns single parsed value as a psS64. The input string must be cleaned and null terminated. */
     269static psS64 parseS64(char *inString, psParseErrorType *status)
     270{
     271    char *end = NULL;
     272    psS64 value = 0.0;
     273
     274
     275    value = (psS64)strtoll(inString, &end, 0);
     276    if(*end != '\0') {
     277        *status = PS_PARSE_ERROR_VALUE;
     278    } else if(inString==end) {
     279        *status = PS_PARSE_ERROR_VALUE;
     280    }
     281
     282    return value;
     283}
     284
     285/** Returns single parsed value as a psF32. The input string must be cleaned and null terminated. */
     286static psF32 parseF32(char *inString, psParseErrorType *status)
     287{
     288    char *end = NULL;
     289    psF32 value = 0.0;
     290
     291
     292    value = (psF32)strtof(inString, &end);
     293    if(*end != '\0') {
     294        *status = PS_PARSE_ERROR_VALUE;
     295    } else if(inString==end) {
     296        *status = PS_PARSE_ERROR_VALUE;
     297    }
     298
     299    return value;
     300}
     301
     302/** Returns single parsed value as a psF64. The input string must be cleaned and null terminated. */
     303static psF64 parseF64(char *inString, psParseErrorType *status)
     304{
     305    char *end = NULL;
     306    psF64 value = 0.0;
     307
     308
     309    value = (psF64)strtod(inString, &end);
     310    if(*end != '\0') {
     311        *status = PS_PARSE_ERROR_VALUE;
     312    } else if(inString==end) {
     313        *status = PS_PARSE_ERROR_VALUE;
     314    }
     315
     316    return value;
     317}
     318
     319/** Returns single parsed value as a double precision number. The input string must be cleaned and null
     320 * terminated. */
     321static void parseValue(psVector *vec, psU64 index, char* strValue, psParseErrorType *status)
     322{
     323    psElemType type;
     324
     325
     326    if(vec == NULL) {
     327        *status = 1;
     328        return;
     329    }
     330
     331    type = vec->type.type;
     332
     333    switch(type) {
     334    case PS_TYPE_U8:
     335        vec->data.U8[index] = parseU8(strValue, status);
     336        break;
     337    case PS_TYPE_S8:
     338        vec->data.S8[index] = parseS8(strValue, status);
     339        break;
     340    case PS_TYPE_U16:
     341        vec->data.U16[index] = parseU16(strValue, status);
     342        break;
     343    case PS_TYPE_S16:
     344        vec->data.S16[index] = parseS16(strValue, status);
     345        break;
     346    case PS_TYPE_U32:
     347        vec->data.U32[index] = parseU32(strValue, status);
     348        break;
     349    case PS_TYPE_S32:
     350        vec->data.S32[index] = parseS32(strValue, status);
     351        break;
     352    case PS_TYPE_U64:
     353        vec->data.U64[index] = parseU64(strValue, status);
     354        break;
     355    case PS_TYPE_S64:
     356        vec->data.S64[index] = parseS64(strValue, status);
     357        break;
     358    case PS_TYPE_F32:
     359        vec->data.F32[index] = parseF32(strValue, status);
     360        break;
     361    case PS_TYPE_F64:
     362        vec->data.F64[index] = parseF64(strValue, status);
     363        break;
     364    default:
     365        *status = PS_PARSE_ERROR_TYPE;
     366    }
     367
     368    return;
     369}
     370
     371static psParseErrorType printError(psU64 lineCount, char* badText, psParseErrorType status)
     372{
     373    switch(status) {
     374    case PS_PARSE_ERROR_VALUE:
     375        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_PARSE_VALUE, badText, lineCount);
     376        break;
     377    case PS_PARSE_ERROR_TYPE:
     378        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_PARSE_TYPE, badText, lineCount);
     379        break;
     380    case PS_PARSE_ERROR_GENERAL:
     381        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_PARSE_GENERAL, badText, lineCount);
     382        break;
     383    default:
     384        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_INVALID_TYPE, badText, lineCount);
     385    }
     386
     387    return PS_LOOKUP_SUCCESS;
     388}
     389
     390static void lookupTableFree(psLookupTable* table)
     391{
     392    if (table == NULL) {
     393        return;
     394    }
     395
     396    psFree(table->values);
     397    psFree(table->index);
     398    psFree((char*)table->fileName);
     399}
     400
     401/*****************************************************************************/
     402/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
     403/*****************************************************************************/
     404
     405psLookupTable* psLookupTableAlloc(const char *fileName, psF64 validFrom, psF64 validTo)
     406{
     407    psLookupTable *outTable = NULL;
     408
     409
     410    // Can't read table if you don't know its name
     411    PS_PTR_CHECK_NULL(fileName,NULL);
     412
     413    // Allocate lookup table
     414    outTable = (psLookupTable*)psAlloc(sizeof(psLookupTable));
     415
     416    // Set deallocator
     417    p_psMemSetDeallocator(outTable, (psFreeFcn)lookupTableFree);
     418
     419    // Allocate and set metadata item comment
     420    outTable->fileName = psStringCopy(fileName);
     421
     422    // Number of table rows and columns. Automatically resized by table read.
     423    outTable->numRows = 0;
     424    outTable->numCols = 0;
     425
     426    // Valid ranges. Automatically set by table read if both zero.
     427    outTable->validFrom = validFrom;
     428    outTable->validTo = validTo;
     429
     430    // Vector of independent index values. Filled by table read.
     431    outTable->index = NULL;
     432
     433    // Array of dependent table values corresponding to index values. Filled by table read.
     434    outTable->values = NULL;
     435
     436    return outTable;
     437}
     438
     439psLookupTable* psLookupTableRead(psLookupTable *table)
     440{
     441    bool typeLine = true;
     442    char *line = NULL;
     443    char *strType = NULL;
     444    char *strValue = NULL;
     445    char *linePtr = NULL;
     446    psParseErrorType status = PS_PARSE_SUCCESS;
     447    psU64 lineCount = 0;
     448    psU64 numRows = 0;
     449    psU64 numCols = 0;
     450    psU64 failedLines = 0;
     451    FILE *fp = NULL;
     452    psElemType elemType;
     453    psVector *indexVec = NULL;
     454    psVector *valuesVec = NULL;
     455    psArray *values = NULL;
     456
     457
     458    // Error checks
     459    PS_PTR_CHECK_NULL(table,NULL);
     460    PS_PTR_CHECK_NULL(table->fileName,NULL);
     461    if((fp=fopen(table->fileName, "r")) == NULL) {
     462        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_FILE_NOT_FOUND, table->fileName);
     463        return NULL;
     464    }
     465
     466    indexVec = table->index;
     467    values = table->values;
     468
     469    // Create reusable line for continuous read
     470    line = (char*)psAlloc(MAX_STRING_LENGTH*sizeof(char));
     471
     472    // Loop through file to get numRows, numCols, and column data types
     473    while(fgets(line, MAX_STRING_LENGTH, fp) != NULL) {
     474
     475        // Initialize variables for new line
     476        linePtr = line;
     477        lineCount++;
     478
     479        // If line is not a comment or blank, then extract data
     480        if(!ignoreLine(linePtr)) {
     481
     482            if(typeLine == true) {
     483
     484                // Determine column types from first line in data file after comments
     485                while((strType=getToken(&linePtr, " ", &status)) != NULL) {
     486                    numCols++;
     487                    typeLine = false;
     488                    if(!strncmp(strType, "psU8", 4)) {
     489                        elemType = PS_TYPE_U8;
     490                    } else if(!strncmp(strType, "psS8", 4)) {
     491                        elemType = PS_TYPE_S8;
     492                    } else if(!strncmp(strType, "psU16", 5)) {
     493                        elemType = PS_TYPE_U16;
     494                    } else if(!strncmp(strType, "psS16", 5)) {
     495                        elemType = PS_TYPE_S16;
     496                    } else if(!strncmp(strType, "psU32", 5)) {
     497                        elemType = PS_TYPE_U32;
     498                    } else if(!strncmp(strType, "psS32", 5)) {
     499                        elemType = PS_TYPE_S32;
     500                    } else if(!strncmp(strType, "psU64", 5)) {
     501                        elemType = PS_TYPE_U64;
     502                    } else if(!strncmp(strType, "psS64", 5)) {
     503                        elemType = PS_TYPE_S64;
     504                    } else if(!strncmp(strType, "psF32", 5)) {
     505                        elemType = PS_TYPE_F32;
     506                    } else if(!strncmp(strType, "psF64", 5)) {
     507                        elemType = PS_TYPE_F64;
     508                    } else {
     509                        status = PS_PARSE_ERROR_TYPE;
     510                    }
     511
     512                    // Realloc number of columns as you go
     513                    if(numCols == 1) {
     514                        indexVec = psVectorAlloc(0, elemType);
     515                    } else {
     516                        values = psArrayRealloc(values, numCols-1);
     517                        values->n = values->nalloc;
     518                        values->data[numCols-2] = psVectorAlloc(0, elemType);
     519                    }
     520
     521                    if(status) {
     522                        status = printError(lineCount, strValue, status);
     523                        failedLines++;
     524                    }
     525                    psFree(strType);
     526                }
     527            } else {
     528
     529                // Parse and add values to all columns
     530                numRows++;
     531                numCols = 0;
     532                while((strValue=getToken(&linePtr, " ", &status)) != NULL) {
     533                    numCols++;
     534
     535                    // Realloc number of rows as you go
     536                    if(numCols == 1) {
     537                        indexVec = psVectorRecycle(indexVec, numRows, indexVec->type.type);
     538                        parseValue(indexVec, numRows-1, strValue, &status);
     539                    } else {
     540                        valuesVec = values->data[numCols-2];
     541                        valuesVec = psVectorRecycle(valuesVec, numRows, valuesVec->type.type);
     542                        parseValue(valuesVec, numRows-1, strValue, &status);
     543                    }
     544
     545                    if(status) {
     546                        status = printError(lineCount, strValue, status);
     547                        failedLines++;
     548                    }
     549                    psFree(strValue);
     550                } // end while
     551            } // end else
     552        } // if ignoreLine
     553    } // end while
     554
     555    psFree(line);
     556
     557    // Set table for return
     558    table->numRows = numRows;
     559    table->numCols = numCols-1;
     560    table->index = indexVec;
     561    table->values = values;
     562
     563    fclose(fp);
     564
     565    return table;
     566}
     567
     568psF64 psLookupTableInterpolate(psLookupTable *table, psF64 index, psU64 column, psLookupStatusType *status)
     569{
     570    psU64 hiIdx = 0;
     571    psU64 loIdx = 0;
     572    psU64 numRows = 0;
     573    psU64 numCols = 0;
     574    psF64 out = 0.0;
     575    psF64 denom = 0.0;
     576    psVector *indexVec = NULL;
     577    psVector *valuesVec = NULL;
     578    psArray *values = NULL;
     579
     580
     581    // Error checks
     582    PS_PTR_CHECK_NULL(table,0.0);
     583    indexVec = table->index;
     584    values = table->values;
     585    numRows = table->numRows;
     586    numCols = table->numCols;
     587    PS_PTR_CHECK_NULL(indexVec,0.0);
     588    PS_PTR_CHECK_NULL(values,0.0);
     589    PS_INT_CHECK_EQUALS(numRows, 0,0.0);
     590    PS_INT_CHECK_EQUALS(numCols, 0,0.0);
     591    PS_INT_CHECK_RANGE(column, 0, numCols-1, 0.0);
     592
     593
     594    valuesVec = (psVector*)values->data[column];
     595    PS_PTR_CHECK_NULL(indexVec,0.0);
     596
     597    if(index<indexVec->data.F64[0] || index<table->validFrom) {
     598
     599        // Index value past top of table
     600        *status = PS_LOOKUP_PAST_TOP;
     601        return valuesVec->data.F64[0];
     602    } else if(index>indexVec->data.F64[numRows-1] || index>table->validTo) {
     603
     604        // Index value past bottom of table
     605        *status = PS_LOOKUP_PAST_BOTTOM;
     606        return valuesVec->data.F64[numRows-1];
     607    } else {
     608
     609        // Interpolation
     610        while(index > indexVec->data.F64[hiIdx]) {
     611            hiIdx++;
     612            if(hiIdx >= numRows) {
     613                psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_INTERPOLATE_HIGH, hiIdx);
     614                return 0.0;
     615            }
     616        }
     617
     618        loIdx = hiIdx--;
     619        if(loIdx < 0) {
     620            psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_INTERPOLATE_LOW, loIdx);
     621            return 0.0;
     622        }
     623
     624        denom = indexVec->data.F64[hiIdx] - indexVec->data.F64[loIdx];
     625        if(fabs(denom) < FLT_EPSILON) {
     626            psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_DIVIDE_BY_ZERO);
     627            return 0.0;
     628        } else {
     629            out = valuesVec->data.F64[loIdx]+(valuesVec->data.F64[hiIdx]-valuesVec->data.F64[loIdx])
     630                  *(index-indexVec->data.F64[loIdx])/denom;
     631        }
     632    }
     633
     634    return out;
     635}
     636
     637psVector* psLookupTableInterpolateAll(psLookupTable *table, psF64 index, psVector *stats)
     638{
     639    psU64 i = 0;
     640    psU64 numCols = 0;
     641    psVector *outVector = NULL;
     642    psLookupStatusType status = PS_LOOKUP_SUCCESS;
     643
     644
     645    // Error checks
     646    PS_PTR_CHECK_NULL(table,NULL);
     647    PS_PTR_CHECK_NULL(stats,NULL);
     648    numCols = table->numCols;
     649    PS_INT_CHECK_EQUALS(numCols, 0,NULL);
     650
     651    outVector = psVectorAlloc(numCols, PS_TYPE_F64);
     652
     653    // Fill vectors with results and status of results
     654    for(i=0; i<numCols; i++) {
     655        outVector->data.F64[i] = psLookupTableInterpolate(table, index, i, &status);
     656        stats->data.U32[i] = status;
     657    }
     658
     659    return outVector;
     660}
     661
  • trunk/psLib/src/dataIO/psLookupTable.h

    r2195 r2302  
    77*  @author Ross Harman, MHPCC
    88*
    9 *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
    10 *  @date $Date: 2004-10-26 00:37:15 $
     9*  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
     10*  @date $Date: 2004-11-09 00:38:14 $
    1111*
    1212*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    1515#ifndef PS_LOOKUPTABLE_H
    1616#define PS_LOOKUPTABLE_H
     17
     18#include "psType.h"
     19#include "psVector.h"
     20#include "psArray.h"
    1721
    1822
     
    2428typedef struct
    2529{
     30    const char *fileName;              ///< Name of file with table
     31    psU64 numRows;                     ///< Number of table rows
     32    psU64 numCols;                     ///< Number of table columns
     33    psF64 validFrom;                   ///< Lower bound for rable read
     34    psF64 validTo;                     ///< Upper bound for table read
    2635    psVector *index;                   ///< Vector of independent index values
    27     psArray *values;                   ///< Array of dependent table values corresponding to index values.
     36    psArray *values;                   ///< Array of dependent table values corresponding to index values
    2837}
    2938psLookupTable;
    3039
    3140
    32 /** Lookup error conditions
     41/** Lookup table lookup status and error conditions
    3342 *
    34  *  Success and failure conditions for table lookups.
     43 *  Success, failure, and status conditions for table lookups.
    3544 */
    3645typedef enum {
    37     PS_LOOKUP_SUCCESS = 0x000,         ///< Table lookup succeeded.
    38     PS_LOOKUP_TOP     = 0x0001,        ///< Lookup off top of table.
    39     PS_LOOKUP_BOTTOM  = 0x0002,        ///< Lookup off bottom of table.
    40     PS_LOOKUP_ERROR   = 0x0003,        ///< Any other type of lookup error.
    41 } psLookupErrorType;
     46    PS_LOOKUP_SUCCESS             = 0x0000,        ///< Table lookup succeeded
     47    PS_LOOKUP_PAST_TOP            = 0x0101,        ///< Lookup off top of table
     48    PS_LOOKUP_PAST_BOTTOM         = 0x0102,        ///< Lookup off bottom of table
     49    PS_LOOKUP_ERROR               = 0x0104         ///< Any other type of lookup error
     50} psLookupStatusType;
     51
     52/** Lookup table parse status and error conditions
     53 *
     54 *  Success, failure, and status conditions for table parsing.
     55 */
     56typedef enum {
     57    PS_PARSE_SUCCESS              = 0x0000,        ///< Table lookup succeeded
     58    PS_PARSE_ERROR_TYPE           = 0x0101,        ///< Error parsing type
     59    PS_PARSE_ERROR_VALUE          = 0x0102,        ///< Error parsing numerical value
     60    PS_PARSE_ERROR_GENERAL        = 0x0104         ///< Any other type of lookup error
     61}psParseErrorType;
    4262
    4363/** Allocator for psLookupTable struct
     
    4868 */
    4969psLookupTable* psLookupTableAlloc(
    50     psU64 numRows,                  ///< Number of rows
    51     psU64 numCols                   ///< number of columns
     70    const char *fileName,           ///< Name of file to read
     71    psF64 validFrom,                ///< Lower bound for rable read
     72    psF64 validTo                   ///< Upper bound for table read
    5273);
    5374
     
    5980 */
    6081psLookupTable* psLookupTableRead(
    61     char *fileName                  ///< Name of file to read
     82    psLookupTable *table            ///< Table to read
    6283);
    6384
     
    6788 *  conditions.
    6889 *
    69  *  @return psLookupTable*     New psLookupTable struct.
     90 *  @return psLookupTable*     New psLookupTable struct
    7091 */
    7192psF64 psLookupTableInterpolate(
    7293    psLookupTable *table,           ///< Table with data
    7394    psF64 index,                    ///< Value to be interpolated
    74     psMaskType *status              ///< Status of lookup.
     95    psU64 column,                   ///< Column in table to be interpolated
     96    psLookupStatusType *status      ///< Status of lookup
    7597);
    7698
     
    80102 *  conditions.
    81103 *
    82  *  @return psLookupTable*     New psLookupTable struct.
     104 *  @return psLookupTable*     New psLookupTable struct
    83105 */
    84 psVector* psLookupTableInterpolate(
     106psVector* psLookupTableInterpolateAll(
    85107    psLookupTable *table,           ///< Table with data
    86108    psF64 index,                    ///< Value to be interpolated
    87     psMaskType *status              ///< Status of lookup.
     109    psVector *stats                 ///< Vector of status for each lookup
    88110);
    89111
  • trunk/psLib/src/fileUtils/psLookupTable.c

    r2195 r2302  
    88*  @author Ross Harman, MHPCC
    99*
    10 *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
    11 *  @date $Date: 2004-10-26 00:36:50 $
     10*  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
     11*  @date $Date: 2004-11-09 00:38:14 $
    1212*
    1313*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
    1414*/
    15 
    16 #include "psLookupTable.c"
    17 
    18 
    19 psLookupTable* psLookupTableAlloc(psU64 numRows, psU64 numCols)
    20 {
    21 }
    22 
    23 psLookupTable* psLookupTableRead(char *fileName)
    24 {
    25 }
    26 
    27 psF64 psLookupTableInterpolate(psLookupTable *table, psF64 index, psMaskType *status)
    28 {
    29 }
    30 
    31 psVector* psLookupTableInterpolate(psLookupTable *table, psF64 index, psMaskType *status)
    32 {
    33 }
    34 
    35 #endif
     15#include <stdio.h>
     16#include <string.h>
     17#include <ctype.h>
     18#include <stdlib.h>
     19#include <math.h>
     20
     21#include "psMemory.h"
     22#include "psString.h"
     23#include "psError.h"
     24#include "psLookupTable.h"
     25#include "psFileUtilsErrors.h"
     26#include "psConstants.h"
     27
     28/******************************************************************************/
     29/*  DEFINE STATEMENTS                                                         */
     30/******************************************************************************/
     31
     32/** Maximum size of a string */
     33#define MAX_STRING_LENGTH 256
     34
     35/******************************************************************************/
     36/*  TYPE DEFINITIONS                                                          */
     37/******************************************************************************/
     38
     39// None
     40
     41/*****************************************************************************/
     42/*  GLOBAL VARIABLES                                                         */
     43/*****************************************************************************/
     44
     45// None
     46
     47/*****************************************************************************/
     48/*  FILE STATIC VARIABLES                                                    */
     49/*****************************************************************************/
     50
     51// None
     52
     53/*****************************************************************************/
     54/*  FUNCTION IMPLEMENTATION - LOCAL                                          */
     55/*****************************************************************************/
     56
     57static bool ignoreLine(char *inString);
     58static char *cleanString(char *inString, int sLen);
     59static char* getToken(char **inString, char *delimiter, psParseErrorType *status);
     60static psU8 parseU8(char *inString, psParseErrorType *status);
     61static psS8 parseS8(char *inString, psParseErrorType *status);
     62static psU16 parseU16(char *inString, psParseErrorType *status);
     63static psS16 parseS16(char *inString, psParseErrorType *status);
     64static psU32 parseU32(char *inString, psParseErrorType *status);
     65static psS32 parseS32(char *inString, psParseErrorType *status);
     66static psU64 parseU64(char *inString, psParseErrorType *status);
     67static psS64 parseS64(char *inString, psParseErrorType *status);
     68static psF32 parseF32(char *inString, psParseErrorType *status);
     69static psF64 parseF64(char *inString, psParseErrorType *status);
     70static void parseValue(psVector *vec, psU64 index, char* strValue, psParseErrorType *status);
     71static void lookupTableFree(psLookupTable* table);
     72
     73/** Determines if a line is blank (whitespace only) or a commentline. It returns true if so. The input string
     74 *  must be null terminated. */
     75static bool ignoreLine(char *inString)
     76{
     77    while(*inString!='\0' && *inString!='#') {
     78        if(!isspace(*inString)) {
     79            return false;
     80        }
     81        inString++;
     82    }
     83
     84    return true;
     85}
     86
     87
     88/** Removes leading and trailing whitespace and # characters from a string. The cleaned string is a new null
     89 *  terminated copy of the original input string. */
     90static char *cleanString(char *inString, int sLen)
     91{
     92    char *ptrB = NULL;
     93    char *ptrE = NULL;
     94    char *cleaned = NULL;
     95
     96
     97    ptrB = inString;
     98
     99    /* Skip over leading # or whitespace */
     100    while (isspace(*ptrB) || *ptrB=='#') {
     101        ptrB++;
     102    }
     103
     104    /* Skip over trailing whitespace, null terminators, and # characters */
     105    ptrE = inString + sLen;
     106    while(isspace(*ptrE) || *ptrE=='\0' || *ptrE=='#') {
     107        ptrE--;
     108    }
     109
     110    // Length, sLen, does not include '\0'
     111    sLen = ptrE - ptrB + 1;
     112
     113    // Adds '\0' to end of string and +1 to sLen
     114    cleaned = psStringNCopy(ptrB, sLen);
     115
     116    return cleaned;
     117}
     118
     119
     120/** Returns cleaned token based on delimiter, but not including delimiter. Also changes the pointer location
     121 * the beginning of the string. Tokens are newly allocated null terminated strings. */
     122static char* getToken(char **inString, char *delimiter, psParseErrorType *status)
     123{
     124    char *cleanToken = NULL;
     125    int sLen = 0;
     126
     127
     128    // Skip over leading whitespace
     129    while(isspace(**inString)) {
     130        (*inString)++;
     131    }
     132
     133    // Length of token, not including delimiter
     134    sLen = strcspn(*inString, delimiter);
     135    if(sLen) {
     136
     137        // Create new, cleaned, and null terminated token
     138        cleanToken = cleanString(*inString, sLen);
     139
     140        // Move to end of token
     141        (*inString) += sLen;
     142    } else if(**inString!='\0' && sLen==0) {
     143        *status = PS_PARSE_ERROR_GENERAL;
     144    }
     145
     146    return cleanToken;
     147}
     148
     149/** Returns single parsed value as a psU8. The input string must be cleaned and null terminated. */
     150static psU8 parseU8(char *inString, psParseErrorType *status)
     151{
     152    char *end = NULL;
     153    psU8 value = 0.0;
     154
     155
     156    value = (psU8)strtoul(inString, &end, 0);
     157    if(*end != '\0') {
     158        *status = PS_PARSE_ERROR_VALUE;
     159    } else if(inString==end) {
     160        *status = PS_PARSE_ERROR_VALUE;
     161    }
     162
     163    return value;
     164}
     165
     166/** Returns single parsed value as a psS8. The input string must be cleaned and null terminated. */
     167static psS8 parseS8(char *inString, psParseErrorType *status)
     168{
     169    char *end = NULL;
     170    psS8 value = 0.0;
     171
     172
     173    value = (psS8)strtol(inString, &end, 0);
     174    if(*end != '\0') {
     175        *status = PS_PARSE_ERROR_VALUE;
     176    } else if(inString==end) {
     177        *status = PS_PARSE_ERROR_VALUE;
     178    }
     179
     180    return value;
     181}
     182
     183/** Returns single parsed value as a psU16. The input string must be cleaned and null terminated. */
     184static psU16 parseU16(char *inString, psParseErrorType *status)
     185{
     186    char *end = NULL;
     187    psU16 value = 0.0;
     188
     189
     190    value = (psU16)strtoul(inString, &end, 0);
     191    if(*end != '\0') {
     192        *status = PS_PARSE_ERROR_VALUE;
     193    } else if(inString==end) {
     194        *status = PS_PARSE_ERROR_VALUE;
     195    }
     196
     197    return value;
     198}
     199
     200/** Returns single parsed value as a psS16. The input string must be cleaned and null terminated. */
     201static psS16 parseS16(char *inString, psParseErrorType *status)
     202{
     203    char *end = NULL;
     204    psS16 value = 0.0;
     205
     206
     207    value = (psS16)strtol(inString, &end, 0);
     208    if(*end != '\0') {
     209        *status = PS_PARSE_ERROR_VALUE;
     210    } else if(inString==end) {
     211        *status = PS_PARSE_ERROR_VALUE;
     212    }
     213
     214    return value;
     215}
     216
     217/** Returns single parsed value as a psU32. The input string must be cleaned and null terminated. */
     218static psU32 parseU32(char *inString, psParseErrorType *status)
     219{
     220    char *end = NULL;
     221    psU32 value = 0.0;
     222
     223
     224    value = (psU32)strtoul(inString, &end, 0);
     225    if(*end != '\0') {
     226        *status = PS_PARSE_ERROR_VALUE;
     227    } else if(inString==end) {
     228        *status = PS_PARSE_ERROR_VALUE;
     229    }
     230
     231    return value;
     232}
     233
     234/** Returns single parsed value as a psS32. The input string must be cleaned and null terminated. */
     235static psS32 parseS32(char *inString, psParseErrorType *status)
     236{
     237    char *end = NULL;
     238    psS32 value = 0.0;
     239
     240
     241    value = (psS32)strtol(inString, &end, 0);
     242    if(*end != '\0') {
     243        *status = PS_PARSE_ERROR_VALUE;
     244    } else if(inString==end) {
     245        *status = PS_PARSE_ERROR_VALUE;
     246    }
     247
     248    return value;
     249}
     250
     251/** Returns single parsed value as a psU64. The input string must be cleaned and null terminated. */
     252static psU64 parseU64(char *inString, psParseErrorType *status)
     253{
     254    char *end = NULL;
     255    psU64 value = 0.0;
     256
     257
     258    value = (psU64)strtoull(inString, &end, 0);
     259    if(*end != '\0') {
     260        *status = PS_PARSE_ERROR_VALUE;
     261    } else if(inString==end) {
     262        *status = PS_PARSE_ERROR_VALUE;
     263    }
     264
     265    return value;
     266}
     267
     268/** Returns single parsed value as a psS64. The input string must be cleaned and null terminated. */
     269static psS64 parseS64(char *inString, psParseErrorType *status)
     270{
     271    char *end = NULL;
     272    psS64 value = 0.0;
     273
     274
     275    value = (psS64)strtoll(inString, &end, 0);
     276    if(*end != '\0') {
     277        *status = PS_PARSE_ERROR_VALUE;
     278    } else if(inString==end) {
     279        *status = PS_PARSE_ERROR_VALUE;
     280    }
     281
     282    return value;
     283}
     284
     285/** Returns single parsed value as a psF32. The input string must be cleaned and null terminated. */
     286static psF32 parseF32(char *inString, psParseErrorType *status)
     287{
     288    char *end = NULL;
     289    psF32 value = 0.0;
     290
     291
     292    value = (psF32)strtof(inString, &end);
     293    if(*end != '\0') {
     294        *status = PS_PARSE_ERROR_VALUE;
     295    } else if(inString==end) {
     296        *status = PS_PARSE_ERROR_VALUE;
     297    }
     298
     299    return value;
     300}
     301
     302/** Returns single parsed value as a psF64. The input string must be cleaned and null terminated. */
     303static psF64 parseF64(char *inString, psParseErrorType *status)
     304{
     305    char *end = NULL;
     306    psF64 value = 0.0;
     307
     308
     309    value = (psF64)strtod(inString, &end);
     310    if(*end != '\0') {
     311        *status = PS_PARSE_ERROR_VALUE;
     312    } else if(inString==end) {
     313        *status = PS_PARSE_ERROR_VALUE;
     314    }
     315
     316    return value;
     317}
     318
     319/** Returns single parsed value as a double precision number. The input string must be cleaned and null
     320 * terminated. */
     321static void parseValue(psVector *vec, psU64 index, char* strValue, psParseErrorType *status)
     322{
     323    psElemType type;
     324
     325
     326    if(vec == NULL) {
     327        *status = 1;
     328        return;
     329    }
     330
     331    type = vec->type.type;
     332
     333    switch(type) {
     334    case PS_TYPE_U8:
     335        vec->data.U8[index] = parseU8(strValue, status);
     336        break;
     337    case PS_TYPE_S8:
     338        vec->data.S8[index] = parseS8(strValue, status);
     339        break;
     340    case PS_TYPE_U16:
     341        vec->data.U16[index] = parseU16(strValue, status);
     342        break;
     343    case PS_TYPE_S16:
     344        vec->data.S16[index] = parseS16(strValue, status);
     345        break;
     346    case PS_TYPE_U32:
     347        vec->data.U32[index] = parseU32(strValue, status);
     348        break;
     349    case PS_TYPE_S32:
     350        vec->data.S32[index] = parseS32(strValue, status);
     351        break;
     352    case PS_TYPE_U64:
     353        vec->data.U64[index] = parseU64(strValue, status);
     354        break;
     355    case PS_TYPE_S64:
     356        vec->data.S64[index] = parseS64(strValue, status);
     357        break;
     358    case PS_TYPE_F32:
     359        vec->data.F32[index] = parseF32(strValue, status);
     360        break;
     361    case PS_TYPE_F64:
     362        vec->data.F64[index] = parseF64(strValue, status);
     363        break;
     364    default:
     365        *status = PS_PARSE_ERROR_TYPE;
     366    }
     367
     368    return;
     369}
     370
     371static psParseErrorType printError(psU64 lineCount, char* badText, psParseErrorType status)
     372{
     373    switch(status) {
     374    case PS_PARSE_ERROR_VALUE:
     375        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_PARSE_VALUE, badText, lineCount);
     376        break;
     377    case PS_PARSE_ERROR_TYPE:
     378        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_PARSE_TYPE, badText, lineCount);
     379        break;
     380    case PS_PARSE_ERROR_GENERAL:
     381        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_PARSE_GENERAL, badText, lineCount);
     382        break;
     383    default:
     384        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_INVALID_TYPE, badText, lineCount);
     385    }
     386
     387    return PS_LOOKUP_SUCCESS;
     388}
     389
     390static void lookupTableFree(psLookupTable* table)
     391{
     392    if (table == NULL) {
     393        return;
     394    }
     395
     396    psFree(table->values);
     397    psFree(table->index);
     398    psFree((char*)table->fileName);
     399}
     400
     401/*****************************************************************************/
     402/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
     403/*****************************************************************************/
     404
     405psLookupTable* psLookupTableAlloc(const char *fileName, psF64 validFrom, psF64 validTo)
     406{
     407    psLookupTable *outTable = NULL;
     408
     409
     410    // Can't read table if you don't know its name
     411    PS_PTR_CHECK_NULL(fileName,NULL);
     412
     413    // Allocate lookup table
     414    outTable = (psLookupTable*)psAlloc(sizeof(psLookupTable));
     415
     416    // Set deallocator
     417    p_psMemSetDeallocator(outTable, (psFreeFcn)lookupTableFree);
     418
     419    // Allocate and set metadata item comment
     420    outTable->fileName = psStringCopy(fileName);
     421
     422    // Number of table rows and columns. Automatically resized by table read.
     423    outTable->numRows = 0;
     424    outTable->numCols = 0;
     425
     426    // Valid ranges. Automatically set by table read if both zero.
     427    outTable->validFrom = validFrom;
     428    outTable->validTo = validTo;
     429
     430    // Vector of independent index values. Filled by table read.
     431    outTable->index = NULL;
     432
     433    // Array of dependent table values corresponding to index values. Filled by table read.
     434    outTable->values = NULL;
     435
     436    return outTable;
     437}
     438
     439psLookupTable* psLookupTableRead(psLookupTable *table)
     440{
     441    bool typeLine = true;
     442    char *line = NULL;
     443    char *strType = NULL;
     444    char *strValue = NULL;
     445    char *linePtr = NULL;
     446    psParseErrorType status = PS_PARSE_SUCCESS;
     447    psU64 lineCount = 0;
     448    psU64 numRows = 0;
     449    psU64 numCols = 0;
     450    psU64 failedLines = 0;
     451    FILE *fp = NULL;
     452    psElemType elemType;
     453    psVector *indexVec = NULL;
     454    psVector *valuesVec = NULL;
     455    psArray *values = NULL;
     456
     457
     458    // Error checks
     459    PS_PTR_CHECK_NULL(table,NULL);
     460    PS_PTR_CHECK_NULL(table->fileName,NULL);
     461    if((fp=fopen(table->fileName, "r")) == NULL) {
     462        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_FILE_NOT_FOUND, table->fileName);
     463        return NULL;
     464    }
     465
     466    indexVec = table->index;
     467    values = table->values;
     468
     469    // Create reusable line for continuous read
     470    line = (char*)psAlloc(MAX_STRING_LENGTH*sizeof(char));
     471
     472    // Loop through file to get numRows, numCols, and column data types
     473    while(fgets(line, MAX_STRING_LENGTH, fp) != NULL) {
     474
     475        // Initialize variables for new line
     476        linePtr = line;
     477        lineCount++;
     478
     479        // If line is not a comment or blank, then extract data
     480        if(!ignoreLine(linePtr)) {
     481
     482            if(typeLine == true) {
     483
     484                // Determine column types from first line in data file after comments
     485                while((strType=getToken(&linePtr, " ", &status)) != NULL) {
     486                    numCols++;
     487                    typeLine = false;
     488                    if(!strncmp(strType, "psU8", 4)) {
     489                        elemType = PS_TYPE_U8;
     490                    } else if(!strncmp(strType, "psS8", 4)) {
     491                        elemType = PS_TYPE_S8;
     492                    } else if(!strncmp(strType, "psU16", 5)) {
     493                        elemType = PS_TYPE_U16;
     494                    } else if(!strncmp(strType, "psS16", 5)) {
     495                        elemType = PS_TYPE_S16;
     496                    } else if(!strncmp(strType, "psU32", 5)) {
     497                        elemType = PS_TYPE_U32;
     498                    } else if(!strncmp(strType, "psS32", 5)) {
     499                        elemType = PS_TYPE_S32;
     500                    } else if(!strncmp(strType, "psU64", 5)) {
     501                        elemType = PS_TYPE_U64;
     502                    } else if(!strncmp(strType, "psS64", 5)) {
     503                        elemType = PS_TYPE_S64;
     504                    } else if(!strncmp(strType, "psF32", 5)) {
     505                        elemType = PS_TYPE_F32;
     506                    } else if(!strncmp(strType, "psF64", 5)) {
     507                        elemType = PS_TYPE_F64;
     508                    } else {
     509                        status = PS_PARSE_ERROR_TYPE;
     510                    }
     511
     512                    // Realloc number of columns as you go
     513                    if(numCols == 1) {
     514                        indexVec = psVectorAlloc(0, elemType);
     515                    } else {
     516                        values = psArrayRealloc(values, numCols-1);
     517                        values->n = values->nalloc;
     518                        values->data[numCols-2] = psVectorAlloc(0, elemType);
     519                    }
     520
     521                    if(status) {
     522                        status = printError(lineCount, strValue, status);
     523                        failedLines++;
     524                    }
     525                    psFree(strType);
     526                }
     527            } else {
     528
     529                // Parse and add values to all columns
     530                numRows++;
     531                numCols = 0;
     532                while((strValue=getToken(&linePtr, " ", &status)) != NULL) {
     533                    numCols++;
     534
     535                    // Realloc number of rows as you go
     536                    if(numCols == 1) {
     537                        indexVec = psVectorRecycle(indexVec, numRows, indexVec->type.type);
     538                        parseValue(indexVec, numRows-1, strValue, &status);
     539                    } else {
     540                        valuesVec = values->data[numCols-2];
     541                        valuesVec = psVectorRecycle(valuesVec, numRows, valuesVec->type.type);
     542                        parseValue(valuesVec, numRows-1, strValue, &status);
     543                    }
     544
     545                    if(status) {
     546                        status = printError(lineCount, strValue, status);
     547                        failedLines++;
     548                    }
     549                    psFree(strValue);
     550                } // end while
     551            } // end else
     552        } // if ignoreLine
     553    } // end while
     554
     555    psFree(line);
     556
     557    // Set table for return
     558    table->numRows = numRows;
     559    table->numCols = numCols-1;
     560    table->index = indexVec;
     561    table->values = values;
     562
     563    fclose(fp);
     564
     565    return table;
     566}
     567
     568psF64 psLookupTableInterpolate(psLookupTable *table, psF64 index, psU64 column, psLookupStatusType *status)
     569{
     570    psU64 hiIdx = 0;
     571    psU64 loIdx = 0;
     572    psU64 numRows = 0;
     573    psU64 numCols = 0;
     574    psF64 out = 0.0;
     575    psF64 denom = 0.0;
     576    psVector *indexVec = NULL;
     577    psVector *valuesVec = NULL;
     578    psArray *values = NULL;
     579
     580
     581    // Error checks
     582    PS_PTR_CHECK_NULL(table,0.0);
     583    indexVec = table->index;
     584    values = table->values;
     585    numRows = table->numRows;
     586    numCols = table->numCols;
     587    PS_PTR_CHECK_NULL(indexVec,0.0);
     588    PS_PTR_CHECK_NULL(values,0.0);
     589    PS_INT_CHECK_EQUALS(numRows, 0,0.0);
     590    PS_INT_CHECK_EQUALS(numCols, 0,0.0);
     591    PS_INT_CHECK_RANGE(column, 0, numCols-1, 0.0);
     592
     593
     594    valuesVec = (psVector*)values->data[column];
     595    PS_PTR_CHECK_NULL(indexVec,0.0);
     596
     597    if(index<indexVec->data.F64[0] || index<table->validFrom) {
     598
     599        // Index value past top of table
     600        *status = PS_LOOKUP_PAST_TOP;
     601        return valuesVec->data.F64[0];
     602    } else if(index>indexVec->data.F64[numRows-1] || index>table->validTo) {
     603
     604        // Index value past bottom of table
     605        *status = PS_LOOKUP_PAST_BOTTOM;
     606        return valuesVec->data.F64[numRows-1];
     607    } else {
     608
     609        // Interpolation
     610        while(index > indexVec->data.F64[hiIdx]) {
     611            hiIdx++;
     612            if(hiIdx >= numRows) {
     613                psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_INTERPOLATE_HIGH, hiIdx);
     614                return 0.0;
     615            }
     616        }
     617
     618        loIdx = hiIdx--;
     619        if(loIdx < 0) {
     620            psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_INTERPOLATE_LOW, loIdx);
     621            return 0.0;
     622        }
     623
     624        denom = indexVec->data.F64[hiIdx] - indexVec->data.F64[loIdx];
     625        if(fabs(denom) < FLT_EPSILON) {
     626            psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_DIVIDE_BY_ZERO);
     627            return 0.0;
     628        } else {
     629            out = valuesVec->data.F64[loIdx]+(valuesVec->data.F64[hiIdx]-valuesVec->data.F64[loIdx])
     630                  *(index-indexVec->data.F64[loIdx])/denom;
     631        }
     632    }
     633
     634    return out;
     635}
     636
     637psVector* psLookupTableInterpolateAll(psLookupTable *table, psF64 index, psVector *stats)
     638{
     639    psU64 i = 0;
     640    psU64 numCols = 0;
     641    psVector *outVector = NULL;
     642    psLookupStatusType status = PS_LOOKUP_SUCCESS;
     643
     644
     645    // Error checks
     646    PS_PTR_CHECK_NULL(table,NULL);
     647    PS_PTR_CHECK_NULL(stats,NULL);
     648    numCols = table->numCols;
     649    PS_INT_CHECK_EQUALS(numCols, 0,NULL);
     650
     651    outVector = psVectorAlloc(numCols, PS_TYPE_F64);
     652
     653    // Fill vectors with results and status of results
     654    for(i=0; i<numCols; i++) {
     655        outVector->data.F64[i] = psLookupTableInterpolate(table, index, i, &status);
     656        stats->data.U32[i] = status;
     657    }
     658
     659    return outVector;
     660}
     661
  • trunk/psLib/src/fileUtils/psLookupTable.h

    r2195 r2302  
    77*  @author Ross Harman, MHPCC
    88*
    9 *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
    10 *  @date $Date: 2004-10-26 00:37:15 $
     9*  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
     10*  @date $Date: 2004-11-09 00:38:14 $
    1111*
    1212*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    1515#ifndef PS_LOOKUPTABLE_H
    1616#define PS_LOOKUPTABLE_H
     17
     18#include "psType.h"
     19#include "psVector.h"
     20#include "psArray.h"
    1721
    1822
     
    2428typedef struct
    2529{
     30    const char *fileName;              ///< Name of file with table
     31    psU64 numRows;                     ///< Number of table rows
     32    psU64 numCols;                     ///< Number of table columns
     33    psF64 validFrom;                   ///< Lower bound for rable read
     34    psF64 validTo;                     ///< Upper bound for table read
    2635    psVector *index;                   ///< Vector of independent index values
    27     psArray *values;                   ///< Array of dependent table values corresponding to index values.
     36    psArray *values;                   ///< Array of dependent table values corresponding to index values
    2837}
    2938psLookupTable;
    3039
    3140
    32 /** Lookup error conditions
     41/** Lookup table lookup status and error conditions
    3342 *
    34  *  Success and failure conditions for table lookups.
     43 *  Success, failure, and status conditions for table lookups.
    3544 */
    3645typedef enum {
    37     PS_LOOKUP_SUCCESS = 0x000,         ///< Table lookup succeeded.
    38     PS_LOOKUP_TOP     = 0x0001,        ///< Lookup off top of table.
    39     PS_LOOKUP_BOTTOM  = 0x0002,        ///< Lookup off bottom of table.
    40     PS_LOOKUP_ERROR   = 0x0003,        ///< Any other type of lookup error.
    41 } psLookupErrorType;
     46    PS_LOOKUP_SUCCESS             = 0x0000,        ///< Table lookup succeeded
     47    PS_LOOKUP_PAST_TOP            = 0x0101,        ///< Lookup off top of table
     48    PS_LOOKUP_PAST_BOTTOM         = 0x0102,        ///< Lookup off bottom of table
     49    PS_LOOKUP_ERROR               = 0x0104         ///< Any other type of lookup error
     50} psLookupStatusType;
     51
     52/** Lookup table parse status and error conditions
     53 *
     54 *  Success, failure, and status conditions for table parsing.
     55 */
     56typedef enum {
     57    PS_PARSE_SUCCESS              = 0x0000,        ///< Table lookup succeeded
     58    PS_PARSE_ERROR_TYPE           = 0x0101,        ///< Error parsing type
     59    PS_PARSE_ERROR_VALUE          = 0x0102,        ///< Error parsing numerical value
     60    PS_PARSE_ERROR_GENERAL        = 0x0104         ///< Any other type of lookup error
     61}psParseErrorType;
    4262
    4363/** Allocator for psLookupTable struct
     
    4868 */
    4969psLookupTable* psLookupTableAlloc(
    50     psU64 numRows,                  ///< Number of rows
    51     psU64 numCols                   ///< number of columns
     70    const char *fileName,           ///< Name of file to read
     71    psF64 validFrom,                ///< Lower bound for rable read
     72    psF64 validTo                   ///< Upper bound for table read
    5273);
    5374
     
    5980 */
    6081psLookupTable* psLookupTableRead(
    61     char *fileName                  ///< Name of file to read
     82    psLookupTable *table            ///< Table to read
    6283);
    6384
     
    6788 *  conditions.
    6889 *
    69  *  @return psLookupTable*     New psLookupTable struct.
     90 *  @return psLookupTable*     New psLookupTable struct
    7091 */
    7192psF64 psLookupTableInterpolate(
    7293    psLookupTable *table,           ///< Table with data
    7394    psF64 index,                    ///< Value to be interpolated
    74     psMaskType *status              ///< Status of lookup.
     95    psU64 column,                   ///< Column in table to be interpolated
     96    psLookupStatusType *status      ///< Status of lookup
    7597);
    7698
     
    80102 *  conditions.
    81103 *
    82  *  @return psLookupTable*     New psLookupTable struct.
     104 *  @return psLookupTable*     New psLookupTable struct
    83105 */
    84 psVector* psLookupTableInterpolate(
     106psVector* psLookupTableInterpolateAll(
    85107    psLookupTable *table,           ///< Table with data
    86108    psF64 index,                    ///< Value to be interpolated
    87     psMaskType *status              ///< Status of lookup.
     109    psVector *stats                 ///< Vector of status for each lookup
    88110);
    89111
  • trunk/psLib/src/types/psLookupTable.c

    r2195 r2302  
    88*  @author Ross Harman, MHPCC
    99*
    10 *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
    11 *  @date $Date: 2004-10-26 00:36:50 $
     10*  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
     11*  @date $Date: 2004-11-09 00:38:14 $
    1212*
    1313*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
    1414*/
    15 
    16 #include "psLookupTable.c"
    17 
    18 
    19 psLookupTable* psLookupTableAlloc(psU64 numRows, psU64 numCols)
    20 {
    21 }
    22 
    23 psLookupTable* psLookupTableRead(char *fileName)
    24 {
    25 }
    26 
    27 psF64 psLookupTableInterpolate(psLookupTable *table, psF64 index, psMaskType *status)
    28 {
    29 }
    30 
    31 psVector* psLookupTableInterpolate(psLookupTable *table, psF64 index, psMaskType *status)
    32 {
    33 }
    34 
    35 #endif
     15#include <stdio.h>
     16#include <string.h>
     17#include <ctype.h>
     18#include <stdlib.h>
     19#include <math.h>
     20
     21#include "psMemory.h"
     22#include "psString.h"
     23#include "psError.h"
     24#include "psLookupTable.h"
     25#include "psFileUtilsErrors.h"
     26#include "psConstants.h"
     27
     28/******************************************************************************/
     29/*  DEFINE STATEMENTS                                                         */
     30/******************************************************************************/
     31
     32/** Maximum size of a string */
     33#define MAX_STRING_LENGTH 256
     34
     35/******************************************************************************/
     36/*  TYPE DEFINITIONS                                                          */
     37/******************************************************************************/
     38
     39// None
     40
     41/*****************************************************************************/
     42/*  GLOBAL VARIABLES                                                         */
     43/*****************************************************************************/
     44
     45// None
     46
     47/*****************************************************************************/
     48/*  FILE STATIC VARIABLES                                                    */
     49/*****************************************************************************/
     50
     51// None
     52
     53/*****************************************************************************/
     54/*  FUNCTION IMPLEMENTATION - LOCAL                                          */
     55/*****************************************************************************/
     56
     57static bool ignoreLine(char *inString);
     58static char *cleanString(char *inString, int sLen);
     59static char* getToken(char **inString, char *delimiter, psParseErrorType *status);
     60static psU8 parseU8(char *inString, psParseErrorType *status);
     61static psS8 parseS8(char *inString, psParseErrorType *status);
     62static psU16 parseU16(char *inString, psParseErrorType *status);
     63static psS16 parseS16(char *inString, psParseErrorType *status);
     64static psU32 parseU32(char *inString, psParseErrorType *status);
     65static psS32 parseS32(char *inString, psParseErrorType *status);
     66static psU64 parseU64(char *inString, psParseErrorType *status);
     67static psS64 parseS64(char *inString, psParseErrorType *status);
     68static psF32 parseF32(char *inString, psParseErrorType *status);
     69static psF64 parseF64(char *inString, psParseErrorType *status);
     70static void parseValue(psVector *vec, psU64 index, char* strValue, psParseErrorType *status);
     71static void lookupTableFree(psLookupTable* table);
     72
     73/** Determines if a line is blank (whitespace only) or a commentline. It returns true if so. The input string
     74 *  must be null terminated. */
     75static bool ignoreLine(char *inString)
     76{
     77    while(*inString!='\0' && *inString!='#') {
     78        if(!isspace(*inString)) {
     79            return false;
     80        }
     81        inString++;
     82    }
     83
     84    return true;
     85}
     86
     87
     88/** Removes leading and trailing whitespace and # characters from a string. The cleaned string is a new null
     89 *  terminated copy of the original input string. */
     90static char *cleanString(char *inString, int sLen)
     91{
     92    char *ptrB = NULL;
     93    char *ptrE = NULL;
     94    char *cleaned = NULL;
     95
     96
     97    ptrB = inString;
     98
     99    /* Skip over leading # or whitespace */
     100    while (isspace(*ptrB) || *ptrB=='#') {
     101        ptrB++;
     102    }
     103
     104    /* Skip over trailing whitespace, null terminators, and # characters */
     105    ptrE = inString + sLen;
     106    while(isspace(*ptrE) || *ptrE=='\0' || *ptrE=='#') {
     107        ptrE--;
     108    }
     109
     110    // Length, sLen, does not include '\0'
     111    sLen = ptrE - ptrB + 1;
     112
     113    // Adds '\0' to end of string and +1 to sLen
     114    cleaned = psStringNCopy(ptrB, sLen);
     115
     116    return cleaned;
     117}
     118
     119
     120/** Returns cleaned token based on delimiter, but not including delimiter. Also changes the pointer location
     121 * the beginning of the string. Tokens are newly allocated null terminated strings. */
     122static char* getToken(char **inString, char *delimiter, psParseErrorType *status)
     123{
     124    char *cleanToken = NULL;
     125    int sLen = 0;
     126
     127
     128    // Skip over leading whitespace
     129    while(isspace(**inString)) {
     130        (*inString)++;
     131    }
     132
     133    // Length of token, not including delimiter
     134    sLen = strcspn(*inString, delimiter);
     135    if(sLen) {
     136
     137        // Create new, cleaned, and null terminated token
     138        cleanToken = cleanString(*inString, sLen);
     139
     140        // Move to end of token
     141        (*inString) += sLen;
     142    } else if(**inString!='\0' && sLen==0) {
     143        *status = PS_PARSE_ERROR_GENERAL;
     144    }
     145
     146    return cleanToken;
     147}
     148
     149/** Returns single parsed value as a psU8. The input string must be cleaned and null terminated. */
     150static psU8 parseU8(char *inString, psParseErrorType *status)
     151{
     152    char *end = NULL;
     153    psU8 value = 0.0;
     154
     155
     156    value = (psU8)strtoul(inString, &end, 0);
     157    if(*end != '\0') {
     158        *status = PS_PARSE_ERROR_VALUE;
     159    } else if(inString==end) {
     160        *status = PS_PARSE_ERROR_VALUE;
     161    }
     162
     163    return value;
     164}
     165
     166/** Returns single parsed value as a psS8. The input string must be cleaned and null terminated. */
     167static psS8 parseS8(char *inString, psParseErrorType *status)
     168{
     169    char *end = NULL;
     170    psS8 value = 0.0;
     171
     172
     173    value = (psS8)strtol(inString, &end, 0);
     174    if(*end != '\0') {
     175        *status = PS_PARSE_ERROR_VALUE;
     176    } else if(inString==end) {
     177        *status = PS_PARSE_ERROR_VALUE;
     178    }
     179
     180    return value;
     181}
     182
     183/** Returns single parsed value as a psU16. The input string must be cleaned and null terminated. */
     184static psU16 parseU16(char *inString, psParseErrorType *status)
     185{
     186    char *end = NULL;
     187    psU16 value = 0.0;
     188
     189
     190    value = (psU16)strtoul(inString, &end, 0);
     191    if(*end != '\0') {
     192        *status = PS_PARSE_ERROR_VALUE;
     193    } else if(inString==end) {
     194        *status = PS_PARSE_ERROR_VALUE;
     195    }
     196
     197    return value;
     198}
     199
     200/** Returns single parsed value as a psS16. The input string must be cleaned and null terminated. */
     201static psS16 parseS16(char *inString, psParseErrorType *status)
     202{
     203    char *end = NULL;
     204    psS16 value = 0.0;
     205
     206
     207    value = (psS16)strtol(inString, &end, 0);
     208    if(*end != '\0') {
     209        *status = PS_PARSE_ERROR_VALUE;
     210    } else if(inString==end) {
     211        *status = PS_PARSE_ERROR_VALUE;
     212    }
     213
     214    return value;
     215}
     216
     217/** Returns single parsed value as a psU32. The input string must be cleaned and null terminated. */
     218static psU32 parseU32(char *inString, psParseErrorType *status)
     219{
     220    char *end = NULL;
     221    psU32 value = 0.0;
     222
     223
     224    value = (psU32)strtoul(inString, &end, 0);
     225    if(*end != '\0') {
     226        *status = PS_PARSE_ERROR_VALUE;
     227    } else if(inString==end) {
     228        *status = PS_PARSE_ERROR_VALUE;
     229    }
     230
     231    return value;
     232}
     233
     234/** Returns single parsed value as a psS32. The input string must be cleaned and null terminated. */
     235static psS32 parseS32(char *inString, psParseErrorType *status)
     236{
     237    char *end = NULL;
     238    psS32 value = 0.0;
     239
     240
     241    value = (psS32)strtol(inString, &end, 0);
     242    if(*end != '\0') {
     243        *status = PS_PARSE_ERROR_VALUE;
     244    } else if(inString==end) {
     245        *status = PS_PARSE_ERROR_VALUE;
     246    }
     247
     248    return value;
     249}
     250
     251/** Returns single parsed value as a psU64. The input string must be cleaned and null terminated. */
     252static psU64 parseU64(char *inString, psParseErrorType *status)
     253{
     254    char *end = NULL;
     255    psU64 value = 0.0;
     256
     257
     258    value = (psU64)strtoull(inString, &end, 0);
     259    if(*end != '\0') {
     260        *status = PS_PARSE_ERROR_VALUE;
     261    } else if(inString==end) {
     262        *status = PS_PARSE_ERROR_VALUE;
     263    }
     264
     265    return value;
     266}
     267
     268/** Returns single parsed value as a psS64. The input string must be cleaned and null terminated. */
     269static psS64 parseS64(char *inString, psParseErrorType *status)
     270{
     271    char *end = NULL;
     272    psS64 value = 0.0;
     273
     274
     275    value = (psS64)strtoll(inString, &end, 0);
     276    if(*end != '\0') {
     277        *status = PS_PARSE_ERROR_VALUE;
     278    } else if(inString==end) {
     279        *status = PS_PARSE_ERROR_VALUE;
     280    }
     281
     282    return value;
     283}
     284
     285/** Returns single parsed value as a psF32. The input string must be cleaned and null terminated. */
     286static psF32 parseF32(char *inString, psParseErrorType *status)
     287{
     288    char *end = NULL;
     289    psF32 value = 0.0;
     290
     291
     292    value = (psF32)strtof(inString, &end);
     293    if(*end != '\0') {
     294        *status = PS_PARSE_ERROR_VALUE;
     295    } else if(inString==end) {
     296        *status = PS_PARSE_ERROR_VALUE;
     297    }
     298
     299    return value;
     300}
     301
     302/** Returns single parsed value as a psF64. The input string must be cleaned and null terminated. */
     303static psF64 parseF64(char *inString, psParseErrorType *status)
     304{
     305    char *end = NULL;
     306    psF64 value = 0.0;
     307
     308
     309    value = (psF64)strtod(inString, &end);
     310    if(*end != '\0') {
     311        *status = PS_PARSE_ERROR_VALUE;
     312    } else if(inString==end) {
     313        *status = PS_PARSE_ERROR_VALUE;
     314    }
     315
     316    return value;
     317}
     318
     319/** Returns single parsed value as a double precision number. The input string must be cleaned and null
     320 * terminated. */
     321static void parseValue(psVector *vec, psU64 index, char* strValue, psParseErrorType *status)
     322{
     323    psElemType type;
     324
     325
     326    if(vec == NULL) {
     327        *status = 1;
     328        return;
     329    }
     330
     331    type = vec->type.type;
     332
     333    switch(type) {
     334    case PS_TYPE_U8:
     335        vec->data.U8[index] = parseU8(strValue, status);
     336        break;
     337    case PS_TYPE_S8:
     338        vec->data.S8[index] = parseS8(strValue, status);
     339        break;
     340    case PS_TYPE_U16:
     341        vec->data.U16[index] = parseU16(strValue, status);
     342        break;
     343    case PS_TYPE_S16:
     344        vec->data.S16[index] = parseS16(strValue, status);
     345        break;
     346    case PS_TYPE_U32:
     347        vec->data.U32[index] = parseU32(strValue, status);
     348        break;
     349    case PS_TYPE_S32:
     350        vec->data.S32[index] = parseS32(strValue, status);
     351        break;
     352    case PS_TYPE_U64:
     353        vec->data.U64[index] = parseU64(strValue, status);
     354        break;
     355    case PS_TYPE_S64:
     356        vec->data.S64[index] = parseS64(strValue, status);
     357        break;
     358    case PS_TYPE_F32:
     359        vec->data.F32[index] = parseF32(strValue, status);
     360        break;
     361    case PS_TYPE_F64:
     362        vec->data.F64[index] = parseF64(strValue, status);
     363        break;
     364    default:
     365        *status = PS_PARSE_ERROR_TYPE;
     366    }
     367
     368    return;
     369}
     370
     371static psParseErrorType printError(psU64 lineCount, char* badText, psParseErrorType status)
     372{
     373    switch(status) {
     374    case PS_PARSE_ERROR_VALUE:
     375        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_PARSE_VALUE, badText, lineCount);
     376        break;
     377    case PS_PARSE_ERROR_TYPE:
     378        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_PARSE_TYPE, badText, lineCount);
     379        break;
     380    case PS_PARSE_ERROR_GENERAL:
     381        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_PARSE_GENERAL, badText, lineCount);
     382        break;
     383    default:
     384        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_INVALID_TYPE, badText, lineCount);
     385    }
     386
     387    return PS_LOOKUP_SUCCESS;
     388}
     389
     390static void lookupTableFree(psLookupTable* table)
     391{
     392    if (table == NULL) {
     393        return;
     394    }
     395
     396    psFree(table->values);
     397    psFree(table->index);
     398    psFree((char*)table->fileName);
     399}
     400
     401/*****************************************************************************/
     402/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
     403/*****************************************************************************/
     404
     405psLookupTable* psLookupTableAlloc(const char *fileName, psF64 validFrom, psF64 validTo)
     406{
     407    psLookupTable *outTable = NULL;
     408
     409
     410    // Can't read table if you don't know its name
     411    PS_PTR_CHECK_NULL(fileName,NULL);
     412
     413    // Allocate lookup table
     414    outTable = (psLookupTable*)psAlloc(sizeof(psLookupTable));
     415
     416    // Set deallocator
     417    p_psMemSetDeallocator(outTable, (psFreeFcn)lookupTableFree);
     418
     419    // Allocate and set metadata item comment
     420    outTable->fileName = psStringCopy(fileName);
     421
     422    // Number of table rows and columns. Automatically resized by table read.
     423    outTable->numRows = 0;
     424    outTable->numCols = 0;
     425
     426    // Valid ranges. Automatically set by table read if both zero.
     427    outTable->validFrom = validFrom;
     428    outTable->validTo = validTo;
     429
     430    // Vector of independent index values. Filled by table read.
     431    outTable->index = NULL;
     432
     433    // Array of dependent table values corresponding to index values. Filled by table read.
     434    outTable->values = NULL;
     435
     436    return outTable;
     437}
     438
     439psLookupTable* psLookupTableRead(psLookupTable *table)
     440{
     441    bool typeLine = true;
     442    char *line = NULL;
     443    char *strType = NULL;
     444    char *strValue = NULL;
     445    char *linePtr = NULL;
     446    psParseErrorType status = PS_PARSE_SUCCESS;
     447    psU64 lineCount = 0;
     448    psU64 numRows = 0;
     449    psU64 numCols = 0;
     450    psU64 failedLines = 0;
     451    FILE *fp = NULL;
     452    psElemType elemType;
     453    psVector *indexVec = NULL;
     454    psVector *valuesVec = NULL;
     455    psArray *values = NULL;
     456
     457
     458    // Error checks
     459    PS_PTR_CHECK_NULL(table,NULL);
     460    PS_PTR_CHECK_NULL(table->fileName,NULL);
     461    if((fp=fopen(table->fileName, "r")) == NULL) {
     462        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_FILE_NOT_FOUND, table->fileName);
     463        return NULL;
     464    }
     465
     466    indexVec = table->index;
     467    values = table->values;
     468
     469    // Create reusable line for continuous read
     470    line = (char*)psAlloc(MAX_STRING_LENGTH*sizeof(char));
     471
     472    // Loop through file to get numRows, numCols, and column data types
     473    while(fgets(line, MAX_STRING_LENGTH, fp) != NULL) {
     474
     475        // Initialize variables for new line
     476        linePtr = line;
     477        lineCount++;
     478
     479        // If line is not a comment or blank, then extract data
     480        if(!ignoreLine(linePtr)) {
     481
     482            if(typeLine == true) {
     483
     484                // Determine column types from first line in data file after comments
     485                while((strType=getToken(&linePtr, " ", &status)) != NULL) {
     486                    numCols++;
     487                    typeLine = false;
     488                    if(!strncmp(strType, "psU8", 4)) {
     489                        elemType = PS_TYPE_U8;
     490                    } else if(!strncmp(strType, "psS8", 4)) {
     491                        elemType = PS_TYPE_S8;
     492                    } else if(!strncmp(strType, "psU16", 5)) {
     493                        elemType = PS_TYPE_U16;
     494                    } else if(!strncmp(strType, "psS16", 5)) {
     495                        elemType = PS_TYPE_S16;
     496                    } else if(!strncmp(strType, "psU32", 5)) {
     497                        elemType = PS_TYPE_U32;
     498                    } else if(!strncmp(strType, "psS32", 5)) {
     499                        elemType = PS_TYPE_S32;
     500                    } else if(!strncmp(strType, "psU64", 5)) {
     501                        elemType = PS_TYPE_U64;
     502                    } else if(!strncmp(strType, "psS64", 5)) {
     503                        elemType = PS_TYPE_S64;
     504                    } else if(!strncmp(strType, "psF32", 5)) {
     505                        elemType = PS_TYPE_F32;
     506                    } else if(!strncmp(strType, "psF64", 5)) {
     507                        elemType = PS_TYPE_F64;
     508                    } else {
     509                        status = PS_PARSE_ERROR_TYPE;
     510                    }
     511
     512                    // Realloc number of columns as you go
     513                    if(numCols == 1) {
     514                        indexVec = psVectorAlloc(0, elemType);
     515                    } else {
     516                        values = psArrayRealloc(values, numCols-1);
     517                        values->n = values->nalloc;
     518                        values->data[numCols-2] = psVectorAlloc(0, elemType);
     519                    }
     520
     521                    if(status) {
     522                        status = printError(lineCount, strValue, status);
     523                        failedLines++;
     524                    }
     525                    psFree(strType);
     526                }
     527            } else {
     528
     529                // Parse and add values to all columns
     530                numRows++;
     531                numCols = 0;
     532                while((strValue=getToken(&linePtr, " ", &status)) != NULL) {
     533                    numCols++;
     534
     535                    // Realloc number of rows as you go
     536                    if(numCols == 1) {
     537                        indexVec = psVectorRecycle(indexVec, numRows, indexVec->type.type);
     538                        parseValue(indexVec, numRows-1, strValue, &status);
     539                    } else {
     540                        valuesVec = values->data[numCols-2];
     541                        valuesVec = psVectorRecycle(valuesVec, numRows, valuesVec->type.type);
     542                        parseValue(valuesVec, numRows-1, strValue, &status);
     543                    }
     544
     545                    if(status) {
     546                        status = printError(lineCount, strValue, status);
     547                        failedLines++;
     548                    }
     549                    psFree(strValue);
     550                } // end while
     551            } // end else
     552        } // if ignoreLine
     553    } // end while
     554
     555    psFree(line);
     556
     557    // Set table for return
     558    table->numRows = numRows;
     559    table->numCols = numCols-1;
     560    table->index = indexVec;
     561    table->values = values;
     562
     563    fclose(fp);
     564
     565    return table;
     566}
     567
     568psF64 psLookupTableInterpolate(psLookupTable *table, psF64 index, psU64 column, psLookupStatusType *status)
     569{
     570    psU64 hiIdx = 0;
     571    psU64 loIdx = 0;
     572    psU64 numRows = 0;
     573    psU64 numCols = 0;
     574    psF64 out = 0.0;
     575    psF64 denom = 0.0;
     576    psVector *indexVec = NULL;
     577    psVector *valuesVec = NULL;
     578    psArray *values = NULL;
     579
     580
     581    // Error checks
     582    PS_PTR_CHECK_NULL(table,0.0);
     583    indexVec = table->index;
     584    values = table->values;
     585    numRows = table->numRows;
     586    numCols = table->numCols;
     587    PS_PTR_CHECK_NULL(indexVec,0.0);
     588    PS_PTR_CHECK_NULL(values,0.0);
     589    PS_INT_CHECK_EQUALS(numRows, 0,0.0);
     590    PS_INT_CHECK_EQUALS(numCols, 0,0.0);
     591    PS_INT_CHECK_RANGE(column, 0, numCols-1, 0.0);
     592
     593
     594    valuesVec = (psVector*)values->data[column];
     595    PS_PTR_CHECK_NULL(indexVec,0.0);
     596
     597    if(index<indexVec->data.F64[0] || index<table->validFrom) {
     598
     599        // Index value past top of table
     600        *status = PS_LOOKUP_PAST_TOP;
     601        return valuesVec->data.F64[0];
     602    } else if(index>indexVec->data.F64[numRows-1] || index>table->validTo) {
     603
     604        // Index value past bottom of table
     605        *status = PS_LOOKUP_PAST_BOTTOM;
     606        return valuesVec->data.F64[numRows-1];
     607    } else {
     608
     609        // Interpolation
     610        while(index > indexVec->data.F64[hiIdx]) {
     611            hiIdx++;
     612            if(hiIdx >= numRows) {
     613                psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_INTERPOLATE_HIGH, hiIdx);
     614                return 0.0;
     615            }
     616        }
     617
     618        loIdx = hiIdx--;
     619        if(loIdx < 0) {
     620            psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_INTERPOLATE_LOW, loIdx);
     621            return 0.0;
     622        }
     623
     624        denom = indexVec->data.F64[hiIdx] - indexVec->data.F64[loIdx];
     625        if(fabs(denom) < FLT_EPSILON) {
     626            psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_DIVIDE_BY_ZERO);
     627            return 0.0;
     628        } else {
     629            out = valuesVec->data.F64[loIdx]+(valuesVec->data.F64[hiIdx]-valuesVec->data.F64[loIdx])
     630                  *(index-indexVec->data.F64[loIdx])/denom;
     631        }
     632    }
     633
     634    return out;
     635}
     636
     637psVector* psLookupTableInterpolateAll(psLookupTable *table, psF64 index, psVector *stats)
     638{
     639    psU64 i = 0;
     640    psU64 numCols = 0;
     641    psVector *outVector = NULL;
     642    psLookupStatusType status = PS_LOOKUP_SUCCESS;
     643
     644
     645    // Error checks
     646    PS_PTR_CHECK_NULL(table,NULL);
     647    PS_PTR_CHECK_NULL(stats,NULL);
     648    numCols = table->numCols;
     649    PS_INT_CHECK_EQUALS(numCols, 0,NULL);
     650
     651    outVector = psVectorAlloc(numCols, PS_TYPE_F64);
     652
     653    // Fill vectors with results and status of results
     654    for(i=0; i<numCols; i++) {
     655        outVector->data.F64[i] = psLookupTableInterpolate(table, index, i, &status);
     656        stats->data.U32[i] = status;
     657    }
     658
     659    return outVector;
     660}
     661
  • trunk/psLib/src/types/psLookupTable.h

    r2195 r2302  
    77*  @author Ross Harman, MHPCC
    88*
    9 *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
    10 *  @date $Date: 2004-10-26 00:37:15 $
     9*  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
     10*  @date $Date: 2004-11-09 00:38:14 $
    1111*
    1212*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    1515#ifndef PS_LOOKUPTABLE_H
    1616#define PS_LOOKUPTABLE_H
     17
     18#include "psType.h"
     19#include "psVector.h"
     20#include "psArray.h"
    1721
    1822
     
    2428typedef struct
    2529{
     30    const char *fileName;              ///< Name of file with table
     31    psU64 numRows;                     ///< Number of table rows
     32    psU64 numCols;                     ///< Number of table columns
     33    psF64 validFrom;                   ///< Lower bound for rable read
     34    psF64 validTo;                     ///< Upper bound for table read
    2635    psVector *index;                   ///< Vector of independent index values
    27     psArray *values;                   ///< Array of dependent table values corresponding to index values.
     36    psArray *values;                   ///< Array of dependent table values corresponding to index values
    2837}
    2938psLookupTable;
    3039
    3140
    32 /** Lookup error conditions
     41/** Lookup table lookup status and error conditions
    3342 *
    34  *  Success and failure conditions for table lookups.
     43 *  Success, failure, and status conditions for table lookups.
    3544 */
    3645typedef enum {
    37     PS_LOOKUP_SUCCESS = 0x000,         ///< Table lookup succeeded.
    38     PS_LOOKUP_TOP     = 0x0001,        ///< Lookup off top of table.
    39     PS_LOOKUP_BOTTOM  = 0x0002,        ///< Lookup off bottom of table.
    40     PS_LOOKUP_ERROR   = 0x0003,        ///< Any other type of lookup error.
    41 } psLookupErrorType;
     46    PS_LOOKUP_SUCCESS             = 0x0000,        ///< Table lookup succeeded
     47    PS_LOOKUP_PAST_TOP            = 0x0101,        ///< Lookup off top of table
     48    PS_LOOKUP_PAST_BOTTOM         = 0x0102,        ///< Lookup off bottom of table
     49    PS_LOOKUP_ERROR               = 0x0104         ///< Any other type of lookup error
     50} psLookupStatusType;
     51
     52/** Lookup table parse status and error conditions
     53 *
     54 *  Success, failure, and status conditions for table parsing.
     55 */
     56typedef enum {
     57    PS_PARSE_SUCCESS              = 0x0000,        ///< Table lookup succeeded
     58    PS_PARSE_ERROR_TYPE           = 0x0101,        ///< Error parsing type
     59    PS_PARSE_ERROR_VALUE          = 0x0102,        ///< Error parsing numerical value
     60    PS_PARSE_ERROR_GENERAL        = 0x0104         ///< Any other type of lookup error
     61}psParseErrorType;
    4262
    4363/** Allocator for psLookupTable struct
     
    4868 */
    4969psLookupTable* psLookupTableAlloc(
    50     psU64 numRows,                  ///< Number of rows
    51     psU64 numCols                   ///< number of columns
     70    const char *fileName,           ///< Name of file to read
     71    psF64 validFrom,                ///< Lower bound for rable read
     72    psF64 validTo                   ///< Upper bound for table read
    5273);
    5374
     
    5980 */
    6081psLookupTable* psLookupTableRead(
    61     char *fileName                  ///< Name of file to read
     82    psLookupTable *table            ///< Table to read
    6283);
    6384
     
    6788 *  conditions.
    6889 *
    69  *  @return psLookupTable*     New psLookupTable struct.
     90 *  @return psLookupTable*     New psLookupTable struct
    7091 */
    7192psF64 psLookupTableInterpolate(
    7293    psLookupTable *table,           ///< Table with data
    7394    psF64 index,                    ///< Value to be interpolated
    74     psMaskType *status              ///< Status of lookup.
     95    psU64 column,                   ///< Column in table to be interpolated
     96    psLookupStatusType *status      ///< Status of lookup
    7597);
    7698
     
    80102 *  conditions.
    81103 *
    82  *  @return psLookupTable*     New psLookupTable struct.
     104 *  @return psLookupTable*     New psLookupTable struct
    83105 */
    84 psVector* psLookupTableInterpolate(
     106psVector* psLookupTableInterpolateAll(
    85107    psLookupTable *table,           ///< Table with data
    86108    psF64 index,                    ///< Value to be interpolated
    87     psMaskType *status              ///< Status of lookup.
     109    psVector *stats                 ///< Vector of status for each lookup
    88110);
    89111
Note: See TracChangeset for help on using the changeset viewer.