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