1 #if 0 2 /* tdlpack is no longer supported by GDAL */ 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <string.h> 6 #include <math.h> 7 #include "tdlpack.h" 8 #include "myerror.h" 9 #include "meta.h" 10 #include "tendian.h" 11 #include "myassert.h" 12 #include "myutil.h" 13 #include "clock.h" 14 #ifdef MEMWATCH 15 #include "memwatch.h" 16 #endif 17 18 #define GRIB_UNSIGN_INT3(a,b,c) ((a<<16)+(b<<8)+c) 19 #define GRIB_UNSIGN_INT2(a,b) ((a<<8)+b) 20 #define GRIB_SIGN_INT3(a,b,c) ((1-(int) ((unsigned) (a & 0x80) >> 6)) * (int) (((a & 127) << 16)+(b<<8)+c)) 21 #define GRIB_SIGN_INT2(a,b) ((1-(int) ((unsigned) (a & 0x80) >> 6)) * (int) (((a & 0x7f) << 8) + b)) 22 23 #ifdef unused_by_GDAL 24 /* *INDENT-OFF* */ 25 static const TDLP_TableType TDLP_B_Table[5] = { 26 /* 0 */ {0, "Continuous field"}, 27 /* 1 */ {1, "Point Binary - cumulative from above"}, 28 /* 2 */ {2, "Point Binary - cumulative from below"}, 29 /* 3 */ {3, "Point Binary - discrete"}, 30 /* 4 */ {5, "Grid Binary - "}, 31 }; 32 33 static const TDLP_TableType TDLP_DD_Table[9] = { 34 /* 0 */ {0, "Independent of model"}, 35 /* 1 */ {6, "NGM model"}, 36 /* 2 */ {7, "Eta model"}, 37 /* 3 */ {8, "AVN model"}, 38 /* 4 */ {9, "MRF model"}, 39 /* 5 */ {79, "NDFD forecast"}, 40 /* 6 */ {80, "MOS AEV forecast"}, 41 /* 7 */ {81, "Local AEV Firecasts"}, 42 /* 8 */ {82, "Obs matching AEV Forecasts"}, 43 }; 44 45 static const TDLP_TableType TDLP_V_Table[4] = { 46 /* 0 */ {0, "No vertical processing"}, 47 /* 1 */ {1, "Difference Levels (UUUU - LLLL)"}, 48 /* 2 */ {2, "Sum Levels (UUUU + LLLL)"}, 49 /* 3 */ {3, "Mean Levels (UUUU + LLLL) / 2."}, 50 }; 51 52 static const TDLP_TableType TDLP_T_Table[3] = { 53 /* 0 */ {0, "No nolinear transform"}, 54 /* 1 */ {1, "Square transform"}, 55 /* 2 */ {2, "Square root transform"}, 56 }; 57 58 static const TDLP_TableType TDLP_Oper_Table[9] = { 59 /* 0 */ {0, "No time operator"}, 60 /* 1 */ {1, "Mean (Var 1, Var 2)"}, 61 /* 2 */ {2, "Difference (Var 1 - Var 2)"}, 62 /* 3 */ {3, "Maximum (Var 1, Var 2)"}, 63 /* 4 */ {4, "Minimum (Var 1, Var 2)"}, 64 /* 5 */ {5, "Mean (Var 1, Var 2)"}, 65 /* 6 */ {6, "Difference (Var 2 - Var 1)"}, 66 /* 7 */ {7, "Maximum (Var 1, Var 2)"}, 67 /* 8 */ {8, "Minimum (Var 1, Var 2)"}, 68 }; 69 70 static const TDLP_TableType TDLP_I_Table[4] = { 71 /* 0 */ {0, "No interpolation"}, 72 /* 1 */ {1, "Bi-quadratic interpolation"}, 73 /* 2 */ {2, "Bi-linear interpolation"}, 74 /* 3 */ {3, "Special interpolation for QPF"}, 75 }; 76 77 static const TDLP_TableType TDLP_S_Table[6] = { 78 /* 0 */ {0, "No smoothing"}, 79 /* 1 */ {1, "5-point smoothing"}, 80 /* 2 */ {2, "9-point smoothing"}, 81 /* 3 */ {3, "25-point smoothing"}, 82 /* 4 */ {4, "81-point smoothing"}, 83 /* 5 */ {5, "168-point smoothing"}, 84 }; 85 /* *INDENT-ON* */ 86 #endif 87 88 typedef struct { 89 sInt4 min; /* Minimum value in a group. Can cause problems if 90 * this is unsigned. */ 91 uChar bit; /* # of bits in a group. 2^31 is the largest # of 92 * bits that can be used to hold # of bits in a 93 * group. However, the # of bits for a number can't 94 * be > 64, and is probably < 32, so bit is < 6 and 95 * probably < 5. */ 96 uInt4 num; /* number of values in the group. May need this to be 97 * signed. */ 98 sInt4 max; /* Max value for the group */ 99 uInt4 start; /* index in Data where group starts. */ 100 uChar f_trySplit; /* Flag, if we have tried to split this group. */ 101 uChar f_tryShift; /* Flag, if we have tried to shift this group. */ 102 } TDLGroupType; 103 104 /***************************************************************************** 105 * ReadTDLPSect1() -- 106 * 107 * Arthur Taylor / MDL 108 * 109 * PURPOSE 110 * Parses the TDLP "Product Definition Section" or section 1, filling out 111 * the pdsMeta data structure. 112 * 113 * ARGUMENTS 114 * pds = The compressed part of the message dealing with "PDS". (Input) 115 * gribLen = The total length of the TDLP message. (Input) 116 * curLoc = Current location in the TDLP message. (Output) 117 * pdsMeta = The filled out pdsMeta data structure. (Output) 118 * f_gds = boolean if there is a Grid Definition Section. (Output) 119 * f_bms = boolean if there is a Bitmap Section. (Output) 120 * DSF = Decimal Scale Factor for unpacking the data. (Output) 121 * BSF = Binary Scale Factor for unpacking the data. (Output) 122 * 123 * FILES/DATABASES: None 124 * 125 * RETURNS: int (could use errSprintf()) 126 * 0 = OK 127 * -1 = gribLen is too small. 128 * 129 * HISTORY 130 * 10/2004 Arthur Taylor (MDL): Created. 131 * 132 * NOTES 133 ***************************************************************************** 134 */ 135 static int ReadTDLPSect1 (uChar *pds, sInt4 tdlpLen, sInt4 *curLoc, 136 pdsTDLPType * pdsMeta, char *f_gds, char *f_bms, 137 short int *DSF, short int *BSF) 138 { 139 char sectLen; /* Length of section. */ 140 sInt4 li_temp; /* Temporary variable. */ 141 int W, XXXX, YY; /* Helps with Threshold calculation. */ 142 int year, t_year; /* The reference year, and a consistency test */ 143 uChar month, t_month; /* The reference month, and a consistency test */ 144 uChar day, t_day; /* The reference day, and a consistency test */ 145 uChar hour, t_hour; /* The reference hour, and a consistency test */ 146 uChar min; /* The reference minute */ 147 uShort2 project_hr; /* The projection in hours. */ 148 sInt4 tau; /* Used to cross check project_hr */ 149 int lenPL; /* Length of the Plain Language descriptor. */ 150 151 sectLen = *(pds++); 152 *curLoc += sectLen; 153 if (*curLoc > tdlpLen) { 154 errSprintf ("Ran out of data in PDS (TDLP Section 1)\n"); 155 return -1; 156 } 157 if( sectLen > 71 ) { 158 errSprintf ("TDLP Section 1 is too big.\n"); 159 return -1; 160 } 161 if (sectLen < 39) { 162 errSprintf ("TDLP Section 1 is too small.\n"); 163 return -1; 164 } 165 *f_bms = (GRIB2BIT_7 & *pds) ? 1 : 0; 166 *f_gds = (GRIB2BIT_8 & *pds) ? 1 : 0; 167 pds++; 168 year = GRIB_UNSIGN_INT2 (*pds, pds[1]); 169 pds += 2; 170 month = *(pds++); 171 day = *(pds++); 172 hour = *(pds++); 173 min = *(pds++); 174 MEMCPY_BIG (&li_temp, pds, sizeof (sInt4)); 175 pds += 4; 176 t_year = li_temp / 1000000; 177 li_temp -= t_year * 1000000; 178 t_month = li_temp / 10000; 179 li_temp -= t_month * 10000; 180 t_day = li_temp / 100; 181 t_hour = li_temp - t_day * 100; 182 if ((t_year != year) || (t_month != month) || (t_day != day) || 183 (t_hour != hour)) { 184 errSprintf ("Error Inconsistent Times in ReadTDLPSect1.\n"); 185 return -1; 186 } 187 if (ParseTime (&(pdsMeta->refTime), year, month, day, hour, min, 0) != 0) { 188 preErrSprintf ("Error In call to ParseTime in ReadTDLPSect1.\n"); 189 return -1; 190 } 191 MEMCPY_BIG (&(li_temp), pds, sizeof (sInt4)); 192 pds += 4; 193 pdsMeta->ID1 = li_temp; 194 pdsMeta->CCC = li_temp / 1000000; 195 li_temp -= pdsMeta->CCC * 1000000; 196 pdsMeta->FFF = li_temp / 1000; 197 li_temp -= pdsMeta->FFF * 1000; 198 pdsMeta->B = li_temp / 100; 199 pdsMeta->DD = li_temp - pdsMeta->B * 100; 200 MEMCPY_BIG (&(li_temp), pds, sizeof (sInt4)); 201 pds += 4; 202 pdsMeta->ID2 = li_temp; 203 pdsMeta->V = li_temp / 100000000; 204 li_temp -= pdsMeta->V * 100000000; 205 pdsMeta->LLLL = li_temp / 10000; 206 pdsMeta->UUUU = li_temp - pdsMeta->LLLL * 10000; 207 MEMCPY_BIG (&(li_temp), pds, sizeof (sInt4)); 208 pds += 4; 209 pdsMeta->ID3 = li_temp; 210 pdsMeta->T = li_temp / 100000000; 211 li_temp -= pdsMeta->T * 100000000; 212 pdsMeta->RR = li_temp / 1000000; 213 li_temp -= pdsMeta->RR * 1000000; 214 pdsMeta->Oper = li_temp / 100000; 215 li_temp -= pdsMeta->Oper * 100000; 216 pdsMeta->HH = li_temp / 1000; 217 pdsMeta->ttt = li_temp - pdsMeta->HH * 1000; 218 MEMCPY_BIG (&(li_temp), pds, sizeof (sInt4)); 219 pds += 4; 220 pdsMeta->ID4 = li_temp; 221 W = li_temp / 1000000000; 222 li_temp -= W * 1000000000; 223 XXXX = li_temp / 100000; 224 li_temp -= XXXX * 100000; 225 if (W) { 226 XXXX = -1 * XXXX; 227 } 228 YY = li_temp / 1000; 229 li_temp -= YY * 1000; 230 if (YY >= 50) { 231 YY = -1 * (YY - 50); 232 } 233 pdsMeta->thresh = (XXXX / 10000.) * pow (10.0, YY); 234 pdsMeta->I = li_temp / 100; 235 li_temp -= pdsMeta->I * 100; 236 pdsMeta->S = li_temp / 10; 237 pdsMeta->G = li_temp - pdsMeta->S * 10; 238 project_hr = GRIB_UNSIGN_INT2 (*pds, pds[1]); 239 tau = pdsMeta->ID3 - ((pdsMeta->ID3 / 1000) * 1000); 240 if (tau != project_hr) { 241 printf ("Warning: Inconsistent Projections in hours in " 242 "ReadTDLPSect1 (%d vs %d)\n", tau, project_hr); 243 /* 244 errSprintf ("Warning: Inconsistent Projections in hours in " 245 "ReadTDLPSect1 (%ld vs %d)\n", tau, project_hr); 246 */ 247 project_hr = tau; 248 /* return -1; */ 249 } 250 pds += 2; 251 pdsMeta->project = project_hr * 3600 + (*(pds++)) * 60; 252 pdsMeta->procNum = (*(pds++)); 253 pdsMeta->seqNum = (*(pds++)); 254 *DSF = (*pds > 128) ? 128 - (*(pds++)) : (*(pds++)); 255 *BSF = (*pds > 128) ? 128 - (*(pds++)) : (*(pds++)); 256 if ((*pds != 0) || (pds[1] != 0) || (pds[2] != 0)) { 257 errSprintf ("Error Reserved was not set to 0 in ReadTDLPSect1.\n"); 258 return -1; 259 } 260 pds += 3; 261 lenPL = (*(pds++)); 262 if (sectLen - lenPL != 39) { 263 errSprintf ("Error sectLen(%d) - lenPL(%d) != 39 in ReadTDLPSect1.\n", 264 sectLen, lenPL); 265 return -1; 266 } 267 if (lenPL > 32) { 268 lenPL = 32; 269 } 270 strncpy (pdsMeta->Descriptor, (char *) pds, lenPL); 271 pdsMeta->Descriptor[lenPL] = '\0'; 272 strTrim (pdsMeta->Descriptor); 273 return 0; 274 } 275 276 #ifdef unused_by_GDAL 277 /***************************************************************************** 278 * TDLP_TableLookUp() -- 279 * 280 * Arthur Taylor / MDL 281 * 282 * PURPOSE 283 * To look up TDL Ids information in a given table. 284 * 285 * ARGUMENTS 286 * table = The Table to look up the Id in. (Input) 287 * tableLen = The length of the Table. (Input) 288 * index = The index into the Table. (Input) 289 * 290 * FILES/DATABASES: None 291 * 292 * RETURNS: char * 293 * Returns the meta data that is associated with index in the table. 294 * 295 * HISTORY 296 * 10/2004 Arthur Taylor (MDL): Created. 297 * 298 * NOTES 299 ***************************************************************************** 300 */ 301 static const char *TDLP_TableLookUp(const TDLP_TableType * table, int tableLen, 302 int index) 303 { 304 int i; /* Loop counter. */ 305 306 for (i = 0; i < tableLen; i++) { 307 if (table[i].index == index) 308 return (table[i].data); 309 } 310 return "Unknown"; 311 } 312 313 /***************************************************************************** 314 * PrintPDS_TDLP() -- 315 * 316 * Arthur Taylor / MDL 317 * 318 * PURPOSE 319 * To generate the message for the Product Definition Sections of the TDLP 320 * Message. 321 * 322 * ARGUMENTS 323 * pds = The TDLP Product Definition Section to print. (Input) 324 * 325 * FILES/DATABASES: None 326 * 327 * RETURNS: void 328 * 329 * HISTORY 330 * 10/2004 Arthur Taylor (MDL): Created. 331 * 332 * NOTES 333 ***************************************************************************** 334 */ 335 void PrintPDS_TDLP (pdsTDLPType * pds) 336 { 337 char buffer[25]; /* Stores format of pds1->refTime. */ 338 339 /* 340 strftime (buffer, 25, "%m/%d/%Y %H:%M:%S UTC", gmtime (&(pds->refTime))); 341 */ 342 Clock_Print (buffer, 25, pds->refTime, "%m/%d/%Y %H:%M:%S UTC", 0); 343 344 Print ("PDS-TDLP", "Reference Time", Prt_S, buffer); 345 Print ("PDS-TDLP", "Plain Language", Prt_S, pds->Descriptor); 346 snprintf(buffer, sizeof(buffer), "%09d", pds->ID1); 347 Print ("PDS-TDLP", "ID 1", Prt_S, buffer); 348 snprintf(buffer, sizeof(buffer), "%09d", pds->ID2); 349 Print ("PDS-TDLP", "ID 2", Prt_S, buffer); 350 snprintf(buffer, sizeof(buffer), "%09d", pds->ID3); 351 Print ("PDS-TDLP", "ID 3", Prt_S, buffer); 352 Print ("PDS-TDLP", "ID 4", Prt_D, pds->ID4); 353 Print ("PDS-TDLP", "Model or Process Number", Prt_D, pds->procNum); 354 Print ("PDS-TDLP", "Sequence Number", Prt_D, pds->seqNum); 355 356 snprintf(buffer, sizeof(buffer), "%03d", pds->CCC); 357 Print ("PDS-TDLP", "ID1-CCC", Prt_S, buffer); 358 snprintf(buffer, sizeof(buffer), "%03d", pds->FFF); 359 Print ("PDS-TDLP", "ID1-FFF", Prt_S, buffer); 360 Print ("PDS-TDLP", "ID1-B", Prt_DS, pds->B, 361 TDLP_TableLookUp (TDLP_B_Table, sizeof (TDLP_B_Table), pds->B)); 362 snprintf(buffer, sizeof(buffer), "%02d", pds->DD); 363 Print ("PDS-TDLP", "ID1-DD", Prt_SS, buffer, 364 TDLP_TableLookUp (TDLP_DD_Table, sizeof (TDLP_DD_Table), pds->DD)); 365 366 Print ("PDS-TDLP", "ID2-V", Prt_DS, pds->V, 367 TDLP_TableLookUp (TDLP_V_Table, sizeof (TDLP_V_Table), pds->V)); 368 snprintf(buffer, sizeof(buffer), "%04d", pds->LLLL); 369 Print ("PDS-TDLP", "ID2-LLLL", Prt_S, buffer); 370 snprintf(buffer, sizeof(buffer), "%04d", pds->UUUU); 371 Print ("PDS-TDLP", "ID2-UUUU", Prt_S, buffer); 372 373 if (pds->Oper != 0) { 374 Print ("PDS-TDLP", "ID3-T", Prt_DS, pds->T, 375 TDLP_TableLookUp (TDLP_T_Table, sizeof (TDLP_T_Table), pds->T)); 376 snprintf(buffer, sizeof(buffer), "%02d", pds->RR); 377 Print ("PDS-TDLP", "ID3-RR", Prt_SS, buffer, 378 "Run time offset in hours"); 379 Print ("PDS-TDLP", "ID3-Oper", Prt_DS, pds->Oper, 380 TDLP_TableLookUp (TDLP_Oper_Table, sizeof (TDLP_Oper_Table), 381 pds->Oper)); 382 snprintf(buffer, sizeof(buffer), "%02d", pds->HH); 383 Print ("PDS-TDLP", "ID3-HH", Prt_SS, buffer, 384 "Number of hours between variables"); 385 } else { 386 Print ("PDS-TDLP", "ID3-Oper", Prt_DS, pds->Oper, 387 TDLP_TableLookUp (TDLP_Oper_Table, sizeof (TDLP_Oper_Table), 388 pds->Oper)); 389 } 390 snprintf(buffer, sizeof(buffer), "%03d", pds->ttt); 391 Print ("PDS-TDLP", "ID3-ttt", Prt_SS, buffer, "Forecast Projection"); 392 393 Print ("PDS-TDLP", "ID4-thresh", Prt_F, pds->thresh); 394 Print ("PDS-TDLP", "ID4-I", Prt_DS, pds->I, 395 TDLP_TableLookUp (TDLP_I_Table, sizeof (TDLP_I_Table), pds->I)); 396 Print ("PDS-TDLP", "ID4-S", Prt_DS, pds->S, 397 TDLP_TableLookUp (TDLP_S_Table, sizeof (TDLP_S_Table), pds->S)); 398 Print ("PDS-TDLP", "ID4-G", Prt_D, pds->G); 399 } 400 #endif // unused_by_GDAL 401 402 /***************************************************************************** 403 * TDLP_ElemSurfUnit() -- 404 * 405 * Arthur Taylor / MDL 406 * 407 * PURPOSE 408 * Deal with element name, unit, and comment for TDLP items. Also deals 409 * with the surface information stored in ID2. 410 * 411 * ARGUMENTS 412 * pds = The TDLP Product Definition Section to parse. (Input) 413 * element = The resulting element name. (Output) 414 * unitName = The resulting unit name. (Output) 415 * comment = The resulting comment. (Output) 416 * shortFstLevel = The resulting short forecast level. (Output) 417 * longFstLevel = The resulting long forecast level. (Output) 418 * 419 * FILES/DATABASES: None 420 * 421 * RETURNS: void 422 * 423 * HISTORY 424 * 10/2004 Arthur Taylor (MDL): Created. 425 * 426 * NOTES 427 ***************************************************************************** 428 */ 429 static void TDLP_ElemSurfUnit (pdsTDLPType * pds, char **element, 430 char **unitName, char **comment, 431 char **shortFstLevel, char **longFstLevel) 432 { 433 char *ptr; /* Help guess unitName, and clean the elemName. */ 434 char *ptr2; /* Help guess unitName, and clean the elemName. */ 435 436 myAssert (*element == NULL); 437 myAssert (*unitName == NULL); 438 myAssert (*comment == NULL); 439 myAssert (*shortFstLevel == NULL); 440 myAssert (*longFstLevel == NULL); 441 442 *element = (char *) malloc (1 + strlen (pds->Descriptor) * sizeof (char)); 443 strcpy (*element, pds->Descriptor); 444 (*element)[strlen (pds->Descriptor)] = '\0'; 445 446 ptr = strchr (*element, '('); 447 if (ptr != nullptr) { 448 ptr2 = strchr (ptr, ')'); 449 *ptr2 = '\0'; 450 if (strcmp (ptr + 1, "unofficial id") == 0) { 451 *unitName = (char *) malloc ((1 + 3) * sizeof (char)); 452 strcpy (*unitName, "[-]"); 453 } else { 454 reallocSprintf (unitName, "[%s]", ptr + 1); 455 } 456 /* Trim any parens from element. */ 457 *ptr = '\0'; 458 strTrimRight (*element, ' '); 459 } else { 460 *unitName = (char *) malloc ((1 + 3) * sizeof (char)); 461 strcpy (*unitName, "[-]"); 462 } 463 ptr = *element; 464 while (*ptr != '\0') { 465 if (*ptr == ' ') { 466 *ptr = '-'; 467 } 468 ptr++; 469 } 470 strCompact (*element, '-'); 471 472 reallocSprintf (comment, "%09ld-%09ld-%09ld-%ld %s", pds->ID1, 473 pds->ID2, pds->ID3, pds->ID4, *unitName); 474 reallocSprintf (shortFstLevel, "%09ld", pds->ID2); 475 reallocSprintf (longFstLevel, "%09ld", pds->ID2); 476 } 477 478 /***************************************************************************** 479 * TDLP_Inventory() -- 480 * 481 * Arthur Taylor / MDL 482 * 483 * PURPOSE 484 * Parses the TDLP "Product Definition Section" for enough information to 485 * fill out the inventory data structure so we can do a simple inventory on 486 * the file in a similar way to how we did it for GRIB1 and GRIB2. 487 * 488 * ARGUMENTS 489 * fp = An opened TDLP file already at the correct message. (Input) 490 * tdlpLen = The total length of the TDLP message. (Input) 491 * inv = The inventory data structure that we need to fill. (Output) 492 * 493 * FILES/DATABASES: None 494 * 495 * RETURNS: int (could use errSprintf()) 496 * 0 = OK 497 * -1 = tdlpLen is too small. 498 * 499 * HISTORY 500 * 10/2004 Arthur Taylor (MDL): Created. 501 * 502 * NOTES 503 * Speed improvements... 504 * 1) pds does not need to be allocated each time. 505 * 2) Not all data is needed, do something like TDLP_RefTime 506 * 3) TDLP_ElemSurfUnit may be slow? 507 ***************************************************************************** 508 */ 509 int TDLP_Inventory (DataSource &fp, sInt4 tdlpLen, inventoryType *inv) 510 { 511 sInt4 curLoc; /* Where we are in the current TDLP message. */ 512 int i_temp; 513 uChar sectLen; /* Length of section. */ 514 uChar *pds; /* The part of the message dealing with the PDS. */ 515 pdsTDLPType pdsMeta; /* The pds parsed into a usable data structure. */ 516 char f_gds; /* flag if there is a GDS section. */ 517 char f_bms; /* flag if there is a BMS section. */ 518 short int DSF; /* Decimal Scale Factor for unpacking the data. */ 519 short int BSF; /* Binary Scale Factor for unpacking the data. */ 520 521 curLoc = 8; 522 if ((i_temp = fp.DataSourceFgetc()) == EOF) { 523 errSprintf ("Ran out of file in PDS (TDLP_Inventory).\n"); 524 return -1; 525 } 526 sectLen = (uChar) i_temp; 527 curLoc += sectLen; 528 if (curLoc > tdlpLen) { 529 errSprintf ("Ran out of data in PDS (TDLP_Inventory)\n"); 530 return -1; 531 } 532 if( sectLen < 1 ) { 533 errSprintf ("Wrong sectLen (TDLP_Inventory)\n"); 534 return -1; 535 } 536 pds = (uChar *) malloc (sectLen * sizeof (uChar)); 537 if( pds == nullptr ) 538 { 539 errSprintf ("Ran out of memory in PDS (TDLP_Inventory)\n"); 540 return -1; 541 } 542 *pds = sectLen; 543 if (fp.DataSourceFread (pds + 1, sizeof (char), sectLen - 1) + 1 != sectLen) { 544 errSprintf ("Ran out of file.\n"); 545 free (pds); 546 return -1; 547 } 548 549 if (ReadTDLPSect1 (pds, tdlpLen, &curLoc, &pdsMeta, &f_gds, &f_bms, 550 &DSF, &BSF) != 0) { 551 preErrSprintf ("Inside TDLP_Inventory\n"); 552 free (pds); 553 return -1; 554 } 555 free (pds); 556 557 inv->element = nullptr; 558 inv->unitName = nullptr; 559 inv->comment = nullptr; 560 free (inv->shortFstLevel); 561 inv->shortFstLevel = nullptr; 562 free (inv->longFstLevel); 563 inv->longFstLevel = nullptr; 564 TDLP_ElemSurfUnit (&pdsMeta, &(inv->element), &(inv->unitName), 565 &(inv->comment), &(inv->shortFstLevel), 566 &(inv->longFstLevel)); 567 568 inv->refTime = pdsMeta.refTime; 569 inv->validTime = pdsMeta.refTime + pdsMeta.project; 570 inv->foreSec = pdsMeta.project; 571 return 0; 572 } 573 574 /***************************************************************************** 575 * TDLP_RefTime() -- 576 * 577 * Arthur Taylor / MDL 578 * 579 * PURPOSE 580 * Return just the reference time of a TDLP message. 581 * 582 * ARGUMENTS 583 * fp = An opened TDLP file already at the correct message. (Input) 584 * tdlpLen = The total length of the TDLP message. (Input) 585 * refTime = The reference time of interest. (Output) 586 * 587 * FILES/DATABASES: None 588 * 589 * RETURNS: int (could use errSprintf()) 590 * 0 = OK 591 * -1 = tdlpLen is too small. 592 * 593 * HISTORY 594 * 10/2004 Arthur Taylor (MDL): Created. 595 * 596 * NOTES 597 ***************************************************************************** 598 */ 599 int TDLP_RefTime (DataSource &fp, sInt4 tdlpLen, double *refTime) 600 { 601 int sectLen; /* Length of section. */ 602 sInt4 curLoc; /* Where we are in the current TDLP message. */ 603 int c_temp; /* Temporary variable for use with fgetc */ 604 short int si_temp; /* Temporary variable. */ 605 int year, t_year; /* The reference year, and a consistency test */ 606 uChar month, t_month; /* The reference month, and a consistency test */ 607 uChar day, t_day; /* The reference day, and a consistency test */ 608 uChar hour, t_hour; /* The reference hour, and a consistency test */ 609 uChar min; /* The reference minute */ 610 sInt4 li_temp; /* Temporary variable. */ 611 612 if ((sectLen = fp.DataSourceFgetc ()) == EOF) 613 goto error; 614 curLoc = 8 + sectLen; 615 if (curLoc > tdlpLen) { 616 errSprintf ("Ran out of data in PDS (TDLP_RefTime)\n"); 617 return -1; 618 } 619 if( sectLen > 71 ) { 620 errSprintf ("TDLP Section 1 is too big.\n"); 621 return -1; 622 } 623 if (sectLen < 39) { 624 errSprintf ("TDLP Section 1 is too small.\n"); 625 return -1; 626 } 627 628 if ((c_temp = fp.DataSourceFgetc()) == EOF) 629 goto error; 630 if (FREAD_BIG (&si_temp, sizeof (short int), 1, fp) != 1) 631 goto error; 632 year = si_temp; 633 if ((c_temp = fp.DataSourceFgetc()) == EOF) 634 goto error; 635 month = c_temp; 636 if ((c_temp = fp.DataSourceFgetc()) == EOF) 637 goto error; 638 day = c_temp; 639 if ((c_temp = fp.DataSourceFgetc()) == EOF) 640 goto error; 641 hour = c_temp; 642 if ((c_temp = fp.DataSourceFgetc()) == EOF) 643 goto error; 644 min = c_temp; 645 646 if (FREAD_BIG (&li_temp, sizeof (sInt4), 1, fp) != 1) 647 goto error; 648 t_year = li_temp / 1000000; 649 li_temp -= t_year * 1000000; 650 t_month = li_temp / 10000; 651 li_temp -= t_month * 10000; 652 t_day = li_temp / 100; 653 t_hour = li_temp - t_day * 100; 654 655 if ((t_year != year) || (t_month != month) || (t_day != day) || 656 (t_hour != hour)) { 657 errSprintf ("Error Inconsistent Times in TDLP_RefTime.\n"); 658 return -1; 659 } 660 if (ParseTime (refTime, year, month, day, hour, min, 0) != 0) { 661 preErrSprintf ("Error In call to ParseTime in TDLP_RefTime.\n"); 662 return -1; 663 } 664 665 /* Get to the end of the TDLP message. */ 666 /* (inventory.c : GRIB2Inventory), is responsible for this. */ 667 /* fseek (fp, gribLen - sectLen, SEEK_CUR); */ 668 return 0; 669 error: 670 errSprintf ("Ran out of file in PDS (TDLP_RefTime).\n"); 671 return -1; 672 } 673 674 /***************************************************************************** 675 * ReadTDLPSect2() -- 676 * 677 * Arthur Taylor / MDL 678 * 679 * PURPOSE 680 * Parses the TDLP "Grid Definition Section" or section 2, filling out 681 * the gdsMeta data structure. 682 * 683 * ARGUMENTS 684 * gds = The compressed part of the message dealing with "GDS". (Input) 685 * tdlpLen = The total length of the TDLP message. (Input) 686 * curLoc = Current location in the TDLP message. (Output) 687 * gdsMeta = The filled out gdsMeta data structure. (Output) 688 * 689 * FILES/DATABASES: None 690 * 691 * RETURNS: int (could use errSprintf()) 692 * 0 = OK 693 * -1 = tdlpLen is too small. 694 * -2 = unexpected values in gds. 695 * 696 * HISTORY 697 * 10/2004 Arthur Taylor (MDL): Created. 698 * 699 * NOTES 700 ***************************************************************************** 701 */ 702 static int ReadTDLPSect2 (uChar *gds, sInt4 tdlpLen, sInt4 *curLoc, 703 gdsType *gdsMeta) 704 { 705 char sectLen; /* Length of section. */ 706 int gridType; /* Which type of grid. (see enumerated types). */ 707 sInt4 li_temp; /* Temporary variable. */ 708 709 sectLen = *(gds++); 710 *curLoc += sectLen; 711 if (*curLoc > tdlpLen) { 712 errSprintf ("Ran out of data in GDS (TDLP Section 2)\n"); 713 return -1; 714 } 715 if( sectLen != 28 ) { 716 errSprintf ("Wrong sectLen (TDLP Section 2)\n"); 717 return -1; 718 } 719 720 gridType = *(gds++); 721 gdsMeta->Nx = GRIB_UNSIGN_INT2 (*gds, gds[1]); 722 gds += 2; 723 gdsMeta->Ny = GRIB_UNSIGN_INT2 (*gds, gds[1]); 724 gds += 2; 725 gdsMeta->lat1 = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) / 10000.0; 726 gds += 3; 727 gdsMeta->lon1 = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) / 10000.0; 728 gdsMeta->lon1 = 360 - gdsMeta->lon1; 729 if (gdsMeta->lon1 < 0) { 730 gdsMeta->lon1 += 360; 731 } 732 if (gdsMeta->lon1 > 360) { 733 gdsMeta->lon1 -= 360; 734 } 735 gds += 3; 736 gdsMeta->orientLon = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) / 10000.0; 737 gdsMeta->orientLon = 360 - gdsMeta->orientLon; 738 if (gdsMeta->orientLon < 0) { 739 gdsMeta->orientLon += 360; 740 } 741 if (gdsMeta->orientLon > 360) { 742 gdsMeta->orientLon -= 360; 743 } 744 gds += 3; 745 MEMCPY_BIG (&li_temp, gds, sizeof (sInt4)); 746 gdsMeta->Dx = li_temp / 1000.0; 747 gds += 4; 748 gdsMeta->meshLat = GRIB_SIGN_INT3 (*gds, gds[1], gds[2]) / 10000.0; 749 gds += 3; 750 if ((*gds != 0) || (gds[1] != 0) || (gds[2] != 0) || (gds[3] != 0) || 751 (gds[4] != 0) || (gds[5] != 0)) { 752 errSprintf ("Error Reserved was not set to 0 in ReadTDLPSect2.\n"); 753 return -1; 754 } 755 756 gdsMeta->numPts = gdsMeta->Nx * gdsMeta->Ny; 757 gdsMeta->f_sphere = 1; 758 gdsMeta->majEarth = 6371.2; 759 gdsMeta->minEarth = 6371.2; 760 gdsMeta->Dy = gdsMeta->Dx; 761 gdsMeta->resFlag = 0; 762 gdsMeta->center = 0; 763 gdsMeta->scan = 64; 764 gdsMeta->lat2 = 0; 765 gdsMeta->lon2 = 0; 766 gdsMeta->scaleLat1 = gdsMeta->meshLat; 767 gdsMeta->scaleLat2 = gdsMeta->meshLat; 768 gdsMeta->southLat = 0; 769 gdsMeta->southLon = 0; 770 switch (gridType) { 771 case TDLP_POLAR: 772 gdsMeta->projType = GS3_POLAR; 773 /* 4/24/2006 Added the following. */ 774 gdsMeta->scaleLat1 = 90; 775 gdsMeta->scaleLat2 = 90; 776 break; 777 case TDLP_LAMBERT: 778 gdsMeta->projType = GS3_LAMBERT; 779 break; 780 case TDLP_MERCATOR: 781 gdsMeta->projType = GS3_MERCATOR; 782 /* 4/24/2006 Added the following. */ 783 gdsMeta->scaleLat1 = 0; 784 gdsMeta->scaleLat2 = 0; 785 break; 786 default: 787 errSprintf ("Grid projection number is %d\n", gridType); 788 return -2; 789 } 790 return 0; 791 } 792 793 /***************************************************************************** 794 * ReadTDLPSect3() -- 795 * 796 * Arthur Taylor / MDL 797 * 798 * PURPOSE 799 * Parses the TDLP "Bit Map Section" or section 3, filling out the bitmap 800 * as needed. 801 * 802 * ARGUMENTS 803 * bms = The compressed part of the message dealing with "BMS". (Input) 804 * tdlpLen = The total length of the TDLP message. (Input) 805 * curLoc = Current location in the TDLP message. (Output) 806 * bitmap = The extracted bitmap. (Output) 807 * NxNy = The total size of the grid. (Input) 808 * 809 * FILES/DATABASES: None 810 * 811 * RETURNS: int (could use errSprintf()) 812 * 0 = OK 813 * -1 = tdlpLen is too small. 814 * -2 = unexpected values in bms. 815 * 816 * HISTORY 817 * 10/2004 Arthur Taylor (MDL): Created. 818 * 819 * NOTES 820 ***************************************************************************** 821 */ 822 static int ReadTDLPSect3 (CPL_UNUSED uChar *bms, 823 CPL_UNUSED sInt4 tdlpLen, 824 CPL_UNUSED sInt4 *curLoc, 825 CPL_UNUSED uChar *bitmap, 826 CPL_UNUSED sInt4 NxNy) 827 { 828 errSprintf ("Bitmap data is Not Supported\n"); 829 return -1; 830 } 831 832 /***************************************************************************** 833 * ReadTDLPSect4() -- 834 * 835 * Arthur Taylor / MDL 836 * 837 * PURPOSE 838 * Unpacks the "Binary Data Section" or section 4. 839 * 840 * ARGUMENTS 841 * bds = The compressed part of the message dealing with "BDS". (Input) 842 * tdlpLen = The total length of the TDLP message. (Input) 843 * curLoc = Current location in the TDLP message. (Output) 844 * DSF = Decimal Scale Factor for unpacking the data. (Input) 845 * BSF = Binary Scale Factor for unpacking the data. (Input) 846 * data = The extracted grid. (Output) 847 * meta = The meta data associated with the grid (Input/Output) 848 * unitM = The M unit conversion value in equation y = Mx + B. (Input) 849 * unitB = The B unit conversion value in equation y = Mx + B. (Input) 850 * 851 * FILES/DATABASES: None 852 * 853 * RETURNS: int (could use errSprintf()) 854 * 0 = OK 855 * -1 = gribLen is too small. 856 * -2 = unexpected values in bds. 857 * 858 * HISTORY 859 * 4/2003 Arthur Taylor (MDL/RSIS): Created 860 * 3/2004 AAT: Switched {# Pts * (# Bits in a Group) + 861 * # of unused bits != # of available bits} to a warning from an 862 * error. 863 * 2/2005 AAT: Found bug: memBitRead grp[i].bit was sizeof sInt4 instead 864 * of uChar. 865 * 2/2005 AAT: Second order diff, no miss value bug (lastData - 1) should 866 * be lastData. 867 * 2/2005 AAT: Added test to see if the number of bits needed matches the 868 * section length. 869 * 870 * NOTES 871 * 1) See metaparse.c : ParseGrid() 872 ***************************************************************************** 873 */ 874 static int ReadTDLPSect4 (uChar *bds, sInt4 tdlpLen, sInt4 *curLoc, 875 short int DSF, short int BSF, double *data, 876 grib_MetaData *meta, 877 CPL_UNUSED double unitM, 878 CPL_UNUSED double unitB) 879 { 880 uInt4 sectLen; /* Length in bytes of the current section. */ 881 uChar f_notGridPnt; /* Not Grid point data? */ 882 uChar f_complexPack; /* Complex packing? */ 883 uChar f_sndOrder; /* Second order differencing? */ 884 uChar f_primMiss; /* Primary missing value? */ 885 uChar f_secMiss; /* Secondary missing value? */ 886 uInt4 numPack; /* Number of points packed. */ 887 sInt4 li_temp; /* Temporary variable. */ 888 uInt4 uli_temp; /* Temporary variable. */ 889 uChar bufLoc; /* Keeps track of where to start getting more data 890 * out of the packed data stream. */ 891 uChar f_negative; /* used to help with signs of numbers. */ 892 size_t numUsed; /* How many bytes were used in a given call to 893 * memBitRead. */ 894 sInt4 origVal = 0; /* Original value. */ 895 uChar mbit; /* # of bits for abs (first first order difference) */ 896 sInt4 fstDiff = 0; /* First first order difference. */ 897 sInt4 diff = 0; /* general first order difference. */ 898 uChar nbit; /* # of bits for abs (overall min value) */ 899 sInt4 minVal; /* Minimum value. */ 900 size_t LX; /* Number of groups. */ 901 uChar ibit; /* # of bits for group min values. */ 902 uChar jbit; /* # of bits for # of bits for group. */ 903 uChar kbit; /* # of bits for # values in a group. */ 904 TDLGroupType *grp; /* Holds the info about each group. */ 905 size_t i, j; /* Loop counters. */ 906 uInt4 t_numPack; /* Used to total number of values in a group to check 907 * the numPack value. */ 908 uInt4 t_numBits; /* Used to total number of bits used in the groups. */ 909 uInt4 t_numBytes; /* Used to total number of bytes used to compare to 910 * sectLen. */ 911 sInt4 maxVal; /* The max value in a group. */ 912 uInt4 dataCnt; /* How many values (miss or otherwise) we have read. */ 913 uInt4 lastData; /* Index to last actual data. */ 914 uInt4 numVal; /* # of actual (non-missing values) we have. */ 915 double scale; /* Amount to scale values by. */ 916 uInt4 dataInd; /* Index into data for this value (used to switch 917 * from a11..a1n,a2n..a21 to normal grid of 918 * a11..a1n,a21..a2n. */ 919 uChar f_missing; /* Used to help with primary missing values, and the 920 * 0 bit possibility. */ 921 #ifdef DEBUG 922 sInt4 t_UK1 = 0; /* Used to test theories about un defined values. */ 923 sInt4 t_UK2 = 0; /* Used to test theories about un defined values. */ 924 #endif 925 926 sectLen = GRIB_UNSIGN_INT3 (*bds, bds[1], bds[2]); 927 *curLoc += sectLen; 928 if (*curLoc > tdlpLen) { 929 errSprintf ("Ran out of data in BDS (TDLP Section 4)\n"); 930 return -1; 931 } 932 bds += 3; 933 t_numBytes = 3; 934 f_notGridPnt = (GRIB2BIT_4 & *bds) ? 1 : 0; 935 f_complexPack = (GRIB2BIT_5 & *bds) ? 1 : 0; 936 f_sndOrder = (GRIB2BIT_6 & *bds) ? 1 : 0; 937 f_primMiss = (GRIB2BIT_7 & *bds) ? 1 : 0; 938 f_secMiss = (GRIB2BIT_8 & *bds) ? 1 : 0; 939 940 if (f_secMiss && (!f_primMiss)) { 941 errSprintf ("Secondary missing value without a primary!\n"); 942 return -1; 943 } 944 if (f_complexPack) { 945 if (!f_sndOrder) { 946 meta->gridAttrib.packType = GS5_CMPLX; 947 } else { 948 meta->gridAttrib.packType = GS5_CMPLXSEC; 949 } 950 } else { 951 errSprintf ("Simple pack is not supported at this time.\n"); 952 return -1; 953 } 954 bds++; 955 MEMCPY_BIG (&numPack, bds, sizeof (sInt4)); 956 bds += 4; 957 t_numBytes += 5; 958 if (!f_notGridPnt) { 959 if (numPack != meta->gds.numPts) { 960 errSprintf ("Number packed %d != number of points %d\n", numPack, 961 meta->gds.numPts); 962 return -1; 963 } 964 } 965 meta->gridAttrib.DSF = DSF; 966 meta->gridAttrib.ESF = BSF; 967 meta->gridAttrib.fieldType = 0; 968 if (!f_primMiss) { 969 meta->gridAttrib.f_miss = 0; 970 meta->gridAttrib.missPri = 0; 971 meta->gridAttrib.missSec = 0; 972 } else { 973 MEMCPY_BIG (&li_temp, bds, sizeof (sInt4)); 974 bds += 4; 975 t_numBytes += 4; 976 meta->gridAttrib.missPri = li_temp / 10000.0; 977 if (!f_secMiss) { 978 meta->gridAttrib.f_miss = 1; 979 meta->gridAttrib.missSec = 0; 980 } else { 981 MEMCPY_BIG (&li_temp, bds, sizeof (sInt4)); 982 bds += 4; 983 t_numBytes += 4; 984 meta->gridAttrib.missSec = li_temp / 10000.0; 985 meta->gridAttrib.f_miss = 2; 986 } 987 } 988 /* Init the buffer location. */ 989 bufLoc = 8; 990 /* The origValue and fstDiff are only present if sndOrder packed. */ 991 if (f_sndOrder) { 992 memBitRead (&f_negative, sizeof (f_negative), bds, 1, &bufLoc, 993 &numUsed); 994 memBitRead (&uli_temp, sizeof (sInt4), bds, 31, &bufLoc, &numUsed); 995 myAssert (numUsed == 4); 996 bds += numUsed; 997 t_numBytes += static_cast<uInt4>(numUsed); 998 origVal = (f_negative) ? -1 * (sInt4)uli_temp : uli_temp; 999 memBitRead (&mbit, sizeof (mbit), bds, 5, &bufLoc, &numUsed); 1000 memBitRead (&f_negative, sizeof (f_negative), bds, 1, &bufLoc, 1001 &numUsed); 1002 myAssert (numUsed == 0); 1003 myAssert ((mbit > 0) && (mbit < 32)); 1004 memBitRead (&uli_temp, sizeof (sInt4), bds, mbit, &bufLoc, &numUsed); 1005 bds += numUsed; 1006 t_numBytes += static_cast<uInt4>(numUsed); 1007 fstDiff = (f_negative) ? -1 * (sInt4)uli_temp : uli_temp; 1008 } 1009 memBitRead (&nbit, sizeof (nbit), bds, 5, &bufLoc, &numUsed); 1010 bds += numUsed; 1011 t_numBytes += static_cast<uInt4>(numUsed); 1012 memBitRead (&f_negative, sizeof (f_negative), bds, 1, &bufLoc, &numUsed); 1013 bds += numUsed; 1014 t_numBytes += static_cast<uInt4>(numUsed); 1015 myAssert ((nbit > 0) && (nbit < 32)); 1016 memBitRead (&uli_temp, sizeof (sInt4), bds, nbit, &bufLoc, &numUsed); 1017 bds += numUsed; 1018 t_numBytes += static_cast<uInt4>(numUsed); 1019 minVal = (f_negative) ? -1 * (sInt4)uli_temp : uli_temp; 1020 memBitRead (&LX, sizeof (LX), bds, 16, &bufLoc, &numUsed); 1021 bds += numUsed; 1022 t_numBytes += static_cast<uInt4>(numUsed); 1023 grp = (TDLGroupType *) malloc (LX * sizeof (TDLGroupType)); 1024 memBitRead (&ibit, sizeof (ibit), bds, 5, &bufLoc, &numUsed); 1025 bds += numUsed; 1026 t_numBytes += static_cast<uInt4>(numUsed); 1027 memBitRead (&jbit, sizeof (jbit), bds, 5, &bufLoc, &numUsed); 1028 /* Following assert is because it is the # of bits of # of bits. Which 1029 * means that # of bits of value that has a max of 64. */ 1030 myAssert (jbit < 6); 1031 bds += numUsed; 1032 t_numBytes += static_cast<uInt4>(numUsed); 1033 memBitRead (&kbit, sizeof (kbit), bds, 5, &bufLoc, &numUsed); 1034 bds += numUsed; 1035 t_numBytes += static_cast<uInt4>(numUsed); 1036 myAssert (ibit < 33); 1037 for (i = 0; i < LX; i++) { 1038 if (ibit == 0) { 1039 grp[i].min = 0; 1040 } else { 1041 memBitRead (&(grp[i].min), sizeof (sInt4), bds, ibit, &bufLoc, 1042 &numUsed); 1043 bds += numUsed; 1044 t_numBytes += static_cast<uInt4>(numUsed); 1045 } 1046 } 1047 myAssert (jbit < 8); 1048 for (i = 0; i < LX; i++) { 1049 if (jbit == 0) { 1050 grp[i].bit = 0; 1051 } else { 1052 myAssert (jbit <= sizeof (uChar) * 8); 1053 memBitRead (&(grp[i].bit), sizeof (uChar), bds, jbit, &bufLoc, 1054 &numUsed); 1055 bds += numUsed; 1056 t_numBytes += static_cast<uInt4>(numUsed); 1057 } 1058 myAssert (grp[i].bit < 32); 1059 } 1060 myAssert (kbit < 33); 1061 t_numPack = 0; 1062 t_numBits = 0; 1063 for (i = 0; i < LX; i++) { 1064 if (kbit == 0) { 1065 grp[i].num = 0; 1066 } else { 1067 memBitRead (&(grp[i].num), sizeof (sInt4), bds, kbit, &bufLoc, 1068 &numUsed); 1069 bds += numUsed; 1070 t_numBytes += static_cast<uInt4>(numUsed); 1071 } 1072 t_numPack += grp[i].num; 1073 t_numBits += grp[i].num * grp[i].bit; 1074 } 1075 if (t_numPack != numPack) { 1076 errSprintf ("Number packed %d != number of values in groups %d\n", 1077 numPack, t_numPack); 1078 free (grp); 1079 return -1; 1080 } 1081 if ((t_numBytes + ceil (t_numBits / 8.)) > sectLen) { 1082 errSprintf ("# bytes in groups %ld (%ld + %ld / 8) > sectLen %ld\n", 1083 (sInt4) (t_numBytes + ceil (t_numBits / 8.)), 1084 t_numBytes, t_numBits, sectLen); 1085 free (grp); 1086 return -1; 1087 } 1088 dataCnt = 0; 1089 dataInd = 0; 1090 1091 #ifdef DEBUG 1092 printf ("nbit %d, ibit %d, jbit %d, kbit %d\n", nbit, ibit, jbit, kbit); 1093 if ((t_numBytes + ceil (t_numBits / 8.)) != sectLen) { 1094 printf ("Caution: # bytes in groups %d (%u + %u / 8) != " 1095 "sectLen %u\n", (sInt4) (t_numBytes + ceil (t_numBits / 8.)), 1096 t_numBytes, t_numBits, sectLen); 1097 } 1098 #endif 1099 1100 /* Binary scale factor in TDLP has reverse sign from GRIB definition. */ 1101 scale = pow (10.0, -1 * DSF) * pow (2.0, -1 * BSF); 1102 1103 meta->gridAttrib.f_maxmin = 0; 1104 /* Work with Second order complex packed data. */ 1105 if (f_sndOrder) { 1106 /* *INDENT-OFF* */ 1107 /* The algorithm appears to be: 1108 * Data: a1 a2 a3 a4 a5 ... 1109 * 1st diff: 0 b2 b3 b4 b5 ... 1110 * 2nd diff: UK1 UK2 c3 c4 c5 ... 1111 * We already know a1 and b2, and unpack a stream of UK1 UK2 c3 c4 1112 * The problem is that UK1, UK2 is undefined. Originally I thought 1113 * this was 0, or c3, but it appears that if b2 != 0, then 1114 * UK2 = c3 + 2 b2, and UK1 = c3 + 1 * b2, otherwise it appears that 1115 * UK1 == UK2, and typically UK1 == c3 (but not always). */ 1116 /* *INDENT-ON* */ 1117 myAssert (numPack >= 2); 1118 if (f_secMiss) { 1119 numVal = 0; 1120 lastData = 0; 1121 for (i = 0; i < LX; i++) { 1122 maxVal = (1 << grp[i].bit) - 1; 1123 for (j = 0; j < grp[i].num; j++) { 1124 /* signed int. */ 1125 memBitRead (&(li_temp), sizeof (sInt4), bds, grp[i].bit, 1126 &bufLoc, &numUsed); 1127 bds += numUsed; 1128 if (li_temp == maxVal) { 1129 data[dataInd] = meta->gridAttrib.missPri; 1130 } else if (li_temp == (maxVal - 1)) { 1131 data[dataInd] = meta->gridAttrib.missSec; 1132 } else { 1133 if (numVal > 1) { 1134 #ifdef DEBUG 1135 if (numVal == 2) { 1136 if (fstDiff != 0) { 1137 /* 1138 myAssert (t_UK1 == li_temp + fstDiff); 1139 myAssert (t_UK2 == li_temp + 2 * fstDiff); 1140 */ 1141 } else { 1142 myAssert (t_UK1 == t_UK2); 1143 } 1144 } 1145 #endif 1146 diff += (li_temp + grp[i].min + minVal); 1147 data[dataInd] = data[lastData] + diff * scale; 1148 lastData = dataInd; 1149 } else if (numVal == 1) { 1150 data[dataInd] = (origVal + fstDiff) * scale; 1151 lastData = dataInd; 1152 diff = fstDiff; 1153 #ifdef DEBUG 1154 t_UK2 = li_temp; 1155 #endif 1156 } else { 1157 data[dataInd] = origVal * scale; 1158 #ifdef DEBUG 1159 t_UK1 = li_temp; 1160 #endif 1161 } 1162 numVal++; 1163 if (!meta->gridAttrib.f_maxmin) { 1164 meta->gridAttrib.min = data[dataInd]; 1165 meta->gridAttrib.max = data[dataInd]; 1166 meta->gridAttrib.f_maxmin = 1; 1167 } else { 1168 if (data[dataInd] < meta->gridAttrib.min) { 1169 meta->gridAttrib.min = data[dataInd]; 1170 } 1171 if (data[dataInd] > meta->gridAttrib.max) { 1172 meta->gridAttrib.max = data[dataInd]; 1173 } 1174 } 1175 } 1176 dataCnt++; 1177 dataInd = ((dataCnt / meta->gds.Nx) % 2) ? 1178 (2 * (dataCnt / meta->gds.Nx) + 1) * 1179 meta->gds.Nx - dataCnt - 1 : dataCnt; 1180 myAssert ((dataInd < numPack) || (dataCnt == numPack)); 1181 } 1182 } 1183 } else if (f_primMiss) { 1184 numVal = 0; 1185 lastData = 0; 1186 for (i = 0; i < LX; i++) { 1187 maxVal = (1 << grp[i].bit) - 1; 1188 for (j = 0; j < grp[i].num; j++) { 1189 /* signed int. */ 1190 memBitRead (&(li_temp), sizeof (sInt4), bds, grp[i].bit, 1191 &bufLoc, &numUsed); 1192 bds += numUsed; 1193 f_missing = 0; 1194 if (li_temp == maxVal) { 1195 data[dataInd] = meta->gridAttrib.missPri; 1196 /* In the case of grp[i].bit == 0, if grp[i].min == 0, then 1197 * it is the missing value, otherwise regular value. Only 1198 * need to be concerned for primary missing values. */ 1199 f_missing = 1; 1200 if ((grp[i].bit == 0) && (grp[i].min != 0)) { 1201 #ifdef DEBUG 1202 printf ("This doesn't happen often.\n"); 1203 printf ("%d %u %d\n", (int) i, grp[i].bit, grp[i].min); 1204 #endif 1205 myAssert (0); 1206 f_missing = 0; 1207 } 1208 } 1209 if (!f_missing) { 1210 if (numVal > 1) { 1211 #ifdef DEBUG 1212 if (numVal == 2) { 1213 if (fstDiff != 0) { 1214 /* 1215 myAssert (t_UK1 == li_temp + fstDiff); 1216 myAssert (t_UK2 == li_temp + 2 * fstDiff); 1217 */ 1218 } else { 1219 myAssert (t_UK1 == t_UK2); 1220 } 1221 } 1222 #endif 1223 diff += (li_temp + grp[i].min + minVal); 1224 data[dataInd] = data[lastData] + diff * scale; 1225 lastData = dataInd; 1226 } else if (numVal == 1) { 1227 data[dataInd] = (origVal + fstDiff) * scale; 1228 lastData = dataInd; 1229 diff = fstDiff; 1230 #ifdef DEBUG 1231 t_UK2 = li_temp; 1232 #endif 1233 } else { 1234 data[dataInd] = origVal * scale; 1235 #ifdef DEBUG 1236 t_UK1 = li_temp; 1237 #endif 1238 } 1239 numVal++; 1240 if (!meta->gridAttrib.f_maxmin) { 1241 meta->gridAttrib.min = data[dataInd]; 1242 meta->gridAttrib.max = data[dataInd]; 1243 meta->gridAttrib.f_maxmin = 1; 1244 } else { 1245 if (data[dataInd] < meta->gridAttrib.min) { 1246 meta->gridAttrib.min = data[dataInd]; 1247 } 1248 if (data[dataInd] > meta->gridAttrib.max) { 1249 meta->gridAttrib.max = data[dataInd]; 1250 } 1251 } 1252 } 1253 dataCnt++; 1254 dataInd = ((dataCnt / meta->gds.Nx) % 2) ? 1255 (2 * (dataCnt / meta->gds.Nx) + 1) * 1256 meta->gds.Nx - dataCnt - 1 : dataCnt; 1257 myAssert ((dataInd < numPack) || (dataCnt == numPack)); 1258 } 1259 } 1260 } else { 1261 lastData = 0; 1262 for (i = 0; i < LX; i++) { 1263 for (j = 0; j < grp[i].num; j++) { 1264 /* signed int. */ 1265 memBitRead (&(li_temp), sizeof (sInt4), bds, grp[i].bit, 1266 &bufLoc, &numUsed); 1267 bds += numUsed; 1268 if (dataCnt > 1) { 1269 #ifdef DEBUG 1270 if (dataCnt == 2) { 1271 if (fstDiff != 0) { 1272 /* 1273 myAssert (t_UK1 == li_temp + fstDiff); 1274 myAssert (t_UK2 == li_temp + 2 * fstDiff); 1275 */ 1276 } else { 1277 myAssert (t_UK1 == t_UK2); 1278 } 1279 } 1280 #endif 1281 diff += (li_temp + grp[i].min + minVal); 1282 data[dataInd] = data[lastData] + diff * scale; 1283 lastData = dataInd; 1284 } else if (dataCnt == 1) { 1285 data[dataInd] = (origVal + fstDiff) * scale; 1286 lastData = dataInd; 1287 diff = fstDiff; 1288 #ifdef DEBUG 1289 t_UK2 = li_temp; 1290 #endif 1291 } else { 1292 data[dataInd] = origVal * scale; 1293 #ifdef DEBUG 1294 t_UK1 = li_temp; 1295 #endif 1296 } 1297 #ifdef DEBUG 1298 /* 1299 if (i >= 4153) { 1300 */ 1301 /* 1302 if ((data[dataInd] > 100) || (data[dataInd] < -100)) { 1303 */ 1304 /* 1305 if ((diff > 50) || (diff < -50)) { 1306 printf ("li_temp :: %ld, diff = %ld\n", li_temp, diff); 1307 printf ("data[dataInd] :: %f\n", data[dataInd]); 1308 printf ("Group # %d element %d, grp[i].min %ld, " 1309 "grp[i].bit %d, minVal %ld\n", i, j, grp[i].min, 1310 grp[i].bit, minVal); 1311 } 1312 */ 1313 #endif 1314 if (!meta->gridAttrib.f_maxmin) { 1315 meta->gridAttrib.min = data[dataInd]; 1316 meta->gridAttrib.max = data[dataInd]; 1317 meta->gridAttrib.f_maxmin = 1; 1318 } else { 1319 if (data[dataInd] < meta->gridAttrib.min) { 1320 meta->gridAttrib.min = data[dataInd]; 1321 } 1322 if (data[dataInd] > meta->gridAttrib.max) { 1323 meta->gridAttrib.max = data[dataInd]; 1324 } 1325 } 1326 dataCnt++; 1327 dataInd = ((dataCnt / meta->gds.Nx) % 2) ? 1328 (2 * (dataCnt / meta->gds.Nx) + 1) * 1329 meta->gds.Nx - dataCnt - 1 : dataCnt; 1330 myAssert ((dataInd < numPack) || (dataCnt == numPack)); 1331 } 1332 } 1333 numVal = dataCnt; 1334 } 1335 1336 /* Work with regular complex packed data. */ 1337 } else { 1338 #ifdef DEBUG 1339 /* 1340 printf ("Work with regular complex packed data\n"); 1341 */ 1342 #endif 1343 if (f_secMiss) { 1344 numVal = 0; 1345 for (i = 0; i < LX; i++) { 1346 maxVal = (1 << grp[i].bit) - 1; 1347 for (j = 0; j < grp[i].num; j++) { 1348 /* signed int. */ 1349 memBitRead (&(li_temp), sizeof (sInt4), bds, grp[i].bit, 1350 &bufLoc, &numUsed); 1351 bds += numUsed; 1352 if (li_temp == maxVal) { 1353 data[dataInd] = meta->gridAttrib.missPri; 1354 } else if (li_temp == (maxVal - 1)) { 1355 data[dataInd] = meta->gridAttrib.missSec; 1356 } else { 1357 data[dataInd] = (li_temp + grp[i].min + minVal) * scale; 1358 numVal++; 1359 if (!meta->gridAttrib.f_maxmin) { 1360 meta->gridAttrib.min = data[dataInd]; 1361 meta->gridAttrib.max = data[dataInd]; 1362 meta->gridAttrib.f_maxmin = 1; 1363 } else { 1364 if (data[dataInd] < meta->gridAttrib.min) { 1365 meta->gridAttrib.min = data[dataInd]; 1366 } 1367 if (data[dataInd] > meta->gridAttrib.max) { 1368 meta->gridAttrib.max = data[dataInd]; 1369 } 1370 } 1371 } 1372 dataCnt++; 1373 dataInd = ((dataCnt / meta->gds.Nx) % 2) ? 1374 (2 * (dataCnt / meta->gds.Nx) + 1) * 1375 meta->gds.Nx - dataCnt - 1 : dataCnt; 1376 myAssert ((dataInd < numPack) || (dataCnt == numPack)); 1377 } 1378 } 1379 } else if (f_primMiss) { 1380 #ifdef DEBUG 1381 /* 1382 printf ("Work with primary missing data\n"); 1383 */ 1384 #endif 1385 numVal = 0; 1386 for (i = 0; i < LX; i++) { 1387 maxVal = (1 << grp[i].bit) - 1; 1388 for (j = 0; j < grp[i].num; j++) { 1389 memBitRead (&(li_temp), sizeof (sInt4), bds, grp[i].bit, 1390 &bufLoc, &numUsed); 1391 bds += numUsed; 1392 f_missing = 0; 1393 if (li_temp == maxVal) { 1394 data[dataInd] = meta->gridAttrib.missPri; 1395 /* In the case of grp[i].bit == 0, if grp[i].min == 0, then 1396 * it is the missing value, otherwise regular value. Only 1397 * need to be concerned for primary missing values. */ 1398 f_missing = 1; 1399 if ((grp[i].bit == 0) && (grp[i].min != 0)) { 1400 #ifdef DEBUG 1401 printf ("This doesn't happen often.\n"); 1402 printf ("%d %u %d\n", (int) i, grp[i].bit, grp[i].min); 1403 myAssert (0); 1404 #endif 1405 f_missing = 0; 1406 } 1407 } 1408 if (!f_missing) { 1409 data[dataInd] = (li_temp + grp[i].min + minVal) * scale; 1410 numVal++; 1411 if (!meta->gridAttrib.f_maxmin) { 1412 meta->gridAttrib.min = data[dataInd]; 1413 meta->gridAttrib.max = data[dataInd]; 1414 meta->gridAttrib.f_maxmin = 1; 1415 } else { 1416 if (data[dataInd] < meta->gridAttrib.min) { 1417 meta->gridAttrib.min = data[dataInd]; 1418 } 1419 if (data[dataInd] > meta->gridAttrib.max) { 1420 meta->gridAttrib.max = data[dataInd]; 1421 } 1422 } 1423 } 1424 dataCnt++; 1425 dataInd = ((dataCnt / meta->gds.Nx) % 2) ? 1426 (2 * (dataCnt / meta->gds.Nx) + 1) * 1427 meta->gds.Nx - dataCnt - 1 : dataCnt; 1428 myAssert ((dataInd < numPack) || (dataCnt == numPack)); 1429 } 1430 } 1431 } else { 1432 for (i = 0; i < LX; i++) { 1433 for (j = 0; j < grp[i].num; j++) { 1434 memBitRead (&(li_temp), sizeof (sInt4), bds, grp[i].bit, 1435 &bufLoc, &numUsed); 1436 bds += numUsed; 1437 data[dataInd] = (li_temp + grp[i].min + minVal) * scale; 1438 if (!meta->gridAttrib.f_maxmin) { 1439 meta->gridAttrib.min = data[dataInd]; 1440 meta->gridAttrib.max = data[dataInd]; 1441 meta->gridAttrib.f_maxmin = 1; 1442 } else { 1443 if (data[dataInd] < meta->gridAttrib.min) { 1444 meta->gridAttrib.min = data[dataInd]; 1445 } 1446 if (data[dataInd] > meta->gridAttrib.max) { 1447 meta->gridAttrib.max = data[dataInd]; 1448 } 1449 } 1450 dataCnt++; 1451 dataInd = ((dataCnt / meta->gds.Nx) % 2) ? 1452 (2 * (dataCnt / meta->gds.Nx) + 1) * 1453 meta->gds.Nx - dataCnt - 1 : dataCnt; 1454 myAssert ((dataInd < numPack) || (dataCnt == numPack)); 1455 } 1456 } 1457 numVal = dataCnt; 1458 } 1459 } 1460 meta->gridAttrib.numMiss = dataCnt - numVal; 1461 meta->gridAttrib.refVal = (float)(minVal * scale); 1462 1463 free (grp); 1464 return 0; 1465 } 1466 1467 /***************************************************************************** 1468 * ReadTDLPRecord() -- 1469 * 1470 * Arthur Taylor / MDL 1471 * 1472 * PURPOSE 1473 * Reads in a TDLP message, and parses the data into various data 1474 * structures, for use with other code. 1475 * 1476 * ARGUMENTS 1477 * fp = An opened TDLP file already at the correct message. (Input) 1478 * TDLP_Data = The read in TDLP data. (Output) 1479 * tdlp_DataLen = Size of TDLP_Data. (Output) 1480 * meta = A filled in meta structure (Output) 1481 * IS = The structure containing all the arrays that the 1482 * unpacker uses (Output) 1483 * sect0 = Already read in section 0 data. (Input) 1484 * tdlpLen = Length of the TDLP message. (Input) 1485 * majEarth = Used to override the TDLP major axis of earth. (Input) 1486 * minEarth = Used to override the TDLP minor axis of earth. (Input) 1487 * 1488 * FILES/DATABASES: 1489 * An already opened file pointing to the desired TDLP message. 1490 * 1491 * RETURNS: int (could use errSprintf()) 1492 * 0 = OK 1493 * -1 = Problems reading in the PDS. 1494 * -2 = Problems reading in the GDS. 1495 * -3 = Problems reading in the BMS. 1496 * -4 = Problems reading in the BDS. 1497 * -5 = Problems reading the closing section. 1498 * 1499 * HISTORY 1500 * 10/2004 Arthur Taylor (MDL): Created 1501 * 1502 * NOTES 1503 ***************************************************************************** 1504 */ 1505 int ReadTDLPRecord (DataSource &fp, double **TDLP_Data, uInt4 *tdlp_DataLen, 1506 grib_MetaData *meta, IS_dataType *IS, 1507 sInt4 sect0[SECT0LEN_WORD], uInt4 tdlpLen, 1508 double majEarth, double minEarth) 1509 { 1510 sInt4 nd5; /* Size of TDLP message rounded up to the nearest * 1511 * sInt4. */ 1512 uChar *c_ipack; /* A char ptr to the message stored in IS->ipack */ 1513 sInt4 curLoc; /* Current location in the GRIB message. */ 1514 char f_gds; /* flag if there is a GDS section. */ 1515 char f_bms; /* flag if there is a BMS section. */ 1516 short int DSF; /* Decimal Scale Factor for unpacking the data. */ 1517 short int BSF; /* Binary Scale Factor for unpacking the data. */ 1518 double *tdlp_Data; /* A pointer to TDLP_Data for ease of manipulation. */ 1519 double unitM = 1; /* M in y = Mx + B, for unit conversion. */ 1520 double unitB = 0; /* B in y = Mx + B, for unit conversion. */ 1521 sInt4 li_temp; /* Used to make sure section 5 is 7777. */ 1522 size_t pad; /* Number of bytes to pad the message to get to the 1523 * correct byte boundary. */ 1524 char buffer[24]; /* Read the trailing bytes in the TDLPack record. */ 1525 uChar *bitmap; /* Would contain bitmap data if it was supported. */ 1526 1527 /* Make room for entire message, and read it in. */ 1528 /* nd5 needs to be tdlpLen in (sInt4) units rounded up. */ 1529 nd5 = (tdlpLen + 3) / 4; 1530 if (nd5 > IS->ipackLen) { 1531 IS->ipackLen = nd5; 1532 IS->ipack = (sInt4 *) realloc ((void *) (IS->ipack), 1533 (IS->ipackLen) * sizeof (sInt4)); 1534 } 1535 c_ipack = (uChar *) IS->ipack; 1536 /* Init last sInt4 to 0, to make sure that the padded bytes are 0. */ 1537 IS->ipack[nd5 - 1] = 0; 1538 /* Init first 2 sInt4 to sect0. */ 1539 memcpy (c_ipack, sect0, SECT0LEN_WORD * 2); 1540 /* Read in the rest of the message. */ 1541 if (fp.DataSourceFread(c_ipack + SECT0LEN_WORD * 2, sizeof (char), 1542 (tdlpLen - SECT0LEN_WORD * 2)) + SECT0LEN_WORD * 2 != tdlpLen) { 1543 errSprintf ("Ran out of file\n"); 1544 return -1; 1545 } 1546 1547 /* Preceding was in degrib2, next part is specific to TDLP. */ 1548 curLoc = 8; 1549 if (ReadTDLPSect1 (c_ipack + curLoc, tdlpLen, &curLoc, &(meta->pdsTdlp), 1550 &f_gds, &f_bms, &DSF, &BSF) != 0) { 1551 preErrSprintf ("Inside ReadGrib1Record\n"); 1552 return -1; 1553 } 1554 1555 /* Figure out some basic stuff about the grid. */ 1556 free (meta->element); 1557 meta->element = nullptr; 1558 free (meta->unitName); 1559 meta->unitName = nullptr; 1560 free (meta->comment); 1561 meta->comment = nullptr; 1562 free (meta->shortFstLevel); 1563 meta->shortFstLevel = nullptr; 1564 free (meta->longFstLevel); 1565 meta->longFstLevel = nullptr; 1566 TDLP_ElemSurfUnit (&(meta->pdsTdlp), &(meta->element), &(meta->unitName), 1567 &(meta->comment), &(meta->shortFstLevel), 1568 &(meta->longFstLevel)); 1569 meta->center = 7; /* US NWS, NCEP */ 1570 meta->subcenter = 14; /* NWS Meteorological Development Laboratory */ 1571 1572 /* strftime (meta->refTime, 20, "%Y%m%d%H%M", 1573 gmtime (&(meta->pdsTdlp.refTime))); 1574 */ 1575 Clock_Print (meta->refTime, 20, meta->pdsTdlp.refTime, "%Y%m%d%H%M", 0); 1576 1577 /* 1578 validTime = meta->pdsTdlp.refTime + meta->pdsTdlp.project; 1579 strftime (meta->validTime, 20, "%Y%m%d%H%M", gmtime (&(validTime))); 1580 */ 1581 Clock_Print (meta->validTime, 20, meta->pdsTdlp.refTime + 1582 meta->pdsTdlp.project, "%Y%m%d%H%M", 0); 1583 1584 meta->deltTime = meta->pdsTdlp.project; 1585 1586 /* Get the Grid Definition Section. */ 1587 if (f_gds) { 1588 if (ReadTDLPSect2 (c_ipack + curLoc, tdlpLen, &curLoc, 1589 &(meta->gds)) != 0) { 1590 preErrSprintf ("Inside ReadGrib1Record\n"); 1591 return -2; 1592 } 1593 } else { 1594 errSprintf ("Don't know how to handle vector data yet.\n"); 1595 return -2; 1596 } 1597 1598 /* Allow over ride of the earth radii. */ 1599 if ((majEarth > 6300) && (majEarth < 6400)) { 1600 if ((minEarth > 6300) && (minEarth < 6400)) { 1601 meta->gds.f_sphere = 0; 1602 meta->gds.majEarth = majEarth; 1603 meta->gds.minEarth = minEarth; 1604 if (majEarth == minEarth) { 1605 meta->gds.f_sphere = 1; 1606 } 1607 } else { 1608 meta->gds.f_sphere = 1; 1609 meta->gds.majEarth = majEarth; 1610 meta->gds.minEarth = majEarth; 1611 } 1612 } 1613 1614 /* Allocate memory for the grid. */ 1615 if (meta->gds.numPts > *tdlp_DataLen) { 1616 *tdlp_DataLen = meta->gds.numPts; 1617 *TDLP_Data = (double *) realloc ((void *) (*TDLP_Data), 1618 (*tdlp_DataLen) * sizeof (double)); 1619 } 1620 tdlp_Data = *TDLP_Data; 1621 1622 /* Get the Bit Map Section. */ 1623 if (f_bms) { 1624 /* errSprintf ("Bitmap data is Not Supported\n");*/ 1625 /* Need to allocate bitmap when this is implemented. */ 1626 bitmap = nullptr; 1627 ReadTDLPSect3 (c_ipack + curLoc, tdlpLen, &curLoc, bitmap, 1628 meta->gds.numPts); 1629 return -1; 1630 } 1631 1632 /* Read the GRID. */ 1633 if (ReadTDLPSect4 (c_ipack + curLoc, tdlpLen, &curLoc, DSF, BSF, 1634 tdlp_Data, meta, unitM, unitB) != 0) { 1635 preErrSprintf ("Inside ReadTDLPRecord\n"); 1636 return -4; 1637 } 1638 1639 /* Read section 5. If it is "7777" == 926365495 we are done. */ 1640 memcpy (&li_temp, c_ipack + curLoc, 4); 1641 if (li_temp != 926365495L) { 1642 errSprintf ("Did not find the end of the message.\n"); 1643 return -5; 1644 } 1645 curLoc += 4; 1646 /* Read the trailing part of the message. */ 1647 /* TDLPack uses 4 bytes for FORTRAN record size, then another 8 bytes for 1648 * the size of the record (so FORTRAN can see it), then the data rounded 1649 * up to an 8 byte boundary, then a trailing 4 bytes for a final FORTRAN 1650 * record size. However it only stores in the gribLen the non-rounded 1651 * amount, so we need to take care of the rounding, and the trailing 4 1652 * bytes here. */ 1653 pad = ((sInt4) (ceil (tdlpLen / 8.0))) * 8 - tdlpLen + 4; 1654 if (fp.DataSourceFread(buffer, sizeof (char), pad) != pad) { 1655 errSprintf ("Ran out of file\n"); 1656 return -1; 1657 } 1658 return 0; 1659 } 1660 1661 #ifdef unused_by_GDAL 1662 1663 /***************************************************************************** 1664 * TDL_ScaleData() -- 1665 * 1666 * Arthur Taylor / MDL 1667 * 1668 * PURPOSE 1669 * Deal with scaling while excluding the primary and secondary missing 1670 * values. After this, dst should contain scaled data + primary or secondary 1671 * missing values 1672 * "tdlpack library"::pack2d.f line 257 or search for: 1673 "the above statement" 1674 * 1675 * ARGUMENTS 1676 * Src = The original data. (Input) 1677 * Dst = The scaled data. (Output) 1678 * numData = The number of elements in data. (Input) 1679 * DSF = Decimal Scale Factor for scaling the data. (Input) 1680 * BSF = Binary Scale Factor for scaling the data. (Input) 1681 * f_primMiss = Flag saying if we have a primary missing value (In/Out) 1682 * primMiss = primary missing value. (In/Out) 1683 * f_secMiss = Flag saying if we have a secondary missing value (In/Out) 1684 * secMiss = secondary missing value. (In/Out) 1685 * f_min = Flag saying if we have the minimum value. (Output) 1686 * min = minimum scaled value in the grid. (Output) 1687 * 1688 * FILES/DATABASES: None 1689 * 1690 * RETURNS: void 1691 * 1692 * HISTORY 1693 * 12/2004 Arthur Taylor (MDL): Updated from "group.c" in "C" tdlpack code. 1694 * 1695 * NOTES 1696 ***************************************************************************** 1697 */ 1698 #define SCALE_MISSING 10000 1699 static void TDL_ScaleData (double *Src, sInt4 *Dst, sInt4 numData, 1700 int DSF, int BSF, char *f_primMiss, 1701 double *primMiss, char *f_secMiss, 1702 double *secMiss, char *f_min, sInt4 *min) 1703 { 1704 sInt4 cnt; 1705 double *src = Src; 1706 sInt4 *dst = Dst; 1707 double scale = pow (10.0, -1 * DSF) * pow (2.0, -1 * BSF); 1708 char f_actualPrim = 0; 1709 char f_actualSec = 0; 1710 sInt4 li_primMiss = (sInt4) (*primMiss * SCALE_MISSING + .5); 1711 sInt4 li_secMiss = (sInt4) (*secMiss * SCALE_MISSING + .5); 1712 1713 *f_min = 0; 1714 for (cnt = 0; cnt < numData; cnt++) { 1715 if (((*f_primMiss) || (*f_secMiss)) && (*src == *primMiss)) { 1716 *(dst++) = li_primMiss; 1717 src++; 1718 f_actualPrim = 1; 1719 } else if ((*f_secMiss) && (*src == *secMiss)) { 1720 *(dst++) = li_secMiss; 1721 src++; 1722 f_actualSec = 1; 1723 } else { 1724 *(dst) = (sInt4) (floor ((*(src++) / scale) + .5)); 1725 /* Check if scaled value == primary missing value. */ 1726 if (((*f_primMiss) || (*f_secMiss)) && (*dst == li_primMiss)) { 1727 *dst = *dst - 1; 1728 } 1729 /* Check if scaled value == secondary missing value. */ 1730 if ((*f_secMiss) && (*dst == li_secMiss)) { 1731 *dst = *dst - 1; 1732 /* Check if adjustment caused scaled value == primary missing. */ 1733 if (*dst == li_primMiss) { 1734 *dst = *dst - 1; 1735 } 1736 } 1737 if (!(*f_min)) { 1738 *min = *dst; 1739 *f_min = 1; 1740 } else if (*min > *dst) { 1741 *min = *dst; 1742 } 1743 dst++; 1744 } 1745 } 1746 if ((*f_secMiss) && (!f_actualSec)) { 1747 *f_secMiss = 0; 1748 } 1749 if (((*f_secMiss) || (*f_primMiss)) && (!f_actualPrim)) { 1750 *f_primMiss = 0; 1751 /* Check consistency. */ 1752 if (*f_secMiss) { 1753 *f_secMiss = 0; 1754 *f_primMiss = 1; 1755 *primMiss = *secMiss; 1756 } 1757 } 1758 } 1759 1760 /***************************************************************************** 1761 * TDL_ReorderGrid() -- 1762 * 1763 * Arthur Taylor / MDL 1764 * 1765 * PURPOSE 1766 * Loop through the data, so that 1767 * data is: "a1,1 ... a1,n a2,n ... a2,1 ..." 1768 * instead of: "a1,1 ... a1,n a2,1 ... a2,n ..." 1769 * 1770 * ARGUMENTS 1771 * Src = The data. (Input/Output) 1772 * NX = The number of X values. (Input) 1773 * NY = The number of Y values. (Input) 1774 * 1775 * FILES/DATABASES: None 1776 * 1777 * RETURNS: void 1778 * 1779 * HISTORY 1780 * 12/2004 Arthur Taylor (MDL): Updated from "group.c" in "C" tdlpack code. 1781 * 1782 * NOTES 1783 ***************************************************************************** 1784 */ 1785 static void TDL_ReorderGrid (sInt4 *Src, short int NX, short int NY) 1786 { 1787 int i, j; 1788 sInt4 *src1, *src2; 1789 sInt4 li_temp; 1790 1791 for (j = 1; j < NY; j += 2) { 1792 src1 = Src + j * NX; 1793 src2 = Src + (j + 1) * NX - 1; 1794 for (i = 0; i < (NX / 2); i++) { 1795 li_temp = *src1; 1796 *(src1++) = *src2; 1797 *(src2--) = li_temp; 1798 } 1799 } 1800 } 1801 1802 /***************************************************************************** 1803 * TDL_GetSecDiff() -- 1804 * 1805 * Arthur Taylor / MDL 1806 * 1807 * PURPOSE 1808 * Get the second order difference where we have special values for missing, 1809 * and for actual data we have the following scheme. 1810 * Data: a1 a2 a3 a4 a5 ... 1811 * 1st diff: 0 b2 b3 b4 b5 ... 1812 * 2nd diff: UK1 UK2 c3 c4 c5 ... 1813 * where UK1 = c3 + b2, and UK2 = c3 + 2 * b2. Note: The choice of UK1, and 1814 * UK2 doesn't matter because of the following FORTRAN unpacking code: 1815 * IWORK(1)=IFIRST 1816 * IWORK(2)=IWORK(1)+IFOD 1817 * ISUM=IFOD 1818 * DO 385 K=3,IS4(3) 1819 * ISUM=IWORK(K)+ISUM 1820 * IWORK(K)=IWORK(K-1)+ISUM 1821 * 385 CONTINUE 1822 * So ISUM is a function of IWORK(3), not IWORK(1). 1823 * 1824 * ARGUMENTS 1825 * Data = The data. (Input) 1826 * numData = The number of elements in data. (Input) 1827 * SecDiff = The secondary differences of the data. (Output) 1828 * f_primMiss = Flag saying if we have a primary missing value (Input) 1829 * li_primMiss = Scaled primary missing value. (Input) 1830 * a1 = First non-missing value in the field. (Output) 1831 * b2 = First non-missing value in the 1st order delta field (Out) 1832 * min = The minimum value (Input). 1833 * 1834 * FILES/DATABASES: None 1835 * 1836 * RETURNS: int 1837 * 0 = Success 1838 * 1 = Couldn't find second differences (don't use). 1839 * 1840 * HISTORY 1841 * 12/2004 Arthur Taylor (MDL): Updated from "group.c" in "C" tdlpack code. 1842 * 1843 * NOTES 1844 ***************************************************************************** 1845 */ 1846 static int TDL_GetSecDiff (sInt4 *Data, int numData, sInt4 *SecDiff, 1847 char f_primMiss, sInt4 li_primMiss, 1848 sInt4 *a1, sInt4 *b2, sInt4 *min) 1849 { 1850 int i; 1851 char f_min = 0; 1852 sInt4 last = 0, before_last = 0; 1853 int a1Index = -1; 1854 int a2Index = -1; 1855 1856 if (numData < 3) { 1857 return 1; 1858 } 1859 if (f_primMiss) { 1860 for (i = 0; i < numData; i++) { 1861 if (Data[i] == li_primMiss) { 1862 SecDiff[i] = li_primMiss; 1863 } else if (a1Index == -1) { 1864 a1Index = i; 1865 *a1 = Data[a1Index]; 1866 } else if (a2Index == -1) { 1867 a2Index = i; 1868 *b2 = Data[a2Index] - Data[a1Index]; 1869 before_last = Data[a1Index]; 1870 last = Data[a2Index]; 1871 } else { 1872 SecDiff[i] = Data[i] - 2 * last + before_last; 1873 before_last = last; 1874 last = Data[i]; 1875 if (!f_min) { 1876 /* Set the UK1, UK2 values. */ 1877 *min = SecDiff[i]; 1878 f_min = 1; 1879 SecDiff[a1Index] = SecDiff[i] + *b2; 1880 SecDiff[a2Index] = SecDiff[i] + 2 * (*b2); 1881 } else if (*min > SecDiff[i]) { 1882 *min = SecDiff[i]; 1883 } 1884 } 1885 } 1886 if (!f_min) { 1887 return 1; 1888 } 1889 } else { 1890 *a1 = Data[0]; 1891 *b2 = Data[1] - Data[0]; 1892 for (i = 3; i < numData; i++) { 1893 SecDiff[i] = Data[i] - 2 * Data[i - 1] - Data[i - 2]; 1894 if (i == 3) { 1895 *min = SecDiff[i]; 1896 /* Set the UK1, UK2 values. */ 1897 SecDiff[0] = SecDiff[i] + *b2; 1898 SecDiff[1] = SecDiff[i] + 2 * (*b2); 1899 } else if (*min > SecDiff[i]) { 1900 *min = SecDiff[i]; 1901 } 1902 } 1903 } 1904 return 0; 1905 } 1906 1907 /***************************************************************************** 1908 * TDL_UseSecDiff_Prim() -- 1909 * 1910 * Arthur Taylor / MDL 1911 * 1912 * PURPOSE 1913 * Checks if the average range of 2nd order differences < average range of 1914 * 0 order differences, to determine if we should use second order 1915 * differences. This deals with the case when we have primary missing values. 1916 * 1917 * ARGUMENTS 1918 * Data = The data. (Input) 1919 * numData = The number of elements in data. (Input) 1920 * SecDiff = The secondary differences of the data. (Input) 1921 * li_primMiss = Scaled primary missing value. (Input) 1922 * minGroup = The minimum group size. (Input) 1923 * 1924 * FILES/DATABASES: None 1925 * 1926 * RETURNS: int 1927 * 0 = Don't use 2nd order differences. 1928 * 1 = Use 2nd order differences. 1929 * 1930 * HISTORY 1931 * 12/2004 Arthur Taylor (MDL): Updated from "group.c" in "C" tdlpack code. 1932 * 1933 * NOTES 1934 ***************************************************************************** 1935 */ 1936 static int TDL_UseSecDiff_Prim (sInt4 *Data, sInt4 numData, 1937 sInt4 *SecDiff, sInt4 li_primMiss, 1938 int minGroup) 1939 { 1940 int i, locCnt; 1941 int range0, range2; 1942 int tot0, tot2; 1943 char f_min; 1944 sInt4 min = 0, max = 0; 1945 1946 locCnt = 0; 1947 range0 = 0; 1948 tot0 = 0; 1949 f_min = 0; 1950 /* Compute scores for no differences */ 1951 for (i = 0; i < numData; i++) { 1952 if (Data[i] != li_primMiss) { 1953 if (!f_min) { 1954 min = Data[i]; 1955 max = Data[i]; 1956 f_min = 1; 1957 } else { 1958 if (min > Data[i]) 1959 min = Data[i]; 1960 if (max < Data[i]) 1961 max = Data[i]; 1962 } 1963 } 1964 locCnt++; 1965 /* Fake a "group" by using the minimum group size. */ 1966 if (locCnt == minGroup) { 1967 if (f_min) { 1968 range0 += (max - min); 1969 tot0++; 1970 f_min = 0; 1971 } 1972 locCnt = 0; 1973 } 1974 } 1975 if (locCnt != 0) { 1976 range0 += (max - min); 1977 tot0++; 1978 } 1979 1980 locCnt = 0; 1981 range2 = 0; 1982 tot2 = 0; 1983 f_min = 0; 1984 /* Compute scores for second order differences */ 1985 for (i = 0; i < numData; i++) { 1986 if (SecDiff[i] != li_primMiss) { 1987 if (!f_min) { 1988 min = SecDiff[i]; 1989 max = SecDiff[i]; 1990 f_min = 1; 1991 } else { 1992 if (min > SecDiff[i]) 1993 min = SecDiff[i]; 1994 if (max < SecDiff[i]) 1995 max = SecDiff[i]; 1996 } 1997 } 1998 locCnt++; 1999 /* Fake a "group" by using the minimum group size. */ 2000 if (locCnt == minGroup) { 2001 if (f_min) { 2002 range2 += (max - min); 2003 tot2++; 2004 f_min = 0; 2005 } 2006 locCnt = 0; 2007 } 2008 } 2009 if (locCnt != 0) { 2010 range2 += (max - min); 2011 tot2++; 2012 } 2013 2014 /* Compare average group size of no differencing to second order. */ 2015 if ((range0 / (tot0 + 0.0)) <= (range2 / (tot2 + 0.0))) { 2016 return 0; 2017 } else { 2018 return 1; 2019 } 2020 } 2021 2022 /***************************************************************************** 2023 * TDL_UseSecDiff() -- 2024 * 2025 * Arthur Taylor / MDL 2026 * 2027 * PURPOSE 2028 * Checks if the average range of 2nd order differences < average range of 2029 * 0 order differences, to determine if we should use second order 2030 * differences. 2031 * 2032 * ARGUMENTS 2033 * Data = The data. (Input) 2034 * numData = The number of elements in data. (Input) 2035 * SecDiff = The secondary differences of the data. (Input) 2036 * minGroup = The minimum group size. (Input) 2037 * 2038 * FILES/DATABASES: None 2039 * 2040 * RETURNS: int 2041 * 0 = Don't use 2nd order differences. 2042 * 1 = Use 2nd order differences. 2043 * 2044 * HISTORY 2045 * 12/2004 Arthur Taylor (MDL): Updated from "group.c" in "C" tdlpack code. 2046 * 2047 * NOTES 2048 ***************************************************************************** 2049 */ 2050 static int TDL_UseSecDiff (sInt4 *Data, sInt4 numData, 2051 sInt4 *SecDiff, int minGroup) 2052 { 2053 int i, locCnt; 2054 int range0, range2; 2055 int tot0, tot2; 2056 sInt4 min = 0, max = 0; 2057 2058 locCnt = 0; 2059 range0 = 0; 2060 tot0 = 0; 2061 /* Compute scores for no differences */ 2062 for (i = 0; i < numData; i++) { 2063 if (locCnt == 0) { 2064 min = Data[i]; 2065 max = Data[i]; 2066 } else { 2067 if (min > Data[i]) 2068 min = Data[i]; 2069 if (max < Data[i]) 2070 max = Data[i]; 2071 } 2072 locCnt++; 2073 /* Fake a "group" by using the minimum group size. */ 2074 if (locCnt == minGroup) { 2075 range0 += (max - min); 2076 tot0++; 2077 locCnt = 0; 2078 } 2079 } 2080 if (locCnt != 0) { 2081 range0 += (max - min); 2082 tot0++; 2083 } 2084 2085 locCnt = 0; 2086 range2 = 0; 2087 tot2 = 0; 2088 /* Compute scores for second order differences */ 2089 for (i = 0; i < numData; i++) { 2090 if (locCnt == 0) { 2091 min = SecDiff[i]; 2092 max = SecDiff[i]; 2093 } else { 2094 if (min > SecDiff[i]) 2095 min = SecDiff[i]; 2096 if (max < SecDiff[i]) 2097 max = SecDiff[i]; 2098 } 2099 locCnt++; 2100 /* Fake a "group" by using the minimum group size. */ 2101 if (locCnt == minGroup) { 2102 range2 += (max - min); 2103 tot2++; 2104 locCnt = 0; 2105 } 2106 } 2107 if (locCnt != 0) { 2108 range2 += (max - min); 2109 tot2++; 2110 } 2111 2112 /* Compare average group size of no differencing to second order. */ 2113 if ((range0 / (tot0 + 0.0)) <= (range2 / (tot2 + 0.0))) { 2114 return 0; 2115 } else { 2116 return 1; 2117 } 2118 } 2119 2120 /***************************************************************************** 2121 * power() -- 2122 * 2123 * Arthur Taylor / MDL 2124 * 2125 * PURPOSE 2126 * Calculate the number of bits required to store a given positive number. 2127 * 2128 * ARGUMENTS 2129 * val = The number to store (Input) 2130 * extra = number of slots to allocate for prim/sec missing values (Input) 2131 * 2132 * FILES/DATABASES: None 2133 * 2134 * RETURNS: int 2135 * The number of bits needed to store this number. 2136 * 2137 * HISTORY 2138 * 12/2004 Arthur Taylor (MDL): Updated from "group.c" in "C" tdlpack code. 2139 * 2140 * NOTES 2141 ***************************************************************************** 2142 */ 2143 static int power (uInt4 val, int extra) 2144 { 2145 int i; 2146 2147 val += extra; 2148 if (val == 0) { 2149 return 1; 2150 } 2151 for (i = 0; val != 0; i++) { 2152 val = val >> 1; 2153 } 2154 return i; 2155 } 2156 2157 /***************************************************************************** 2158 * findMaxMin2() -- 2159 * 2160 * Arthur Taylor / MDL 2161 * 2162 * PURPOSE 2163 * Find the min/max value between start/stop index values in the data 2164 * Assuming primary and secondary missing values. 2165 * 2166 * ARGUMENTS 2167 * Data = The data. (Input) 2168 * start = The starting index in data (Input) 2169 * stop = The stopping index in data (Input) 2170 * li_primMiss = scaled primary missing value (Input) 2171 * li_secMiss = scaled secondary missing value (Input) 2172 * min = The min value found (Output) 2173 * max = The max value found (Output) 2174 * 2175 * FILES/DATABASES: None 2176 * 2177 * RETURNS: char 2178 * Flag if min/max are valid. 2179 * 2180 * HISTORY 2181 * 12/2004 Arthur Taylor (MDL): Updated from "group.c" in "C" tdlpack code. 2182 * 2183 * NOTES 2184 ***************************************************************************** 2185 */ 2186 static char findMaxMin2 (sInt4 *Data, int start, int stop, 2187 sInt4 li_primMiss, sInt4 li_secMiss, 2188 sInt4 *min, sInt4 *max) 2189 { 2190 char f_min = 0; /* Flag if we found the max/min values */ 2191 int i; /* Loop counter. */ 2192 2193 *max = *min = Data[start]; 2194 for (i = start; i < stop; i++) { 2195 if ((Data[i] != li_secMiss) && (Data[i] != li_primMiss)) { 2196 if (!f_min) { 2197 *max = Data[i]; 2198 *min = Data[i]; 2199 f_min = 1; 2200 } else { 2201 if (*max < Data[i]) { 2202 *max = Data[i]; 2203 } else if (*min > Data[i]) { 2204 *min = Data[i]; 2205 } 2206 } 2207 } 2208 } 2209 return f_min; 2210 } 2211 2212 /***************************************************************************** 2213 * findMaxMin1() -- 2214 * 2215 * Arthur Taylor / MDL 2216 * 2217 * PURPOSE 2218 * Find the min/max value between start/stop index values in the data 2219 * Assuming primary missing values. 2220 * 2221 * ARGUMENTS 2222 * Data = The data. (Input) 2223 * start = The starting index in data (Input) 2224 * stop = The stopping index in data (Input) 2225 * li_primMiss = scaled primary missing value (Input) 2226 * min = The min value found (Output) 2227 * max = The max value found (Output) 2228 * 2229 * FILES/DATABASES: None 2230 * 2231 * RETURNS: char 2232 * Flag if min/max are valid. 2233 * 2234 * HISTORY 2235 * 12/2004 Arthur Taylor (MDL): Updated from "group.c" in "C" tdlpack code. 2236 * 2237 * NOTES 2238 ***************************************************************************** 2239 */ 2240 static char findMaxMin1 (sInt4 *Data, int start, int stop, 2241 sInt4 li_primMiss, sInt4 *min, sInt4 *max) 2242 { 2243 char f_min = 0; /* Flag if we found the max/min values */ 2244 int i; /* Loop counter. */ 2245 2246 *max = *min = Data[start]; 2247 for (i = start; i < stop; i++) { 2248 if (Data[i] != li_primMiss) { 2249 if (!f_min) { 2250 *max = Data[i]; 2251 *min = Data[i]; 2252 f_min = 1; 2253 } else { 2254 if (*max < Data[i]) { 2255 *max = Data[i]; 2256 } else if (*min > Data[i]) { 2257 *min = Data[i]; 2258 } 2259 } 2260 } 2261 } 2262 return f_min; 2263 } 2264 2265 /***************************************************************************** 2266 * findMaxMin0() -- 2267 * 2268 * Arthur Taylor / MDL 2269 * 2270 * PURPOSE 2271 * Find the min/max value between start/stop index values in the data 2272 * Assuming no missing values. 2273 * 2274 * ARGUMENTS 2275 * Data = The data. (Input) 2276 * start = The starting index in data (Input) 2277 * stop = The stopping index in data (Input) 2278 * min = The min value found (Output) 2279 * max = The max value found (Output) 2280 * 2281 * FILES/DATABASES: None 2282 * 2283 * RETURNS: void 2284 * 2285 * HISTORY 2286 * 12/2004 Arthur Taylor (MDL): Updated from "group.c" in "C" tdlpack code. 2287 * 2288 * NOTES 2289 ***************************************************************************** 2290 */ 2291 static void findMaxMin0 (sInt4 *Data, int start, int stop, sInt4 *min, 2292 sInt4 *max) 2293 { 2294 int i; /* Loop counter. */ 2295 2296 *max = *min = Data[start]; 2297 for (i = start + 1; i < stop; i++) { 2298 if (*max < Data[i]) { 2299 *max = Data[i]; 2300 } else if (*min > Data[i]) { 2301 *min = Data[i]; 2302 } 2303 } 2304 } 2305 2306 /***************************************************************************** 2307 * findGroup2() -- 2308 * 2309 * Arthur Taylor / MDL 2310 * 2311 * PURPOSE 2312 * Find "split" so that the numbers between start and split are within 2313 * "range" of each other... stops if it reaches "stop". 2314 * Assumes primary and secondary missing values. 2315 * 2316 * ARGUMENTS 2317 * Data = The data. (Input) 2318 * start = The starting index in data (Input) 2319 * stop = The stopping index in data (Input) 2320 * li_primMiss = scaled primary missing value (Input) 2321 * li_secMiss = scaled secondary missing value (Input) 2322 * range = The range to use (Input) 2323 * split = The first index that is out of the range (Output) 2324 * min = The min value for the group. (Output) 2325 * max = The max value for the group. (Output) 2326 * 2327 * FILES/DATABASES: None 2328 * 2329 * RETURNS: void 2330 * 2331 * HISTORY 2332 * 1/2005 Arthur Taylor (MDL): Created 2333 * 2334 * NOTES 2335 ***************************************************************************** 2336 */ 2337 static void findGroup2 (sInt4 *Data, int start, int stop, 2338 sInt4 li_primMiss, sInt4 li_secMiss, 2339 sInt4 range, int *split, sInt4 *min, sInt4 *max) 2340 { 2341 char f_min = 0; /* Flag if we found the max/min values */ 2342 int i; /* Loop counter. */ 2343 2344 *min = *max = 0; 2345 for (i = start; i < stop; i++) { 2346 if ((Data[i] != li_secMiss) && (Data[i] != li_primMiss)) { 2347 if (!f_min) { 2348 *max = *min = Data[i]; 2349 f_min = 1; 2350 } else { 2351 if (*max < Data[i]) { 2352 if ((Data[i] - *min) > range) { 2353 *split = i; 2354 return; 2355 } 2356 *max = Data[i]; 2357 } else if (*min > Data[i]) { 2358 if ((*max - Data[i]) > range) { 2359 *split = i; 2360 return; 2361 } 2362 *min = Data[i]; 2363 } 2364 } 2365 } 2366 } 2367 *split = stop; 2368 } 2369 2370 /***************************************************************************** 2371 * findGroup1() -- 2372 * 2373 * Arthur Taylor / MDL 2374 * 2375 * PURPOSE 2376 * Find "split" so that the numbers between start and split are within 2377 * "range" of each other... stops if it reaches "stop". 2378 * Assumes primary missing values. 2379 * 2380 * ARGUMENTS 2381 * Data = The data. (Input) 2382 * start = The starting index in data (Input) 2383 * stop = The stopping index in data (Input) 2384 * li_primMiss = scaled primary missing value (Input) 2385 * range = The range to use (Input) 2386 * split = The first index that is out of the range (Output) 2387 * min = The min value for the group. (Output) 2388 * max = The max value for the group. (Output) 2389 * 2390 * FILES/DATABASES: None 2391 * 2392 * RETURNS: void 2393 * 2394 * HISTORY 2395 * 1/2005 Arthur Taylor (MDL): Created 2396 * 2397 * NOTES 2398 ***************************************************************************** 2399 */ 2400 static void findGroup1 (sInt4 *Data, int start, int stop, 2401 sInt4 li_primMiss, sInt4 range, int *split, 2402 sInt4 *min, sInt4 *max) 2403 { 2404 char f_min = 0; /* Flag if we found the max/min values */ 2405 int i; /* Loop counter. */ 2406 2407 *min = *max = 0; 2408 for (i = start; i < stop; i++) { 2409 if (Data[i] != li_primMiss) { 2410 if (!f_min) { 2411 *max = *min = Data[i]; 2412 f_min = 1; 2413 } else { 2414 if (*max < Data[i]) { 2415 if ((Data[i] - *min) > range) { 2416 *split = i; 2417 return; 2418 } 2419 *max = Data[i]; 2420 } else if (*min > Data[i]) { 2421 if ((*max - Data[i]) > range) { 2422 *split = i; 2423 return; 2424 } 2425 *min = Data[i]; 2426 } 2427 } 2428 } 2429 } 2430 *split = stop; 2431 } 2432 2433 /***************************************************************************** 2434 * findGroup0() -- 2435 * 2436 * Arthur Taylor / MDL 2437 * 2438 * PURPOSE 2439 * Find "split" so that the numbers between start and split are within 2440 * "range" of each other... stops if it reaches "stop". 2441 * Assumes no missing values. 2442 * 2443 * ARGUMENTS 2444 * Data = The data. (Input) 2445 * start = The starting index in data (Input) 2446 * stop = The stopping index in data (Input) 2447 * range = The range to use (Input) 2448 * split = The first index that is out of the range (Output) 2449 * min = The min value for the group. (Output) 2450 * max = The max value for the group. (Output) 2451 * 2452 * FILES/DATABASES: None 2453 * 2454 * RETURNS: void 2455 * 2456 * HISTORY 2457 * 1/2005 Arthur Taylor (MDL): Created 2458 * 2459 * NOTES 2460 ***************************************************************************** 2461 */ 2462 static void findGroup0 (sInt4 *Data, int start, int stop, 2463 sInt4 range, int *split, sInt4 *min, sInt4 *max) 2464 { 2465 int i; /* Loop counter. */ 2466 2467 *max = *min = Data[0]; 2468 for (i = start + 1; i < stop; i++) { 2469 if (*max < Data[i]) { 2470 if ((Data[i] - *min) > range) { 2471 *split = i; 2472 return; 2473 } 2474 *max = Data[i]; 2475 } else if (*min > Data[i]) { 2476 if ((*max - Data[i]) > range) { 2477 *split = i; 2478 return; 2479 } 2480 *min = Data[i]; 2481 } 2482 } 2483 *split = stop; 2484 } 2485 2486 /***************************************************************************** 2487 * findGroupRev2() -- 2488 * 2489 * Arthur Taylor / MDL 2490 * 2491 * PURPOSE 2492 * Find "split" so that the numbers between split and stop are within 2493 * "range" of each other... stops if it reaches "start". 2494 * Assumes primary and secondary missing values. 2495 * 2496 * ARGUMENTS 2497 * Data = The data. (Input) 2498 * start = The starting index in data (Input) 2499 * stop = The stopping index in data (Input) 2500 * li_primMiss = scaled primary missing value (Input) 2501 * li_secMiss = scaled secondary missing value (Input) 2502 * range = The range to use (Input) 2503 * split = The first index that is still in the range (Output) 2504 * min = The min value for the group. (Output) 2505 * max = The max value for the group. (Output) 2506 * 2507 * FILES/DATABASES: None 2508 * 2509 * RETURNS: void 2510 * 2511 * HISTORY 2512 * 1/2005 Arthur Taylor (MDL): Created 2513 * 2514 * NOTES 2515 ***************************************************************************** 2516 */ 2517 static void findGroupRev2 (sInt4 *Data, int start, int stop, 2518 sInt4 li_primMiss, sInt4 li_secMiss, 2519 sInt4 range, int *split, sInt4 *min, sInt4 *max) 2520 { 2521 char f_min = 0; /* Flag if we found the max/min values */ 2522 int i; /* Loop counter. */ 2523 2524 *min = *max = 0; 2525 for (i = stop - 1; i >= start; i--) { 2526 if ((Data[i] != li_secMiss) && (Data[i] != li_primMiss)) { 2527 if (!f_min) { 2528 *max = *min = Data[i]; 2529 f_min = 1; 2530 } else { 2531 if (*max < Data[i]) { 2532 if ((Data[i] - *min) > range) { 2533 *split = i + 1; 2534 return; 2535 } 2536 *max = Data[i]; 2537 } else if (*min > Data[i]) { 2538 if ((*max - Data[i]) > range) { 2539 *split = i + 1; 2540 return; 2541 } 2542 *min = Data[i]; 2543 } 2544 } 2545 } 2546 } 2547 *split = start; 2548 } 2549 2550 /***************************************************************************** 2551 * findGroupRev1() -- 2552 * 2553 * Arthur Taylor / MDL 2554 * 2555 * PURPOSE 2556 * Find "split" so that the numbers between split and stop are within 2557 * "range" of each other... stops if it reaches "start". 2558 * Assumes primary missing values. 2559 * 2560 * ARGUMENTS 2561 * Data = The data. (Input) 2562 * start = The starting index in data (Input) 2563 * stop = The stopping index in data (Input) 2564 * li_primMiss = scaled primary missing value (Input) 2565 * range = The range to use (Input) 2566 * split = The first index that is still in the range (Output) 2567 * min = The min value for the group. (Output) 2568 * max = The max value for the group. (Output) 2569 * 2570 * FILES/DATABASES: None 2571 * 2572 * RETURNS: void 2573 * 2574 * HISTORY 2575 * 1/2005 Arthur Taylor (MDL): Created 2576 * 2577 * NOTES 2578 ***************************************************************************** 2579 */ 2580 static void findGroupRev1 (sInt4 *Data, int start, int stop, 2581 sInt4 li_primMiss, sInt4 range, int *split, 2582 sInt4 *min, sInt4 *max) 2583 { 2584 char f_min = 0; /* Flag if we found the max/min values */ 2585 int i; /* Loop counter. */ 2586 2587 *min = *max = 0; 2588 for (i = stop - 1; i >= start; i--) { 2589 if (Data[i] != li_primMiss) { 2590 if (!f_min) { 2591 *max = *min = Data[i]; 2592 f_min = 1; 2593 } else { 2594 if (*max < Data[i]) { 2595 if ((Data[i] - *min) > range) { 2596 *split = i + 1; 2597 return; 2598 } 2599 *max = Data[i]; 2600 } else if (*min > Data[i]) { 2601 if ((*max - Data[i]) > range) { 2602 *split = i + 1; 2603 return; 2604 } 2605 *min = Data[i]; 2606 } 2607 } 2608 } 2609 } 2610 *split = start; 2611 } 2612 2613 /***************************************************************************** 2614 * findGroupRev0() -- 2615 * 2616 * Arthur Taylor / MDL 2617 * 2618 * PURPOSE 2619 * Find "split" so that the numbers between split and stop are within 2620 * "range" of each other... stops if it reaches "start". 2621 * Assumes no missing values. 2622 * 2623 * ARGUMENTS 2624 * Data = The data. (Input) 2625 * start = The starting index in data (Input) 2626 * stop = The stopping index in data (Input) 2627 * li_primMiss = scaled primary missing value (Input) 2628 * range = The range to use (Input) 2629 * split = The first index that is still in the range (Output) 2630 * min = The min value for the group. (Output) 2631 * max = The max value for the group. (Output) 2632 * 2633 * FILES/DATABASES: None 2634 * 2635 * RETURNS: void 2636 * 2637 * HISTORY 2638 * 1/2005 Arthur Taylor (MDL): Created 2639 * 2640 * NOTES 2641 ***************************************************************************** 2642 */ 2643 static void findGroupRev0 (sInt4 *Data, int start, int stop, 2644 sInt4 range, int *split, sInt4 *min, sInt4 *max) 2645 { 2646 int i; /* Loop counter. */ 2647 2648 *max = *min = Data[stop - 1]; 2649 for (i = stop - 2; i >= start; i--) { 2650 if (*max < Data[i]) { 2651 if ((Data[i] - *min) > range) { 2652 *split = i + 1; 2653 return; 2654 } 2655 *max = Data[i]; 2656 } else if (*min > Data[i]) { 2657 if ((*max - Data[i]) > range) { 2658 *split = i + 1; 2659 return; 2660 } 2661 *min = Data[i]; 2662 } 2663 } 2664 *split = start; 2665 } 2666 2667 /***************************************************************************** 2668 * shiftGroup2() -- 2669 * 2670 * Arthur Taylor / MDL 2671 * 2672 * PURPOSE 2673 * Find "split" so that the numbers between split and start1 are all inside 2674 * the range defined by max, min and bit. It allows max and min to change, 2675 * as long as it doesn't exceed the range defined by bit. 2676 * This is very similar to findGroupRev?() but here we already know 2677 * information about the min/max values, and are just expanding the group a 2678 * little, while the other one knew nothing about the group, and just wanted 2679 * a group of a given range. 2680 * Assumes primary and secondary missing values. 2681 * 2682 * ARGUMENTS 2683 * Data = The data. (Input) 2684 * start1 = The starting index in data (Input) 2685 * start2 = The starting index of the earlier group (i.e. don't go to any 2686 * earlier indices than this. (Input) 2687 * li_primMiss = scaled primary missing value (Input) 2688 * li_secMiss = scaled secondary missing value (Input) 2689 * bit = The range we are allowed to store this in. (Input) 2690 * min = The min value for the group. (Input/Output) 2691 * max = The max value for the group. (Input/Output) 2692 * split = The first index that is still in the range (Output) 2693 * 2694 * FILES/DATABASES: None 2695 * 2696 * RETURNS: void 2697 * 2698 * HISTORY 2699 * 1/2005 Arthur Taylor (MDL): Created 2700 * 2701 * NOTES 2702 ***************************************************************************** 2703 */ 2704 static void shiftGroup2 (sInt4 *Data, int start1, int start2, 2705 sInt4 li_primMiss, sInt4 li_secMiss, int bit, 2706 sInt4 *min, sInt4 *max, size_t *split) 2707 { 2708 int i; /* Loop counter. */ 2709 int range; /* The range defined by bit. */ 2710 2711 range = (int) (pow (2.0, bit) - 1) - 1; 2712 myAssert (start2 <= start1); 2713 for (i = start1; i >= start2; i--) { 2714 if ((Data[i] != li_primMiss) && (Data[i] != li_secMiss)) { 2715 if (Data[i] > *max) { 2716 if ((Data[i] - *min) <= range) { 2717 *max = Data[i]; 2718 } else { 2719 *split = i + 1; 2720 return; 2721 } 2722 } else if (Data[i] < *min) { 2723 if ((*max - Data[i]) <= range) { 2724 *min = Data[i]; 2725 } else { 2726 *split = i + 1; 2727 return; 2728 } 2729 } 2730 } 2731 } 2732 *split = start2; 2733 } 2734 2735 /***************************************************************************** 2736 * shiftGroup1() -- 2737 * 2738 * Arthur Taylor / MDL 2739 * 2740 * PURPOSE 2741 * Find "split" so that the numbers between split and start1 are all inside 2742 * the range defined by max, min and bit. It allows max and min to change, 2743 * as long as it doesn't exceed the range defined by bit. 2744 * This is very similar to findGroupRev?() but here we already know 2745 * information about the min/max values, and are just expanding the group a 2746 * little, while the other one knew nothing about the group, and just wanted 2747 * a group of a given range. 2748 * Assumes primary missing values. 2749 * 2750 * ARGUMENTS 2751 * Data = The data. (Input) 2752 * start1 = The starting index in data (Input) 2753 * start2 = The starting index of the earlier group (i.e. don't go to any 2754 * earlier indices than this. (Input) 2755 * li_primMiss = scaled primary missing value (Input) 2756 * bit = The range we are allowed to store this in. (Input) 2757 * min = The min value for the group. (Input/Output) 2758 * max = The max value for the group. (Input/Output) 2759 * split = The first index that is still in the range (Output) 2760 * 2761 * FILES/DATABASES: None 2762 * 2763 * RETURNS: void 2764 * 2765 * HISTORY 2766 * 1/2005 Arthur Taylor (MDL): Created 2767 * 2768 * NOTES 2769 ***************************************************************************** 2770 */ 2771 static void shiftGroup1 (sInt4 *Data, int start1, int start2, 2772 sInt4 li_primMiss, int bit, 2773 sInt4 *min, sInt4 *max, size_t *split) 2774 { 2775 int i; /* Loop counter. */ 2776 int range; /* The range defined by bit. */ 2777 2778 range = (int) (pow (2.0, bit) - 1) - 1; 2779 myAssert (start2 <= start1); 2780 for (i = start1; i >= start2; i--) { 2781 if (Data[i] != li_primMiss) { 2782 if (Data[i] > *max) { 2783 if ((Data[i] - *min) <= range) { 2784 *max = Data[i]; 2785 } else { 2786 *split = i + 1; 2787 return; 2788 } 2789 } else if (Data[i] < *min) { 2790 if ((*max - Data[i]) <= range) { 2791 *min = Data[i]; 2792 } else { 2793 *split = i + 1; 2794 return; 2795 } 2796 } 2797 } 2798 } 2799 *split = start2; 2800 } 2801 2802 /***************************************************************************** 2803 * shiftGroup0() -- 2804 * 2805 * Arthur Taylor / MDL 2806 * 2807 * PURPOSE 2808 * Find "split" so that the numbers between split and start1 are all inside 2809 * the range defined by max, min and bit. It allows max and min to change, 2810 * as long as it doesn't exceed the range defined by bit. 2811 * This is very similar to findGroupRev?() but here we already know 2812 * information about the min/max values, and are just expanding the group a 2813 * little, while the other one knew nothing about the group, and just wanted 2814 * a group of a given range. 2815 * Assumes no missing values. 2816 * 2817 * ARGUMENTS 2818 * Data = The data. (Input) 2819 * start1 = The starting index in data (Input) 2820 * start2 = The starting index of the earlier group (i.e. don't go to any 2821 * earlier indices than this. (Input) 2822 * bit = The range we are allowed to store this in. (Input) 2823 * min = The min value for the group. (Input/Output) 2824 * max = The max value for the group. (Input/Output) 2825 * split = The first index that is still in the range (Output) 2826 * 2827 * FILES/DATABASES: None 2828 * 2829 * RETURNS: void 2830 * 2831 * HISTORY 2832 * 1/2005 Arthur Taylor (MDL): Created 2833 * 2834 * NOTES 2835 ***************************************************************************** 2836 */ 2837 static void shiftGroup0 (sInt4 *Data, int start1, int start2, int bit, 2838 sInt4 *min, sInt4 *max, size_t *split) 2839 { 2840 int i; /* Loop counter. */ 2841 int range; /* The range defined by bit. */ 2842 2843 range = (int) (pow (2.0, bit) - 1) - 0; 2844 myAssert (start2 <= start1); 2845 for (i = start1; i >= start2; i--) { 2846 if (Data[i] > *max) { 2847 if ((Data[i] - *min) <= range) { 2848 *max = Data[i]; 2849 } else { 2850 *split = i + 1; 2851 return; 2852 } 2853 } else if (Data[i] < *min) { 2854 if ((*max - Data[i]) <= range) { 2855 *min = Data[i]; 2856 } else { 2857 *split = i + 1; 2858 return; 2859 } 2860 } 2861 } 2862 *split = start2; 2863 } 2864 2865 /***************************************************************************** 2866 * doSplit() -- 2867 * 2868 * Arthur Taylor / MDL 2869 * 2870 * PURPOSE 2871 * Reduce the "bit range", and create groups that grab as much as they can 2872 * to the right. Then reduce those groups if they improve the score. 2873 * 2874 * ARGUMENTS 2875 * Data = The data. (Input) 2876 * numData = The number of elements in data. (Input) 2877 * G = The group to split. (Input) 2878 * lclGroup = The resulting groups (Output) 2879 * numLclGroup = The number of resulting groups. (Output) 2880 * f_primMiss = Flag if we have a primary missing value (Input) 2881 * li_primMiss = scaled primary missing value (Input) 2882 * f_secMiss = Flag if we have a secondary missing value (Input) 2883 * li_secMiss = scaled secondary missing value (Input) 2884 * xFactor = Estimate of cost (in bits) of a group. (Input) 2885 * 2886 * FILES/DATABASES: None 2887 * 2888 * RETURNS: void 2889 * 2890 * HISTORY 2891 * 1/2005 Arthur Taylor (MDL): Created. 2892 * 2893 * NOTES 2894 ***************************************************************************** 2895 */ 2896 static void doSplit (sInt4 *Data, 2897 CPL_UNUSED int numData, 2898 TDLGroupType * G, 2899 TDLGroupType ** lclGroup, int *numLclGroup, 2900 char f_primMiss, sInt4 li_primMiss, 2901 char f_secMiss, sInt4 li_secMiss, int xFactor) 2902 { 2903 int start; /* Where to start the current group. */ 2904 int range; /* The range to make the groups. */ 2905 int final; /* One more than the last index in the group G. */ 2906 int split; /* Where to split the group. */ 2907 TDLGroupType G1; /* The current group to add. */ 2908 TDLGroupType G2; /* The group if we evaporated the previous group. */ 2909 int evaporate; /* How many groups we have "evaporated". */ 2910 int i; /* Loop counter to help "evaporate" groups. */ 2911 sInt4 scoreA; /* The original score for 2 groups */ 2912 sInt4 scoreB; /* The new score (having evaporated a group) */ 2913 int GroupLen; /* Actual alloc'ed group len. */ 2914 2915 /* *INDENT-OFF* */ 2916 /* The (pow (2, ..) -1) is because 2^n - 1 is max range of a group. 2917 * Example n = 1, 2^1 -1 = 1 range of (1,0) is 1. 2918 * Example n = 2, 2^2 -1 = 3 range of (3,2,1,0) is 3. 2919 * The G.bit - 1 is because we are trying to reduce the range. */ 2920 /* *INDENT-ON* */ 2921 range = (int) (pow (2.0, G->bit - 1) - 1) - (f_secMiss + f_primMiss); 2922 split = G->start; 2923 start = G->start; 2924 final = G->start + G->num; 2925 myAssert (final <= numData); 2926 *numLclGroup = 0; 2927 GroupLen = 1; 2928 *lclGroup = (TDLGroupType *) malloc (GroupLen * sizeof (TDLGroupType)); 2929 while (split < final) { 2930 if (f_secMiss) { 2931 findGroup2 (Data, start, final, li_primMiss, li_secMiss, range, 2932 &split, &(G1.min), &(G1.max)); 2933 } else if (f_primMiss) { 2934 findGroup1 (Data, start, final, li_primMiss, range, &split, 2935 &(G1.min), &(G1.max)); 2936 } else { 2937 findGroup0 (Data, start, final, range, &split, &(G1.min), &(G1.max)); 2938 } 2939 G1.bit = (char) power ((uInt4) (G1.max - G1.min), 2940 f_secMiss + f_primMiss); 2941 G1.num = split - start; 2942 G1.start = start; 2943 G1.f_trySplit = 1; 2944 G1.f_tryShift = 1; 2945 /* Test if we should add to previous group, or create a new group. */ 2946 if (*numLclGroup == 0) { 2947 *numLclGroup = 1; 2948 (*lclGroup)[0] = G1; 2949 } else { 2950 G2.start = (*lclGroup)[*numLclGroup - 1].start; 2951 G2.num = (*lclGroup)[*numLclGroup - 1].num + G1.num; 2952 G2.min = ((*lclGroup)[*numLclGroup - 1].min < G1.min) ? 2953 (*lclGroup)[*numLclGroup - 1].min : G1.min; 2954 G2.max = ((*lclGroup)[*numLclGroup - 1].max > G1.max) ? 2955 (*lclGroup)[*numLclGroup - 1].max : G1.max; 2956 G2.bit = (char) power ((uInt4) (G2.max - G2.min), 2957 f_secMiss + f_primMiss); 2958 G2.f_trySplit = 1; 2959 G2.f_tryShift = 1; 2960 scoreA = ((*lclGroup)[*numLclGroup - 1].bit * 2961 (*lclGroup)[*numLclGroup - 1].num) + xFactor; 2962 scoreA += G1.bit * G1.num + xFactor; 2963 scoreB = G2.bit * G2.num + xFactor; 2964 if (scoreB < scoreA) { 2965 (*lclGroup)[*numLclGroup - 1] = G2; 2966 /* See if we can evaporate any of the old groups */ 2967 evaporate = 0; 2968 for (i = *numLclGroup - 1; i > 0; i--) { 2969 G1.start = (*lclGroup)[i - 1].start; 2970 G1.num = (*lclGroup)[i].num + (*lclGroup)[i - 1].num; 2971 G1.min = ((*lclGroup)[i].min < (*lclGroup)[i - 1].min) ? 2972 (*lclGroup)[i].min : (*lclGroup)[i - 1].min; 2973 G1.max = ((*lclGroup)[i].max > (*lclGroup)[i - 1].max) ? 2974 (*lclGroup)[i].max : (*lclGroup)[i - 1].max; 2975 G1.bit = (char) power ((uInt4) (G1.max - G1.min), 2976 f_secMiss + f_primMiss); 2977 G1.f_trySplit = 1; 2978 G1.f_tryShift = 1; 2979 scoreA = (*lclGroup)[i].bit * (*lclGroup)[i].num + xFactor; 2980 scoreA += ((*lclGroup)[i - 1].bit * (*lclGroup)[i - 1].num + 2981 xFactor); 2982 scoreB = G1.bit * G1.num + xFactor; 2983 if (scoreB < scoreA) { 2984 evaporate++; 2985 (*lclGroup)[i - 1] = G1; 2986 } else { 2987 break; 2988 } 2989 } 2990 if (evaporate != 0) { 2991 *numLclGroup = *numLclGroup - evaporate; 2992 } 2993 } else { 2994 *numLclGroup = *numLclGroup + 1; 2995 if (*numLclGroup > GroupLen) { 2996 GroupLen = *numLclGroup; 2997 *lclGroup = (TDLGroupType *) realloc ((void *) *lclGroup, 2998 GroupLen * 2999 sizeof (TDLGroupType)); 3000 } 3001 (*lclGroup)[*numLclGroup - 1] = G1; 3002 } 3003 } 3004 start = split; 3005 } 3006 } 3007 3008 /***************************************************************************** 3009 * doSplitRight() -- 3010 * 3011 * Arthur Taylor / MDL 3012 * 3013 * PURPOSE 3014 * Break into two groups right has range n - 1, left has range n. 3015 * 3016 * ARGUMENTS 3017 * Data = The data. (Input) 3018 * numData = The number of elements in data. (Input) 3019 * G = The group to split. (Input) 3020 * G1 = The right most group (Output) 3021 * G2 = The remainder. (Output) 3022 * f_primMiss = Flag if we have a primary missing value (Input) 3023 * li_primMiss = scaled primary missing value (Input) 3024 * f_secMiss = Flag if we have a secondary missing value (Input) 3025 * li_secMiss = scaled secondary missing value (Input) 3026 * 3027 * FILES/DATABASES: None 3028 * 3029 * RETURNS: void 3030 * 3031 * HISTORY 3032 * 1/2005 Arthur Taylor (MDL): Created. 3033 * 3034 * NOTES 3035 ***************************************************************************** 3036 */ 3037 static void doSplitRight (sInt4 *Data, 3038 CPL_UNUSED int numData, 3039 TDLGroupType * G, 3040 TDLGroupType * G1, TDLGroupType * G2, 3041 char f_primMiss, sInt4 li_primMiss, 3042 char f_secMiss, sInt4 li_secMiss) 3043 { 3044 int range; /* The range to make the right most group. */ 3045 int final; /* One more than the last index in the group. */ 3046 int split; /* Where to split the group. */ 3047 3048 /* *INDENT-OFF* */ 3049 /* The (pow (2, ..) -1) is because 2^n - 1 is max range of a group. 3050 * Example n = 1, 2^1 -1 = 1 range of (1,0) is 1. 3051 * Example n = 2, 2^2 -1 = 3 range of (3,2,1,0) is 3. 3052 * The G.bit - 1 is because we are trying to reduce the range. */ 3053 /* *INDENT-ON* */ 3054 range = (int) (pow (2.0, G->bit - 1) - 1) - (f_secMiss + f_primMiss); 3055 final = G->start + G->num; 3056 split = final; 3057 myAssert (final <= numData); 3058 3059 if (f_secMiss) { 3060 findGroupRev2 (Data, G->start, final, li_primMiss, li_secMiss, range, 3061 &split, &(G1->min), &(G1->max)); 3062 findMaxMin2 (Data, G->start, split, li_primMiss, li_secMiss, 3063 &(G2->min), &(G2->max)); 3064 } else if (f_primMiss) { 3065 findGroupRev1 (Data, G->start, final, li_primMiss, range, &split, 3066 &(G1->min), &(G1->max)); 3067 findMaxMin1 (Data, G->start, split, li_primMiss, &(G2->min), 3068 &(G2->max)); 3069 } else { 3070 findGroupRev0 (Data, G->start, final, range, &split, &(G1->min), 3071 &(G1->max)); 3072 findMaxMin0 (Data, G->start, split, &(G2->min), &(G2->max)); 3073 } 3074 3075 G1->bit = (char) power ((uInt4) (G1->max - G1->min), 3076 f_secMiss + f_primMiss); 3077 G2->bit = (char) power ((uInt4) (G2->max - G2->min), 3078 f_secMiss + f_primMiss); 3079 G1->start = split; 3080 G2->start = G->start; 3081 G1->num = final - split; 3082 G2->num = split - G->start; 3083 G1->f_trySplit = 1; 3084 G1->f_tryShift = 1; 3085 G2->f_trySplit = 1; 3086 G2->f_tryShift = 1; 3087 } 3088 3089 /***************************************************************************** 3090 * ComputeGroupSize() -- 3091 * 3092 * Arthur Taylor / MDL 3093 * 3094 * PURPOSE 3095 * Compute the number of bits needed for the various elements of the groups 3096 * as well as the total number of bits needed. 3097 * 3098 * ARGUMENTS 3099 * group = Groups (Input) 3100 * numGroup = Number of groups (Input) 3101 * ibit = Number of bits needed for the minimum values of each group. 3102 * Find max absolute value of group mins. Note: all group mins 3103 * are positive (Output) 3104 * jbit = Number of bits needed for the number of bits for each group. 3105 * Find max absolute value of number of bits. (Output) 3106 * kbit = Number of bits needed for the number of values for each group. 3107 * Find max absolute value of number of values. (Output) 3108 * 3109 * FILES/DATABASES: None 3110 * 3111 * RETURNS: sInt4 3112 * number of bits needed by the groups 3113 * 3114 * HISTORY 3115 * 12/2004 Arthur Taylor (MDL): Updated from "tdlpack.c" in "C" tdlpack code 3116 * 3117 * NOTES 3118 ***************************************************************************** 3119 */ 3120 static sInt4 ComputeGroupSize (TDLGroupType * group, int numGroup, 3121 size_t *ibit, size_t *jbit, size_t *kbit) 3122 { 3123 int i; /* loop counter. */ 3124 sInt4 ans = 0; /* The number of bits needed. */ 3125 sInt4 maxMin = 0; /* The largest min value in the groups */ 3126 uChar maxBit = 0; /* The largest needed bits in the groups */ 3127 uInt4 maxNum = 0; /* The largest number of values in the groups. */ 3128 3129 for (i = 0; i < numGroup; i++) { 3130 ans += group[i].bit * group[i].num; 3131 if (group[i].min > maxMin) { 3132 maxMin = group[i].min; 3133 } 3134 if (group[i].bit > maxBit) { 3135 maxBit = group[i].bit; 3136 } 3137 if (group[i].num > maxNum) { 3138 maxNum = group[i].num; 3139 } 3140 } 3141 /* This only works for pos numbers... */ 3142 for (i = 0; (maxMin != 0); i++) { 3143 maxMin = maxMin >> 1; 3144 } 3145 /* Allow 0 bits for min. Assumes that decoder allows 0 bits */ 3146 *ibit = i; 3147 /* This only works for pos numbers... */ 3148 for (i = 0; (maxBit != 0); i++) { 3149 maxBit = maxBit >> 1; 3150 } 3151 /* Allow 0 bits for min. Assumes that decoder allows 0 bits */ 3152 *jbit = i; 3153 /* This only works for pos numbers... */ 3154 for (i = 0; (maxNum != 0); i++) { 3155 maxNum = maxNum >> 1; 3156 } 3157 /* Allow 0 bits for min. Assumes that decoder allows 0 bits */ 3158 *kbit = i; 3159 ans += (sInt4) (((*ibit) + (*jbit) + (*kbit)) * numGroup); 3160 return ans; 3161 } 3162 3163 /***************************************************************************** 3164 * splitGroup() -- 3165 * 3166 * Arthur Taylor / MDL 3167 * 3168 * PURPOSE 3169 * Tries to reduce (split) each group by 1 bit. It does this by: 3170 * A) reduce the "bit range", and create groups that grab as much as they 3171 * can to the right. Then reduce those groups if they improve the score. 3172 * B) reduce the bit range and grab the left most group only, leaving the 3173 * rest unchanged. 3174 * C) reduce the bit range and grab the right most group only, leaving the 3175 * rest unchanged. 3176 * 3177 * ARGUMENTS 3178 * Data = The data. (Input) 3179 * numData = The number of elements in data. (Input) 3180 * group = The groups using the "best minGroup. (Input) 3181 * numGroup = Number of groups (Input) 3182 * lclGroup = The local copy of the groups (Output) 3183 * numLclGroup = Number of local groups (Output) 3184 * f_primMiss = Flag if we have a primary missing value (Input) 3185 * li_primMiss = scaled primary missing value (Input) 3186 * f_secMiss = Flag if we have a secondary missing value (Input) 3187 * li_secMiss = scaled secondary missing value (Input) 3188 * xFactor = Estimate of cost (in bits) of a group. (Input) 3189 * 3190 * FILES/DATABASES: None 3191 * 3192 * RETURNS: void 3193 * 3194 * HISTORY 3195 * 1/2005 Arthur Taylor (MDL): Created. 3196 * 3197 * NOTES 3198 ***************************************************************************** 3199 */ 3200 static int splitGroup (sInt4 *Data, int numData, TDLGroupType * group, 3201 int numGroup, TDLGroupType ** lclGroup, 3202 int *numLclGroup, char f_primMiss, 3203 sInt4 li_primMiss, char f_secMiss, 3204 sInt4 li_secMiss, size_t xFactor) 3205 { 3206 uInt4 minBit = 1; /* The fewest # of bits, with no subdivision. */ 3207 TDLGroupType *subGroup; /* The subgroups that we tried splitting the 3208 * primary group into. */ 3209 int numSubGroup; /* The number of groups in subGroup. */ 3210 sInt4 A_max; /* Max value of a given group. */ 3211 sInt4 A_min; /* Min value of a given group. */ 3212 sInt4 scoreA; /* The original score for a given group */ 3213 sInt4 scoreB; /* The new score */ 3214 int f_adjust = 0; /* Flag if group has changed. */ 3215 int f_keep; /* Flag to keep the subgroup instead of original */ 3216 int i; /* Loop counters */ 3217 int sub; /* loop counter over the sub group. */ 3218 int lclIndex; /* Used to help copy data from subGroup to answer. */ 3219 int GroupLen; /* Actual alloc'ed group len. */ 3220 int extra; /* Used to reduce number of allocs. */ 3221 3222 /* Figure out how few bits a group can have without being able to further 3223 * divide it. */ 3224 if (f_secMiss) { 3225 /* 11 = primMiss 10 = secMiss 01, 00 = data. */ 3226 minBit = 2; 3227 } 3228 #ifdef useless 3229 else if (f_primMiss) { 3230 /* 1 = primMiss 0 = data. */ 3231 /* might try minBit = 1 here. */ 3232 minBit = 1; 3233 } else { 3234 /* 1, 0 = data. */ 3235 minBit = 1; 3236 } 3237 #endif 3238 3239 *numLclGroup = 0; 3240 *lclGroup = (TDLGroupType *) malloc (numGroup * sizeof (TDLGroupType)); 3241 GroupLen = numGroup; 3242 extra = 0; 3243 for (i = 0; i < numGroup; i++) { 3244 /* Check if we have already tried to split this group, or it has too 3245 * few members, or it doesn't have enough bits to split. If so, skip 3246 * this group. */ 3247 if ((group[i].f_trySplit) && (group[i].num > xFactor) && 3248 (group[i].bit > minBit)) { 3249 f_keep = 0; 3250 doSplit (Data, numData, &(group[i]), &subGroup, &numSubGroup, 3251 f_primMiss, li_primMiss, f_secMiss, li_secMiss, static_cast<int>(xFactor)); 3252 if (numSubGroup != 1) { 3253 scoreA = static_cast<sInt4>(group[i].bit * group[i].num + xFactor); 3254 scoreB = 0; 3255 for (sub = 0; sub < numSubGroup; sub++) { 3256 scoreB += (sInt4) (subGroup[sub].bit * subGroup[sub].num + xFactor); 3257 } 3258 if (scoreB < scoreA) { 3259 f_keep = 1; 3260 } else if (numSubGroup > 2) { 3261 /* We can do "doSplitLeft" (which is breaking it into 2 groups 3262 * the first having range n - 1, the second having range n, 3263 * using what we know from doSplit. */ 3264 subGroup[1].num = group[i].num - subGroup[0].num; 3265 if (f_secMiss) { 3266 findMaxMin2 (Data, subGroup[1].start, 3267 subGroup[1].start + subGroup[1].num, 3268 li_primMiss, li_secMiss, &A_min, &A_max); 3269 } else if (f_primMiss) { 3270 findMaxMin1 (Data, subGroup[1].start, 3271 subGroup[1].start + subGroup[1].num, 3272 li_primMiss, &A_min, &A_max); 3273 } else { 3274 findMaxMin0 (Data, subGroup[1].start, 3275 subGroup[1].start + subGroup[1].num, 3276 &A_min, &A_max); 3277 } 3278 subGroup[1].min = A_min; 3279 subGroup[1].max = A_max; 3280 subGroup[1].bit = power ((uInt4) (A_max - A_min), 3281 f_secMiss + f_primMiss); 3282 subGroup[1].f_trySplit = 1; 3283 subGroup[1].f_tryShift = 1; 3284 numSubGroup = 2; 3285 scoreB = static_cast<sInt4>(subGroup[0].bit * subGroup[0].num + xFactor); 3286 scoreB += static_cast<sInt4>(subGroup[1].bit * subGroup[1].num + xFactor); 3287 if (scoreB < scoreA) { 3288 f_keep = 1; 3289 } 3290 } 3291 } 3292 if (!f_keep) { 3293 if (numSubGroup == 1) { 3294 subGroup = (TDLGroupType *) realloc (subGroup, 3295 2 * 3296 sizeof (TDLGroupType)); 3297 } 3298 numSubGroup = 2; 3299 doSplitRight (Data, numData, &(group[i]), &(subGroup[1]), 3300 &(subGroup[0]), f_primMiss, li_primMiss, f_secMiss, 3301 li_secMiss); 3302 scoreA = static_cast<sInt4>(group[i].bit * group[i].num + xFactor); 3303 scoreB = static_cast<sInt4>(subGroup[0].bit * subGroup[0].num + xFactor); 3304 scoreB += static_cast<sInt4>(subGroup[1].bit * subGroup[1].num + xFactor); 3305 if (scoreB < scoreA) { 3306 f_keep = 1; 3307 } 3308 } 3309 if (f_keep) { 3310 lclIndex = *numLclGroup; 3311 *numLclGroup = *numLclGroup + numSubGroup; 3312 if (*numLclGroup > GroupLen) { 3313 GroupLen += extra; 3314 extra = 0; 3315 if (*numLclGroup > GroupLen) { 3316 GroupLen = *numLclGroup; 3317 } 3318 *lclGroup = (TDLGroupType *) realloc ((void *) *lclGroup, 3319 GroupLen * 3320 sizeof (TDLGroupType)); 3321 } else { 3322 extra += numSubGroup - 1; 3323 } 3324 memcpy ((*lclGroup) + lclIndex, subGroup, 3325 numSubGroup * sizeof (TDLGroupType)); 3326 f_adjust = 1; 3327 } else { 3328 *numLclGroup = *numLclGroup + 1; 3329 if (*numLclGroup > GroupLen) { 3330 GroupLen += extra; 3331 extra = 0; 3332 if (*numLclGroup > GroupLen) { 3333 GroupLen = *numLclGroup; 3334 } 3335 *lclGroup = (TDLGroupType *) realloc ((void *) *lclGroup, 3336 GroupLen * 3337 sizeof (TDLGroupType)); 3338 } 3339 (*lclGroup)[*numLclGroup - 1] = group[i]; 3340 (*lclGroup)[*numLclGroup - 1].f_trySplit = 0; 3341 } 3342 free (subGroup); 3343 subGroup = NULL; 3344 } else { 3345 *numLclGroup = *numLclGroup + 1; 3346 if (*numLclGroup > GroupLen) { 3347 GroupLen += extra; 3348 extra = 0; 3349 if (*numLclGroup > GroupLen) { 3350 GroupLen = *numLclGroup; 3351 } 3352 *lclGroup = (TDLGroupType *) realloc ((void *) *lclGroup, 3353 GroupLen * 3354 sizeof (TDLGroupType)); 3355 } 3356 (*lclGroup)[*numLclGroup - 1] = group[i]; 3357 (*lclGroup)[*numLclGroup - 1].f_trySplit = 0; 3358 } 3359 } 3360 myAssert (GroupLen == *numLclGroup); 3361 return f_adjust; 3362 } 3363 3364 /***************************************************************************** 3365 * shiftGroup() -- 3366 * 3367 * Arthur Taylor / MDL 3368 * 3369 * PURPOSE 3370 * Tries to shift / join the groups together. It does this by first 3371 * calculating if a group should still exist. If it should, then it has 3372 * each group grab as much as it can to the left without increasing its "bit 3373 * range". 3374 * 3375 * ARGUMENTS 3376 * Data = The data. (Input) 3377 * numData = The number of elements in data. (Input) 3378 * group = The resulting groups. (Output) 3379 * numGroup = Number of groups (Output) 3380 * f_primMiss = Flag if we have a primary missing value (Input) 3381 * li_primMiss = scaled primary missing value (Input) 3382 * f_secMiss = Flag if we have a secondary missing value (Input) 3383 * li_secMiss = scaled secondary missing value (Input) 3384 * xFactor = Estimate of cost (in bits) of a group. (Input) 3385 * 3386 * FILES/DATABASES: None 3387 * 3388 * RETURNS: void 3389 * 3390 * HISTORY 3391 * 1/2005 Arthur Taylor (MDL): Created. 3392 * 3393 * NOTES 3394 ***************************************************************************** 3395 */ 3396 static void shiftGroup (sInt4 *Data, 3397 CPL_UNUSED int numData, 3398 TDLGroupType ** Group, 3399 size_t *NumGroup, char f_primMiss, sInt4 li_primMiss, 3400 char f_secMiss, sInt4 li_secMiss, int xFactor) 3401 { 3402 TDLGroupType *group = (*Group); /* Local pointer to Group. */ 3403 int numGroup = static_cast<int>(*NumGroup); /* # elements in group. */ 3404 int i, j; /* loop counters. */ 3405 sInt4 A_max; /* Max value of a given group. */ 3406 sInt4 A_min; /* Min value of a given group. */ 3407 size_t begin; /* New start to the group. */ 3408 sInt4 scoreA; /* The original score for group i and i - 1 */ 3409 sInt4 scoreB; /* The new score for group i and i - 1 */ 3410 TDLGroupType G1; /* The "new" group[i - 1]. */ 3411 TDLGroupType G2; /* The "new" group[i]. */ 3412 int evaporate = 0; /* number of groups that "evaporated" */ 3413 int index; /* index while getting rid of "evaporated groups". */ 3414 3415 for (i = numGroup - 1; i > 0; i--) { 3416 myAssert (group[i].num > 0); 3417 /* See if we can evaporate the group n - 1 */ 3418 G1.start = group[i - 1].start; 3419 G1.num = group[i].num + group[i - 1].num; 3420 G1.min = (group[i].min < group[i - 1].min) ? 3421 group[i].min : group[i - 1].min; 3422 G1.max = (group[i].max > group[i - 1].max) ? 3423 group[i].max : group[i - 1].max; 3424 G1.bit = (char) power ((uInt4) (G1.max - G1.min), 3425 f_secMiss + f_primMiss); 3426 G1.f_trySplit = 1; 3427 G1.f_tryShift = 1; 3428 scoreA = group[i].bit * group[i].num + xFactor; 3429 scoreA += group[i - 1].bit * group[i - 1].num + xFactor; 3430 scoreB = G1.bit * G1.num + xFactor; 3431 if (scoreB < scoreA) { 3432 /* One of the groups evaporated. */ 3433 evaporate++; 3434 group[i - 1] = G1; 3435 group[i].num = 0; 3436 /* See if that affects any of the previous groups. */ 3437 for (j = i + 1; j < numGroup; j++) { 3438 if (group[j].num != 0) { 3439 /*G1.start = G1. start;*/ /* self-assignment... */ 3440 G1.num = group[i - 1].num + group[j].num; 3441 G1.min = (group[i - 1].min < group[j].min) ? 3442 group[i - 1].min : group[j].min; 3443 G1.max = (group[i - 1].max > group[j].max) ? 3444 group[i - 1].max : group[j].max; 3445 G1.bit = (char) power ((uInt4) (G1.max - G1.min), 3446 f_secMiss + f_primMiss); 3447 G1.f_trySplit = 1; 3448 G1.f_tryShift = 1; 3449 scoreA = group[i - 1].bit * group[i - 1].num + xFactor; 3450 scoreA += group[j].bit * group[j].num + xFactor; 3451 scoreB = G1.bit * G1.num + xFactor; 3452 if (scoreB < scoreA) { 3453 evaporate++; 3454 group[i - 1] = G1; 3455 group[j].num = 0; 3456 } else { 3457 break; 3458 } 3459 } 3460 } 3461 } else if (group[i].f_tryShift) { 3462 /* Group did not evaporate, so do the "grabby" algorithm. */ 3463 if ((group[i].bit != 0) && (group[i - 1].bit >= group[i].bit)) { 3464 if (f_secMiss) { 3465 A_max = group[i].max; 3466 A_min = group[i].min; 3467 shiftGroup2 (Data, group[i].start - 1, group[i - 1].start, 3468 li_primMiss, li_secMiss, group[i].bit, &A_min, 3469 &A_max, &begin); 3470 } else if (f_primMiss) { 3471 A_max = group[i].max; 3472 A_min = group[i].min; 3473 shiftGroup1 (Data, group[i].start - 1, group[i - 1].start, 3474 li_primMiss, group[i].bit, &A_min, &A_max, 3475 &begin); 3476 } else { 3477 A_max = group[i].max; 3478 A_min = group[i].min; 3479 shiftGroup0 (Data, group[i].start - 1, group[i - 1].start, 3480 group[i].bit, &A_min, &A_max, &begin); 3481 } 3482 if (begin != group[i].start) { 3483 /* Re-Calculate min/max of group[i - 1], since it could have 3484 * moved to group[i] */ 3485 G1 = group[i - 1]; 3486 G2 = group[i]; 3487 G2.min = A_min; 3488 G2.max = A_max; 3489 G1.num -= static_cast<uInt4>(group[i].start - begin); 3490 if (f_secMiss) { 3491 findMaxMin2 (Data, G1.start, G1.start + G1.num, 3492 li_primMiss, li_secMiss, &A_min, &A_max); 3493 } else if (f_primMiss) { 3494 findMaxMin1 (Data, G1.start, G1.start + G1.num, 3495 li_primMiss, &A_min, &A_max); 3496 } else { 3497 findMaxMin0 (Data, G1.start, G1.start + G1.num, 3498 &A_min, &A_max); 3499 } 3500 if ((A_min != G1.min) || (A_max != G1.max)) { 3501 G1.min = A_min; 3502 G1.max = A_max; 3503 G1.bit = (char) power ((uInt4) (A_max - A_min), 3504 f_secMiss + f_primMiss); 3505 G1.f_trySplit = 1; 3506 G1.f_tryShift = 1; 3507 } 3508 G2.num += static_cast<uInt4>(group[i].start - begin); 3509 G2.start = static_cast<uInt4>(begin); 3510 G2.f_trySplit = 1; 3511 G2.f_tryShift = 1; 3512 scoreA = group[i].bit * group[i].num + xFactor; 3513 scoreA += group[i - 1].bit * group[i - 1].num + xFactor; 3514 scoreB = G2.bit * G2.num + xFactor; 3515 if (G1.num != 0) { 3516 scoreB += G1.bit * G1.num + xFactor; 3517 } 3518 #ifdef DEBUG 3519 if (scoreB > scoreA) { 3520 printf ("Made score worse!\n"); 3521 } 3522 #endif 3523 if (begin == group[i - 1].start) { 3524 /* Grabby algorithm evaporated a group. */ 3525 evaporate++; 3526 myAssert (G1.num == 0); 3527 /* Switch the evaporating group to other side so we have 3528 * potential to continue evaporating the next group down. */ 3529 group[i - 1] = G2; 3530 group[i] = G1; 3531 } else { 3532 group[i - 1] = G1; 3533 group[i] = G2; 3534 } 3535 } else { 3536 group[i].f_tryShift = 0; 3537 } 3538 } 3539 } 3540 } 3541 /* Loop through the grid removing the evaporated groups. */ 3542 if (evaporate != 0) { 3543 index = 0; 3544 for (i = 0; i < numGroup; i++) { 3545 if (group[i].num != 0) { 3546 group[index] = group[i]; 3547 index++; 3548 } 3549 } 3550 *NumGroup = numGroup - evaporate; 3551 *Group = (TDLGroupType *) realloc ((void *) (*Group), 3552 *NumGroup * sizeof (TDLGroupType)); 3553 } 3554 } 3555 3556 /***************************************************************************** 3557 * GroupIt() -- 3558 * 3559 * Arthur Taylor / MDL 3560 * 3561 * PURPOSE 3562 * Attempts to find groups for packing the data. It starts by preparing 3563 * the data, by removing the overall min value. 3564 * 3565 * Next it Creates any 0 bit groups (primary missing: missing are all 0 3566 * bit groups, const values are 0 bit groups. No missing: const values are 3567 * 0 bit groups.) 3568 * 3569 * Next it tries to reduce (split) each group by 1 bit. It does this by: 3570 * A) reduce the "bit range", and create groups that grab as much as they 3571 * can to the right. Then reduce those groups if they improve the score. 3572 * B) reduce the bit range and grab the left most group only, leaving the 3573 * rest unchanged. 3574 * C) reduce the bit range and grab the right most group only, leaving the 3575 * rest unchanged. 3576 * 3577 * Next it tries to shift / join those groups together. It does this by 3578 * first calculating if a group should still exist. If it should, then it 3579 * has each group grab as much as it can to the left without increasing its 3580 * "bit range". 3581 * 3582 * ARGUMENTS 3583 * OverallMin = The overall min value in the data. (Input) 3584 * Data = The data. (Input) 3585 * numData = The number of elements in data. (Input) 3586 * group = The resulting groups. (Output) 3587 * numGroup = Number of groups (Output) 3588 * f_primMiss = Flag if we have a primary missing value (Input) 3589 * li_primMiss = scaled primary missing value (Input) 3590 * f_secMiss = Flag if we have a secondary missing value (Input) 3591 * li_secMiss = scaled secondary missing value (Input) 3592 * groupSize = How many bytes the groups and data will take. (Output) 3593 * ibit = # of bits for largest minimum value in groups (Output) 3594 * jbit = # of bits for largest # bits in groups (Output) 3595 * kbit = # of bits for largest # values in groups (Output) 3596 * 3597 * FILES/DATABASES: None 3598 * 3599 * RETURNS: void 3600 * 3601 * HISTORY 3602 * 1/2005 Arthur Taylor (MDL): Created. 3603 * 3604 * NOTES 3605 * 1) Have not implemented const 0 bit groups for prim miss or no miss. 3606 * 2) MAX_GROUP_LEN (found experimentally) is useful to keep cost of groups 3607 * down. 3608 ***************************************************************************** 3609 */ 3610 #define MAX_GROUP_LEN 255 3611 static void GroupIt (sInt4 OverallMin, sInt4 *Data, size_t numData, 3612 TDLGroupType ** group, size_t *numGroup, char f_primMiss, 3613 sInt4 li_primMiss, char f_secMiss, 3614 sInt4 li_secMiss, sInt4 *groupSize, size_t *ibit, 3615 size_t *jbit, size_t *kbit) 3616 { 3617 sInt4 A_max; /* Max value of a given group. */ 3618 sInt4 A_min; /* Min value of a given group. */ 3619 TDLGroupType G; /* Used to init the groups. */ 3620 int f_adjust; /* Flag if we have changed the groups. */ 3621 TDLGroupType *lclGroup; /* A temporary copy of the groups. */ 3622 int numLclGroup; /* # of groups in lclGroup. */ 3623 size_t xFactor; /* Estimate of cost (in bits) of a group. */ 3624 size_t i; /* loop counter. */ 3625 3626 /* Subtract the Overall Min Value. */ 3627 if (OverallMin != 0) { 3628 if (f_secMiss) { 3629 for (i = 0; i < numData; i++) { 3630 if ((Data[i] != li_secMiss) && (Data[i] != li_primMiss)) { 3631 Data[i] -= OverallMin; 3632 // Check if we accidentally adjusted to prim or sec, if so add 1. 3633 if ((Data[i] == li_secMiss) || (Data[i] == li_primMiss)) { 3634 myAssert (0); 3635 Data[i]++; 3636 if ((Data[i] == li_secMiss) || (Data[i] == li_primMiss)) { 3637 myAssert (0); 3638 Data[i]++; 3639 } 3640 } 3641 } 3642 } 3643 } else if (f_primMiss) { 3644 for (i = 0; i < numData; i++) { 3645 if (Data[i] != li_primMiss) { 3646 Data[i] -= OverallMin; 3647 // Check if we accidentally adjusted to prim or sec, if so add 1. 3648 if (Data[i] == li_primMiss) { 3649 myAssert (0); 3650 Data[i]++; 3651 } 3652 } 3653 } 3654 } else { 3655 for (i = 0; i < numData; i++) { 3656 Data[i] -= OverallMin; 3657 } 3658 } 3659 } 3660 3661 myAssert ((f_secMiss == 0) || (f_secMiss == 1)); 3662 myAssert ((f_primMiss == 0) || (f_primMiss == 1)); 3663 3664 /* Create zero groups. */ 3665 *numGroup = 0; 3666 *group = NULL; 3667 if (f_primMiss) { 3668 G.min = Data[0]; 3669 G.max = Data[0]; 3670 G.num = 1; 3671 G.start = 0; 3672 for (i = 1; i < numData; i++) { 3673 if (G.min == li_primMiss) { 3674 if (Data[i] == li_primMiss) { 3675 G.num++; 3676 if (G.num == (MAX_GROUP_LEN + 1)) { 3677 /* Close a missing group */ 3678 G.f_trySplit = 0; 3679 G.f_tryShift = 1; 3680 G.bit = 0; 3681 G.min = 0; 3682 G.max = 0; 3683 G.num = MAX_GROUP_LEN; 3684 (*numGroup)++; 3685 *group = (TDLGroupType *) realloc ((void *) *group, 3686 *numGroup * 3687 sizeof (TDLGroupType)); 3688 (*group)[(*numGroup) - 1] = G; 3689 /* Init a missing group. */ 3690 G.min = Data[i]; 3691 G.max = Data[i]; 3692 G.num = 1; 3693 G.start = static_cast<uInt4>(i); 3694 } 3695 } else { 3696 /* Close a missing group */ 3697 G.f_trySplit = 0; 3698 G.f_tryShift = 1; 3699 G.bit = 0; 3700 G.min = 0; 3701 G.max = 0; 3702 (*numGroup)++; 3703 *group = (TDLGroupType *) realloc ((void *) *group, 3704 *numGroup * 3705 sizeof (TDLGroupType)); 3706 (*group)[(*numGroup) - 1] = G; 3707 /* Init a non-missing group. */ 3708 G.min = Data[i]; 3709 G.max = Data[i]; 3710 G.num = 1; 3711 G.start = static_cast<uInt4>(i); 3712 } 3713 } else { 3714 if (Data[i] == li_primMiss) { 3715 /* Close a non-missing group */ 3716 G.f_trySplit = 1; 3717 G.f_tryShift = 1; 3718 G.bit = (char) power ((uInt4) (G.max - G.min), 3719 f_secMiss + f_primMiss); 3720 myAssert (G.bit != 0); 3721 if ((G.min == 0) && (G.bit == 0) && (f_primMiss == 1)) { 3722 printf ("Warning: potential confusion between const value " 3723 "and prim-missing.\n"); 3724 G.bit = 1; 3725 } 3726 (*numGroup)++; 3727 *group = (TDLGroupType *) realloc ((void *) *group, 3728 *numGroup * 3729 sizeof (TDLGroupType)); 3730 (*group)[(*numGroup) - 1] = G; 3731 /* Init a missing group. */ 3732 G.min = Data[i]; 3733 G.max = Data[i]; 3734 G.num = 1; 3735 G.start = static_cast<uInt4>(i); 3736 } else { 3737 if (G.min > Data[i]) { 3738 G.min = Data[i]; 3739 } else if (G.max < Data[i]) { 3740 G.max = Data[i]; 3741 } 3742 G.num++; 3743 } 3744 } 3745 } 3746 if (G.min == li_primMiss) { 3747 /* Close a missing group */ 3748 G.f_trySplit = 0; 3749 G.f_tryShift = 1; 3750 G.bit = 0; 3751 G.min = 0; 3752 G.max = 0; 3753 (*numGroup)++; 3754 *group = (TDLGroupType *) realloc ((void *) *group, 3755 *numGroup * 3756 sizeof (TDLGroupType)); 3757 (*group)[(*numGroup) - 1] = G; 3758 } else { 3759 /* Close a non-missing group */ 3760 G.f_trySplit = 1; 3761 G.f_tryShift = 1; 3762 G.bit = (char) power ((uInt4) (G.max - G.min), 3763 f_secMiss + f_primMiss); 3764 myAssert (G.bit != 0); 3765 if ((G.min == 0) && (G.bit == 0) && (f_primMiss == 1)) { 3766 printf ("Warning: potential confusion between const value and " 3767 "prim-missing.\n"); 3768 G.bit = 1; 3769 } 3770 (*numGroup)++; 3771 *group = (TDLGroupType *) realloc ((void *) *group, 3772 *numGroup * 3773 sizeof (TDLGroupType)); 3774 (*group)[(*numGroup) - 1] = G; 3775 } 3776 } else { 3777 /* Already handled the f_primMiss case */ 3778 if (f_secMiss) { 3779 findMaxMin2 (Data, 0, static_cast<int>(numData), li_primMiss, li_secMiss, &A_min, 3780 &A_max); 3781 } else { 3782 findMaxMin0 (Data, 0, static_cast<int>(numData), &A_min, &A_max); 3783 } 3784 G.start = 0; 3785 G.num = static_cast<uInt4>(numData); 3786 G.min = A_min; 3787 G.max = A_max; 3788 G.bit = (char) power ((uInt4) (A_max - A_min), f_secMiss + f_primMiss); 3789 G.f_trySplit = 1; 3790 G.f_tryShift = 1; 3791 *numGroup = 1; 3792 *group = (TDLGroupType *) malloc (sizeof (TDLGroupType)); 3793 (*group)[0] = G; 3794 } 3795 3796 lclGroup = NULL; 3797 numLclGroup = 0; 3798 *groupSize = ComputeGroupSize (*group, static_cast<int>(*numGroup), ibit, jbit, kbit); 3799 xFactor = *ibit + *jbit + *kbit; 3800 #ifdef DEBUG 3801 /* 3802 printf ("NumGroup = %d: Bytes = %ld: XFactor %d\n", *numGroup, 3803 (*groupSize / 8) + 1, xFactor); 3804 */ 3805 #endif 3806 3807 f_adjust = 1; 3808 while (f_adjust) { 3809 f_adjust = splitGroup (Data, static_cast<int>(numData), *group, static_cast<int>(*numGroup), &lclGroup, 3810 &numLclGroup, f_primMiss, li_primMiss, 3811 f_secMiss, li_secMiss, xFactor); 3812 free (*group); 3813 *group = lclGroup; 3814 *numGroup = numLclGroup; 3815 3816 if (f_adjust) { 3817 shiftGroup (Data, static_cast<int>(numData), group, numGroup, f_primMiss, 3818 li_primMiss, f_secMiss, li_secMiss, static_cast<int>(xFactor)); 3819 *groupSize = ComputeGroupSize (*group, static_cast<int>(*numGroup), ibit, jbit, kbit); 3820 if (xFactor != *ibit + *jbit + *kbit) { 3821 for (i = 0; i < *numGroup; i++) { 3822 if (((*group)[i].num > *ibit + *jbit + *kbit) && 3823 ((*group)[i].num <= xFactor)) { 3824 (*group)[i].f_trySplit = 1; 3825 } 3826 } 3827 } 3828 xFactor = *ibit + *jbit + *kbit; 3829 #ifdef DEBUG 3830 /* 3831 printf ("NumGroup = %d: Bytes = %ld: XFactor %d\n", *numGroup, 3832 (*groupSize / 8) + 1, xFactor); 3833 fflush (stdout); 3834 */ 3835 #endif 3836 } 3837 } 3838 } 3839 3840 /***************************************************************************** 3841 * GroupPack() -- 3842 * 3843 * Arthur Taylor / MDL 3844 * 3845 * PURPOSE 3846 * To compute groups for packing the data using complex or second order 3847 * complex packing. 3848 * 3849 * ARGUMENTS 3850 * Src = The original data. (Input) 3851 * Dst = The scaled data. (Output) 3852 * numData = The number of elements in data. (Input) 3853 * DSF = Decimal Scale Factor for scaling the data. (Input) 3854 * BSF = Binary Scale Factor for scaling the data. (Input) 3855 * f_primMiss = Flag saying if we have a primary missing value (In/Out) 3856 * primMiss = primary missing value. (In/Out) 3857 * f_secMiss = Flag saying if we have a secondary missing value (In/Out) 3858 * secMiss = secondary missing value. (In/Out) 3859 * f_grid = Flag if this is grid data (or vector) (Input) 3860 * NX = The number of X values. (Input) 3861 * NY = The number of Y values. (Input) 3862 * f_sndOrder = Flag if we should do second order differencing (Output) 3863 * group = Resulting groups. (Output) 3864 * numGroup = Number of groups. (Output) 3865 * Min = Overall minimum. (Output) 3866 * a1 = if f_sndOrder, the first first order difference (Output) 3867 * b2 = if f_sndOrder, the first second order difference (Output) 3868 * groupSize = How many bytes the groups and data will take. (Output) 3869 * ibit = # of bits for largest minimum value in groups (Output) 3870 * jbit = # of bits for largest # bits in groups (Output) 3871 * kbit = # of bits for largest # values in groups (Output) 3872 * 3873 * FILES/DATABASES: None 3874 * 3875 * RETURNS: int (could use errSprintf()) 3876 * 0 = OK 3877 * -1 = Primary or Secondary missing value == 0. 3878 * 3879 * HISTORY 3880 * 12/2004 Arthur Taylor (MDL): Updated from "group.c" in "C" tdlpack code. 3881 * 1/2005 AAT: Cleaned up. 3882 * 3883 * NOTES 3884 ***************************************************************************** 3885 */ 3886 static int GroupPack (double *Src, sInt4 **Dst, sInt4 numData, 3887 int DSF, int BSF, char *f_primMiss, double *primMiss, 3888 char *f_secMiss, double *secMiss, char f_grid, 3889 short int NX, short int NY, char *f_sndOrder, 3890 TDLGroupType ** group, size_t *numGroup, 3891 sInt4 *Min, sInt4 *a1, sInt4 *b2, 3892 sInt4 *groupSize, size_t *ibit, size_t *jbit, 3893 size_t *kbit) 3894 { 3895 sInt4 *SecDiff = NULL; /* Consists of the 2nd order differences if * 3896 * requested. */ 3897 sInt4 *Data; /* The scaled data. */ 3898 char f_min; /* Flag saying overallMin is valid. */ 3899 sInt4 overallMin = 0; /* The overall min of the scaled data. */ 3900 sInt4 secMin; /* The overall min of the 2nd order differences */ 3901 sInt4 li_primMiss = 0; /* The scaled primary missing value */ 3902 sInt4 li_secMiss = 0; /* The scaled secondary missing value */ 3903 int minGroup = 20; /* The minimum group size. Equivalent to xFactor? 3904 * Chose 20 because that was a good estimate of 3905 * XFactor. */ 3906 3907 /* Check consistency of f_primMiss and f_secMiss. */ 3908 if (*primMiss == *secMiss) { 3909 *f_secMiss = 0; 3910 } 3911 if ((*f_secMiss) && (!(*f_primMiss))) { 3912 *f_primMiss = *f_secMiss; 3913 *primMiss = *secMiss; 3914 *f_secMiss = 0; 3915 } 3916 if (*f_secMiss && (*secMiss == 0)) { 3917 errSprintf ("Error: Secondary missing value not allowed to = 0.\n"); 3918 return -1; 3919 } 3920 if (*f_primMiss && (*primMiss == 0)) { 3921 errSprintf ("Error: Primary missing value not allowed to = 0.\n"); 3922 return -1; 3923 } 3924 3925 /* Check minGroup size. */ 3926 if (minGroup > numData) { 3927 minGroup = numData; 3928 } 3929 3930 /* Scale the data and check if we can change f_prim or f_sec. */ 3931 /* Note: if we use sec_diff, we have a different overall min. */ 3932 f_min = 0; 3933 Data = (sInt4 *) malloc (numData * sizeof (sInt4)); 3934 TDL_ScaleData (Src, Data, numData, DSF, BSF, f_primMiss, primMiss, 3935 f_secMiss, secMiss, &f_min, &overallMin); 3936 /* Note: ScaleData also scales missing values. */ 3937 if (*f_primMiss) { 3938 li_primMiss = (sInt4) (*primMiss * SCALE_MISSING + .5); 3939 } 3940 if (*f_secMiss) { 3941 li_secMiss = (sInt4) (*secMiss * SCALE_MISSING + .5); 3942 } 3943 3944 /* Reason this is after TDL_ScaleData is we don't want to reorder the 3945 * caller's copy of the data. */ 3946 if (f_grid) { 3947 TDL_ReorderGrid (Data, NX, NY); 3948 } else { 3949 /* TDLPack requires the following (see pack2d.f and pack1d.f) */ 3950 *f_sndOrder = 0; 3951 } 3952 /* TDLPack requires the following (see pack2d.f) */ 3953 if (*f_secMiss) { 3954 *f_sndOrder = 0; 3955 } 3956 /* If overallMin is "invalid" then they are all prim or sec values. */ 3957 /* See pack2d.f line 336 */ 3958 /* IF ALL VALUES ARE MISSING, JUST PACK; DON'T CONSIDER 2ND ORDER 3959 * DIFFERENCES. */ 3960 if (!f_min) { 3961 *f_sndOrder = 0; 3962 } 3963 3964 /* This has to be after TDL_ReorderGrid */ 3965 if (*f_sndOrder) { 3966 SecDiff = (sInt4 *) malloc (numData * sizeof (sInt4)); 3967 if (TDL_GetSecDiff (Data, numData, SecDiff, *f_primMiss, li_primMiss, 3968 a1, b2, &secMin)) { 3969 /* Problem finding SecDiff, so we don't bother with it. */ 3970 *f_sndOrder = 0; 3971 } else { 3972 /* Check if it is worth doing second order differences. */ 3973 if (*f_primMiss) { 3974 *f_sndOrder = TDL_UseSecDiff_Prim (Data, numData, SecDiff, 3975 li_primMiss, minGroup); 3976 } else { 3977 *f_sndOrder = TDL_UseSecDiff (Data, numData, SecDiff, minGroup); 3978 } 3979 } 3980 } 3981 3982 /* Side affect of GroupIt2: it subtracts OverallMin from Data. */ 3983 if (!(*f_sndOrder)) { 3984 GroupIt (overallMin, Data, numData, group, numGroup, *f_primMiss, 3985 li_primMiss, *f_secMiss, li_secMiss, groupSize, ibit, jbit, 3986 kbit); 3987 *Min = overallMin; 3988 *a1 = 0; 3989 *b2 = 0; 3990 *Dst = Data; 3991 free (SecDiff); 3992 } else { 3993 GroupIt (secMin, SecDiff, numData, group, numGroup, *f_primMiss, 3994 li_primMiss, *f_secMiss, li_secMiss, groupSize, ibit, jbit, 3995 kbit); 3996 *Min = secMin; 3997 *Dst = SecDiff; 3998 free (Data); 3999 } 4000 return 0; 4001 } 4002 4003 /***************************************************************************** 4004 * WriteTDLPRecord() -- 4005 * 4006 * Arthur Taylor / MDL 4007 * 4008 * PURPOSE 4009 * Writes a TDLP message to file. 4010 * 4011 * ARGUMENTS 4012 * fp = An opened TDLP file already at the correct location. (Input) 4013 * Data = The data to write. (Input) 4014 * DataLen = Length of Data. (Input) 4015 * DSF = Decimal scale factor to apply to the data (Input) 4016 * BSF = Binary scale factor to apply to the data (Input) 4017 * f_primMiss = Flag saying if we have a primary missing value (Input) 4018 * primMiss = primary missing value. (Input) 4019 * f_secMiss = Flag saying if we have a secondary missing value (Input) 4020 * secMiss = secondary missing value. (Input) 4021 * gds = The grid definition section (Input) 4022 * comment = Describes the kind of data (max 32 bytes). (Input) 4023 * refTime = The reference (creation) time of this message. (Input) 4024 * ID1 = TDLPack ID1 (Input) 4025 * ID2 = TDLPack ID2 (Input) 4026 * ID3 = TDLPack ID3 (Input) 4027 * ID4 = TDLPack ID4 (Input) 4028 * projSec = The projection in seconds (Input) 4029 * processNum = The process number that created it (Input) 4030 * seqNum = The sequence number that created it (Input) 4031 * 4032 * FILES/DATABASES: 4033 * An already opened file pointing to the desired TDLP message. 4034 * 4035 * RETURNS: int (could use errSprintf()) 4036 * 0 = OK 4037 * -1 = comment is too long. 4038 * -2 = projHr is inconsistent with ID3. 4039 * -3 = Type of map projection that TDLP can't handle. 4040 * -4 = Primary or Secondary missing value == 0. 4041 * 4042 * HISTORY 4043 * 12/2004 Arthur Taylor (MDL): Created 4044 * 1/2005 AAT: Cleaned up. 4045 * 4046 * NOTES 4047 ***************************************************************************** 4048 */ 4049 int WriteTDLPRecord (FILE * fp, double *Data, sInt4 DataLen, int DSF, 4050 int BSF, char f_primMiss, double primMiss, 4051 char f_secMiss, double secMiss, gdsType *gds, 4052 char *comment, double refTime, sInt4 ID1, 4053 sInt4 ID2, sInt4 ID3, sInt4 ID4, 4054 sInt4 projSec, sInt4 processNum, sInt4 seqNum) 4055 { 4056 sInt4 *Scaled; /* The scaled data. */ 4057 TDLGroupType *group; /* The groups used to pack the data. */ 4058 size_t numGroup; /* Number of groups. */ 4059 char f_grid = 1; /* Flag if this is gridded data. In theory can handle 4060 * vector data, but haven't tested it. */ 4061 char f_sndOrder; /* Flag if we should try second order packing. */ 4062 4063 /* TODO: Trace overallMin to figure out how it could be used uninitialized */ 4064 sInt4 overallMin; /* Overall min value of the scaled data. */ 4065 4066 sInt4 a1; /* 2nd order difference: 1st value. */ 4067 sInt4 b2; /* 2nd order difference: 1st 1st order difference */ 4068 sInt4 li_primMiss; /* Scaled primary missing value. */ 4069 sInt4 li_secMiss; /* Scaled secondary missing value. */ 4070 int mbit; /* # of bits for b2. */ 4071 int nbit; /* # of bits for overallMin. */ 4072 size_t ibit; /* # of bits for largest minimum value in groups */ 4073 size_t jbit; /* # of bits for largest # bits in groups */ 4074 size_t kbit; /* # of bits for largest # values in groups */ 4075 int sec1Len; /* Length of section 1. */ 4076 size_t pad; /* Number of bytes to pad the message to get to the 4077 * correct byte boundary. */ 4078 sInt4 groupSize; /* How many bytes the groups and data will take. */ 4079 sInt4 sec4Len; /* Length of section 4. */ 4080 sInt4 tdlRecSize; /* Size of the TDLP message. */ 4081 sInt4 recSize; /* Actual record size (including FORTRAN bytes). */ 4082 int commentLen; /* Length of comment */ 4083 short int projHr; /* The hours part of the forecast projection. */ 4084 char projMin; /* The minutes part of the forecast projection. */ 4085 sInt4 year; /* The reference year. */ 4086 int month, day; /* The reference month day. */ 4087 int hour, min; /* The reference hour minute. */ 4088 double sec; /* The reference second. */ 4089 char f_bitmap = 0; /* Bitmap flag: not implemented in specs. */ 4090 #ifdef always_true 4091 char f_simple = 0; /* Simple Pack flag: not implemented in specs. */ 4092 #endif 4093 int gridType; /* Which type of grid. (Polar, Mercator, Lambert). */ 4094 int dataCnt; /* Keeps track of which element we are writing. */ 4095 sInt4 max0; /* The max value in a group. Represents primary or * 4096 * secondary missing value depending on scheme. */ 4097 sInt4 max1; /* The next to max value in a group. Represents * 4098 * secondary missing value. */ 4099 size_t i, j; /* loop counters */ 4100 sInt4 li_temp; /* Temporary variable (sInt4). */ 4101 short int si_temp; /* Temporary variable (short int). */ 4102 double d_temp; /* Temporary variable (double). */ 4103 char buffer[6]; /* Used to write reserved values */ 4104 uChar pbuf; /* A buffer of bits that were not written to disk */ 4105 sChar pbufLoc; /* Where in pbuf to add more bits. */ 4106 4107 commentLen = static_cast<int>(strlen (comment)); 4108 if (commentLen > 32) { 4109 errSprintf ("Error: '%s' is > 32 bytes long\n", comment); 4110 return -1; 4111 } 4112 projHr = projSec / 3600; 4113 projMin = (projSec % 3600) / 60; 4114 if (projHr != (ID3 - ((ID3 / 1000) * 1000))) { 4115 errSprintf ("Error: projHr = %d is inconsistent with ID3 = %ld\n", 4116 projHr, ID3); 4117 return -2; 4118 } 4119 if (f_grid) { 4120 switch (gds->projType) { 4121 case GS3_POLAR: 4122 gridType = TDLP_POLAR; 4123 break; 4124 case GS3_LAMBERT: 4125 gridType = TDLP_LAMBERT; 4126 break; 4127 case GS3_MERCATOR: 4128 gridType = TDLP_MERCATOR; 4129 break; 4130 default: 4131 errSprintf ("TDLPack can't handle GRIB projection type %d\n", 4132 gds->projType); 4133 return -3; 4134 } 4135 } 4136 4137 if (GroupPack (Data, &Scaled, DataLen, DSF, BSF, &f_primMiss, &primMiss, 4138 &f_secMiss, &secMiss, f_grid, gds->Nx, gds->Ny, 4139 &f_sndOrder, &group, &numGroup, &overallMin, &a1, &b2, 4140 &groupSize, &ibit, &jbit, &kbit) != 0) { 4141 return -4; 4142 } 4143 4144 /* Make sure missing data is properly scaled. */ 4145 if (f_primMiss) { 4146 li_primMiss = (sInt4) (primMiss * SCALE_MISSING + .5); 4147 } 4148 if (f_secMiss) { 4149 li_secMiss = (sInt4) (secMiss * SCALE_MISSING + .5); 4150 } 4151 4152 /* Compute TDL record size. */ 4153 /* *INDENT-OFF* */ 4154 /* TDL Record size 4155 * 8 (section 0), 4156 * 39 + strlen(comment) (section 1), 4157 * 0 or 28 (depending on if you have a section 2), 4158 * 0 (section 3), 4159 * 16 + 5 + 1 + nbit(min val) + 16 + 5 + 5 + 5 + GroupSize() (section 4) 4160 * 4 (section 5) 4161 * pad (to even 8 bytes...) 4162 * Group size uses: 4163 * ibit * num_groups + jbit * num_groups + 4164 * kbit * num_groups + group.nbit * group.nvalues */ 4165 /* *INDENT-ON* */ 4166 sec1Len = 39 + commentLen; 4167 if (overallMin < 0) { 4168 nbit = power (-1 * overallMin, 0); 4169 } else { 4170 nbit = power (overallMin, 0); 4171 } 4172 if (!f_sndOrder) { 4173 if (f_secMiss) { 4174 sec4Len = 16 + (sInt4) (ceil ((5 + 1 + nbit + 16 + 5 + 5 + 5 4175 + groupSize) / 8.)); 4176 } else if (f_primMiss) { 4177 sec4Len = 12 + (sInt4) (ceil ((5 + 1 + nbit + 16 + 5 + 5 + 5 4178 + groupSize) / 8.)); 4179 } else { 4180 sec4Len = 8 + (sInt4) (ceil ((5 + 1 + nbit + 16 + 5 + 5 + 5 4181 + groupSize) / 8.)); 4182 } 4183 } else { 4184 if (b2 < 0) { 4185 mbit = power (-1 * b2, 0); 4186 } else { 4187 mbit = power (b2, 0); 4188 } 4189 if (f_secMiss) { 4190 sec4Len = 4191 16 + 4192 (sInt4) (ceil 4193 ((32 + 5 + 1 + mbit + 5 + 1 + nbit + 16 + 5 + 5 + 5 + 4194 groupSize) / 8.)); 4195 } else if (f_primMiss) { 4196 sec4Len = 4197 12 + 4198 (sInt4) (ceil 4199 ((32 + 5 + 1 + mbit + 5 + 1 + nbit + 16 + 5 + 5 + 5 + 4200 groupSize) / 8.)); 4201 } else { 4202 sec4Len = 4203 8 + 4204 (sInt4) (ceil 4205 ((32 + 5 + 1 + mbit + 5 + 1 + nbit + 16 + 5 + 5 + 5 + 4206 groupSize) / 8.)); 4207 } 4208 } 4209 if (f_grid) { 4210 tdlRecSize = 8 + sec1Len + 28 + 0 + sec4Len + 4; 4211 } else { 4212 tdlRecSize = 8 + sec1Len + 0 + 0 + sec4Len + 4; 4213 } 4214 /* Actual recSize is 8 + round(tdlRecSize) to nearest 8 byte boundary. */ 4215 recSize = 8 + (sInt4) (ceil (tdlRecSize / 8.0)) * 8; 4216 pad = (int) ((recSize - 8) - tdlRecSize); 4217 4218 /* --- Start Writing record. --- */ 4219 /* First write FORTRAN record information */ 4220 FWRITE_BIG (&(recSize), sizeof (sInt4), 1, fp); 4221 li_temp = 0; 4222 FWRITE_BIG (&(li_temp), sizeof (sInt4), 1, fp); 4223 li_temp = recSize - 8; /* FORTRAN rec length. */ 4224 FWRITE_BIG (&(li_temp), sizeof (sInt4), 1, fp); 4225 4226 /* Now write section 0. */ 4227 fwrite ("TDLP", sizeof (char), 4, fp); 4228 FWRITE_ODDINT_BIG (&(tdlRecSize), 3, fp); 4229 /* version number */ 4230 fputc (0, fp); 4231 4232 /* Now write section 1. */ 4233 fputc (sec1Len, fp); 4234 /* output type specification... */ 4235 i = 0; 4236 if (f_grid) { 4237 i |= 1; 4238 } 4239 if (f_bitmap) { 4240 i |= 2; 4241 } 4242 fputc (static_cast<int>(i), fp); 4243 /* tempTime = gmtime (&(refTime));*/ 4244 Clock_PrintDate (refTime, &year, &month, &day, &hour, &min, &sec); 4245 /* year = tempTime->tm_year + 1900; 4246 month = tempTime->tm_mon + 1; 4247 day = tempTime->tm_mday; 4248 hour = tempTime->tm_hour; 4249 min = tempTime->tm_min; 4250 */ 4251 si_temp = year; 4252 FWRITE_BIG (&si_temp, sizeof (short int), 1, fp); 4253 fputc (month, fp); 4254 fputc (day, fp); 4255 fputc (hour, fp); 4256 fputc (min, fp); 4257 li_temp = (year * 1000000 + month * 10000 + day * 100 + hour); 4258 FWRITE_BIG (&li_temp, sizeof (sInt4), 1, fp); 4259 FWRITE_BIG (&ID1, sizeof (sInt4), 1, fp); 4260 FWRITE_BIG (&ID2, sizeof (sInt4), 1, fp); 4261 FWRITE_BIG (&ID3, sizeof (sInt4), 1, fp); 4262 FWRITE_BIG (&ID4, sizeof (sInt4), 1, fp); 4263 FWRITE_BIG (&projHr, sizeof (short int), 1, fp); 4264 fputc (projMin, fp); 4265 fputc (processNum, fp); 4266 fputc (seqNum, fp); 4267 i = (DSF < 0) ? 128 - DSF : DSF; 4268 fputc (static_cast<int>(i), fp); 4269 i = (BSF < 0) ? 128 - BSF : BSF; 4270 fputc (static_cast<int>(i), fp); 4271 /* Reserved: 3 bytes of 0. */ 4272 li_temp = 0; 4273 fwrite (&li_temp, sizeof (char), 3, fp); 4274 fputc (commentLen, fp); 4275 fwrite (comment, sizeof (char), commentLen, fp); 4276 4277 /* Now write section 2. */ 4278 if (f_grid) { 4279 fputc (28, fp); 4280 fputc (gridType, fp); 4281 si_temp = gds->Nx; 4282 FWRITE_BIG (&si_temp, sizeof (short int), 1, fp); 4283 si_temp = gds->Ny; 4284 FWRITE_BIG (&si_temp, sizeof (short int), 1, fp); 4285 li_temp = (sInt4) (gds->lat1 * 10000. + .5); 4286 if (li_temp < 0) { 4287 pbuf = 128; 4288 li_temp = -1 * li_temp; 4289 } else { 4290 pbuf = 0; 4291 } 4292 pbufLoc = 7; 4293 fileBitWrite (&(li_temp), sizeof (li_temp), 23, fp, &pbuf, &pbufLoc); 4294 myAssert (pbufLoc == 8); 4295 myAssert (pbuf == 0); 4296 d_temp = 360 - gds->lon1; 4297 if (d_temp < 0) 4298 d_temp += 360; 4299 if (d_temp > 360) 4300 d_temp -= 360; 4301 li_temp = (sInt4) (d_temp * 10000. + .5); 4302 if (li_temp < 0) { 4303 pbuf = 128; 4304 li_temp = -1 * li_temp; 4305 } 4306 pbufLoc = 7; 4307 fileBitWrite (&(li_temp), sizeof (li_temp), 23, fp, &pbuf, &pbufLoc); 4308 myAssert (pbufLoc == 8); 4309 myAssert (pbuf == 0); 4310 d_temp = 360 - gds->orientLon; 4311 if (d_temp < 0) 4312 d_temp += 360; 4313 if (d_temp > 360) 4314 d_temp -= 360; 4315 li_temp = (sInt4) (d_temp * 10000. + .5); 4316 if (li_temp < 0) { 4317 pbuf = 128; 4318 li_temp = -1 * li_temp; 4319 } 4320 pbufLoc = 7; 4321 fileBitWrite (&(li_temp), sizeof (li_temp), 23, fp, &pbuf, &pbufLoc); 4322 myAssert (pbufLoc == 8); 4323 myAssert (pbuf == 0); 4324 li_temp = (sInt4) (gds->Dx * 1000. + .5); 4325 FWRITE_BIG (&li_temp, sizeof (sInt4), 1, fp); 4326 li_temp = (sInt4) (gds->meshLat * 10000. + .5); 4327 if (li_temp < 0) { 4328 pbuf = 128; 4329 li_temp = -1 * li_temp; 4330 } 4331 pbufLoc = 7; 4332 fileBitWrite (&(li_temp), sizeof (li_temp), 23, fp, &pbuf, &pbufLoc); 4333 myAssert (pbufLoc == 8); 4334 myAssert (pbuf == 0); 4335 memset (buffer, 0, 6); 4336 fwrite (buffer, sizeof (char), 6, fp); 4337 } 4338 4339 /* Now write section 3. */ 4340 /* Bitmap is not supported, skipping. */ 4341 myAssert (!f_bitmap); 4342 4343 /* Now write section 4. */ 4344 FWRITE_ODDINT_BIG (&(sec4Len), 3, fp); 4345 i = 0; 4346 if (f_secMiss) 4347 i |= 1; 4348 if (f_primMiss) 4349 i |= 2; 4350 if (f_sndOrder) 4351 i |= 4; 4352 #ifdef always_true 4353 if (!f_simple) 4354 #endif 4355 i |= 8; 4356 if (!f_grid) 4357 i |= 16; 4358 fputc (static_cast<int>(i), fp); 4359 li_temp = DataLen; 4360 FWRITE_BIG (&li_temp, sizeof (sInt4), 1, fp); 4361 if (f_primMiss) { 4362 FWRITE_BIG (&(li_primMiss), sizeof (sInt4), 1, fp); 4363 if (f_secMiss) { 4364 FWRITE_BIG (&(li_secMiss), sizeof (sInt4), 1, fp); 4365 } 4366 } 4367 if (f_sndOrder) { 4368 if (a1 < 0) { 4369 pbuf = 128; 4370 li_temp = -1 * a1; 4371 } else { 4372 pbuf = 0; 4373 li_temp = a1; 4374 } 4375 pbufLoc = 7; 4376 fileBitWrite (&(li_temp), sizeof (li_temp), 31, fp, &pbuf, &pbufLoc); 4377 myAssert (pbufLoc == 8); 4378 myAssert (pbuf == 0); 4379 fileBitWrite (&mbit, sizeof (mbit), 5, fp, &pbuf, &pbufLoc); 4380 if (b2 < 0) { 4381 i = 1; 4382 li_temp = -1 * b2; 4383 } else { 4384 i = 0; 4385 li_temp = b2; 4386 } 4387 fileBitWrite (&i, sizeof (i), 1, fp, &pbuf, &pbufLoc); 4388 myAssert (pbufLoc == 2); 4389 fileBitWrite (&li_temp, sizeof (li_temp), (unsigned short int) mbit, 4390 fp, &pbuf, &pbufLoc); 4391 } 4392 fileBitWrite (&nbit, sizeof (nbit), 5, fp, &pbuf, &pbufLoc); 4393 if (overallMin < 0) { 4394 i = 1; 4395 li_temp = -1 * overallMin; 4396 } else { 4397 i = 0; 4398 li_temp = overallMin; 4399 } 4400 fileBitWrite (&i, sizeof (i), 1, fp, &pbuf, &pbufLoc); 4401 fileBitWrite (&li_temp, sizeof (li_temp), (unsigned short int) nbit, fp, 4402 &pbuf, &pbufLoc); 4403 fileBitWrite (&numGroup, sizeof (numGroup), 16, fp, &pbuf, &pbufLoc); 4404 fileBitWrite (&ibit, sizeof (ibit), 5, fp, &pbuf, &pbufLoc); 4405 fileBitWrite (&jbit, sizeof (jbit), 5, fp, &pbuf, &pbufLoc); 4406 fileBitWrite (&kbit, sizeof (kbit), 5, fp, &pbuf, &pbufLoc); 4407 for (i = 0; i < numGroup; i++) { 4408 fileBitWrite (&(group[i].min), sizeof (sInt4), 4409 (unsigned short int) ibit, fp, &pbuf, &pbufLoc); 4410 } 4411 for (i = 0; i < numGroup; i++) { 4412 fileBitWrite (&(group[i].bit), sizeof (char), 4413 (unsigned short int) jbit, fp, &pbuf, &pbufLoc); 4414 } 4415 #ifdef DEBUG 4416 li_temp = 0; 4417 #endif 4418 for (i = 0; i < numGroup; i++) { 4419 fileBitWrite (&(group[i].num), sizeof (sInt4), 4420 (unsigned short int) kbit, fp, &pbuf, &pbufLoc); 4421 #ifdef DEBUG 4422 li_temp += group[i].num; 4423 #endif 4424 } 4425 #ifdef DEBUG 4426 /* Sanity check ! */ 4427 if (li_temp != DataLen) { 4428 printf ("Total packed in groups %d != DataLen %d\n", li_temp, 4429 DataLen); 4430 } 4431 myAssert (li_temp == DataLen); 4432 #endif 4433 4434 dataCnt = 0; 4435 /* Start going through the data. Grid data has already been reordered. 4436 * Already taken care of 2nd order differences. Data at this point should 4437 * contain a stream of either 2nd order differences or 0 order 4438 * differences. We have also removed overallMin from all non-missing 4439 * elements in the stream */ 4440 if (f_secMiss) { 4441 for (i = 0; i < numGroup; i++) { 4442 max0 = (1 << group[i].bit) - 1; 4443 max1 = (1 << group[i].bit) - 2; 4444 for (j = 0; j < group[i].num; j++) { 4445 if (Scaled[dataCnt] == li_primMiss) { 4446 li_temp = max0; 4447 } else if (Scaled[dataCnt] == li_secMiss) { 4448 li_temp = max1; 4449 } else { 4450 li_temp = Scaled[dataCnt] - group[i].min; 4451 } 4452 fileBitWrite (&(li_temp), sizeof (sInt4), group[i].bit, fp, 4453 &pbuf, &pbufLoc); 4454 dataCnt++; 4455 } 4456 } 4457 } else if (f_primMiss) { 4458 for (i = 0; i < numGroup; i++) { 4459 /* see what happens when bit == 0. */ 4460 max0 = (1 << group[i].bit) - 1; 4461 for (j = 0; j < group[i].num; j++) { 4462 if (group[i].bit != 0) { 4463 if (Scaled[dataCnt] == li_primMiss) { 4464 li_temp = max0; 4465 } else { 4466 li_temp = Scaled[dataCnt] - group[i].min; 4467 } 4468 fileBitWrite (&(li_temp), sizeof (sInt4), group[i].bit, fp, 4469 &pbuf, &pbufLoc); 4470 } 4471 dataCnt++; 4472 } 4473 } 4474 } else { 4475 for (i = 0; i < numGroup; i++) { 4476 for (j = 0; j < group[i].num; j++) { 4477 li_temp = Scaled[dataCnt] - group[i].min; 4478 if (group[i].bit != 0) { 4479 fileBitWrite (&(li_temp), sizeof (sInt4), group[i].bit, fp, 4480 &pbuf, &pbufLoc); 4481 } 4482 dataCnt++; 4483 } 4484 } 4485 } 4486 myAssert (dataCnt == DataLen); 4487 /* flush the PutBit buffer... */ 4488 if (pbufLoc != 8) { 4489 fputc ((int) pbuf, fp); 4490 } 4491 4492 /* Now write section 5. */ 4493 fwrite ("7777", sizeof (char), 4, fp); 4494 4495 /* Deal with padding at end of record... */ 4496 for (i = 0; i < pad; i++) { 4497 fputc (0, fp); 4498 } 4499 /* Now write FORTRAN record information */ 4500 FWRITE_BIG (&(recSize), sizeof (sInt4), 1, fp); 4501 4502 free (Scaled); 4503 free (group); 4504 return 0; 4505 } 4506 4507 #endif // unused_by_GDAL 4508 #endif 4509 /* tdlpack is no longer supported by GDAL */ 4510