Changeset 4050
- Timestamp:
- May 31, 2005, 11:46:56 AM (21 years ago)
- Location:
- trunk/psLib/src
- Files:
-
- 4 edited
-
dataIO/psLookupTable.c (modified) (25 diffs)
-
dataIO/psLookupTable.h (modified) (6 diffs)
-
types/psLookupTable.c (modified) (25 diffs)
-
types/psLookupTable.h (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/dataIO/psLookupTable.c
r4031 r4050 7 7 * @author Ross Harman, MHPCC 8 8 * 9 * @version $Revision: 1.1 4$ $Name: not supported by cvs2svn $10 * @date $Date: 2005-05- 25 22:46:47$9 * @version $Revision: 1.15 $ $Name: not supported by cvs2svn $ 10 * @date $Date: 2005-05-31 21:46:56 $ 11 11 * 12 * Copyright 2004- 5 Maui High Performance Computing Center, Universityof Hawaii12 * Copyright 2004-2005 Maui High Performance Computing Center, Univ. of Hawaii 13 13 */ 14 14 #include <stdio.h> … … 64 64 static char *cleanString(char *inString, int sLen); 65 65 static char* getToken(char **inString, char *delimiter, psParseErrorType *status); 66 static psU8 parseU8(char *inString, psParseErrorType *status);67 static psS8 parseS8(char *inString, psParseErrorType *status);68 static psU16 parseU16(char *inString, psParseErrorType *status);69 static psS16 parseS16(char *inString, psParseErrorType *status);70 static psU32 parseU32(char *inString, psParseErrorType *status);71 66 static psS32 parseS32(char *inString, psParseErrorType *status); 72 static psU64 parseU64(char *inString, psParseErrorType *status);73 67 static psS64 parseS64(char *inString, psParseErrorType *status); 74 68 static psF32 parseF32(char *inString, psParseErrorType *status); … … 87 81 inString++; 88 82 } 89 90 83 return true; 91 84 } … … 100 93 char *cleaned = NULL; 101 94 102 103 95 ptrB = inString; 104 96 105 / * Skip over leading # or whitespace */97 // Skip over leading # or whitespace 106 98 while (isspace(*ptrB) || *ptrB=='#') { 107 99 ptrB++; 108 100 } 109 101 110 / * Skip over trailing whitespace, null terminators, and # characters */102 // Skip over trailing whitespace, null terminators, and # characters 111 103 ptrE = inString + sLen; 112 104 while(isspace(*ptrE) || *ptrE=='\0' || *ptrE=='#') { … … 130 122 char *cleanToken = NULL; 131 123 int sLen = 0; 132 133 124 134 125 // Skip over leading whitespace … … 151 142 152 143 return cleanToken; 153 }154 155 /** Returns single parsed value as a psU8. The input string must be cleaned and null terminated. */156 static psU8 parseU8(char *inString, psParseErrorType *status)157 {158 char *end = NULL;159 psU8 value = 0.0;160 161 162 value = (psU8)strtoul(inString, &end, 0);163 if(*end != '\0') {164 *status = PS_PARSE_ERROR_VALUE;165 } else if(inString==end) {166 *status = PS_PARSE_ERROR_VALUE;167 }168 169 return value;170 }171 172 /** Returns single parsed value as a psS8. The input string must be cleaned and null terminated. */173 static psS8 parseS8(char *inString, psParseErrorType *status)174 {175 char *end = NULL;176 psS8 value = 0.0;177 178 179 value = (psS8)strtol(inString, &end, 0);180 if(*end != '\0') {181 *status = PS_PARSE_ERROR_VALUE;182 } else if(inString==end) {183 *status = PS_PARSE_ERROR_VALUE;184 }185 186 return value;187 }188 189 /** Returns single parsed value as a psU16. The input string must be cleaned and null terminated. */190 static psU16 parseU16(char *inString, psParseErrorType *status)191 {192 char *end = NULL;193 psU16 value = 0.0;194 195 196 value = (psU16)strtoul(inString, &end, 0);197 if(*end != '\0') {198 *status = PS_PARSE_ERROR_VALUE;199 } else if(inString==end) {200 *status = PS_PARSE_ERROR_VALUE;201 }202 203 return value;204 }205 206 /** Returns single parsed value as a psS16. The input string must be cleaned and null terminated. */207 static psS16 parseS16(char *inString, psParseErrorType *status)208 {209 char *end = NULL;210 psS16 value = 0.0;211 212 213 value = (psS16)strtol(inString, &end, 0);214 if(*end != '\0') {215 *status = PS_PARSE_ERROR_VALUE;216 } else if(inString==end) {217 *status = PS_PARSE_ERROR_VALUE;218 }219 220 return value;221 }222 223 /** Returns single parsed value as a psU32. The input string must be cleaned and null terminated. */224 static psU32 parseU32(char *inString, psParseErrorType *status)225 {226 char *end = NULL;227 psU32 value = 0.0;228 229 230 value = (psU32)strtoul(inString, &end, 0);231 if(*end != '\0') {232 *status = PS_PARSE_ERROR_VALUE;233 } else if(inString==end) {234 *status = PS_PARSE_ERROR_VALUE;235 }236 237 return value;238 144 } 239 145 … … 255 161 } 256 162 257 /** Returns single parsed value as a psU64. The input string must be cleaned and null terminated. */258 static psU64 parseU64(char *inString, psParseErrorType *status)259 {260 char *end = NULL;261 psU64 value = 0.0;262 263 264 value = (psU64)strtoull(inString, &end, 0);265 if(*end != '\0') {266 *status = PS_PARSE_ERROR_VALUE;267 } else if(inString==end) {268 *status = PS_PARSE_ERROR_VALUE;269 }270 271 return value;272 }273 274 163 /** Returns single parsed value as a psS64. The input string must be cleaned and null terminated. */ 275 164 static psS64 parseS64(char *inString, psParseErrorType *status) … … 277 166 char *end = NULL; 278 167 psS64 value = 0.0; 279 280 168 281 169 value = (psS64)strtoll(inString, &end, 0); … … 295 183 psF32 value = 0.0; 296 184 297 298 185 value = (psF32)strtof(inString, &end); 299 186 if(*end != '\0') { … … 312 199 psF64 value = 0.0; 313 200 314 315 201 value = (psF64)strtod(inString, &end); 316 202 if(*end != '\0') { … … 338 224 339 225 switch(type) { 340 case PS_TYPE_U8:341 vec->data.U8[index] = parseU8(strValue, status);342 break;343 case PS_TYPE_S8:344 vec->data.S8[index] = parseS8(strValue, status);345 break;346 case PS_TYPE_U16:347 vec->data.U16[index] = parseU16(strValue, status);348 break;349 case PS_TYPE_S16:350 vec->data.S16[index] = parseS16(strValue, status);351 break;352 case PS_TYPE_U32:353 vec->data.U32[index] = parseU32(strValue, status);354 break;355 226 case PS_TYPE_S32: 356 227 vec->data.S32[index] = parseS32(strValue, status); 357 break;358 case PS_TYPE_U64:359 vec->data.U64[index] = parseU64(strValue, status);360 228 break; 361 229 case PS_TYPE_S64: … … 375 243 } 376 244 377 static psParseErrorType printError(psU64 lineCount, char* badText, psParseErrorType status)378 {379 switch(status) {380 case PS_PARSE_ERROR_VALUE:381 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_PARSE_VALUE, badText, lineCount);382 break;383 case PS_PARSE_ERROR_TYPE:384 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_PARSE_TYPE, badText, lineCount);385 break;386 case PS_PARSE_ERROR_GENERAL:387 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_PARSE_GENERAL, badText, lineCount);388 break;389 default:390 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_INVALID_TYPE, badText, lineCount);391 }392 393 return PS_LOOKUP_SUCCESS;394 }395 396 245 static void lookupTableFree(psLookupTable* table) 397 246 { … … 401 250 402 251 psFree(table->values); 403 psFree( table->index);404 psFree((char*)table->f ileName);252 psFree((char*)table->filename); 253 psFree((char*)table->format); 405 254 } 406 255 … … 409 258 /*****************************************************************************/ 410 259 411 psLookupTable* psLookupTableAlloc(const char *fileName, psF64 validFrom, psF64 validTo)260 psLookupTable* psLookupTableAlloc(const char *fileName, const char *format, int indexCol) 412 261 { 413 262 psLookupTable *outTable = NULL; 414 415 263 416 264 // Can't read table if you don't know its name 417 265 PS_ASSERT_PTR_NON_NULL(fileName,NULL); 418 266 267 // Can't read table if you don't know its format 268 PS_ASSERT_PTR_NON_NULL(format,NULL); 269 419 270 // Allocate lookup table 420 271 outTable = (psLookupTable*)psAlloc(sizeof(psLookupTable)); … … 423 274 psMemSetDeallocator(outTable, (psFreeFcn)lookupTableFree); 424 275 425 // Allocate and set metadata item comment 426 outTable->fileName = psStringCopy(fileName); 427 428 // Number of table rows and columns. Automatically resized by table read. 429 outTable->numRows = 0; 430 outTable->numCols = 0; 276 // Allocate and set file name and format strings 277 outTable->filename = psStringCopy(fileName); 278 outTable->format = psStringCopy(format); 431 279 432 280 // Valid ranges. Automatically set by table read if both zero. 433 outTable->validFrom = validFrom; 434 outTable->validTo = validTo; 281 outTable->validFrom = 0; 282 outTable->validTo = 0; 283 outTable->indexCol = indexCol; 435 284 436 285 // Vector of independent index values. Filled by table read. … … 447 296 case PS_TYPE_U8: \ 448 297 TABLE->validFrom = (psF64)TABLE->index->data.U8[0]; \ 449 TABLE->validTo = (psF64)TABLE->index->data.U8[TABLE->index->n alloc-1];\298 TABLE->validTo = (psF64)TABLE->index->data.U8[TABLE->index->n-1]; \ 450 299 break; \ 451 300 case PS_TYPE_S8: \ 452 301 TABLE->validFrom = (psF64)TABLE->index->data.S8[0]; \ 453 TABLE->validTo = (psF64)TABLE->index->data.S8[TABLE->index->n alloc-1];\302 TABLE->validTo = (psF64)TABLE->index->data.S8[TABLE->index->n-1]; \ 454 303 break; \ 455 304 case PS_TYPE_U16: \ 456 305 TABLE->validFrom = (psF64)TABLE->index->data.U16[0]; \ 457 TABLE->validTo = (psF64)TABLE->index->data.U16[TABLE->index->n alloc-1];\306 TABLE->validTo = (psF64)TABLE->index->data.U16[TABLE->index->n-1]; \ 458 307 break; \ 459 308 case PS_TYPE_S16: \ 460 309 TABLE->validFrom = (psF64)TABLE->index->data.S16[0]; \ 461 TABLE->validTo = (psF64)TABLE->index->data.S16[TABLE->index->n alloc-1];\310 TABLE->validTo = (psF64)TABLE->index->data.S16[TABLE->index->n-1]; \ 462 311 break; \ 463 312 case PS_TYPE_U32: \ 464 313 TABLE->validFrom = (psF64)TABLE->index->data.U32[0]; \ 465 TABLE->validTo = (psF64)TABLE->index->data.U32[TABLE->index->n alloc-1];\314 TABLE->validTo = (psF64)TABLE->index->data.U32[TABLE->index->n-1]; \ 466 315 break; \ 467 316 case PS_TYPE_S32: \ 468 317 TABLE->validFrom = (psF64)TABLE->index->data.S32[0]; \ 469 TABLE->validTo = (psF64)TABLE->index->data.S32[TABLE->index->n alloc-1];\318 TABLE->validTo = (psF64)TABLE->index->data.S32[TABLE->index->n-1]; \ 470 319 break; \ 471 320 case PS_TYPE_U64: \ 472 321 TABLE->validFrom = (psF64)TABLE->index->data.U64[0]; \ 473 TABLE->validTo = (psF64)TABLE->index->data.U64[TABLE->index->n alloc-1];\322 TABLE->validTo = (psF64)TABLE->index->data.U64[TABLE->index->n-1]; \ 474 323 break; \ 475 324 case PS_TYPE_S64: \ 476 325 TABLE->validFrom = (psF64)TABLE->index->data.S64[0]; \ 477 TABLE->validTo = (psF64)TABLE->index->data.S64[TABLE->index->n alloc-1];\326 TABLE->validTo = (psF64)TABLE->index->data.S64[TABLE->index->n-1]; \ 478 327 break; \ 479 328 case PS_TYPE_F32: \ 480 329 TABLE->validFrom = (psF64)TABLE->index->data.F32[0]; \ 481 TABLE->validTo = (psF64)TABLE->index->data.F32[TABLE->index->n alloc-1];\330 TABLE->validTo = (psF64)TABLE->index->data.F32[TABLE->index->n-1]; \ 482 331 break; \ 483 332 case PS_TYPE_F64: \ 484 333 TABLE->validFrom = (psF64)TABLE->index->data.F64[0]; \ 485 TABLE->validTo = (psF64)TABLE->index->data.F64[TABLE->index->n alloc-1];\334 TABLE->validTo = (psF64)TABLE->index->data.F64[TABLE->index->n-1]; \ 486 335 break; \ 487 336 default: \ … … 513 362 case PS_TYPE_S32: \ 514 363 ((psVector*)VEC_OUT)->data.S32[INDEX_OUT] = ((psVector*)VEC_IN)->data.S32[INDEX_IN]; \ 364 if(INDEX_OUT == 0) { \ 365 validFrom = ((psVector*)VEC_OUT)->data.S32[INDEX_OUT]; \ 366 } \ 367 if(INDEX_OUT == ((psVector*)VEC_OUT)->n-1 ) { \ 368 validTo = ((psVector*)VEC_OUT)->data.S32[INDEX_OUT]; \ 369 } \ 515 370 break; \ 516 371 case PS_TYPE_S64: \ 517 372 ((psVector*)VEC_OUT)->data.S64[INDEX_OUT] = ((psVector*)VEC_IN)->data.S64[INDEX_IN]; \ 373 if(INDEX_OUT == 0) { \ 374 validFrom = ((psVector*)VEC_OUT)->data.S64[INDEX_OUT]; \ 375 } \ 376 if(INDEX_OUT == ((psVector*)VEC_OUT)->n-1 ) { \ 377 validTo = ((psVector*)VEC_OUT)->data.S64[INDEX_OUT]; \ 378 } \ 518 379 break; \ 519 380 case PS_TYPE_F32: \ 520 381 ((psVector*)VEC_OUT)->data.F32[INDEX_OUT] = ((psVector*)VEC_IN)->data.F32[INDEX_IN]; \ 382 if(INDEX_OUT == 0) { \ 383 validFrom = ((psVector*)VEC_OUT)->data.F32[INDEX_OUT]; \ 384 } \ 385 if(INDEX_OUT == ((psVector*)VEC_OUT)->n-1 ) { \ 386 validTo = ((psVector*)VEC_OUT)->data.F32[INDEX_OUT]; \ 387 } \ 521 388 break; \ 522 389 case PS_TYPE_F64: \ 523 390 ((psVector*)VEC_OUT)->data.F64[INDEX_OUT] = ((psVector*)VEC_IN)->data.F64[INDEX_IN]; \ 391 if(INDEX_OUT == 0) { \ 392 validFrom = ((psVector*)VEC_OUT)->data.F64[INDEX_OUT]; \ 393 } \ 394 if(INDEX_OUT == ((psVector*)VEC_OUT)->n-1 ) { \ 395 validTo = ((psVector*)VEC_OUT)->data.F64[INDEX_OUT]; \ 396 } \ 524 397 break; \ 525 398 default: \ … … 527 400 } 528 401 529 530 psLookupTable* psLookupTableRead(psLookupTable *table) 531 { 532 bool typeLine = true; 533 char *line = NULL; 534 char *strType = NULL; 535 char *strValue = NULL; 536 char *linePtr = NULL; 537 psParseErrorType status = PS_PARSE_SUCCESS; 538 psParseErrorType lineStatus = PS_PARSE_SUCCESS; 539 psU64 lineCount = 0; 540 psU64 numRows = 0; 541 psU64 numCols = 0; 542 psU64 failedLines = 0; 543 FILE *fp = NULL; 544 psElemType elemType; 545 psVector *indexVec = NULL; 546 psVector *valuesVec = NULL; 547 psArray *values = NULL; 548 psBool sortIndex = false; 402 psArray *psVectorsReadFromFile(const char *filename, const char *format) 403 { 404 psArray* outputArray = NULL; 405 psVector* colVector = NULL; 406 char* strValue = NULL; 407 char* strNum = NULL; 408 char* line = NULL; 409 char* linePtr = NULL; 410 int numCols = 0; 411 int numRows = 0; 412 FILE* fp = NULL; 413 const char* tempFormat = NULL; 414 psParseErrorType parseStatus = PS_PARSE_SUCCESS; 415 416 // Check for nul file name 417 PS_ASSERT_PTR_NON_NULL(filename,NULL); 418 419 // Parse format string for valid string 420 PS_ASSERT_PTR_NON_NULL(format,NULL); 421 422 // Create temp pointer which can then be used several times 423 tempFormat = format; 424 425 // Create output array and set array elements to zero 426 outputArray = psArrayAlloc(10); 427 outputArray->n = 0; 428 429 // Parse the format string to determine how many vectors 430 // and whether the format string is valid 431 while((strValue=getToken((char**)&tempFormat," ",&parseStatus))) { 432 433 // Check for %d format sub string 434 if(strcmp(strValue,"\%d") == 0 ) { 435 numCols++; 436 colVector = psVectorAlloc(1,PS_TYPE_S32); 437 outputArray = psArrayAdd(outputArray,1,colVector); 438 psFree(colVector); 439 } else if (strcmp(strValue,"\%ld") == 0) { 440 numCols++; 441 colVector = psVectorAlloc(1,PS_TYPE_S64); 442 outputArray = psArrayAdd(outputArray,1,colVector); 443 psFree(colVector); 444 } else if (strcmp(strValue,"\%f") == 0) { 445 numCols++; 446 colVector = psVectorAlloc(1,PS_TYPE_F32); 447 outputArray = psArrayAdd(outputArray,1,colVector); 448 psFree(colVector); 449 } else if (strcmp(strValue,"\%lf") == 0) { 450 numCols++; 451 colVector = psVectorAlloc(1,PS_TYPE_F64); 452 outputArray = psArrayAdd(outputArray,1,colVector); 453 psFree(colVector); 454 } else if (strstr(strValue,"\%*") != 0) { 455 // Don't increase number of columns 456 } else { 457 psError(PS_ERR_BAD_PARAMETER_VALUE,true,"Invalid format specifier"); 458 psFree(strValue); 459 numCols = 0; 460 break; 461 } 462 psFree(strValue); 463 } 464 465 // If the format string was parsed successfully and return numCols the 466 // prepare to open file and read values 467 if(numCols > 0) { 468 469 // Open specified file 470 if((fp=fopen(filename, "r")) == NULL) { 471 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_FILE_NOT_FOUND, 472 filename); 473 psFree(outputArray); 474 return NULL; 475 } else { 476 // Initialize array index 477 int arrayIndex = 0; 478 479 // Create reusable line for continuous read 480 line = (char*)psAlloc(MAX_STRING_LENGTH*sizeof(char)); 481 482 // Loop through file to get numRows, numCols, and column data types 483 while((fgets(line, MAX_STRING_LENGTH, fp) != NULL) && (parseStatus == PS_PARSE_SUCCESS)) { 484 485 // Copy pointer to line for parsing 486 linePtr = line; 487 488 // If line is not a comment or blank, then extract data 489 if(!ignoreLine(linePtr)) { 490 numRows++; 491 492 // Copy format pointer for parsing 493 tempFormat = format; 494 arrayIndex = 0; 495 parseStatus = PS_PARSE_SUCCESS; 496 497 // Loop through format and line strings to get values in text table file 498 while((strValue=getToken((char**)&tempFormat," ",&parseStatus)) && 499 (strNum=getToken((char**)&linePtr," ",&parseStatus)) ) { 500 501 // Set column vector 502 colVector = outputArray->data[arrayIndex]; 503 504 // Set column entries based on format string defining the type 505 if(strcmp(strValue,"\%d") == 0 ) { 506 colVector = psVectorRecycle(colVector, numRows, colVector->type.type); 507 parseValue(colVector,numRows-1,strNum,&parseStatus); 508 arrayIndex++; 509 } else if (strcmp(strValue,"\%ld") == 0) { 510 colVector = psVectorRecycle(colVector, numRows, colVector->type.type); 511 parseValue(colVector,numRows-1,strNum,&parseStatus); 512 arrayIndex++; 513 } else if (strcmp(strValue,"\%f") == 0) { 514 colVector = psVectorRecycle(colVector, numRows, colVector->type.type); 515 parseValue(colVector,numRows-1,strNum,&parseStatus); 516 arrayIndex++; 517 } else if (strcmp(strValue,"\%lf") == 0) { 518 colVector = psVectorRecycle(colVector, numRows, colVector->type.type); 519 parseValue(colVector,numRows-1,strNum,&parseStatus); 520 arrayIndex++; 521 } else if (strstr(strValue,"\%*") != 0) { 522 // Don't increase number of columns 523 } 524 psFree(strValue); 525 psFree(strNum); 526 527 // If the file line was not parsed successful report error and return NULL 528 if(parseStatus != PS_PARSE_SUCCESS) { 529 psError(PS_ERR_UNKNOWN,true,"Parsing text file failed."); 530 fclose(fp); 531 psFree(outputArray); 532 psFree(line); 533 return NULL; 534 } 535 } 536 } // ignore line 537 } 538 539 // Read on the lines in the file - close file pointer 540 fclose(fp); 541 psFree(line); 542 } 543 } else { 544 // Format string parse error detected 545 psError(PS_ERR_UNKNOWN,true,"Format string was not parsed sucessfully"); 546 psFree(outputArray); 547 return NULL; 548 } 549 550 // Return populated array 551 return outputArray; 552 } 553 554 psLookupTable *psLookupTableImport(psLookupTable *table, const psArray *vectors, int indexCol) 555 { 556 psLookupTable* outputTable = NULL; 557 psBool sortNeeded = false; 558 psF64 validTo = 0; 559 psF64 validFrom = 0; 549 560 550 561 // Check for NULL input table 551 562 PS_ASSERT_PTR_NON_NULL(table,NULL); 552 563 553 // Check for input table with NULL file name 554 PS_ASSERT_PTR_NON_NULL(table->fileName,NULL); 555 556 // Open table file specified by table->fileName 557 if((fp=fopen(table->fileName, "r")) == NULL) { 558 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_FILE_NOT_FOUND, 559 table->fileName); 560 return table; 561 } 562 563 // Initialize vector pointers 564 indexVec = table->index; 565 values = table->values = psArrayAlloc(10); 566 values->n = 0; 567 568 // Create reusable line for continuous read 569 line = (char*)psAlloc(MAX_STRING_LENGTH*sizeof(char)); 570 571 // Loop through file to get numRows, numCols, and column data types 572 while((fgets(line, MAX_STRING_LENGTH, fp) != NULL) && (lineStatus == PS_PARSE_SUCCESS)) { 573 574 // Initialize variables for new line 575 linePtr = line; 576 lineCount++; 577 578 // If line is not a comment or blank, then extract data 579 if(!ignoreLine(linePtr)) { 580 581 if(typeLine == true) { 582 583 // Determine column types from first line in data file after comments 584 while((strType=getToken(&linePtr," ",&status))) { 585 numCols++; 586 typeLine = false; 587 if(!strncmp(strType, "psU8", 4)) { 588 elemType = PS_TYPE_U8; 589 } else if(!strncmp(strType, "psS8", 4)) { 590 elemType = PS_TYPE_S8; 591 } else if(!strncmp(strType, "psU16", 5)) { 592 elemType = PS_TYPE_U16; 593 } else if(!strncmp(strType, "psS16", 5)) { 594 elemType = PS_TYPE_S16; 595 } else if(!strncmp(strType, "psU32", 5)) { 596 elemType = PS_TYPE_U32; 597 } else if(!strncmp(strType, "psS32", 5)) { 598 elemType = PS_TYPE_S32; 599 } else if(!strncmp(strType, "psU64", 5)) { 600 elemType = PS_TYPE_U64; 601 } else if(!strncmp(strType, "psS64", 5)) { 602 elemType = PS_TYPE_S64; 603 } else if(!strncmp(strType, "psF32", 5)) { 604 elemType = PS_TYPE_F32; 605 } else if(!strncmp(strType, "psF64", 5)) { 606 elemType = PS_TYPE_F64; 607 } else { 608 status = PS_PARSE_ERROR_TYPE; 609 } 610 611 // Realloc number of columns as you go 612 psVector* vec = psVectorAlloc(0, elemType); 613 if(numCols == 1) { 614 indexVec = vec; 615 } else { 616 psArrayAdd(values,0,vec); 617 psFree(vec); 618 } 619 620 if(status) { 621 printError(lineCount, strValue, status); 622 failedLines++; 623 lineStatus = status; 624 status = PS_PARSE_SUCCESS; 625 } 626 psFree(strType); 627 } 628 } else { 629 // Parse and add values to all columns 630 numRows++; 631 numCols = 0; 632 while((strValue=getToken(&linePtr," ",&status))) { 633 numCols++; 634 635 // Realloc number of rows as you go 636 if(numCols == 1) { 637 sortIndex = false; 638 indexVec = psVectorRecycle(indexVec, numRows, indexVec->type.type); 639 parseValue(indexVec, numRows-1, strValue, &status); 640 } else { 641 valuesVec = values->data[numCols-2]; 642 valuesVec = psVectorRecycle(valuesVec, numRows, valuesVec->type.type); 643 parseValue(valuesVec, numRows-1, strValue, &status); 644 } 645 646 if(status) { 647 printError(lineCount, strValue, status); 648 failedLines++; 649 lineStatus = status; 650 status = PS_PARSE_SUCCESS; 651 } 652 psFree(strValue); 653 } // end while 654 } // end else 655 } // if ignoreLine 656 } // end while 657 658 psFree(line); 659 660 // Set table for return 661 table->numRows = numRows; 662 table->numCols = numCols-1; 663 table->index = indexVec; 664 table->values = values; 665 666 // Set table values to indicate error detected during the read 667 if(lineStatus) { 668 table->numRows = 0; 669 table->numCols = 0; 670 table->validFrom = 0; 671 table->validTo = 0; 672 psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psLookupTable_TABLE_INVALID); 673 } else { 674 // Check if index vector needs to be sorted 675 psVector* sortedIndex = psVectorAlloc(table->numRows,PS_TYPE_U32); 676 sortedIndex = psVectorSortIndex(sortedIndex,table->index); 677 for(psS32 i = 0; i < numRows; i++ ) { 678 if(sortedIndex->data.U32[i] != i) { 679 sortIndex = true; 680 break; 564 // Check for NULL vectors 565 PS_ASSERT_PTR_NON_NULL(vectors,NULL); 566 567 // Check for invalid index column 568 if(indexCol < 0 ) { 569 psError(PS_ERR_BAD_PARAMETER_VALUE,true,"Index column cannot be less than zero"); 570 return NULL; 571 } 572 573 psVector* indexColumnVector = vectors->data[indexCol]; 574 psS32 numRows = indexColumnVector->n; 575 psS32 numCols = vectors->n; 576 577 // Check if array is sorted on the index column 578 psVector* sortedIndex = psVectorAlloc(numRows,PS_TYPE_U32); 579 sortedIndex = psVectorSortIndex(sortedIndex,indexColumnVector); 580 for(psS32 i = 0; i < numRows; i++ ) { 581 if(sortedIndex->data.U32[i] != i) { 582 sortNeeded = true; 583 break; 584 } 585 } 586 587 // Check if it is necessary to sort value vectors 588 if(sortNeeded) { 589 // Allocate new array to contain sorted vectors 590 psArray* newValueArray = psArrayAlloc(numCols); 591 for(psS32 j = 0; j < numCols; j++) { 592 psS32 type = ((psVector*)(vectors->data[j]))->type.type; 593 newValueArray->data[j] = psVectorAlloc(numRows,type); 594 } 595 596 // Populate new array/vectors with sorted values 597 for(psS32 i = 0; i < numRows; i++) { 598 // Populate new index vector 599 psU32 sortIndex = sortedIndex->data.U32[i]; 600 // For every column populate new value vectors 601 for(psS32 j=0; j < numCols; j++) { 602 COPY_VECTOR_VALUES(newValueArray->data[j],i,vectors->data[j], sortIndex) 681 603 } 682 604 } 683 // Check if it is necessary to sort value vectors 684 if(sortIndex) { 685 // Allocate new index vector 686 psVector* newIndexVector = psVectorAlloc(numRows,indexVec->type.type); 687 // Allocate new value vectors 688 psArray* newValueArray = psArrayAlloc(numCols-1); 689 for(psS32 j = 0; j < numCols-1; j++) { 690 psS32 type = ((psVector*)(table->values->data[j]))->type.type; 691 newValueArray->data[j] = psVectorAlloc(numRows,type); 692 } 693 for(psS32 i = 0; i < numRows; i++) { 694 // Populate new index vector 695 psU32 sortIndex = sortedIndex->data.U32[i]; 696 COPY_VECTOR_VALUES(newIndexVector,i, indexVec,sortIndex) 697 // For every column populate new value vectors 698 for(psS32 j=0; j < numCols-1; j++) { 699 COPY_VECTOR_VALUES(newValueArray->data[j],i,table->values->data[j], sortIndex) 700 } 701 } 702 // Free old index vector 703 psFree(table->index); 704 // Free old value vectors 705 psFree(table->values); 706 // Assign new vector value to table 707 table->index = newIndexVector; 708 // Assign new value vectors to table array 709 table->values = newValueArray; 605 // Assign new vector value to table 606 table->index = newValueArray->data[indexCol]; 607 // Assign new value vectors to table array 608 table->values = newValueArray; 609 // Assign indexCol 610 table->indexCol = indexCol; 611 // Assign validTo and validFrom values 612 UPDATE_VALID_TO_FROM(table) 613 614 // Set return value 615 outputTable = table; 616 617 } else { 618 // Index vector is already sorted 619 // Assign array vector specified by indexCol to table index vector and increment memory ref 620 table->index = vectors->data[indexCol]; 621 table->values = (psArray*)vectors; 622 psMemIncrRefCounter((psArray*)vectors); 623 624 // Assign indexCol 625 table->indexCol = indexCol; 626 // Assign validTo and validFrom values 627 UPDATE_VALID_TO_FROM(table); 628 629 // Set return value 630 outputTable = table; 631 } 632 633 // Free sort vector 634 psFree(sortedIndex); 635 636 return outputTable; 637 } 638 639 psS32 psLookupTableRead(psLookupTable* table) 640 { 641 psS32 numRows = 0; 642 psArray* vectors = NULL; 643 psLookupTable* outTable = NULL; 644 645 // Check if the input table is NULL then return 0 646 PS_ASSERT_PTR_NON_NULL(table,0); 647 648 // Read vectors from file specified in table 649 vectors = psVectorsReadFromFile(table->filename, table->format); 650 651 // Check for valid array after reading from file 652 if(vectors != NULL) { 653 654 // Import vector into table 655 outTable = psLookupTableImport(table, vectors, table->indexCol); 656 657 psFree(vectors); 658 659 // Update the number of rows read if outTable is not NULL 660 if(outTable != NULL) { 661 numRows = table->index->n; 710 662 } 711 psFree(sortedIndex); 712 // Update the validTo and validFrom 713 UPDATE_VALID_TO_FROM(table) 714 } 715 716 fclose(fp); 717 718 return table; 663 } 664 665 // Return the number of lines read 666 return numRows; 719 667 } 720 668 … … 756 704 } 757 705 758 759 #define CHECK_LOWER_UPPER_BOUND(TABLE,INDEX,COLUMN) \ 760 switch (TABLE->index->type.type) { \ 761 case PS_TYPE_U8: \ 762 if( (psU8)index < TABLE->index->data.U8[0] ) { \ 763 *status = PS_LOOKUP_PAST_TOP; \ 764 } \ 765 if( (psU8)index > TABLE->index->data.U8[numRows-1]) { \ 766 *status = PS_LOOKUP_PAST_BOTTOM; \ 767 } \ 768 break; \ 769 case PS_TYPE_U16: \ 770 if( (psU16)index < TABLE->index->data.U16[0] ) { \ 771 *status = PS_LOOKUP_PAST_TOP; \ 772 } \ 773 if( (psU16)index > TABLE->index->data.U16[numRows-1] ) { \ 774 *status = PS_LOOKUP_PAST_BOTTOM; \ 775 } \ 776 break; \ 777 case PS_TYPE_U32: \ 778 if( (psU32)index < TABLE->index->data.U32[0]) { \ 779 *status = PS_LOOKUP_PAST_TOP; \ 780 } \ 781 if ( (psU32)index > TABLE->index->data.U32[numRows-1] ) { \ 782 *status = PS_LOOKUP_PAST_BOTTOM; \ 783 } \ 784 break; \ 785 case PS_TYPE_U64: \ 786 if( (psU64)index < TABLE->index->data.U64[0] ) { \ 787 *status = PS_LOOKUP_PAST_TOP; \ 788 } \ 789 if( (psU64)index > TABLE->index->data.U64[numRows-1] ) { \ 790 *status = PS_LOOKUP_PAST_BOTTOM; \ 791 } \ 792 break; \ 793 case PS_TYPE_S8: \ 794 if( (psS8)index < TABLE->index->data.S8[0] ) { \ 795 *status = PS_LOOKUP_PAST_TOP; \ 796 } \ 797 if( (psS8)index > TABLE->index->data.S8[numRows-1] ) { \ 798 *status = PS_LOOKUP_PAST_BOTTOM; \ 799 } \ 800 break; \ 801 case PS_TYPE_S16: \ 802 if( (psS16)index < TABLE->index->data.S16[0] ) { \ 803 *status = PS_LOOKUP_PAST_TOP; \ 804 } \ 805 if( (psS16)index > TABLE->index->data.S16[numRows-1] ) { \ 806 *status = PS_LOOKUP_PAST_BOTTOM; \ 807 } \ 808 break; \ 809 case PS_TYPE_S32: \ 810 if( (psS32)index < TABLE->index->data.S32[0] ) { \ 811 *status = PS_LOOKUP_PAST_TOP; \ 812 } \ 813 if( (psS32)index > TABLE->index->data.S32[numRows-1] ) { \ 814 *status = PS_LOOKUP_PAST_BOTTOM; \ 815 } \ 816 break; \ 817 case PS_TYPE_S64: \ 818 if( (psS64)index < TABLE->index->data.S64[0] ) { \ 819 *status = PS_LOOKUP_PAST_TOP; \ 820 } \ 821 if( (psS64)index > TABLE->index->data.S64[numRows-1] ) { \ 822 *status = PS_LOOKUP_PAST_BOTTOM; \ 823 } \ 824 break; \ 825 case PS_TYPE_F32: \ 826 if( (psF32)index < TABLE->index->data.F32[0] ) { \ 827 *status = PS_LOOKUP_PAST_TOP; \ 828 } \ 829 if( (psF32)index > TABLE->index->data.F32[numRows-1] ) { \ 830 *status = PS_LOOKUP_PAST_BOTTOM; \ 831 } \ 832 break; \ 833 case PS_TYPE_F64: \ 834 if( index < TABLE->index->data.F64[0] ) { \ 835 *status = PS_LOOKUP_PAST_TOP; \ 836 } \ 837 if( index > TABLE->index->data.F64[numRows-1] ) { \ 838 *status = PS_LOOKUP_PAST_BOTTOM; \ 839 } \ 840 break; \ 841 default: \ 842 *status = PS_LOOKUP_ERROR; \ 843 return NAN; \ 844 break; \ 845 } \ 846 if(*status == PS_LOOKUP_PAST_TOP) { \ 847 CONVERT_VALUE_TO_F64(((psVector*)(TABLE->values->data[COLUMN])),0,out) \ 848 return out; \ 849 } else if (*status == PS_LOOKUP_PAST_BOTTOM) { \ 850 CONVERT_VALUE_TO_F64(((psVector*)(TABLE->values->data[COLUMN])),numRows-1,out) \ 851 return out; \ 852 } 853 854 855 psF64 psLookupTableInterpolate(psLookupTable *table, psF64 index, psU64 column, psLookupStatusType *status) 706 #define CHECK_LOWER_UPPER_BOUND(TABLE,INDEX,COLUMN) \ 707 switch (TABLE->index->type.type) { \ 708 case PS_TYPE_S32: \ 709 if( (psS32)index < TABLE->index->data.S32[0] ) { \ 710 return NAN; \ 711 } \ 712 if( (psS32)index > TABLE->index->data.S32[numRows-1] ) { \ 713 return NAN; \ 714 } \ 715 break; \ 716 case PS_TYPE_S64: \ 717 if( (psS64)index < TABLE->index->data.S64[0] ) { \ 718 return NAN; \ 719 } \ 720 if( (psS64)index > TABLE->index->data.S64[numRows-1] ) { \ 721 return NAN; \ 722 } \ 723 break; \ 724 case PS_TYPE_F32: \ 725 if( (psF32)index < TABLE->index->data.F32[0] ) { \ 726 return NAN; \ 727 } \ 728 if( (psF32)index > TABLE->index->data.F32[numRows-1] ) { \ 729 return NAN; \ 730 } \ 731 break; \ 732 case PS_TYPE_F64: \ 733 if( index < TABLE->index->data.F64[0] ) { \ 734 return NAN; \ 735 } \ 736 if( index > TABLE->index->data.F64[numRows-1] ) { \ 737 return NAN; \ 738 } \ 739 break; \ 740 default: \ 741 return NAN; \ 742 break; \ 743 } 744 745 psF64 psLookupTableInterpolate(const psLookupTable *table, psF64 index, psS32 column) 856 746 { 857 747 psU64 hiIdx = 0; … … 867 757 psArray *values = NULL; 868 758 869 // Error checks 870 // Set status to error prior to check since if checks fails it will immediately return 871 PS_ASSERT_PTR_NON_NULL(status,NAN); 872 *status = PS_LOOKUP_ERROR; 759 // Check for NULL table 873 760 PS_ASSERT_PTR_NON_NULL(table,NAN); 761 874 762 indexVec = table->index; 875 763 values = table->values; 876 numRows = table-> numRows;877 numCols = table-> numCols;764 numRows = table->index->n; 765 numCols = table->values->n; 878 766 PS_ASSERT_PTR_NON_NULL(indexVec,NAN); 879 767 PS_ASSERT_PTR_NON_NULL(values,NAN); … … 884 772 valuesVec = (psVector*)values->data[column]; 885 773 PS_ASSERT_PTR_NON_NULL(indexVec,NAN); 886 887 // Set status to success since it passed all parameter checks888 *status = PS_LOOKUP_SUCCESS;889 774 890 775 // Verify the index is within the bounds of the table … … 898 783 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 899 784 PS_ERRORTEXT_psLookupTable_INTERPOLATE_HIGH, hiIdx); 900 *status = PS_LOOKUP_ERROR;901 785 return NAN; 902 786 } … … 909 793 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 910 794 PS_ERRORTEXT_psLookupTable_INTERPOLATE_LOW, loIdx); 911 *status = PS_LOOKUP_ERROR;912 795 return NAN; 913 796 } … … 919 802 if(fabs(denom) < FLT_EPSILON) { 920 803 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_DIVIDE_BY_ZERO); 921 *status = PS_LOOKUP_ERROR;922 804 return NAN; 923 805 } else { … … 934 816 } 935 817 936 psVector* psLookupTableInterpolateAll(psLookupTable *table, psF64 index, psVector *stats) 937 { 938 psU64 i = 0; 818 psVector* psLookupTableInterpolateAll(psLookupTable *table, psF64 index) 819 { 939 820 psU64 numCols = 0; 940 821 psVector *outVector = NULL; 941 psLookupStatusType status = PS_LOOKUP_SUCCESS;942 822 943 823 // Error checks 944 824 PS_ASSERT_PTR_NON_NULL(table,NULL); 945 PS_ASSERT_PTR_NON_NULL(stats,NULL); 946 numCols = table->numCols; 825 numCols = table->values->n; 947 826 PS_ASSERT_INT_UNEQUAL(numCols, 0,NULL); 948 827 949 outVector = psVectorAlloc(numCols+1, PS_TYPE_F64); 828 // Create output vector 829 outVector = psVectorAlloc(numCols, PS_TYPE_F64); 950 830 951 831 // Fill vectors with results and status of results 952 for(i=0; i<numCols; i++) { 953 outVector->data.F64[i] = psLookupTableInterpolate(table, index, i, &status); 954 stats->data.U32[i] = status; 832 for(psU64 i=0; i<numCols; i++) { 833 outVector->data.F64[i] = psLookupTableInterpolate(table, index, i); 834 if(isnan(outVector->data.F64[i])) { 835 // Free allocated vector 836 psFree(outVector); 837 outVector = NULL; 838 // Break out of loop since error detected 839 break; 840 } 955 841 } 956 842 -
trunk/psLib/src/dataIO/psLookupTable.h
r3684 r4050 7 7 * @author Ross Harman, MHPCC 8 8 * 9 * @version $Revision: 1. 5$ $Name: not supported by cvs2svn $10 * @date $Date: 2005-0 4-08 17:58:57$9 * @version $Revision: 1.6 $ $Name: not supported by cvs2svn $ 10 * @date $Date: 2005-05-31 21:46:56 $ 11 11 * 12 12 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii … … 28 28 typedef struct 29 29 { 30 const char *fileName; ///< Name of file with table 31 psU64 numRows; ///< Number of table rows 32 psU64 numCols; ///< Number of table columns 30 const char *filename; ///< Name of file with table 31 const char *format; ///< scanf-like format string for file 32 unsigned int indexCol; ///< Column of the index vector (starting at zero) 33 psVector *index; ///< Vector of independent index values 34 psArray *values; ///< Array of dependent table values corresponding to index values 33 35 psF64 validFrom; ///< Lower bound for rable read 34 36 psF64 validTo; ///< Upper bound for table read 35 psVector *index; ///< Vector of independent index values36 psArray *values; ///< Array of dependent table values corresponding to index values37 37 } 38 38 psLookupTable; … … 69 69 psLookupTable* psLookupTableAlloc( 70 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 71 const char *format, ///< scanf-like format string 72 int indexCol ///< Column of the index vector (starting at zero) 73 ); 74 75 /** Read vectors from file 76 * 77 * Read numeric vectors from ASCII text file 78 * 79 * @return psArray* New array of psVectors corresponding to the columns of the table 80 */ 81 psArray *psVectorsReadFromFile( 82 const char* filename, ///< File to be read 83 const char* format ///< scanf-like format string 84 ); 85 86 /** Import arrays of vectors into a table 87 * 88 * Import array of vectors read from text file into a table structure 89 * 90 * @return psLookupTable* Lookup table structure with array vector data 91 */ 92 psLookupTable *psLookupTableImport( 93 psLookupTable *table, ///< Lookup table into which to import 94 const psArray *vectors, ///< Array of vectors 95 int indexCol ///< Index of the index vector in the array of vectors 73 96 ); 74 97 … … 77 100 * Reads a lookup table and fills corresponding psLookupTable struct. 78 101 * 79 * @return ps LookupTable* New psLookupTable struct.102 * @return psS32 Number of valid lines read 80 103 */ 81 ps LookupTable*psLookupTableRead(104 psS32 psLookupTableRead( 82 105 psLookupTable *table ///< Table to read 83 106 ); … … 91 114 */ 92 115 psF64 psLookupTableInterpolate( 93 psLookupTable *table,///< Table with data116 const psLookupTable *table, ///< Table with data 94 117 psF64 index, ///< Value to be interpolated 95 psU64 column, ///< Column in table to be interpolated 96 psLookupStatusType *status ///< Status of lookup 118 psS32 column ///< Column in table to be interpolated 97 119 ); 98 120 … … 106 128 psVector* psLookupTableInterpolateAll( 107 129 psLookupTable *table, ///< Table with data 108 psF64 index, ///< Value to be interpolated 109 psVector *stats ///< Vector of status for each lookup 130 psF64 index ///< Value to be interpolated 110 131 ); 111 132 -
trunk/psLib/src/types/psLookupTable.c
r4031 r4050 7 7 * @author Ross Harman, MHPCC 8 8 * 9 * @version $Revision: 1.1 4$ $Name: not supported by cvs2svn $10 * @date $Date: 2005-05- 25 22:46:47$9 * @version $Revision: 1.15 $ $Name: not supported by cvs2svn $ 10 * @date $Date: 2005-05-31 21:46:56 $ 11 11 * 12 * Copyright 2004- 5 Maui High Performance Computing Center, Universityof Hawaii12 * Copyright 2004-2005 Maui High Performance Computing Center, Univ. of Hawaii 13 13 */ 14 14 #include <stdio.h> … … 64 64 static char *cleanString(char *inString, int sLen); 65 65 static char* getToken(char **inString, char *delimiter, psParseErrorType *status); 66 static psU8 parseU8(char *inString, psParseErrorType *status);67 static psS8 parseS8(char *inString, psParseErrorType *status);68 static psU16 parseU16(char *inString, psParseErrorType *status);69 static psS16 parseS16(char *inString, psParseErrorType *status);70 static psU32 parseU32(char *inString, psParseErrorType *status);71 66 static psS32 parseS32(char *inString, psParseErrorType *status); 72 static psU64 parseU64(char *inString, psParseErrorType *status);73 67 static psS64 parseS64(char *inString, psParseErrorType *status); 74 68 static psF32 parseF32(char *inString, psParseErrorType *status); … … 87 81 inString++; 88 82 } 89 90 83 return true; 91 84 } … … 100 93 char *cleaned = NULL; 101 94 102 103 95 ptrB = inString; 104 96 105 / * Skip over leading # or whitespace */97 // Skip over leading # or whitespace 106 98 while (isspace(*ptrB) || *ptrB=='#') { 107 99 ptrB++; 108 100 } 109 101 110 / * Skip over trailing whitespace, null terminators, and # characters */102 // Skip over trailing whitespace, null terminators, and # characters 111 103 ptrE = inString + sLen; 112 104 while(isspace(*ptrE) || *ptrE=='\0' || *ptrE=='#') { … … 130 122 char *cleanToken = NULL; 131 123 int sLen = 0; 132 133 124 134 125 // Skip over leading whitespace … … 151 142 152 143 return cleanToken; 153 }154 155 /** Returns single parsed value as a psU8. The input string must be cleaned and null terminated. */156 static psU8 parseU8(char *inString, psParseErrorType *status)157 {158 char *end = NULL;159 psU8 value = 0.0;160 161 162 value = (psU8)strtoul(inString, &end, 0);163 if(*end != '\0') {164 *status = PS_PARSE_ERROR_VALUE;165 } else if(inString==end) {166 *status = PS_PARSE_ERROR_VALUE;167 }168 169 return value;170 }171 172 /** Returns single parsed value as a psS8. The input string must be cleaned and null terminated. */173 static psS8 parseS8(char *inString, psParseErrorType *status)174 {175 char *end = NULL;176 psS8 value = 0.0;177 178 179 value = (psS8)strtol(inString, &end, 0);180 if(*end != '\0') {181 *status = PS_PARSE_ERROR_VALUE;182 } else if(inString==end) {183 *status = PS_PARSE_ERROR_VALUE;184 }185 186 return value;187 }188 189 /** Returns single parsed value as a psU16. The input string must be cleaned and null terminated. */190 static psU16 parseU16(char *inString, psParseErrorType *status)191 {192 char *end = NULL;193 psU16 value = 0.0;194 195 196 value = (psU16)strtoul(inString, &end, 0);197 if(*end != '\0') {198 *status = PS_PARSE_ERROR_VALUE;199 } else if(inString==end) {200 *status = PS_PARSE_ERROR_VALUE;201 }202 203 return value;204 }205 206 /** Returns single parsed value as a psS16. The input string must be cleaned and null terminated. */207 static psS16 parseS16(char *inString, psParseErrorType *status)208 {209 char *end = NULL;210 psS16 value = 0.0;211 212 213 value = (psS16)strtol(inString, &end, 0);214 if(*end != '\0') {215 *status = PS_PARSE_ERROR_VALUE;216 } else if(inString==end) {217 *status = PS_PARSE_ERROR_VALUE;218 }219 220 return value;221 }222 223 /** Returns single parsed value as a psU32. The input string must be cleaned and null terminated. */224 static psU32 parseU32(char *inString, psParseErrorType *status)225 {226 char *end = NULL;227 psU32 value = 0.0;228 229 230 value = (psU32)strtoul(inString, &end, 0);231 if(*end != '\0') {232 *status = PS_PARSE_ERROR_VALUE;233 } else if(inString==end) {234 *status = PS_PARSE_ERROR_VALUE;235 }236 237 return value;238 144 } 239 145 … … 255 161 } 256 162 257 /** Returns single parsed value as a psU64. The input string must be cleaned and null terminated. */258 static psU64 parseU64(char *inString, psParseErrorType *status)259 {260 char *end = NULL;261 psU64 value = 0.0;262 263 264 value = (psU64)strtoull(inString, &end, 0);265 if(*end != '\0') {266 *status = PS_PARSE_ERROR_VALUE;267 } else if(inString==end) {268 *status = PS_PARSE_ERROR_VALUE;269 }270 271 return value;272 }273 274 163 /** Returns single parsed value as a psS64. The input string must be cleaned and null terminated. */ 275 164 static psS64 parseS64(char *inString, psParseErrorType *status) … … 277 166 char *end = NULL; 278 167 psS64 value = 0.0; 279 280 168 281 169 value = (psS64)strtoll(inString, &end, 0); … … 295 183 psF32 value = 0.0; 296 184 297 298 185 value = (psF32)strtof(inString, &end); 299 186 if(*end != '\0') { … … 312 199 psF64 value = 0.0; 313 200 314 315 201 value = (psF64)strtod(inString, &end); 316 202 if(*end != '\0') { … … 338 224 339 225 switch(type) { 340 case PS_TYPE_U8:341 vec->data.U8[index] = parseU8(strValue, status);342 break;343 case PS_TYPE_S8:344 vec->data.S8[index] = parseS8(strValue, status);345 break;346 case PS_TYPE_U16:347 vec->data.U16[index] = parseU16(strValue, status);348 break;349 case PS_TYPE_S16:350 vec->data.S16[index] = parseS16(strValue, status);351 break;352 case PS_TYPE_U32:353 vec->data.U32[index] = parseU32(strValue, status);354 break;355 226 case PS_TYPE_S32: 356 227 vec->data.S32[index] = parseS32(strValue, status); 357 break;358 case PS_TYPE_U64:359 vec->data.U64[index] = parseU64(strValue, status);360 228 break; 361 229 case PS_TYPE_S64: … … 375 243 } 376 244 377 static psParseErrorType printError(psU64 lineCount, char* badText, psParseErrorType status)378 {379 switch(status) {380 case PS_PARSE_ERROR_VALUE:381 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_PARSE_VALUE, badText, lineCount);382 break;383 case PS_PARSE_ERROR_TYPE:384 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_PARSE_TYPE, badText, lineCount);385 break;386 case PS_PARSE_ERROR_GENERAL:387 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_PARSE_GENERAL, badText, lineCount);388 break;389 default:390 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_INVALID_TYPE, badText, lineCount);391 }392 393 return PS_LOOKUP_SUCCESS;394 }395 396 245 static void lookupTableFree(psLookupTable* table) 397 246 { … … 401 250 402 251 psFree(table->values); 403 psFree( table->index);404 psFree((char*)table->f ileName);252 psFree((char*)table->filename); 253 psFree((char*)table->format); 405 254 } 406 255 … … 409 258 /*****************************************************************************/ 410 259 411 psLookupTable* psLookupTableAlloc(const char *fileName, psF64 validFrom, psF64 validTo)260 psLookupTable* psLookupTableAlloc(const char *fileName, const char *format, int indexCol) 412 261 { 413 262 psLookupTable *outTable = NULL; 414 415 263 416 264 // Can't read table if you don't know its name 417 265 PS_ASSERT_PTR_NON_NULL(fileName,NULL); 418 266 267 // Can't read table if you don't know its format 268 PS_ASSERT_PTR_NON_NULL(format,NULL); 269 419 270 // Allocate lookup table 420 271 outTable = (psLookupTable*)psAlloc(sizeof(psLookupTable)); … … 423 274 psMemSetDeallocator(outTable, (psFreeFcn)lookupTableFree); 424 275 425 // Allocate and set metadata item comment 426 outTable->fileName = psStringCopy(fileName); 427 428 // Number of table rows and columns. Automatically resized by table read. 429 outTable->numRows = 0; 430 outTable->numCols = 0; 276 // Allocate and set file name and format strings 277 outTable->filename = psStringCopy(fileName); 278 outTable->format = psStringCopy(format); 431 279 432 280 // Valid ranges. Automatically set by table read if both zero. 433 outTable->validFrom = validFrom; 434 outTable->validTo = validTo; 281 outTable->validFrom = 0; 282 outTable->validTo = 0; 283 outTable->indexCol = indexCol; 435 284 436 285 // Vector of independent index values. Filled by table read. … … 447 296 case PS_TYPE_U8: \ 448 297 TABLE->validFrom = (psF64)TABLE->index->data.U8[0]; \ 449 TABLE->validTo = (psF64)TABLE->index->data.U8[TABLE->index->n alloc-1];\298 TABLE->validTo = (psF64)TABLE->index->data.U8[TABLE->index->n-1]; \ 450 299 break; \ 451 300 case PS_TYPE_S8: \ 452 301 TABLE->validFrom = (psF64)TABLE->index->data.S8[0]; \ 453 TABLE->validTo = (psF64)TABLE->index->data.S8[TABLE->index->n alloc-1];\302 TABLE->validTo = (psF64)TABLE->index->data.S8[TABLE->index->n-1]; \ 454 303 break; \ 455 304 case PS_TYPE_U16: \ 456 305 TABLE->validFrom = (psF64)TABLE->index->data.U16[0]; \ 457 TABLE->validTo = (psF64)TABLE->index->data.U16[TABLE->index->n alloc-1];\306 TABLE->validTo = (psF64)TABLE->index->data.U16[TABLE->index->n-1]; \ 458 307 break; \ 459 308 case PS_TYPE_S16: \ 460 309 TABLE->validFrom = (psF64)TABLE->index->data.S16[0]; \ 461 TABLE->validTo = (psF64)TABLE->index->data.S16[TABLE->index->n alloc-1];\310 TABLE->validTo = (psF64)TABLE->index->data.S16[TABLE->index->n-1]; \ 462 311 break; \ 463 312 case PS_TYPE_U32: \ 464 313 TABLE->validFrom = (psF64)TABLE->index->data.U32[0]; \ 465 TABLE->validTo = (psF64)TABLE->index->data.U32[TABLE->index->n alloc-1];\314 TABLE->validTo = (psF64)TABLE->index->data.U32[TABLE->index->n-1]; \ 466 315 break; \ 467 316 case PS_TYPE_S32: \ 468 317 TABLE->validFrom = (psF64)TABLE->index->data.S32[0]; \ 469 TABLE->validTo = (psF64)TABLE->index->data.S32[TABLE->index->n alloc-1];\318 TABLE->validTo = (psF64)TABLE->index->data.S32[TABLE->index->n-1]; \ 470 319 break; \ 471 320 case PS_TYPE_U64: \ 472 321 TABLE->validFrom = (psF64)TABLE->index->data.U64[0]; \ 473 TABLE->validTo = (psF64)TABLE->index->data.U64[TABLE->index->n alloc-1];\322 TABLE->validTo = (psF64)TABLE->index->data.U64[TABLE->index->n-1]; \ 474 323 break; \ 475 324 case PS_TYPE_S64: \ 476 325 TABLE->validFrom = (psF64)TABLE->index->data.S64[0]; \ 477 TABLE->validTo = (psF64)TABLE->index->data.S64[TABLE->index->n alloc-1];\326 TABLE->validTo = (psF64)TABLE->index->data.S64[TABLE->index->n-1]; \ 478 327 break; \ 479 328 case PS_TYPE_F32: \ 480 329 TABLE->validFrom = (psF64)TABLE->index->data.F32[0]; \ 481 TABLE->validTo = (psF64)TABLE->index->data.F32[TABLE->index->n alloc-1];\330 TABLE->validTo = (psF64)TABLE->index->data.F32[TABLE->index->n-1]; \ 482 331 break; \ 483 332 case PS_TYPE_F64: \ 484 333 TABLE->validFrom = (psF64)TABLE->index->data.F64[0]; \ 485 TABLE->validTo = (psF64)TABLE->index->data.F64[TABLE->index->n alloc-1];\334 TABLE->validTo = (psF64)TABLE->index->data.F64[TABLE->index->n-1]; \ 486 335 break; \ 487 336 default: \ … … 513 362 case PS_TYPE_S32: \ 514 363 ((psVector*)VEC_OUT)->data.S32[INDEX_OUT] = ((psVector*)VEC_IN)->data.S32[INDEX_IN]; \ 364 if(INDEX_OUT == 0) { \ 365 validFrom = ((psVector*)VEC_OUT)->data.S32[INDEX_OUT]; \ 366 } \ 367 if(INDEX_OUT == ((psVector*)VEC_OUT)->n-1 ) { \ 368 validTo = ((psVector*)VEC_OUT)->data.S32[INDEX_OUT]; \ 369 } \ 515 370 break; \ 516 371 case PS_TYPE_S64: \ 517 372 ((psVector*)VEC_OUT)->data.S64[INDEX_OUT] = ((psVector*)VEC_IN)->data.S64[INDEX_IN]; \ 373 if(INDEX_OUT == 0) { \ 374 validFrom = ((psVector*)VEC_OUT)->data.S64[INDEX_OUT]; \ 375 } \ 376 if(INDEX_OUT == ((psVector*)VEC_OUT)->n-1 ) { \ 377 validTo = ((psVector*)VEC_OUT)->data.S64[INDEX_OUT]; \ 378 } \ 518 379 break; \ 519 380 case PS_TYPE_F32: \ 520 381 ((psVector*)VEC_OUT)->data.F32[INDEX_OUT] = ((psVector*)VEC_IN)->data.F32[INDEX_IN]; \ 382 if(INDEX_OUT == 0) { \ 383 validFrom = ((psVector*)VEC_OUT)->data.F32[INDEX_OUT]; \ 384 } \ 385 if(INDEX_OUT == ((psVector*)VEC_OUT)->n-1 ) { \ 386 validTo = ((psVector*)VEC_OUT)->data.F32[INDEX_OUT]; \ 387 } \ 521 388 break; \ 522 389 case PS_TYPE_F64: \ 523 390 ((psVector*)VEC_OUT)->data.F64[INDEX_OUT] = ((psVector*)VEC_IN)->data.F64[INDEX_IN]; \ 391 if(INDEX_OUT == 0) { \ 392 validFrom = ((psVector*)VEC_OUT)->data.F64[INDEX_OUT]; \ 393 } \ 394 if(INDEX_OUT == ((psVector*)VEC_OUT)->n-1 ) { \ 395 validTo = ((psVector*)VEC_OUT)->data.F64[INDEX_OUT]; \ 396 } \ 524 397 break; \ 525 398 default: \ … … 527 400 } 528 401 529 530 psLookupTable* psLookupTableRead(psLookupTable *table) 531 { 532 bool typeLine = true; 533 char *line = NULL; 534 char *strType = NULL; 535 char *strValue = NULL; 536 char *linePtr = NULL; 537 psParseErrorType status = PS_PARSE_SUCCESS; 538 psParseErrorType lineStatus = PS_PARSE_SUCCESS; 539 psU64 lineCount = 0; 540 psU64 numRows = 0; 541 psU64 numCols = 0; 542 psU64 failedLines = 0; 543 FILE *fp = NULL; 544 psElemType elemType; 545 psVector *indexVec = NULL; 546 psVector *valuesVec = NULL; 547 psArray *values = NULL; 548 psBool sortIndex = false; 402 psArray *psVectorsReadFromFile(const char *filename, const char *format) 403 { 404 psArray* outputArray = NULL; 405 psVector* colVector = NULL; 406 char* strValue = NULL; 407 char* strNum = NULL; 408 char* line = NULL; 409 char* linePtr = NULL; 410 int numCols = 0; 411 int numRows = 0; 412 FILE* fp = NULL; 413 const char* tempFormat = NULL; 414 psParseErrorType parseStatus = PS_PARSE_SUCCESS; 415 416 // Check for nul file name 417 PS_ASSERT_PTR_NON_NULL(filename,NULL); 418 419 // Parse format string for valid string 420 PS_ASSERT_PTR_NON_NULL(format,NULL); 421 422 // Create temp pointer which can then be used several times 423 tempFormat = format; 424 425 // Create output array and set array elements to zero 426 outputArray = psArrayAlloc(10); 427 outputArray->n = 0; 428 429 // Parse the format string to determine how many vectors 430 // and whether the format string is valid 431 while((strValue=getToken((char**)&tempFormat," ",&parseStatus))) { 432 433 // Check for %d format sub string 434 if(strcmp(strValue,"\%d") == 0 ) { 435 numCols++; 436 colVector = psVectorAlloc(1,PS_TYPE_S32); 437 outputArray = psArrayAdd(outputArray,1,colVector); 438 psFree(colVector); 439 } else if (strcmp(strValue,"\%ld") == 0) { 440 numCols++; 441 colVector = psVectorAlloc(1,PS_TYPE_S64); 442 outputArray = psArrayAdd(outputArray,1,colVector); 443 psFree(colVector); 444 } else if (strcmp(strValue,"\%f") == 0) { 445 numCols++; 446 colVector = psVectorAlloc(1,PS_TYPE_F32); 447 outputArray = psArrayAdd(outputArray,1,colVector); 448 psFree(colVector); 449 } else if (strcmp(strValue,"\%lf") == 0) { 450 numCols++; 451 colVector = psVectorAlloc(1,PS_TYPE_F64); 452 outputArray = psArrayAdd(outputArray,1,colVector); 453 psFree(colVector); 454 } else if (strstr(strValue,"\%*") != 0) { 455 // Don't increase number of columns 456 } else { 457 psError(PS_ERR_BAD_PARAMETER_VALUE,true,"Invalid format specifier"); 458 psFree(strValue); 459 numCols = 0; 460 break; 461 } 462 psFree(strValue); 463 } 464 465 // If the format string was parsed successfully and return numCols the 466 // prepare to open file and read values 467 if(numCols > 0) { 468 469 // Open specified file 470 if((fp=fopen(filename, "r")) == NULL) { 471 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_FILE_NOT_FOUND, 472 filename); 473 psFree(outputArray); 474 return NULL; 475 } else { 476 // Initialize array index 477 int arrayIndex = 0; 478 479 // Create reusable line for continuous read 480 line = (char*)psAlloc(MAX_STRING_LENGTH*sizeof(char)); 481 482 // Loop through file to get numRows, numCols, and column data types 483 while((fgets(line, MAX_STRING_LENGTH, fp) != NULL) && (parseStatus == PS_PARSE_SUCCESS)) { 484 485 // Copy pointer to line for parsing 486 linePtr = line; 487 488 // If line is not a comment or blank, then extract data 489 if(!ignoreLine(linePtr)) { 490 numRows++; 491 492 // Copy format pointer for parsing 493 tempFormat = format; 494 arrayIndex = 0; 495 parseStatus = PS_PARSE_SUCCESS; 496 497 // Loop through format and line strings to get values in text table file 498 while((strValue=getToken((char**)&tempFormat," ",&parseStatus)) && 499 (strNum=getToken((char**)&linePtr," ",&parseStatus)) ) { 500 501 // Set column vector 502 colVector = outputArray->data[arrayIndex]; 503 504 // Set column entries based on format string defining the type 505 if(strcmp(strValue,"\%d") == 0 ) { 506 colVector = psVectorRecycle(colVector, numRows, colVector->type.type); 507 parseValue(colVector,numRows-1,strNum,&parseStatus); 508 arrayIndex++; 509 } else if (strcmp(strValue,"\%ld") == 0) { 510 colVector = psVectorRecycle(colVector, numRows, colVector->type.type); 511 parseValue(colVector,numRows-1,strNum,&parseStatus); 512 arrayIndex++; 513 } else if (strcmp(strValue,"\%f") == 0) { 514 colVector = psVectorRecycle(colVector, numRows, colVector->type.type); 515 parseValue(colVector,numRows-1,strNum,&parseStatus); 516 arrayIndex++; 517 } else if (strcmp(strValue,"\%lf") == 0) { 518 colVector = psVectorRecycle(colVector, numRows, colVector->type.type); 519 parseValue(colVector,numRows-1,strNum,&parseStatus); 520 arrayIndex++; 521 } else if (strstr(strValue,"\%*") != 0) { 522 // Don't increase number of columns 523 } 524 psFree(strValue); 525 psFree(strNum); 526 527 // If the file line was not parsed successful report error and return NULL 528 if(parseStatus != PS_PARSE_SUCCESS) { 529 psError(PS_ERR_UNKNOWN,true,"Parsing text file failed."); 530 fclose(fp); 531 psFree(outputArray); 532 psFree(line); 533 return NULL; 534 } 535 } 536 } // ignore line 537 } 538 539 // Read on the lines in the file - close file pointer 540 fclose(fp); 541 psFree(line); 542 } 543 } else { 544 // Format string parse error detected 545 psError(PS_ERR_UNKNOWN,true,"Format string was not parsed sucessfully"); 546 psFree(outputArray); 547 return NULL; 548 } 549 550 // Return populated array 551 return outputArray; 552 } 553 554 psLookupTable *psLookupTableImport(psLookupTable *table, const psArray *vectors, int indexCol) 555 { 556 psLookupTable* outputTable = NULL; 557 psBool sortNeeded = false; 558 psF64 validTo = 0; 559 psF64 validFrom = 0; 549 560 550 561 // Check for NULL input table 551 562 PS_ASSERT_PTR_NON_NULL(table,NULL); 552 563 553 // Check for input table with NULL file name 554 PS_ASSERT_PTR_NON_NULL(table->fileName,NULL); 555 556 // Open table file specified by table->fileName 557 if((fp=fopen(table->fileName, "r")) == NULL) { 558 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_FILE_NOT_FOUND, 559 table->fileName); 560 return table; 561 } 562 563 // Initialize vector pointers 564 indexVec = table->index; 565 values = table->values = psArrayAlloc(10); 566 values->n = 0; 567 568 // Create reusable line for continuous read 569 line = (char*)psAlloc(MAX_STRING_LENGTH*sizeof(char)); 570 571 // Loop through file to get numRows, numCols, and column data types 572 while((fgets(line, MAX_STRING_LENGTH, fp) != NULL) && (lineStatus == PS_PARSE_SUCCESS)) { 573 574 // Initialize variables for new line 575 linePtr = line; 576 lineCount++; 577 578 // If line is not a comment or blank, then extract data 579 if(!ignoreLine(linePtr)) { 580 581 if(typeLine == true) { 582 583 // Determine column types from first line in data file after comments 584 while((strType=getToken(&linePtr," ",&status))) { 585 numCols++; 586 typeLine = false; 587 if(!strncmp(strType, "psU8", 4)) { 588 elemType = PS_TYPE_U8; 589 } else if(!strncmp(strType, "psS8", 4)) { 590 elemType = PS_TYPE_S8; 591 } else if(!strncmp(strType, "psU16", 5)) { 592 elemType = PS_TYPE_U16; 593 } else if(!strncmp(strType, "psS16", 5)) { 594 elemType = PS_TYPE_S16; 595 } else if(!strncmp(strType, "psU32", 5)) { 596 elemType = PS_TYPE_U32; 597 } else if(!strncmp(strType, "psS32", 5)) { 598 elemType = PS_TYPE_S32; 599 } else if(!strncmp(strType, "psU64", 5)) { 600 elemType = PS_TYPE_U64; 601 } else if(!strncmp(strType, "psS64", 5)) { 602 elemType = PS_TYPE_S64; 603 } else if(!strncmp(strType, "psF32", 5)) { 604 elemType = PS_TYPE_F32; 605 } else if(!strncmp(strType, "psF64", 5)) { 606 elemType = PS_TYPE_F64; 607 } else { 608 status = PS_PARSE_ERROR_TYPE; 609 } 610 611 // Realloc number of columns as you go 612 psVector* vec = psVectorAlloc(0, elemType); 613 if(numCols == 1) { 614 indexVec = vec; 615 } else { 616 psArrayAdd(values,0,vec); 617 psFree(vec); 618 } 619 620 if(status) { 621 printError(lineCount, strValue, status); 622 failedLines++; 623 lineStatus = status; 624 status = PS_PARSE_SUCCESS; 625 } 626 psFree(strType); 627 } 628 } else { 629 // Parse and add values to all columns 630 numRows++; 631 numCols = 0; 632 while((strValue=getToken(&linePtr," ",&status))) { 633 numCols++; 634 635 // Realloc number of rows as you go 636 if(numCols == 1) { 637 sortIndex = false; 638 indexVec = psVectorRecycle(indexVec, numRows, indexVec->type.type); 639 parseValue(indexVec, numRows-1, strValue, &status); 640 } else { 641 valuesVec = values->data[numCols-2]; 642 valuesVec = psVectorRecycle(valuesVec, numRows, valuesVec->type.type); 643 parseValue(valuesVec, numRows-1, strValue, &status); 644 } 645 646 if(status) { 647 printError(lineCount, strValue, status); 648 failedLines++; 649 lineStatus = status; 650 status = PS_PARSE_SUCCESS; 651 } 652 psFree(strValue); 653 } // end while 654 } // end else 655 } // if ignoreLine 656 } // end while 657 658 psFree(line); 659 660 // Set table for return 661 table->numRows = numRows; 662 table->numCols = numCols-1; 663 table->index = indexVec; 664 table->values = values; 665 666 // Set table values to indicate error detected during the read 667 if(lineStatus) { 668 table->numRows = 0; 669 table->numCols = 0; 670 table->validFrom = 0; 671 table->validTo = 0; 672 psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psLookupTable_TABLE_INVALID); 673 } else { 674 // Check if index vector needs to be sorted 675 psVector* sortedIndex = psVectorAlloc(table->numRows,PS_TYPE_U32); 676 sortedIndex = psVectorSortIndex(sortedIndex,table->index); 677 for(psS32 i = 0; i < numRows; i++ ) { 678 if(sortedIndex->data.U32[i] != i) { 679 sortIndex = true; 680 break; 564 // Check for NULL vectors 565 PS_ASSERT_PTR_NON_NULL(vectors,NULL); 566 567 // Check for invalid index column 568 if(indexCol < 0 ) { 569 psError(PS_ERR_BAD_PARAMETER_VALUE,true,"Index column cannot be less than zero"); 570 return NULL; 571 } 572 573 psVector* indexColumnVector = vectors->data[indexCol]; 574 psS32 numRows = indexColumnVector->n; 575 psS32 numCols = vectors->n; 576 577 // Check if array is sorted on the index column 578 psVector* sortedIndex = psVectorAlloc(numRows,PS_TYPE_U32); 579 sortedIndex = psVectorSortIndex(sortedIndex,indexColumnVector); 580 for(psS32 i = 0; i < numRows; i++ ) { 581 if(sortedIndex->data.U32[i] != i) { 582 sortNeeded = true; 583 break; 584 } 585 } 586 587 // Check if it is necessary to sort value vectors 588 if(sortNeeded) { 589 // Allocate new array to contain sorted vectors 590 psArray* newValueArray = psArrayAlloc(numCols); 591 for(psS32 j = 0; j < numCols; j++) { 592 psS32 type = ((psVector*)(vectors->data[j]))->type.type; 593 newValueArray->data[j] = psVectorAlloc(numRows,type); 594 } 595 596 // Populate new array/vectors with sorted values 597 for(psS32 i = 0; i < numRows; i++) { 598 // Populate new index vector 599 psU32 sortIndex = sortedIndex->data.U32[i]; 600 // For every column populate new value vectors 601 for(psS32 j=0; j < numCols; j++) { 602 COPY_VECTOR_VALUES(newValueArray->data[j],i,vectors->data[j], sortIndex) 681 603 } 682 604 } 683 // Check if it is necessary to sort value vectors 684 if(sortIndex) { 685 // Allocate new index vector 686 psVector* newIndexVector = psVectorAlloc(numRows,indexVec->type.type); 687 // Allocate new value vectors 688 psArray* newValueArray = psArrayAlloc(numCols-1); 689 for(psS32 j = 0; j < numCols-1; j++) { 690 psS32 type = ((psVector*)(table->values->data[j]))->type.type; 691 newValueArray->data[j] = psVectorAlloc(numRows,type); 692 } 693 for(psS32 i = 0; i < numRows; i++) { 694 // Populate new index vector 695 psU32 sortIndex = sortedIndex->data.U32[i]; 696 COPY_VECTOR_VALUES(newIndexVector,i, indexVec,sortIndex) 697 // For every column populate new value vectors 698 for(psS32 j=0; j < numCols-1; j++) { 699 COPY_VECTOR_VALUES(newValueArray->data[j],i,table->values->data[j], sortIndex) 700 } 701 } 702 // Free old index vector 703 psFree(table->index); 704 // Free old value vectors 705 psFree(table->values); 706 // Assign new vector value to table 707 table->index = newIndexVector; 708 // Assign new value vectors to table array 709 table->values = newValueArray; 605 // Assign new vector value to table 606 table->index = newValueArray->data[indexCol]; 607 // Assign new value vectors to table array 608 table->values = newValueArray; 609 // Assign indexCol 610 table->indexCol = indexCol; 611 // Assign validTo and validFrom values 612 UPDATE_VALID_TO_FROM(table) 613 614 // Set return value 615 outputTable = table; 616 617 } else { 618 // Index vector is already sorted 619 // Assign array vector specified by indexCol to table index vector and increment memory ref 620 table->index = vectors->data[indexCol]; 621 table->values = (psArray*)vectors; 622 psMemIncrRefCounter((psArray*)vectors); 623 624 // Assign indexCol 625 table->indexCol = indexCol; 626 // Assign validTo and validFrom values 627 UPDATE_VALID_TO_FROM(table); 628 629 // Set return value 630 outputTable = table; 631 } 632 633 // Free sort vector 634 psFree(sortedIndex); 635 636 return outputTable; 637 } 638 639 psS32 psLookupTableRead(psLookupTable* table) 640 { 641 psS32 numRows = 0; 642 psArray* vectors = NULL; 643 psLookupTable* outTable = NULL; 644 645 // Check if the input table is NULL then return 0 646 PS_ASSERT_PTR_NON_NULL(table,0); 647 648 // Read vectors from file specified in table 649 vectors = psVectorsReadFromFile(table->filename, table->format); 650 651 // Check for valid array after reading from file 652 if(vectors != NULL) { 653 654 // Import vector into table 655 outTable = psLookupTableImport(table, vectors, table->indexCol); 656 657 psFree(vectors); 658 659 // Update the number of rows read if outTable is not NULL 660 if(outTable != NULL) { 661 numRows = table->index->n; 710 662 } 711 psFree(sortedIndex); 712 // Update the validTo and validFrom 713 UPDATE_VALID_TO_FROM(table) 714 } 715 716 fclose(fp); 717 718 return table; 663 } 664 665 // Return the number of lines read 666 return numRows; 719 667 } 720 668 … … 756 704 } 757 705 758 759 #define CHECK_LOWER_UPPER_BOUND(TABLE,INDEX,COLUMN) \ 760 switch (TABLE->index->type.type) { \ 761 case PS_TYPE_U8: \ 762 if( (psU8)index < TABLE->index->data.U8[0] ) { \ 763 *status = PS_LOOKUP_PAST_TOP; \ 764 } \ 765 if( (psU8)index > TABLE->index->data.U8[numRows-1]) { \ 766 *status = PS_LOOKUP_PAST_BOTTOM; \ 767 } \ 768 break; \ 769 case PS_TYPE_U16: \ 770 if( (psU16)index < TABLE->index->data.U16[0] ) { \ 771 *status = PS_LOOKUP_PAST_TOP; \ 772 } \ 773 if( (psU16)index > TABLE->index->data.U16[numRows-1] ) { \ 774 *status = PS_LOOKUP_PAST_BOTTOM; \ 775 } \ 776 break; \ 777 case PS_TYPE_U32: \ 778 if( (psU32)index < TABLE->index->data.U32[0]) { \ 779 *status = PS_LOOKUP_PAST_TOP; \ 780 } \ 781 if ( (psU32)index > TABLE->index->data.U32[numRows-1] ) { \ 782 *status = PS_LOOKUP_PAST_BOTTOM; \ 783 } \ 784 break; \ 785 case PS_TYPE_U64: \ 786 if( (psU64)index < TABLE->index->data.U64[0] ) { \ 787 *status = PS_LOOKUP_PAST_TOP; \ 788 } \ 789 if( (psU64)index > TABLE->index->data.U64[numRows-1] ) { \ 790 *status = PS_LOOKUP_PAST_BOTTOM; \ 791 } \ 792 break; \ 793 case PS_TYPE_S8: \ 794 if( (psS8)index < TABLE->index->data.S8[0] ) { \ 795 *status = PS_LOOKUP_PAST_TOP; \ 796 } \ 797 if( (psS8)index > TABLE->index->data.S8[numRows-1] ) { \ 798 *status = PS_LOOKUP_PAST_BOTTOM; \ 799 } \ 800 break; \ 801 case PS_TYPE_S16: \ 802 if( (psS16)index < TABLE->index->data.S16[0] ) { \ 803 *status = PS_LOOKUP_PAST_TOP; \ 804 } \ 805 if( (psS16)index > TABLE->index->data.S16[numRows-1] ) { \ 806 *status = PS_LOOKUP_PAST_BOTTOM; \ 807 } \ 808 break; \ 809 case PS_TYPE_S32: \ 810 if( (psS32)index < TABLE->index->data.S32[0] ) { \ 811 *status = PS_LOOKUP_PAST_TOP; \ 812 } \ 813 if( (psS32)index > TABLE->index->data.S32[numRows-1] ) { \ 814 *status = PS_LOOKUP_PAST_BOTTOM; \ 815 } \ 816 break; \ 817 case PS_TYPE_S64: \ 818 if( (psS64)index < TABLE->index->data.S64[0] ) { \ 819 *status = PS_LOOKUP_PAST_TOP; \ 820 } \ 821 if( (psS64)index > TABLE->index->data.S64[numRows-1] ) { \ 822 *status = PS_LOOKUP_PAST_BOTTOM; \ 823 } \ 824 break; \ 825 case PS_TYPE_F32: \ 826 if( (psF32)index < TABLE->index->data.F32[0] ) { \ 827 *status = PS_LOOKUP_PAST_TOP; \ 828 } \ 829 if( (psF32)index > TABLE->index->data.F32[numRows-1] ) { \ 830 *status = PS_LOOKUP_PAST_BOTTOM; \ 831 } \ 832 break; \ 833 case PS_TYPE_F64: \ 834 if( index < TABLE->index->data.F64[0] ) { \ 835 *status = PS_LOOKUP_PAST_TOP; \ 836 } \ 837 if( index > TABLE->index->data.F64[numRows-1] ) { \ 838 *status = PS_LOOKUP_PAST_BOTTOM; \ 839 } \ 840 break; \ 841 default: \ 842 *status = PS_LOOKUP_ERROR; \ 843 return NAN; \ 844 break; \ 845 } \ 846 if(*status == PS_LOOKUP_PAST_TOP) { \ 847 CONVERT_VALUE_TO_F64(((psVector*)(TABLE->values->data[COLUMN])),0,out) \ 848 return out; \ 849 } else if (*status == PS_LOOKUP_PAST_BOTTOM) { \ 850 CONVERT_VALUE_TO_F64(((psVector*)(TABLE->values->data[COLUMN])),numRows-1,out) \ 851 return out; \ 852 } 853 854 855 psF64 psLookupTableInterpolate(psLookupTable *table, psF64 index, psU64 column, psLookupStatusType *status) 706 #define CHECK_LOWER_UPPER_BOUND(TABLE,INDEX,COLUMN) \ 707 switch (TABLE->index->type.type) { \ 708 case PS_TYPE_S32: \ 709 if( (psS32)index < TABLE->index->data.S32[0] ) { \ 710 return NAN; \ 711 } \ 712 if( (psS32)index > TABLE->index->data.S32[numRows-1] ) { \ 713 return NAN; \ 714 } \ 715 break; \ 716 case PS_TYPE_S64: \ 717 if( (psS64)index < TABLE->index->data.S64[0] ) { \ 718 return NAN; \ 719 } \ 720 if( (psS64)index > TABLE->index->data.S64[numRows-1] ) { \ 721 return NAN; \ 722 } \ 723 break; \ 724 case PS_TYPE_F32: \ 725 if( (psF32)index < TABLE->index->data.F32[0] ) { \ 726 return NAN; \ 727 } \ 728 if( (psF32)index > TABLE->index->data.F32[numRows-1] ) { \ 729 return NAN; \ 730 } \ 731 break; \ 732 case PS_TYPE_F64: \ 733 if( index < TABLE->index->data.F64[0] ) { \ 734 return NAN; \ 735 } \ 736 if( index > TABLE->index->data.F64[numRows-1] ) { \ 737 return NAN; \ 738 } \ 739 break; \ 740 default: \ 741 return NAN; \ 742 break; \ 743 } 744 745 psF64 psLookupTableInterpolate(const psLookupTable *table, psF64 index, psS32 column) 856 746 { 857 747 psU64 hiIdx = 0; … … 867 757 psArray *values = NULL; 868 758 869 // Error checks 870 // Set status to error prior to check since if checks fails it will immediately return 871 PS_ASSERT_PTR_NON_NULL(status,NAN); 872 *status = PS_LOOKUP_ERROR; 759 // Check for NULL table 873 760 PS_ASSERT_PTR_NON_NULL(table,NAN); 761 874 762 indexVec = table->index; 875 763 values = table->values; 876 numRows = table-> numRows;877 numCols = table-> numCols;764 numRows = table->index->n; 765 numCols = table->values->n; 878 766 PS_ASSERT_PTR_NON_NULL(indexVec,NAN); 879 767 PS_ASSERT_PTR_NON_NULL(values,NAN); … … 884 772 valuesVec = (psVector*)values->data[column]; 885 773 PS_ASSERT_PTR_NON_NULL(indexVec,NAN); 886 887 // Set status to success since it passed all parameter checks888 *status = PS_LOOKUP_SUCCESS;889 774 890 775 // Verify the index is within the bounds of the table … … 898 783 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 899 784 PS_ERRORTEXT_psLookupTable_INTERPOLATE_HIGH, hiIdx); 900 *status = PS_LOOKUP_ERROR;901 785 return NAN; 902 786 } … … 909 793 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 910 794 PS_ERRORTEXT_psLookupTable_INTERPOLATE_LOW, loIdx); 911 *status = PS_LOOKUP_ERROR;912 795 return NAN; 913 796 } … … 919 802 if(fabs(denom) < FLT_EPSILON) { 920 803 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psLookupTable_DIVIDE_BY_ZERO); 921 *status = PS_LOOKUP_ERROR;922 804 return NAN; 923 805 } else { … … 934 816 } 935 817 936 psVector* psLookupTableInterpolateAll(psLookupTable *table, psF64 index, psVector *stats) 937 { 938 psU64 i = 0; 818 psVector* psLookupTableInterpolateAll(psLookupTable *table, psF64 index) 819 { 939 820 psU64 numCols = 0; 940 821 psVector *outVector = NULL; 941 psLookupStatusType status = PS_LOOKUP_SUCCESS;942 822 943 823 // Error checks 944 824 PS_ASSERT_PTR_NON_NULL(table,NULL); 945 PS_ASSERT_PTR_NON_NULL(stats,NULL); 946 numCols = table->numCols; 825 numCols = table->values->n; 947 826 PS_ASSERT_INT_UNEQUAL(numCols, 0,NULL); 948 827 949 outVector = psVectorAlloc(numCols+1, PS_TYPE_F64); 828 // Create output vector 829 outVector = psVectorAlloc(numCols, PS_TYPE_F64); 950 830 951 831 // Fill vectors with results and status of results 952 for(i=0; i<numCols; i++) { 953 outVector->data.F64[i] = psLookupTableInterpolate(table, index, i, &status); 954 stats->data.U32[i] = status; 832 for(psU64 i=0; i<numCols; i++) { 833 outVector->data.F64[i] = psLookupTableInterpolate(table, index, i); 834 if(isnan(outVector->data.F64[i])) { 835 // Free allocated vector 836 psFree(outVector); 837 outVector = NULL; 838 // Break out of loop since error detected 839 break; 840 } 955 841 } 956 842 -
trunk/psLib/src/types/psLookupTable.h
r3684 r4050 7 7 * @author Ross Harman, MHPCC 8 8 * 9 * @version $Revision: 1. 5$ $Name: not supported by cvs2svn $10 * @date $Date: 2005-0 4-08 17:58:57$9 * @version $Revision: 1.6 $ $Name: not supported by cvs2svn $ 10 * @date $Date: 2005-05-31 21:46:56 $ 11 11 * 12 12 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii … … 28 28 typedef struct 29 29 { 30 const char *fileName; ///< Name of file with table 31 psU64 numRows; ///< Number of table rows 32 psU64 numCols; ///< Number of table columns 30 const char *filename; ///< Name of file with table 31 const char *format; ///< scanf-like format string for file 32 unsigned int indexCol; ///< Column of the index vector (starting at zero) 33 psVector *index; ///< Vector of independent index values 34 psArray *values; ///< Array of dependent table values corresponding to index values 33 35 psF64 validFrom; ///< Lower bound for rable read 34 36 psF64 validTo; ///< Upper bound for table read 35 psVector *index; ///< Vector of independent index values36 psArray *values; ///< Array of dependent table values corresponding to index values37 37 } 38 38 psLookupTable; … … 69 69 psLookupTable* psLookupTableAlloc( 70 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 71 const char *format, ///< scanf-like format string 72 int indexCol ///< Column of the index vector (starting at zero) 73 ); 74 75 /** Read vectors from file 76 * 77 * Read numeric vectors from ASCII text file 78 * 79 * @return psArray* New array of psVectors corresponding to the columns of the table 80 */ 81 psArray *psVectorsReadFromFile( 82 const char* filename, ///< File to be read 83 const char* format ///< scanf-like format string 84 ); 85 86 /** Import arrays of vectors into a table 87 * 88 * Import array of vectors read from text file into a table structure 89 * 90 * @return psLookupTable* Lookup table structure with array vector data 91 */ 92 psLookupTable *psLookupTableImport( 93 psLookupTable *table, ///< Lookup table into which to import 94 const psArray *vectors, ///< Array of vectors 95 int indexCol ///< Index of the index vector in the array of vectors 73 96 ); 74 97 … … 77 100 * Reads a lookup table and fills corresponding psLookupTable struct. 78 101 * 79 * @return ps LookupTable* New psLookupTable struct.102 * @return psS32 Number of valid lines read 80 103 */ 81 ps LookupTable*psLookupTableRead(104 psS32 psLookupTableRead( 82 105 psLookupTable *table ///< Table to read 83 106 ); … … 91 114 */ 92 115 psF64 psLookupTableInterpolate( 93 psLookupTable *table,///< Table with data116 const psLookupTable *table, ///< Table with data 94 117 psF64 index, ///< Value to be interpolated 95 psU64 column, ///< Column in table to be interpolated 96 psLookupStatusType *status ///< Status of lookup 118 psS32 column ///< Column in table to be interpolated 97 119 ); 98 120 … … 106 128 psVector* psLookupTableInterpolateAll( 107 129 psLookupTable *table, ///< Table with data 108 psF64 index, ///< Value to be interpolated 109 psVector *stats ///< Vector of status for each lookup 130 psF64 index ///< Value to be interpolated 110 131 ); 111 132
Note:
See TracChangeset
for help on using the changeset viewer.
