IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 3271


Ignore:
Timestamp:
Feb 17, 2005, 11:54:09 AM (21 years ago)
Author:
evanalst
Message:

Update psLookupTable functions to met requirements.

Location:
trunk/psLib/src
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/psLib/src/dataIO/psFileUtilsErrors.dat

    r3028 r3271  
    1515psLookupTable_DIVIDE_BY_ZERO           Divide by zero error during interpolation.
    1616psLookupTable_INVALID_TYPE             Invalid psLookupType, %d;
     17psLookupTable_TABLE_INVALID            Lookup table is invalid.
    1718#
    1819psFits_NULL                            The input psFits object can not NULL.
  • trunk/psLib/src/dataIO/psFileUtilsErrors.h

    r3264 r3271  
    77 *  @author Robert DeSonia, MHPCC
    88 *
    9  *  @version $Revision: 1.11 $ $Name: not supported by cvs2svn $
    10  *  @date $Date: 2005-02-17 19:26:24 $
     9 *  @version $Revision: 1.12 $ $Name: not supported by cvs2svn $
     10 *  @date $Date: 2005-02-17 21:54:09 $
    1111 *
    1212 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     
    3636#define PS_ERRORTEXT_psLookupTable_DIVIDE_BY_ZERO "Divide by zero error during interpolation."
    3737#define PS_ERRORTEXT_psLookupTable_INVALID_TYPE "Invalid psLookupType, %d;"
     38#define PS_ERRORTEXT_psLookupTable_TABLE_INVALID "Lookup table is invalid."
    3839#define PS_ERRORTEXT_psFits_NULL "The input psFits object can not NULL."
    3940#define PS_ERRORTEXT_psFits_FILENAME_INVALID "Could not open file,'%s'.\nCFITSIO Error: %s"
  • trunk/psLib/src/dataIO/psLookupTable.c

    r3264 r3271  
    77*  @author Ross Harman, MHPCC
    88*
    9 *  @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
    10 *  @date $Date: 2005-02-17 19:26:24 $
     9*  @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
     10*  @date $Date: 2005-02-17 21:54:09 $
    1111*
    12 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     12*  Copyright 2004-5 Maui High Performance Computing Center, University of Hawaii
    1313*/
    1414#include <stdio.h>
    1515#include <string.h>
    1616#include <ctype.h>
     17//#ifdef DARWIN
    1718#undef __STRICT_ANSI__
     19//#endif
    1820#include <stdlib.h>
    19 #include <limits.h>
     21//#ifdef DARWIN
     22#define __STRICT_ANSI__
     23//#endif
    2024#include <math.h>
     25#include <stdlib.h>
    2126
    2227#include "psMemory.h"
     
    438443}
    439444
     445#define UPDATE_VALID_TO_FROM(TABLE)                                             \
     446switch (TABLE->index->type.type) {                                              \
     447case PS_TYPE_U8:                                                                \
     448    TABLE->validFrom = (psF64)TABLE->index->data.U8[0];                         \
     449    TABLE->validTo   = (psF64)TABLE->index->data.U8[TABLE->index->nalloc-1];    \
     450    break;                                                                      \
     451case PS_TYPE_S8:                                                                \
     452    TABLE->validFrom = (psF64)TABLE->index->data.S8[0];                         \
     453    TABLE->validTo   = (psF64)TABLE->index->data.S8[TABLE->index->nalloc-1];    \
     454    break;                                                                      \
     455case PS_TYPE_U16:                                                               \
     456    TABLE->validFrom = (psF64)TABLE->index->data.U16[0];                        \
     457    TABLE->validTo   = (psF64)TABLE->index->data.U16[TABLE->index->nalloc-1];   \
     458    break;                                                                      \
     459case PS_TYPE_S16:                                                               \
     460    TABLE->validFrom = (psF64)TABLE->index->data.S16[0];                        \
     461    TABLE->validTo   = (psF64)TABLE->index->data.S16[TABLE->index->nalloc-1];   \
     462    break;                                                                      \
     463case PS_TYPE_U32:                                                               \
     464    TABLE->validFrom = (psF64)TABLE->index->data.U32[0];                        \
     465    TABLE->validTo   = (psF64)TABLE->index->data.U32[TABLE->index->nalloc-1];   \
     466    break;                                                                      \
     467case PS_TYPE_S32:                                                               \
     468    TABLE->validFrom = (psF64)TABLE->index->data.S32[0];                        \
     469    TABLE->validTo   = (psF64)TABLE->index->data.S32[TABLE->index->nalloc-1];   \
     470    break;                                                                      \
     471case PS_TYPE_U64:                                                               \
     472    TABLE->validFrom = (psF64)TABLE->index->data.U64[0];                        \
     473    TABLE->validTo   = (psF64)TABLE->index->data.U64[TABLE->index->nalloc-1];   \
     474    break;                                                                      \
     475case PS_TYPE_S64:                                                               \
     476    TABLE->validFrom = (psF64)TABLE->index->data.S64[0];                        \
     477    TABLE->validTo   = (psF64)TABLE->index->data.S64[TABLE->index->nalloc-1];   \
     478    break;                                                                      \
     479case PS_TYPE_F32:                                                               \
     480    TABLE->validFrom = (psF64)TABLE->index->data.F32[0];                        \
     481    TABLE->validTo   = (psF64)TABLE->index->data.F32[TABLE->index->nalloc-1];   \
     482    break;                                                                      \
     483case PS_TYPE_F64:                                                               \
     484    TABLE->validFrom = (psF64)TABLE->index->data.F64[0];                        \
     485    TABLE->validTo   = (psF64)TABLE->index->data.F64[TABLE->index->nalloc-1];   \
     486    break;                                                                      \
     487default:                                                                        \
     488    TABLE->validFrom = (psF64)0;                                                \
     489    TABLE->validTo   = (psF64)0;                                                \
     490    break;                                                                      \
     491}
     492
     493#define COPY_VECTOR_VALUES(VEC_OUT,INDEX_OUT,VEC_IN,INDEX_IN)                              \
     494switch(((psVector*)(VEC_IN))->type.type) {                                                 \
     495case PS_TYPE_U8:                                                                           \
     496    ((psVector*)VEC_OUT)->data.U8[INDEX_OUT] = ((psVector*)VEC_IN)->data.U8[INDEX_IN];     \
     497    break;                                                                                 \
     498case PS_TYPE_U16:                                                                          \
     499    ((psVector*)VEC_OUT)->data.U16[INDEX_OUT] = ((psVector*)VEC_IN)->data.U16[INDEX_IN];   \
     500    break;                                                                                 \
     501case PS_TYPE_U32:                                                                          \
     502    ((psVector*)VEC_OUT)->data.U32[INDEX_OUT] = ((psVector*)VEC_IN)->data.U32[INDEX_IN];   \
     503    break;                                                                                 \
     504case PS_TYPE_U64:                                                                          \
     505    ((psVector*)VEC_OUT)->data.U64[INDEX_OUT] = ((psVector*)VEC_IN)->data.U64[INDEX_IN];   \
     506    break;                                                                                 \
     507case PS_TYPE_S8:                                                                           \
     508    ((psVector*)VEC_OUT)->data.S8[INDEX_OUT] = ((psVector*)VEC_IN)->data.S8[INDEX_IN];     \
     509    break;                                                                                 \
     510case PS_TYPE_S16:                                                                          \
     511    ((psVector*)VEC_OUT)->data.S16[INDEX_OUT] = ((psVector*)VEC_IN)->data.S16[INDEX_IN];   \
     512    break;                                                                                 \
     513case PS_TYPE_S32:                                                                          \
     514    ((psVector*)VEC_OUT)->data.S32[INDEX_OUT] = ((psVector*)VEC_IN)->data.S32[INDEX_IN];   \
     515    break;                                                                                 \
     516case PS_TYPE_S64:                                                                          \
     517    ((psVector*)VEC_OUT)->data.S64[INDEX_OUT] = ((psVector*)VEC_IN)->data.S64[INDEX_IN];   \
     518    break;                                                                                 \
     519case PS_TYPE_F32:                                                                          \
     520    ((psVector*)VEC_OUT)->data.F32[INDEX_OUT] = ((psVector*)VEC_IN)->data.F32[INDEX_IN];   \
     521    break;                                                                                 \
     522case PS_TYPE_F64:                                                                          \
     523    ((psVector*)VEC_OUT)->data.F64[INDEX_OUT] = ((psVector*)VEC_IN)->data.F64[INDEX_IN];   \
     524    break;                                                                                 \
     525default:                                                                                   \
     526    break;                                                                                 \
     527}
     528
     529
    440530psLookupTable* psLookupTableRead(psLookupTable *table)
    441531{
     
    446536    char *linePtr = NULL;
    447537    psParseErrorType status = PS_PARSE_SUCCESS;
     538    psParseErrorType lineStatus = PS_PARSE_SUCCESS;
    448539    psU64 lineCount = 0;
    449540    psU64 numRows = 0;
     
    451542    psU64 failedLines = 0;
    452543    FILE *fp = NULL;
    453     psElemType elemType = PS_TYPE_PTR;
     544    psElemType elemType;
    454545    psVector *indexVec = NULL;
    455546    psVector *valuesVec = NULL;
    456547    psArray *values = NULL;
    457 
    458 
    459     // Error checks
     548    psBool sortIndex = false;
     549
     550    // Check for NULL input table
    460551    PS_PTR_CHECK_NULL(table,NULL);
     552
     553    // Check for input table with NULL file name
    461554    PS_PTR_CHECK_NULL(table->fileName,NULL);
     555
     556    // Open table file specified by table->fileName
    462557    if((fp=fopen(table->fileName, "r")) == NULL) {
    463         psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_FILE_NOT_FOUND, table->fileName);
     558        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_FILE_NOT_FOUND,
     559                table->fileName);
    464560        return table;
    465561    }
    466562
     563    // Initialize vector pointers
    467564    indexVec = table->index;
    468565    table->values = psArrayAlloc(1);
     
    473570
    474571    // Loop through file to get numRows, numCols, and column data types
    475     while(fgets(line, MAX_STRING_LENGTH, fp) != NULL) {
     572    while((fgets(line, MAX_STRING_LENGTH, fp) != NULL) && (lineStatus == PS_PARSE_SUCCESS)) {
    476573
    477574        // Initialize variables for new line
     
    485582
    486583                // Determine column types from first line in data file after comments
    487                 while((strType=getToken(&linePtr, " ", &status)) != NULL) {
     584                while((strType=getToken(&linePtr," ",&status))) {
    488585                    numCols++;
    489586                    typeLine = false;
     
    522619
    523620                    if(status) {
    524                         status = printError(lineCount, strValue, status);
     621                        printError(lineCount, strValue, status);
    525622                        failedLines++;
     623                        lineStatus = status;
     624                        status = PS_PARSE_SUCCESS;
    526625                    }
    527626                    psFree(strType);
    528627                }
    529628            } else {
    530 
    531629                // Parse and add values to all columns
    532630                numRows++;
    533631                numCols = 0;
    534                 while((strValue=getToken(&linePtr, " ", &status)) != NULL) {
     632                while((strValue=getToken(&linePtr," ",&status))) {
    535633                    numCols++;
    536634
    537635                    // Realloc number of rows as you go
    538636                    if(numCols == 1) {
     637                        sortIndex = false;
    539638                        indexVec = psVectorRecycle(indexVec, numRows, indexVec->type.type);
    540639                        parseValue(indexVec, numRows-1, strValue, &status);
     
    546645
    547646                    if(status) {
    548                         status = printError(lineCount, strValue, status);
     647                        printError(lineCount, strValue, status);
    549648                        failedLines++;
     649                        lineStatus = status;
     650                        status = PS_PARSE_SUCCESS;
    550651                    }
    551652                    psFree(strValue);
     
    563664    table->values = values;
    564665
     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;
     681            }
     682        }
     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;
     710        }
     711        psFree(sortedIndex);
     712        // Update the validTo and validFrom
     713        UPDATE_VALID_TO_FROM(table)
     714    }
     715
    565716    fclose(fp);
    566717
    567718    return table;
    568719}
     720
     721#define CONVERT_VALUE_TO_F64(VECTOR,INDEX,RESULT)     \
     722switch(VECTOR->type.type) {                           \
     723case PS_TYPE_U8:                                      \
     724    RESULT = (psF64)VECTOR->data.U8[INDEX];           \
     725    break;                                            \
     726case PS_TYPE_U16:                                     \
     727    RESULT = (psF64)VECTOR->data.U16[INDEX];          \
     728    break;                                            \
     729case PS_TYPE_U32:                                     \
     730    RESULT = (psF64)VECTOR->data.U32[INDEX];          \
     731    break;                                            \
     732case PS_TYPE_U64:                                     \
     733    RESULT = (psF64)VECTOR->data.U64[INDEX];          \
     734    break;                                            \
     735case PS_TYPE_S8:                                      \
     736    RESULT = (psF64)VECTOR->data.S8[INDEX];           \
     737    break;                                            \
     738case PS_TYPE_S16:                                     \
     739    RESULT = (psF64)VECTOR->data.S16[INDEX];          \
     740    break;                                            \
     741case PS_TYPE_S32:                                     \
     742    RESULT = (psF64)VECTOR->data.S32[INDEX];          \
     743    break;                                            \
     744case PS_TYPE_S64:                                     \
     745    RESULT = (psF64)VECTOR->data.S64[INDEX];          \
     746    break;                                            \
     747case PS_TYPE_F32:                                     \
     748    RESULT = (psF64)VECTOR->data.F32[INDEX];          \
     749    break;                                            \
     750case PS_TYPE_F64:                                     \
     751    RESULT = VECTOR->data.F64[INDEX];                 \
     752    break;                                            \
     753default:                                              \
     754    RESULT = NAN;                                     \
     755    break;                                            \
     756}
     757
     758
     759#define CHECK_LOWER_UPPER_BOUND(TABLE,INDEX,COLUMN)                                \
     760switch (TABLE->index->type.type) {                                                 \
     761case 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;                                                                         \
     769case 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;                                                                         \
     777case 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;                                                                         \
     785case 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;                                                                         \
     793case 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;                                                                         \
     801case 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;                                                                         \
     809case 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;                                                                         \
     817case 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;                                                                         \
     825case 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;                                                                         \
     833case 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;                                                                         \
     841default:                                                                           \
     842    *status = PS_LOOKUP_ERROR;                                                     \
     843    return NAN;                                                                    \
     844    break;                                                                         \
     845}                                                                                  \
     846if(*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
    569854
    570855psF64 psLookupTableInterpolate(psLookupTable *table, psF64 index, psU64 column, psLookupStatusType *status)
     
    576861    psF64 out = 0.0;
    577862    psF64 denom = 0.0;
     863    psF64 convertVal = 0.0;
     864    psF64 tempVal = 0.0;
    578865    psVector *indexVec = NULL;
    579866    psVector *valuesVec = NULL;
    580867    psArray *values = NULL;
    581868
    582 
    583869    // Error checks
    584     PS_PTR_CHECK_NULL(table,0.0);
     870    // Set status to error prior to check since if checks fails it will immediately return
     871    PS_PTR_CHECK_NULL(status,NAN);
     872    *status = PS_LOOKUP_ERROR;
     873    PS_PTR_CHECK_NULL(table,NAN);
    585874    indexVec = table->index;
    586875    values = table->values;
    587876    numRows = table->numRows;
    588877    numCols = table->numCols;
    589     PS_PTR_CHECK_NULL(indexVec,0.0);
    590     PS_PTR_CHECK_NULL(values,0.0);
    591     PS_INT_CHECK_EQUALS(numRows, 0,0.0);
    592     PS_INT_CHECK_EQUALS(numCols, 0,0.0);
    593     PS_INT_CHECK_RANGE(column, 0, numCols-1, 0.0);
    594 
     878    PS_PTR_CHECK_NULL(indexVec,NAN);
     879    PS_PTR_CHECK_NULL(values,NAN);
     880    PS_INT_CHECK_EQUALS(numRows, 0,NAN);
     881    PS_INT_CHECK_EQUALS(numCols, 0,NAN);
     882    PS_INT_CHECK_RANGE(column, 0, (int)(numCols-1), NAN);
    595883
    596884    valuesVec = (psVector*)values->data[column];
    597     PS_PTR_CHECK_NULL(indexVec,0.0);
    598 
    599     if(index<indexVec->data.F64[0] || index<table->validFrom) {
    600 
    601         // Index value past top of table
    602         *status = PS_LOOKUP_PAST_TOP;
    603         return valuesVec->data.F64[0];
    604     } else if(index>indexVec->data.F64[numRows-1] || index>table->validTo) {
    605 
    606         // Index value past bottom of table
    607         *status = PS_LOOKUP_PAST_BOTTOM;
    608         return valuesVec->data.F64[numRows-1];
     885    PS_PTR_CHECK_NULL(indexVec,NAN);
     886
     887    // Set status to success since it passed all parameter checks
     888    *status = PS_LOOKUP_SUCCESS;
     889
     890    // Verify the index is within the bounds of the table
     891    CHECK_LOWER_UPPER_BOUND(table,index,column)
     892
     893    // Find location in table where specified index is between to entries
     894    CONVERT_VALUE_TO_F64(indexVec, 0, convertVal)
     895    while(index > convertVal ) {
     896        hiIdx++;
     897        if(hiIdx >= numRows) {
     898            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
     899                    PS_ERRORTEXT_psLookupTable_INTERPOLATE_HIGH, hiIdx);
     900            *status = PS_LOOKUP_ERROR;
     901            return NAN;
     902        }
     903        CONVERT_VALUE_TO_F64(indexVec, hiIdx, convertVal)
     904    }
     905
     906    // Check for negative low index and generate error
     907    loIdx = hiIdx--;
     908    if(loIdx < 0) {
     909        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
     910                PS_ERRORTEXT_psLookupTable_INTERPOLATE_LOW, loIdx);
     911        *status = PS_LOOKUP_ERROR;
     912        return NAN;
     913    }
     914
     915    // Perform linear interpolation to calculate return value
     916    CONVERT_VALUE_TO_F64(indexVec, hiIdx, denom)
     917    CONVERT_VALUE_TO_F64(indexVec, loIdx, convertVal);
     918    denom -= convertVal;
     919    if(fabs(denom) < FLT_EPSILON) {
     920        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_DIVIDE_BY_ZERO);
     921        *status = PS_LOOKUP_ERROR;
     922        return NAN;
    609923    } else {
    610 
    611         // Interpolation
    612         while(index > indexVec->data.F64[hiIdx]) {
    613             hiIdx++;
    614             if(hiIdx >= numRows) {
    615                 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_INTERPOLATE_HIGH, hiIdx);
    616                 *status = PS_LOOKUP_ERROR;
    617                 return 0.0;
    618             }
    619         }
    620 
    621         loIdx = hiIdx--;
    622         if(loIdx < 0) {
    623             psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_INTERPOLATE_LOW, loIdx);
    624             *status = PS_LOOKUP_ERROR;
    625             return 0.0;
    626         }
    627 
    628         denom = indexVec->data.F64[hiIdx] - indexVec->data.F64[loIdx];
    629         if(fabs(denom) < FLT_EPSILON) {
    630             psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_DIVIDE_BY_ZERO);
    631             *status = PS_LOOKUP_ERROR;
    632             return 0.0;
    633         } else {
    634             out = valuesVec->data.F64[loIdx]+(valuesVec->data.F64[hiIdx]-valuesVec->data.F64[loIdx])
    635                   *(index-indexVec->data.F64[loIdx])/denom;
    636         }
     924        CONVERT_VALUE_TO_F64(valuesVec,hiIdx,tempVal)
     925        CONVERT_VALUE_TO_F64(valuesVec,loIdx,convertVal)
     926        tempVal -= convertVal;
     927        CONVERT_VALUE_TO_F64(indexVec,loIdx,convertVal)
     928        out = tempVal*(index-convertVal)/denom;
     929        CONVERT_VALUE_TO_F64(valuesVec,loIdx,convertVal)
     930        out += convertVal;
    637931    }
    638932
     
    646940    psVector *outVector = NULL;
    647941    psLookupStatusType status = PS_LOOKUP_SUCCESS;
    648 
    649942
    650943    // Error checks
     
    654947    PS_INT_CHECK_EQUALS(numCols, 0,NULL);
    655948
    656     outVector = psVectorAlloc(numCols, PS_TYPE_F64);
     949    outVector = psVectorAlloc(numCols+1, PS_TYPE_F64);
    657950
    658951    // Fill vectors with results and status of results
  • trunk/psLib/src/dataIO/psLookupTable.h

    r3264 r3271  
    77*  @author Ross Harman, MHPCC
    88*
    9 *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
    10 *  @date $Date: 2005-02-17 19:26:24 $
     9*  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
     10*  @date $Date: 2005-02-17 21:54:09 $
    1111*
    12 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     12*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
    1313*/
    1414
  • trunk/psLib/src/fileUtils/psFileUtilsErrors.dat

    r3028 r3271  
    1515psLookupTable_DIVIDE_BY_ZERO           Divide by zero error during interpolation.
    1616psLookupTable_INVALID_TYPE             Invalid psLookupType, %d;
     17psLookupTable_TABLE_INVALID            Lookup table is invalid.
    1718#
    1819psFits_NULL                            The input psFits object can not NULL.
  • trunk/psLib/src/fileUtils/psFileUtilsErrors.h

    r3264 r3271  
    77 *  @author Robert DeSonia, MHPCC
    88 *
    9  *  @version $Revision: 1.11 $ $Name: not supported by cvs2svn $
    10  *  @date $Date: 2005-02-17 19:26:24 $
     9 *  @version $Revision: 1.12 $ $Name: not supported by cvs2svn $
     10 *  @date $Date: 2005-02-17 21:54:09 $
    1111 *
    1212 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     
    3636#define PS_ERRORTEXT_psLookupTable_DIVIDE_BY_ZERO "Divide by zero error during interpolation."
    3737#define PS_ERRORTEXT_psLookupTable_INVALID_TYPE "Invalid psLookupType, %d;"
     38#define PS_ERRORTEXT_psLookupTable_TABLE_INVALID "Lookup table is invalid."
    3839#define PS_ERRORTEXT_psFits_NULL "The input psFits object can not NULL."
    3940#define PS_ERRORTEXT_psFits_FILENAME_INVALID "Could not open file,'%s'.\nCFITSIO Error: %s"
  • trunk/psLib/src/fileUtils/psLookupTable.c

    r3264 r3271  
    77*  @author Ross Harman, MHPCC
    88*
    9 *  @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
    10 *  @date $Date: 2005-02-17 19:26:24 $
     9*  @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
     10*  @date $Date: 2005-02-17 21:54:09 $
    1111*
    12 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     12*  Copyright 2004-5 Maui High Performance Computing Center, University of Hawaii
    1313*/
    1414#include <stdio.h>
    1515#include <string.h>
    1616#include <ctype.h>
     17//#ifdef DARWIN
    1718#undef __STRICT_ANSI__
     19//#endif
    1820#include <stdlib.h>
    19 #include <limits.h>
     21//#ifdef DARWIN
     22#define __STRICT_ANSI__
     23//#endif
    2024#include <math.h>
     25#include <stdlib.h>
    2126
    2227#include "psMemory.h"
     
    438443}
    439444
     445#define UPDATE_VALID_TO_FROM(TABLE)                                             \
     446switch (TABLE->index->type.type) {                                              \
     447case PS_TYPE_U8:                                                                \
     448    TABLE->validFrom = (psF64)TABLE->index->data.U8[0];                         \
     449    TABLE->validTo   = (psF64)TABLE->index->data.U8[TABLE->index->nalloc-1];    \
     450    break;                                                                      \
     451case PS_TYPE_S8:                                                                \
     452    TABLE->validFrom = (psF64)TABLE->index->data.S8[0];                         \
     453    TABLE->validTo   = (psF64)TABLE->index->data.S8[TABLE->index->nalloc-1];    \
     454    break;                                                                      \
     455case PS_TYPE_U16:                                                               \
     456    TABLE->validFrom = (psF64)TABLE->index->data.U16[0];                        \
     457    TABLE->validTo   = (psF64)TABLE->index->data.U16[TABLE->index->nalloc-1];   \
     458    break;                                                                      \
     459case PS_TYPE_S16:                                                               \
     460    TABLE->validFrom = (psF64)TABLE->index->data.S16[0];                        \
     461    TABLE->validTo   = (psF64)TABLE->index->data.S16[TABLE->index->nalloc-1];   \
     462    break;                                                                      \
     463case PS_TYPE_U32:                                                               \
     464    TABLE->validFrom = (psF64)TABLE->index->data.U32[0];                        \
     465    TABLE->validTo   = (psF64)TABLE->index->data.U32[TABLE->index->nalloc-1];   \
     466    break;                                                                      \
     467case PS_TYPE_S32:                                                               \
     468    TABLE->validFrom = (psF64)TABLE->index->data.S32[0];                        \
     469    TABLE->validTo   = (psF64)TABLE->index->data.S32[TABLE->index->nalloc-1];   \
     470    break;                                                                      \
     471case PS_TYPE_U64:                                                               \
     472    TABLE->validFrom = (psF64)TABLE->index->data.U64[0];                        \
     473    TABLE->validTo   = (psF64)TABLE->index->data.U64[TABLE->index->nalloc-1];   \
     474    break;                                                                      \
     475case PS_TYPE_S64:                                                               \
     476    TABLE->validFrom = (psF64)TABLE->index->data.S64[0];                        \
     477    TABLE->validTo   = (psF64)TABLE->index->data.S64[TABLE->index->nalloc-1];   \
     478    break;                                                                      \
     479case PS_TYPE_F32:                                                               \
     480    TABLE->validFrom = (psF64)TABLE->index->data.F32[0];                        \
     481    TABLE->validTo   = (psF64)TABLE->index->data.F32[TABLE->index->nalloc-1];   \
     482    break;                                                                      \
     483case PS_TYPE_F64:                                                               \
     484    TABLE->validFrom = (psF64)TABLE->index->data.F64[0];                        \
     485    TABLE->validTo   = (psF64)TABLE->index->data.F64[TABLE->index->nalloc-1];   \
     486    break;                                                                      \
     487default:                                                                        \
     488    TABLE->validFrom = (psF64)0;                                                \
     489    TABLE->validTo   = (psF64)0;                                                \
     490    break;                                                                      \
     491}
     492
     493#define COPY_VECTOR_VALUES(VEC_OUT,INDEX_OUT,VEC_IN,INDEX_IN)                              \
     494switch(((psVector*)(VEC_IN))->type.type) {                                                 \
     495case PS_TYPE_U8:                                                                           \
     496    ((psVector*)VEC_OUT)->data.U8[INDEX_OUT] = ((psVector*)VEC_IN)->data.U8[INDEX_IN];     \
     497    break;                                                                                 \
     498case PS_TYPE_U16:                                                                          \
     499    ((psVector*)VEC_OUT)->data.U16[INDEX_OUT] = ((psVector*)VEC_IN)->data.U16[INDEX_IN];   \
     500    break;                                                                                 \
     501case PS_TYPE_U32:                                                                          \
     502    ((psVector*)VEC_OUT)->data.U32[INDEX_OUT] = ((psVector*)VEC_IN)->data.U32[INDEX_IN];   \
     503    break;                                                                                 \
     504case PS_TYPE_U64:                                                                          \
     505    ((psVector*)VEC_OUT)->data.U64[INDEX_OUT] = ((psVector*)VEC_IN)->data.U64[INDEX_IN];   \
     506    break;                                                                                 \
     507case PS_TYPE_S8:                                                                           \
     508    ((psVector*)VEC_OUT)->data.S8[INDEX_OUT] = ((psVector*)VEC_IN)->data.S8[INDEX_IN];     \
     509    break;                                                                                 \
     510case PS_TYPE_S16:                                                                          \
     511    ((psVector*)VEC_OUT)->data.S16[INDEX_OUT] = ((psVector*)VEC_IN)->data.S16[INDEX_IN];   \
     512    break;                                                                                 \
     513case PS_TYPE_S32:                                                                          \
     514    ((psVector*)VEC_OUT)->data.S32[INDEX_OUT] = ((psVector*)VEC_IN)->data.S32[INDEX_IN];   \
     515    break;                                                                                 \
     516case PS_TYPE_S64:                                                                          \
     517    ((psVector*)VEC_OUT)->data.S64[INDEX_OUT] = ((psVector*)VEC_IN)->data.S64[INDEX_IN];   \
     518    break;                                                                                 \
     519case PS_TYPE_F32:                                                                          \
     520    ((psVector*)VEC_OUT)->data.F32[INDEX_OUT] = ((psVector*)VEC_IN)->data.F32[INDEX_IN];   \
     521    break;                                                                                 \
     522case PS_TYPE_F64:                                                                          \
     523    ((psVector*)VEC_OUT)->data.F64[INDEX_OUT] = ((psVector*)VEC_IN)->data.F64[INDEX_IN];   \
     524    break;                                                                                 \
     525default:                                                                                   \
     526    break;                                                                                 \
     527}
     528
     529
    440530psLookupTable* psLookupTableRead(psLookupTable *table)
    441531{
     
    446536    char *linePtr = NULL;
    447537    psParseErrorType status = PS_PARSE_SUCCESS;
     538    psParseErrorType lineStatus = PS_PARSE_SUCCESS;
    448539    psU64 lineCount = 0;
    449540    psU64 numRows = 0;
     
    451542    psU64 failedLines = 0;
    452543    FILE *fp = NULL;
    453     psElemType elemType = PS_TYPE_PTR;
     544    psElemType elemType;
    454545    psVector *indexVec = NULL;
    455546    psVector *valuesVec = NULL;
    456547    psArray *values = NULL;
    457 
    458 
    459     // Error checks
     548    psBool sortIndex = false;
     549
     550    // Check for NULL input table
    460551    PS_PTR_CHECK_NULL(table,NULL);
     552
     553    // Check for input table with NULL file name
    461554    PS_PTR_CHECK_NULL(table->fileName,NULL);
     555
     556    // Open table file specified by table->fileName
    462557    if((fp=fopen(table->fileName, "r")) == NULL) {
    463         psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_FILE_NOT_FOUND, table->fileName);
     558        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_FILE_NOT_FOUND,
     559                table->fileName);
    464560        return table;
    465561    }
    466562
     563    // Initialize vector pointers
    467564    indexVec = table->index;
    468565    table->values = psArrayAlloc(1);
     
    473570
    474571    // Loop through file to get numRows, numCols, and column data types
    475     while(fgets(line, MAX_STRING_LENGTH, fp) != NULL) {
     572    while((fgets(line, MAX_STRING_LENGTH, fp) != NULL) && (lineStatus == PS_PARSE_SUCCESS)) {
    476573
    477574        // Initialize variables for new line
     
    485582
    486583                // Determine column types from first line in data file after comments
    487                 while((strType=getToken(&linePtr, " ", &status)) != NULL) {
     584                while((strType=getToken(&linePtr," ",&status))) {
    488585                    numCols++;
    489586                    typeLine = false;
     
    522619
    523620                    if(status) {
    524                         status = printError(lineCount, strValue, status);
     621                        printError(lineCount, strValue, status);
    525622                        failedLines++;
     623                        lineStatus = status;
     624                        status = PS_PARSE_SUCCESS;
    526625                    }
    527626                    psFree(strType);
    528627                }
    529628            } else {
    530 
    531629                // Parse and add values to all columns
    532630                numRows++;
    533631                numCols = 0;
    534                 while((strValue=getToken(&linePtr, " ", &status)) != NULL) {
     632                while((strValue=getToken(&linePtr," ",&status))) {
    535633                    numCols++;
    536634
    537635                    // Realloc number of rows as you go
    538636                    if(numCols == 1) {
     637                        sortIndex = false;
    539638                        indexVec = psVectorRecycle(indexVec, numRows, indexVec->type.type);
    540639                        parseValue(indexVec, numRows-1, strValue, &status);
     
    546645
    547646                    if(status) {
    548                         status = printError(lineCount, strValue, status);
     647                        printError(lineCount, strValue, status);
    549648                        failedLines++;
     649                        lineStatus = status;
     650                        status = PS_PARSE_SUCCESS;
    550651                    }
    551652                    psFree(strValue);
     
    563664    table->values = values;
    564665
     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;
     681            }
     682        }
     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;
     710        }
     711        psFree(sortedIndex);
     712        // Update the validTo and validFrom
     713        UPDATE_VALID_TO_FROM(table)
     714    }
     715
    565716    fclose(fp);
    566717
    567718    return table;
    568719}
     720
     721#define CONVERT_VALUE_TO_F64(VECTOR,INDEX,RESULT)     \
     722switch(VECTOR->type.type) {                           \
     723case PS_TYPE_U8:                                      \
     724    RESULT = (psF64)VECTOR->data.U8[INDEX];           \
     725    break;                                            \
     726case PS_TYPE_U16:                                     \
     727    RESULT = (psF64)VECTOR->data.U16[INDEX];          \
     728    break;                                            \
     729case PS_TYPE_U32:                                     \
     730    RESULT = (psF64)VECTOR->data.U32[INDEX];          \
     731    break;                                            \
     732case PS_TYPE_U64:                                     \
     733    RESULT = (psF64)VECTOR->data.U64[INDEX];          \
     734    break;                                            \
     735case PS_TYPE_S8:                                      \
     736    RESULT = (psF64)VECTOR->data.S8[INDEX];           \
     737    break;                                            \
     738case PS_TYPE_S16:                                     \
     739    RESULT = (psF64)VECTOR->data.S16[INDEX];          \
     740    break;                                            \
     741case PS_TYPE_S32:                                     \
     742    RESULT = (psF64)VECTOR->data.S32[INDEX];          \
     743    break;                                            \
     744case PS_TYPE_S64:                                     \
     745    RESULT = (psF64)VECTOR->data.S64[INDEX];          \
     746    break;                                            \
     747case PS_TYPE_F32:                                     \
     748    RESULT = (psF64)VECTOR->data.F32[INDEX];          \
     749    break;                                            \
     750case PS_TYPE_F64:                                     \
     751    RESULT = VECTOR->data.F64[INDEX];                 \
     752    break;                                            \
     753default:                                              \
     754    RESULT = NAN;                                     \
     755    break;                                            \
     756}
     757
     758
     759#define CHECK_LOWER_UPPER_BOUND(TABLE,INDEX,COLUMN)                                \
     760switch (TABLE->index->type.type) {                                                 \
     761case 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;                                                                         \
     769case 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;                                                                         \
     777case 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;                                                                         \
     785case 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;                                                                         \
     793case 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;                                                                         \
     801case 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;                                                                         \
     809case 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;                                                                         \
     817case 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;                                                                         \
     825case 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;                                                                         \
     833case 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;                                                                         \
     841default:                                                                           \
     842    *status = PS_LOOKUP_ERROR;                                                     \
     843    return NAN;                                                                    \
     844    break;                                                                         \
     845}                                                                                  \
     846if(*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
    569854
    570855psF64 psLookupTableInterpolate(psLookupTable *table, psF64 index, psU64 column, psLookupStatusType *status)
     
    576861    psF64 out = 0.0;
    577862    psF64 denom = 0.0;
     863    psF64 convertVal = 0.0;
     864    psF64 tempVal = 0.0;
    578865    psVector *indexVec = NULL;
    579866    psVector *valuesVec = NULL;
    580867    psArray *values = NULL;
    581868
    582 
    583869    // Error checks
    584     PS_PTR_CHECK_NULL(table,0.0);
     870    // Set status to error prior to check since if checks fails it will immediately return
     871    PS_PTR_CHECK_NULL(status,NAN);
     872    *status = PS_LOOKUP_ERROR;
     873    PS_PTR_CHECK_NULL(table,NAN);
    585874    indexVec = table->index;
    586875    values = table->values;
    587876    numRows = table->numRows;
    588877    numCols = table->numCols;
    589     PS_PTR_CHECK_NULL(indexVec,0.0);
    590     PS_PTR_CHECK_NULL(values,0.0);
    591     PS_INT_CHECK_EQUALS(numRows, 0,0.0);
    592     PS_INT_CHECK_EQUALS(numCols, 0,0.0);
    593     PS_INT_CHECK_RANGE(column, 0, numCols-1, 0.0);
    594 
     878    PS_PTR_CHECK_NULL(indexVec,NAN);
     879    PS_PTR_CHECK_NULL(values,NAN);
     880    PS_INT_CHECK_EQUALS(numRows, 0,NAN);
     881    PS_INT_CHECK_EQUALS(numCols, 0,NAN);
     882    PS_INT_CHECK_RANGE(column, 0, (int)(numCols-1), NAN);
    595883
    596884    valuesVec = (psVector*)values->data[column];
    597     PS_PTR_CHECK_NULL(indexVec,0.0);
    598 
    599     if(index<indexVec->data.F64[0] || index<table->validFrom) {
    600 
    601         // Index value past top of table
    602         *status = PS_LOOKUP_PAST_TOP;
    603         return valuesVec->data.F64[0];
    604     } else if(index>indexVec->data.F64[numRows-1] || index>table->validTo) {
    605 
    606         // Index value past bottom of table
    607         *status = PS_LOOKUP_PAST_BOTTOM;
    608         return valuesVec->data.F64[numRows-1];
     885    PS_PTR_CHECK_NULL(indexVec,NAN);
     886
     887    // Set status to success since it passed all parameter checks
     888    *status = PS_LOOKUP_SUCCESS;
     889
     890    // Verify the index is within the bounds of the table
     891    CHECK_LOWER_UPPER_BOUND(table,index,column)
     892
     893    // Find location in table where specified index is between to entries
     894    CONVERT_VALUE_TO_F64(indexVec, 0, convertVal)
     895    while(index > convertVal ) {
     896        hiIdx++;
     897        if(hiIdx >= numRows) {
     898            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
     899                    PS_ERRORTEXT_psLookupTable_INTERPOLATE_HIGH, hiIdx);
     900            *status = PS_LOOKUP_ERROR;
     901            return NAN;
     902        }
     903        CONVERT_VALUE_TO_F64(indexVec, hiIdx, convertVal)
     904    }
     905
     906    // Check for negative low index and generate error
     907    loIdx = hiIdx--;
     908    if(loIdx < 0) {
     909        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
     910                PS_ERRORTEXT_psLookupTable_INTERPOLATE_LOW, loIdx);
     911        *status = PS_LOOKUP_ERROR;
     912        return NAN;
     913    }
     914
     915    // Perform linear interpolation to calculate return value
     916    CONVERT_VALUE_TO_F64(indexVec, hiIdx, denom)
     917    CONVERT_VALUE_TO_F64(indexVec, loIdx, convertVal);
     918    denom -= convertVal;
     919    if(fabs(denom) < FLT_EPSILON) {
     920        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_DIVIDE_BY_ZERO);
     921        *status = PS_LOOKUP_ERROR;
     922        return NAN;
    609923    } else {
    610 
    611         // Interpolation
    612         while(index > indexVec->data.F64[hiIdx]) {
    613             hiIdx++;
    614             if(hiIdx >= numRows) {
    615                 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_INTERPOLATE_HIGH, hiIdx);
    616                 *status = PS_LOOKUP_ERROR;
    617                 return 0.0;
    618             }
    619         }
    620 
    621         loIdx = hiIdx--;
    622         if(loIdx < 0) {
    623             psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_INTERPOLATE_LOW, loIdx);
    624             *status = PS_LOOKUP_ERROR;
    625             return 0.0;
    626         }
    627 
    628         denom = indexVec->data.F64[hiIdx] - indexVec->data.F64[loIdx];
    629         if(fabs(denom) < FLT_EPSILON) {
    630             psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_DIVIDE_BY_ZERO);
    631             *status = PS_LOOKUP_ERROR;
    632             return 0.0;
    633         } else {
    634             out = valuesVec->data.F64[loIdx]+(valuesVec->data.F64[hiIdx]-valuesVec->data.F64[loIdx])
    635                   *(index-indexVec->data.F64[loIdx])/denom;
    636         }
     924        CONVERT_VALUE_TO_F64(valuesVec,hiIdx,tempVal)
     925        CONVERT_VALUE_TO_F64(valuesVec,loIdx,convertVal)
     926        tempVal -= convertVal;
     927        CONVERT_VALUE_TO_F64(indexVec,loIdx,convertVal)
     928        out = tempVal*(index-convertVal)/denom;
     929        CONVERT_VALUE_TO_F64(valuesVec,loIdx,convertVal)
     930        out += convertVal;
    637931    }
    638932
     
    646940    psVector *outVector = NULL;
    647941    psLookupStatusType status = PS_LOOKUP_SUCCESS;
    648 
    649942
    650943    // Error checks
     
    654947    PS_INT_CHECK_EQUALS(numCols, 0,NULL);
    655948
    656     outVector = psVectorAlloc(numCols, PS_TYPE_F64);
     949    outVector = psVectorAlloc(numCols+1, PS_TYPE_F64);
    657950
    658951    // Fill vectors with results and status of results
  • trunk/psLib/src/fileUtils/psLookupTable.h

    r3264 r3271  
    77*  @author Ross Harman, MHPCC
    88*
    9 *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
    10 *  @date $Date: 2005-02-17 19:26:24 $
     9*  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
     10*  @date $Date: 2005-02-17 21:54:09 $
    1111*
    12 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     12*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
    1313*/
    1414
  • trunk/psLib/src/types/psLookupTable.c

    r3264 r3271  
    77*  @author Ross Harman, MHPCC
    88*
    9 *  @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
    10 *  @date $Date: 2005-02-17 19:26:24 $
     9*  @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
     10*  @date $Date: 2005-02-17 21:54:09 $
    1111*
    12 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     12*  Copyright 2004-5 Maui High Performance Computing Center, University of Hawaii
    1313*/
    1414#include <stdio.h>
    1515#include <string.h>
    1616#include <ctype.h>
     17//#ifdef DARWIN
    1718#undef __STRICT_ANSI__
     19//#endif
    1820#include <stdlib.h>
    19 #include <limits.h>
     21//#ifdef DARWIN
     22#define __STRICT_ANSI__
     23//#endif
    2024#include <math.h>
     25#include <stdlib.h>
    2126
    2227#include "psMemory.h"
     
    438443}
    439444
     445#define UPDATE_VALID_TO_FROM(TABLE)                                             \
     446switch (TABLE->index->type.type) {                                              \
     447case PS_TYPE_U8:                                                                \
     448    TABLE->validFrom = (psF64)TABLE->index->data.U8[0];                         \
     449    TABLE->validTo   = (psF64)TABLE->index->data.U8[TABLE->index->nalloc-1];    \
     450    break;                                                                      \
     451case PS_TYPE_S8:                                                                \
     452    TABLE->validFrom = (psF64)TABLE->index->data.S8[0];                         \
     453    TABLE->validTo   = (psF64)TABLE->index->data.S8[TABLE->index->nalloc-1];    \
     454    break;                                                                      \
     455case PS_TYPE_U16:                                                               \
     456    TABLE->validFrom = (psF64)TABLE->index->data.U16[0];                        \
     457    TABLE->validTo   = (psF64)TABLE->index->data.U16[TABLE->index->nalloc-1];   \
     458    break;                                                                      \
     459case PS_TYPE_S16:                                                               \
     460    TABLE->validFrom = (psF64)TABLE->index->data.S16[0];                        \
     461    TABLE->validTo   = (psF64)TABLE->index->data.S16[TABLE->index->nalloc-1];   \
     462    break;                                                                      \
     463case PS_TYPE_U32:                                                               \
     464    TABLE->validFrom = (psF64)TABLE->index->data.U32[0];                        \
     465    TABLE->validTo   = (psF64)TABLE->index->data.U32[TABLE->index->nalloc-1];   \
     466    break;                                                                      \
     467case PS_TYPE_S32:                                                               \
     468    TABLE->validFrom = (psF64)TABLE->index->data.S32[0];                        \
     469    TABLE->validTo   = (psF64)TABLE->index->data.S32[TABLE->index->nalloc-1];   \
     470    break;                                                                      \
     471case PS_TYPE_U64:                                                               \
     472    TABLE->validFrom = (psF64)TABLE->index->data.U64[0];                        \
     473    TABLE->validTo   = (psF64)TABLE->index->data.U64[TABLE->index->nalloc-1];   \
     474    break;                                                                      \
     475case PS_TYPE_S64:                                                               \
     476    TABLE->validFrom = (psF64)TABLE->index->data.S64[0];                        \
     477    TABLE->validTo   = (psF64)TABLE->index->data.S64[TABLE->index->nalloc-1];   \
     478    break;                                                                      \
     479case PS_TYPE_F32:                                                               \
     480    TABLE->validFrom = (psF64)TABLE->index->data.F32[0];                        \
     481    TABLE->validTo   = (psF64)TABLE->index->data.F32[TABLE->index->nalloc-1];   \
     482    break;                                                                      \
     483case PS_TYPE_F64:                                                               \
     484    TABLE->validFrom = (psF64)TABLE->index->data.F64[0];                        \
     485    TABLE->validTo   = (psF64)TABLE->index->data.F64[TABLE->index->nalloc-1];   \
     486    break;                                                                      \
     487default:                                                                        \
     488    TABLE->validFrom = (psF64)0;                                                \
     489    TABLE->validTo   = (psF64)0;                                                \
     490    break;                                                                      \
     491}
     492
     493#define COPY_VECTOR_VALUES(VEC_OUT,INDEX_OUT,VEC_IN,INDEX_IN)                              \
     494switch(((psVector*)(VEC_IN))->type.type) {                                                 \
     495case PS_TYPE_U8:                                                                           \
     496    ((psVector*)VEC_OUT)->data.U8[INDEX_OUT] = ((psVector*)VEC_IN)->data.U8[INDEX_IN];     \
     497    break;                                                                                 \
     498case PS_TYPE_U16:                                                                          \
     499    ((psVector*)VEC_OUT)->data.U16[INDEX_OUT] = ((psVector*)VEC_IN)->data.U16[INDEX_IN];   \
     500    break;                                                                                 \
     501case PS_TYPE_U32:                                                                          \
     502    ((psVector*)VEC_OUT)->data.U32[INDEX_OUT] = ((psVector*)VEC_IN)->data.U32[INDEX_IN];   \
     503    break;                                                                                 \
     504case PS_TYPE_U64:                                                                          \
     505    ((psVector*)VEC_OUT)->data.U64[INDEX_OUT] = ((psVector*)VEC_IN)->data.U64[INDEX_IN];   \
     506    break;                                                                                 \
     507case PS_TYPE_S8:                                                                           \
     508    ((psVector*)VEC_OUT)->data.S8[INDEX_OUT] = ((psVector*)VEC_IN)->data.S8[INDEX_IN];     \
     509    break;                                                                                 \
     510case PS_TYPE_S16:                                                                          \
     511    ((psVector*)VEC_OUT)->data.S16[INDEX_OUT] = ((psVector*)VEC_IN)->data.S16[INDEX_IN];   \
     512    break;                                                                                 \
     513case PS_TYPE_S32:                                                                          \
     514    ((psVector*)VEC_OUT)->data.S32[INDEX_OUT] = ((psVector*)VEC_IN)->data.S32[INDEX_IN];   \
     515    break;                                                                                 \
     516case PS_TYPE_S64:                                                                          \
     517    ((psVector*)VEC_OUT)->data.S64[INDEX_OUT] = ((psVector*)VEC_IN)->data.S64[INDEX_IN];   \
     518    break;                                                                                 \
     519case PS_TYPE_F32:                                                                          \
     520    ((psVector*)VEC_OUT)->data.F32[INDEX_OUT] = ((psVector*)VEC_IN)->data.F32[INDEX_IN];   \
     521    break;                                                                                 \
     522case PS_TYPE_F64:                                                                          \
     523    ((psVector*)VEC_OUT)->data.F64[INDEX_OUT] = ((psVector*)VEC_IN)->data.F64[INDEX_IN];   \
     524    break;                                                                                 \
     525default:                                                                                   \
     526    break;                                                                                 \
     527}
     528
     529
    440530psLookupTable* psLookupTableRead(psLookupTable *table)
    441531{
     
    446536    char *linePtr = NULL;
    447537    psParseErrorType status = PS_PARSE_SUCCESS;
     538    psParseErrorType lineStatus = PS_PARSE_SUCCESS;
    448539    psU64 lineCount = 0;
    449540    psU64 numRows = 0;
     
    451542    psU64 failedLines = 0;
    452543    FILE *fp = NULL;
    453     psElemType elemType = PS_TYPE_PTR;
     544    psElemType elemType;
    454545    psVector *indexVec = NULL;
    455546    psVector *valuesVec = NULL;
    456547    psArray *values = NULL;
    457 
    458 
    459     // Error checks
     548    psBool sortIndex = false;
     549
     550    // Check for NULL input table
    460551    PS_PTR_CHECK_NULL(table,NULL);
     552
     553    // Check for input table with NULL file name
    461554    PS_PTR_CHECK_NULL(table->fileName,NULL);
     555
     556    // Open table file specified by table->fileName
    462557    if((fp=fopen(table->fileName, "r")) == NULL) {
    463         psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_FILE_NOT_FOUND, table->fileName);
     558        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_FILE_NOT_FOUND,
     559                table->fileName);
    464560        return table;
    465561    }
    466562
     563    // Initialize vector pointers
    467564    indexVec = table->index;
    468565    table->values = psArrayAlloc(1);
     
    473570
    474571    // Loop through file to get numRows, numCols, and column data types
    475     while(fgets(line, MAX_STRING_LENGTH, fp) != NULL) {
     572    while((fgets(line, MAX_STRING_LENGTH, fp) != NULL) && (lineStatus == PS_PARSE_SUCCESS)) {
    476573
    477574        // Initialize variables for new line
     
    485582
    486583                // Determine column types from first line in data file after comments
    487                 while((strType=getToken(&linePtr, " ", &status)) != NULL) {
     584                while((strType=getToken(&linePtr," ",&status))) {
    488585                    numCols++;
    489586                    typeLine = false;
     
    522619
    523620                    if(status) {
    524                         status = printError(lineCount, strValue, status);
     621                        printError(lineCount, strValue, status);
    525622                        failedLines++;
     623                        lineStatus = status;
     624                        status = PS_PARSE_SUCCESS;
    526625                    }
    527626                    psFree(strType);
    528627                }
    529628            } else {
    530 
    531629                // Parse and add values to all columns
    532630                numRows++;
    533631                numCols = 0;
    534                 while((strValue=getToken(&linePtr, " ", &status)) != NULL) {
     632                while((strValue=getToken(&linePtr," ",&status))) {
    535633                    numCols++;
    536634
    537635                    // Realloc number of rows as you go
    538636                    if(numCols == 1) {
     637                        sortIndex = false;
    539638                        indexVec = psVectorRecycle(indexVec, numRows, indexVec->type.type);
    540639                        parseValue(indexVec, numRows-1, strValue, &status);
     
    546645
    547646                    if(status) {
    548                         status = printError(lineCount, strValue, status);
     647                        printError(lineCount, strValue, status);
    549648                        failedLines++;
     649                        lineStatus = status;
     650                        status = PS_PARSE_SUCCESS;
    550651                    }
    551652                    psFree(strValue);
     
    563664    table->values = values;
    564665
     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;
     681            }
     682        }
     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;
     710        }
     711        psFree(sortedIndex);
     712        // Update the validTo and validFrom
     713        UPDATE_VALID_TO_FROM(table)
     714    }
     715
    565716    fclose(fp);
    566717
    567718    return table;
    568719}
     720
     721#define CONVERT_VALUE_TO_F64(VECTOR,INDEX,RESULT)     \
     722switch(VECTOR->type.type) {                           \
     723case PS_TYPE_U8:                                      \
     724    RESULT = (psF64)VECTOR->data.U8[INDEX];           \
     725    break;                                            \
     726case PS_TYPE_U16:                                     \
     727    RESULT = (psF64)VECTOR->data.U16[INDEX];          \
     728    break;                                            \
     729case PS_TYPE_U32:                                     \
     730    RESULT = (psF64)VECTOR->data.U32[INDEX];          \
     731    break;                                            \
     732case PS_TYPE_U64:                                     \
     733    RESULT = (psF64)VECTOR->data.U64[INDEX];          \
     734    break;                                            \
     735case PS_TYPE_S8:                                      \
     736    RESULT = (psF64)VECTOR->data.S8[INDEX];           \
     737    break;                                            \
     738case PS_TYPE_S16:                                     \
     739    RESULT = (psF64)VECTOR->data.S16[INDEX];          \
     740    break;                                            \
     741case PS_TYPE_S32:                                     \
     742    RESULT = (psF64)VECTOR->data.S32[INDEX];          \
     743    break;                                            \
     744case PS_TYPE_S64:                                     \
     745    RESULT = (psF64)VECTOR->data.S64[INDEX];          \
     746    break;                                            \
     747case PS_TYPE_F32:                                     \
     748    RESULT = (psF64)VECTOR->data.F32[INDEX];          \
     749    break;                                            \
     750case PS_TYPE_F64:                                     \
     751    RESULT = VECTOR->data.F64[INDEX];                 \
     752    break;                                            \
     753default:                                              \
     754    RESULT = NAN;                                     \
     755    break;                                            \
     756}
     757
     758
     759#define CHECK_LOWER_UPPER_BOUND(TABLE,INDEX,COLUMN)                                \
     760switch (TABLE->index->type.type) {                                                 \
     761case 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;                                                                         \
     769case 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;                                                                         \
     777case 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;                                                                         \
     785case 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;                                                                         \
     793case 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;                                                                         \
     801case 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;                                                                         \
     809case 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;                                                                         \
     817case 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;                                                                         \
     825case 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;                                                                         \
     833case 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;                                                                         \
     841default:                                                                           \
     842    *status = PS_LOOKUP_ERROR;                                                     \
     843    return NAN;                                                                    \
     844    break;                                                                         \
     845}                                                                                  \
     846if(*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
    569854
    570855psF64 psLookupTableInterpolate(psLookupTable *table, psF64 index, psU64 column, psLookupStatusType *status)
     
    576861    psF64 out = 0.0;
    577862    psF64 denom = 0.0;
     863    psF64 convertVal = 0.0;
     864    psF64 tempVal = 0.0;
    578865    psVector *indexVec = NULL;
    579866    psVector *valuesVec = NULL;
    580867    psArray *values = NULL;
    581868
    582 
    583869    // Error checks
    584     PS_PTR_CHECK_NULL(table,0.0);
     870    // Set status to error prior to check since if checks fails it will immediately return
     871    PS_PTR_CHECK_NULL(status,NAN);
     872    *status = PS_LOOKUP_ERROR;
     873    PS_PTR_CHECK_NULL(table,NAN);
    585874    indexVec = table->index;
    586875    values = table->values;
    587876    numRows = table->numRows;
    588877    numCols = table->numCols;
    589     PS_PTR_CHECK_NULL(indexVec,0.0);
    590     PS_PTR_CHECK_NULL(values,0.0);
    591     PS_INT_CHECK_EQUALS(numRows, 0,0.0);
    592     PS_INT_CHECK_EQUALS(numCols, 0,0.0);
    593     PS_INT_CHECK_RANGE(column, 0, numCols-1, 0.0);
    594 
     878    PS_PTR_CHECK_NULL(indexVec,NAN);
     879    PS_PTR_CHECK_NULL(values,NAN);
     880    PS_INT_CHECK_EQUALS(numRows, 0,NAN);
     881    PS_INT_CHECK_EQUALS(numCols, 0,NAN);
     882    PS_INT_CHECK_RANGE(column, 0, (int)(numCols-1), NAN);
    595883
    596884    valuesVec = (psVector*)values->data[column];
    597     PS_PTR_CHECK_NULL(indexVec,0.0);
    598 
    599     if(index<indexVec->data.F64[0] || index<table->validFrom) {
    600 
    601         // Index value past top of table
    602         *status = PS_LOOKUP_PAST_TOP;
    603         return valuesVec->data.F64[0];
    604     } else if(index>indexVec->data.F64[numRows-1] || index>table->validTo) {
    605 
    606         // Index value past bottom of table
    607         *status = PS_LOOKUP_PAST_BOTTOM;
    608         return valuesVec->data.F64[numRows-1];
     885    PS_PTR_CHECK_NULL(indexVec,NAN);
     886
     887    // Set status to success since it passed all parameter checks
     888    *status = PS_LOOKUP_SUCCESS;
     889
     890    // Verify the index is within the bounds of the table
     891    CHECK_LOWER_UPPER_BOUND(table,index,column)
     892
     893    // Find location in table where specified index is between to entries
     894    CONVERT_VALUE_TO_F64(indexVec, 0, convertVal)
     895    while(index > convertVal ) {
     896        hiIdx++;
     897        if(hiIdx >= numRows) {
     898            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
     899                    PS_ERRORTEXT_psLookupTable_INTERPOLATE_HIGH, hiIdx);
     900            *status = PS_LOOKUP_ERROR;
     901            return NAN;
     902        }
     903        CONVERT_VALUE_TO_F64(indexVec, hiIdx, convertVal)
     904    }
     905
     906    // Check for negative low index and generate error
     907    loIdx = hiIdx--;
     908    if(loIdx < 0) {
     909        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
     910                PS_ERRORTEXT_psLookupTable_INTERPOLATE_LOW, loIdx);
     911        *status = PS_LOOKUP_ERROR;
     912        return NAN;
     913    }
     914
     915    // Perform linear interpolation to calculate return value
     916    CONVERT_VALUE_TO_F64(indexVec, hiIdx, denom)
     917    CONVERT_VALUE_TO_F64(indexVec, loIdx, convertVal);
     918    denom -= convertVal;
     919    if(fabs(denom) < FLT_EPSILON) {
     920        psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_DIVIDE_BY_ZERO);
     921        *status = PS_LOOKUP_ERROR;
     922        return NAN;
    609923    } else {
    610 
    611         // Interpolation
    612         while(index > indexVec->data.F64[hiIdx]) {
    613             hiIdx++;
    614             if(hiIdx >= numRows) {
    615                 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_INTERPOLATE_HIGH, hiIdx);
    616                 *status = PS_LOOKUP_ERROR;
    617                 return 0.0;
    618             }
    619         }
    620 
    621         loIdx = hiIdx--;
    622         if(loIdx < 0) {
    623             psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_INTERPOLATE_LOW, loIdx);
    624             *status = PS_LOOKUP_ERROR;
    625             return 0.0;
    626         }
    627 
    628         denom = indexVec->data.F64[hiIdx] - indexVec->data.F64[loIdx];
    629         if(fabs(denom) < FLT_EPSILON) {
    630             psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_DIVIDE_BY_ZERO);
    631             *status = PS_LOOKUP_ERROR;
    632             return 0.0;
    633         } else {
    634             out = valuesVec->data.F64[loIdx]+(valuesVec->data.F64[hiIdx]-valuesVec->data.F64[loIdx])
    635                   *(index-indexVec->data.F64[loIdx])/denom;
    636         }
     924        CONVERT_VALUE_TO_F64(valuesVec,hiIdx,tempVal)
     925        CONVERT_VALUE_TO_F64(valuesVec,loIdx,convertVal)
     926        tempVal -= convertVal;
     927        CONVERT_VALUE_TO_F64(indexVec,loIdx,convertVal)
     928        out = tempVal*(index-convertVal)/denom;
     929        CONVERT_VALUE_TO_F64(valuesVec,loIdx,convertVal)
     930        out += convertVal;
    637931    }
    638932
     
    646940    psVector *outVector = NULL;
    647941    psLookupStatusType status = PS_LOOKUP_SUCCESS;
    648 
    649942
    650943    // Error checks
     
    654947    PS_INT_CHECK_EQUALS(numCols, 0,NULL);
    655948
    656     outVector = psVectorAlloc(numCols, PS_TYPE_F64);
     949    outVector = psVectorAlloc(numCols+1, PS_TYPE_F64);
    657950
    658951    // Fill vectors with results and status of results
  • trunk/psLib/src/types/psLookupTable.h

    r3264 r3271  
    77*  @author Ross Harman, MHPCC
    88*
    9 *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
    10 *  @date $Date: 2005-02-17 19:26:24 $
     9*  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
     10*  @date $Date: 2005-02-17 21:54:09 $
    1111*
    12 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     12*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
    1313*/
    1414
Note: See TracChangeset for help on using the changeset viewer.