OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
dim_mgr.cpp
Go to the documentation of this file.
1 /********************************************************************
2  dim_mgr.cpp - logic for the dimension manager
3  for a n dimensional array where you need only m (< n) dimensions
4  manage the storege for just the m-n dimensions for only the grid boxes
5  needed - this saves reading a big block in when you only need some
6  kind of slice.
7 
8  Modification history:
9  Programmer Date Description of change
10  ---------- ---- ---------------------
11  W. Robinson 8 Jan 2020 Original development
12  W. Robinson Nov 2020 make as a class in c++
13 
14 ********************************************************************/
15 #include "dim_mgr.hpp"
16 
17 // for class dim_mgr
18 // Separate the constructor out
19 
20  // ndim is # of dimensions to be managed
21 /********************************************************************
22  dim_mgr - 1st constructor form for dim_mgr class
23 
24  ndim I # of dimensions under management
25 ********************************************************************/
26  dim_mgr::dim_mgr(int32_t ndim) {
27  hash_tbl_siz = 7;
28  this->hash_tbl_siz = hash_tbl_siz;
29  this->const_hlp(ndim);
30  //cout << __FILE__ << ": 1-arg dim_mgr\n";
31  }
32 
33 /********************************************************************
34  dim_mgr - 2nd constructor form for dim_mgr class
35 
36  ndim I # of dimensions under management
37  hash_tbl_siz I # elements in the hash tablew
38 ********************************************************************/
39  dim_mgr::dim_mgr(int32_t ndim, int32_t hash_tbl_sz) {
40  hash_tbl_siz = hash_tbl_sz;
41  this->const_hlp(ndim);
42  this->hash_tbl_siz = hash_tbl_siz;
43  //cout << __FILE__ << ": 2-arg dim_mgr\n";
44  }
45 
46 /********************************************************************
47  const_hlp - helper for the 2 constructors
48  This does the real set-up of the dimension manager
49 
50  ndim I # of dimensions under management
51 ********************************************************************/
52  void dim_mgr::const_hlp(int32_t ndim) {
53  this->ndim = ndim;
54  prev_int = NULL;
55  n_tot_dat_blobs = 0;
56  dim_info = ( dim_info_struc ** )malloc
57  ( ndim * sizeof( dim_info_struc * ) );
58  //cout << __FILE__ << ": Setting the # dims\n";
59  // allocate all dim_info structs
60  for( int i = 0; i < ndim; i++ )
61  {
62  dim_info[i] = (dim_info_struc *) malloc( sizeof(dim_info_struc) );
63  dim_info[i]->dim_coords = NULL; // so we know if not filled
64  dim_info[i]->nvals = 0; // ditto
65  dim_info[i]->type = 0; // ditto
66  }
67  // to set the hash table
68  hash_tbl = new vector <hash_entry_struc>[hash_tbl_siz];
69  gpt_hash_tbl = new vector <gpt_hash_struc>[hash_tbl_siz];
70 
71  // to set up the point information structure
72  int ncorner = pow( 2, ndim );
73  pt_info.pt_status = (int32_t *)malloc( ncorner * sizeof(int32_t ) );
74  pt_info.pt_base_loc = (int32_t *)malloc( ndim * sizeof(int32_t ) );
75  pt_info.wt = (double *)malloc( ndim * sizeof(double) );
76  pt_info.wt_pt = (double *)malloc( ncorner * sizeof(double) );
77  pt_info.dat_ptrs = (void **)malloc( ncorner * sizeof(void *) );
78  }
79 
80 /********************************************************************
81  ~dim_mgr - destructor - needed for clean up of the class
82 ********************************************************************/
84  delete[] hash_tbl;
85  delete[] gpt_hash_tbl;
86  for( int i = 0; i < ndim; i++ )
87  {
88  if( dim_info[i]->type == 1 )
89  free( dim_info[i]->dim_coords );
90  free(dim_info[i]);
91  }
92  // dispense with point info
93  free( pt_info.pt_status );
94  free( pt_info.pt_base_loc );
95  free( pt_info.wt );
96  free( pt_info.wt_pt );
97  free( pt_info.dat_ptrs );
98  //
99  free( dim_info );
100  }
101 
102  // record an addition of points
103 /********************************************************************
104  add_pts - add to the total count of data blobs under management
105 
106  Returns:
107  void - none
108  Parameters: (in calling order)
109  Type Name I/O Description
110  ---- ---- --- -----------
111  int32_t nptadd I # grid points added
112 ********************************************************************/
113  void dim_mgr::add_pts( int32_t nptadd ) {
114  n_tot_dat_blobs += nptadd;
115  }
116 
117 /********************************************************************
118  get_tot_blobs - get total # data blobs being managed
119 
120  Returns:
121  int32_t # data blobs being managed
122 ********************************************************************/
123  int32_t dim_mgr::get_tot_blobs() { return n_tot_dat_blobs; }
124 
125 /********************************************************************
126  init_dim - initialize information for a dimension. First form is for
127  the dimension coordinates specified in an array
128 
129  Returns:
130  int32_t - status 0 = good
131 
132  Parameters: (in calling order)
133  Type Name I/O Description
134  ---- ---- --- -----------
135  int32_t dim_num I Dimension to set
136  int32_t nvals I # grid pts in this dim
137  double min I min of dimension range
138  double max I max of dimension range
139 ********************************************************************/
140  int32_t dim_mgr::init_dim( int32_t dim_num, int32_t nvals,
141  double min, double max ) {
142  // set the dim_info_struc if not set yet
143  if( dim_info == NULL ) {
144  cout << __FILE__ << __LINE__ << " dim_info array is null\n";
145  return 0;
146  }
147  if( dim_info[dim_num]->nvals != 0 ) {
148  cout << __FILE__ << __LINE__ << " dim_info array entry " << dim_num <<
149  " is filled already\n";
150  return 0;
151  }
152  dim_info[dim_num]->nvals = nvals;
153  dim_info[dim_num]->min = min;
154  dim_info[dim_num]->max = max;
155  dim_info[dim_num]->type = 0;
156  dim_info[dim_num]->delta = ( max - min ) / ( nvals - 1 );
157  return 0;
158  }
159 
160 /********************************************************************
161  init_dim - initialize information for a dimension. Second form is for
162  the dimension coordinates specified in an array
163 
164  Parameters: (in calling order)
165  Type Name I/O Description
166  ---- ---- --- -----------
167  int32_t dim_num I Dimension to set
168  int32_t nvals I # grid pts in this dim
169  double * dim_coords I set of coordinates for this
170  dimension
171 ********************************************************************/
172  int32_t dim_mgr::init_dim( int32_t dim_num, int32_t nvals,
173  double *dim_coords ) {
174 
175  if( dim_info == NULL ) {
176  cout << __FILE__ << __LINE__ << " dim_info array is null\n";
177  return 0;
178  }
179  if( dim_info[dim_num]->dim_coords != NULL ) {
180  cout << __FILE__ << __LINE__ << " dim_info array entry " << dim_num <<
181  " is filled already\n";
182  return 0;
183  }
184  dim_info[dim_num]->nvals = nvals;
185  dim_info[dim_num]->min = dim_coords[0];
186  dim_info[dim_num]->max = dim_coords[ nvals - 1 ];
187  dim_info[dim_num]->type = 1;
188  dim_info[dim_num]->dim_coords =
189  (double *)malloc( nvals * sizeof( double ) );
190  for( int i = 0; i < nvals; i++ )
191  dim_info[dim_num]->dim_coords[i] = dim_coords[i];
192  return 0;
193  }
194 
195 /********************************************************************
196  update_new_data - Update info about new data under management
197 
198  This will refresh the interval's data status and data pointer using
199  the pt_info structure the user updated.
200 
201 ********************************************************************/
203  int32_t npt = pow( 2, ndim );
204 
205  // just may as well update all points
206  for( int i = 0; i < npt; i++ )
207  {
208  prev_int->dat_info[i]->dat_status = pt_info.pt_status[i];
209  prev_int->dat_info[i]->dat = pt_info.dat_ptrs[i];
210  }
211  }
212 
213 /********************************************************************
214  mng_pt - for a point in a grid, find or set up the location for the
215  associated data and return that and the weights to apply
216 
217  Returns:
218  pt_info_struc * the structure with all point information
219  needed to interpolagte the data
220 
221  Parameters: (in calling order)
222  Type Name I/O Description
223  ---- ---- --- -----------
224  double * pt I coordinates of the point to
225  locate
226  int32_t access_id I A last time of access to
227  assign to the bottom interval
228  the lower the value, the
229  more time since last access
230  int32_t * status O return status 0 = good,
231  1 = code failure, you
232  shoiuld fail at this point
233  2 = not valid point (not in
234  the grid bounds) treat as
235  unable to do the point
236  Modification history:
237  Programmer Date Description of change
238  ---------- ---- ---------------------
239  W. Robinson 1 Sep 2020 based loosly on sparse_mng_pt()
240 ********************************************************************/
241  pt_info_struc * dim_mgr::mng_pt( double *pt, int32_t access_id,
242  int32_t *status ) {
243 
244  int32_t idim, idat, ndat, same_interval;
245  int32_t *ix, *ix_real, *offset_lcl, acc_mode, ret;
246  interval_struc *found_int;
247 
248  *status = 0; // start with good status
249  /*
250  * If the new point is the same as the old, just return the same point info
251  */
252  // not in std c++ so... if( isnormal( old_pt[0] )
253  if( old_pt[0] == old_pt[0] )
254  {
255  int32_t match = 1;
256  for( idim = 0; idim < ndim; idim++ )
257  {
258  if( *( pt + idim ) != *( old_pt + idim ) )
259  {
260  match = 0;
261  break;
262  }
263  }
264  if( match == 1 )
265  {
266  *status = old_status;
267  return &pt_info;
268  }
269  }
270  for( idim = 0; idim < ndim; idim++ )
271  *( old_pt + idim ) = *( pt + idim );
272  /*
273  * set up some local storage
274  */
275  if( ( ( ix = (int32_t *) malloc( ndim * sizeof( int32_t ) ) ) == NULL ) ||
276  ( ( ix_real = (int32_t *)
277  malloc( ndim * sizeof( int32_t ) ) ) == NULL ) ||
278  ( ( offset_lcl = (int32_t *)
279  malloc( ndim * sizeof( int32_t ) ) ) == NULL ) )
280  {
281  printf( "%s, %d: Unable to allocate the dim index array\n", __FILE__,
282  __LINE__ );
283  *status = 1;
284  return &pt_info;
285  }
286  /*
287  * also set the weight and point weight if needed
288  */
289  ndat = pow( 2., ndim );
290  /*
291  * get the index of the point in all dims and the weight to it
292  */
293  if( sparse_get_loc( dim_info, ndim, pt, ix, pt_info.wt, pt_info.wt_pt )
294  != 0 )
295  {
296  *status = 2;
297  old_status = 2;
298  return &pt_info;
299  }
300  /*
301  printf( "\n\n%s - index: %d,%d, weight: %f,%f\n", __FILE__,
302  ix[0], ix[1], pt_info.wt[0], pt_info.wt[1] );
303  printf( "data point: (%f, %f)\n", pt[0], pt[1] );
304  */
305  /*
306  * Its likely that the previous point is in the same grid box as the current
307  * point. In this case, just return the previously found interval
308  */
309  same_interval = 0;
310  pt_info.interval_needs_data = 0;
311  if( prev_int != NULL )
312  {
313  /* see if we are in the same interval */
314  same_interval = 1;
315  for( idim = 0; idim < ndim; idim++ )
316  {
317  if( ix[idim] != prev_int->dat_info[0]->ix_arr[idim] )
318  {
319  same_interval = 0;
320  break;
321  }
322  }
323  }
324 
325  if( same_interval == 1 )
326  {
327  found_int = prev_int;
328  found_int->access_id = access_id;
329  }
330  else
331  {
332  /*
333  * get/set the interval for this grid point
334  */
335  acc_mode = 0;
336  valarray<int> ix_val(ndim);
337  for( int i = 0; i < ndim; i++ )
338  ix_val[i] = ix[i];
339  found_int = access( ix_val, acc_mode );
340 
341  /*
342  * Set the found interval's access id to the one passed in
343  */
344  found_int->access_id = access_id;
345  /*
346  * if interval is new, we need to donate any data areas shared
347  * to the new interval
348  */
349  if( found_int->dat_filled == 0 )
350  {
351  idim = -1; // set this way to start at the top
352 
353  if( share_gpt( found_int, ix ) != 0 ) {
354  *status = 1;
355  return &pt_info;
356  }
357  // this should be obsolete
358  /* set the interval filled value to yes */
359  found_int->dat_filled = 1;
360  /* loop through all data pointers in the new interval */
361  /* and set up the data structures, less the pointer to the data */
362  for( idat = 0; idat < ndat; idat++ )
363  {
364  /* if the data for this corner is not there, create and fill it */
365  if( found_int->dat_info[idat] == NULL )
366  {
367  valarray<int> ixv_off(ndim);
368  pt_info.interval_needs_data = 1; // flag that data needed
369  // for this interval / grid box
370  /* set up each data info struct */
371  found_int->dat_info[idat] =
372  (data_info_struc *) malloc( sizeof( data_info_struc ) );
373  /* get index for this point */
374  linear_to_offset( ndim, idat, offset_lcl );
375  found_int->dat_info[idat]->ix_arr = (int32_t *) malloc( ndim *
376  sizeof( int32_t ) );
377  for( idim = 0; idim < ndim; idim++ )
378  {
379  ix_real[idim] = ix[idim] + offset_lcl[idim];
380  ixv_off[idim] = ix_real[idim];
381  found_int->dat_info[idat]->ix_arr[idim] = ix_real[idim];
382  }
383  /*
384  * set data status to not filled and # intervals pointing to it to 1
385  */
386  found_int->dat_info[idat]->dat_status = -1; /* not filled here */
387  found_int->dat_info[idat]->n_intervals = 1;
388  /*
389  * add new data_info to the grid point hash table
390  */
391  ret = gpt_add( ixv_off, found_int->dat_info[idat] );
392  if( ret != 0 )
393  {
394  *status = 1;
395  return &pt_info;
396  }
397  }
398  else /* for data already there, incriment access count */
399  {
400  // WDR keep in case some functions needed here
401  }
402  }
403  }
404  /* remember the found interval and its dim location */
405  prev_int = found_int;
406  }
407 
408  /* end set up of (possible) new grid interval */
409 
410  free( ix ); free( ix_real ); free( offset_lcl );
411 
412  // put the needed info into the pt_info struct
413  for( int i = 0; i < ndim; i++ )
414  pt_info.pt_base_loc[i] = found_int->dat_info[0]->ix_arr[i];
415  for( int i = 0; i < ndat; i++ ) {
416  pt_info.pt_status[i] = found_int->dat_info[i]->dat_status;
417  // pt_info.wt_pt, and wt are already set
418  pt_info.dat_ptrs[i] = found_int->dat_info[i]->dat;
419  }
420  /*
421  * return success
422  */
423  *status = 0;
424  old_status = 0;
425  return &pt_info;
426  }
427  // all the rest of routines that go with mng_pt
428 
429  int32_t dim_mgr::sparse_get_loc( dim_info_struc **dim_info, int32_t ndim,
430  double *pt, int32_t *ix, double *wt, double *wt_pt )
431 /********************************************************************
432  sparse_get_loc - get the location of a point in all grid dimensions
433  and the weights
434 
435  Returns:
436  int32_t - status 0 = good
437 
438  Parameters: (in calling order)
439  Type Name I/O Description
440  ---- ---- --- -----------
441  dim_info_struc ** dim_info I array of descriptions of each
442  dimension
443  that is handled
444  int32_t ndim I # dimensions handled
445  double * pt I coordinates of the point to
446  locate
447  int32_t * ix O index of the grid interval
448  for all dimensions
449  double * wt O for each dimension, the weight
450  to apply to the index point
451  (1 - wt for the next index
452  point)
453  double * wt_pt O set of consolidated weights to
454  apply to the data blobs pointed
455  to by the dat_info_struc
456  Modification history:
457  Programmer Date Description of change
458  ---------- ---- ---------------------
459  W. Robinson 26 Nov 2019 Original development
460 
461 ********************************************************************/
462  {
463  int32_t idim, iint, full_len, msk;
464  /*
465  * we start with all composite weights at 1
466  */
467  full_len = pow( 2, ndim );
468  for( idim = 0; idim < full_len; idim++ )
469  *( wt_pt + idim ) = 1.;
470  /*
471  loop through all dimensions and get the point and weight
472  */
473  for( idim = 0; idim < ndim; idim++ )
474  {
475  /* for now, assume the grid is uneven and we look through each interval */
476  if( ( pt[idim] < dim_info[idim]->min ) ||
477  ( pt[idim] > dim_info[idim]->max ) )
478  {
479  //printf( "%s, %d - point is outside grid dimension range\n",
480  // __FILE__, __LINE__ );
481  return 1;
482  }
483  for( iint = 1; iint < dim_info[idim]->nvals; iint++ )
484  {
485  if( pt[idim] <= dim_info[idim]->dim_coords[iint] )
486  {
487  ix[idim] = iint - 1;
488 
489  wt[idim] = ( pt[idim] - dim_info[idim]->dim_coords[iint-1] ) /
490  ( dim_info[idim]->dim_coords[iint] -
491  dim_info[idim]->dim_coords[iint-1] );
492 
493  break;
494  }
495  }
496  /*
497  * This will modify the composite weight so it applies to each
498  * corner's data - apply the weight to the end point
499  * of that grid else 1 - weight
500  */
501  msk = pow( 2, idim );
502  for( iint = 0; iint < full_len; iint++ )
503  {
504  if( ( iint & msk ) == 0 ) /* apply 1 - wt */
505  *( wt_pt + iint ) *= 1. - wt[idim];
506  else
507  *( wt_pt + iint ) *= wt[idim];
508  }
509  }
510  return 0;
511  }
512 
513 interval_struc * dim_mgr::access( valarray<int>& s, int32_t acc_mode )
514 /********************************************************************
515  access search / insert interval defining the data at the grid point
516 
517  Returns:
518  interval_struc * pointer to the interval information
519 
520  Parameters: (in calling order)
521  Type Name I/O Description
522  ---- ---- --- -----------
523  valarray<int> s I set of coordinates of the point
524  int32_t acc_mode I action: 0 - find the interval,
525  if not there, make it. return
526  the interval pointer, 1 -
527  find interval and return NULL
528  if not found, 2 - remove an
529  entry based on coordinates s
530  Modification history:
531  Programmer Date Description of change
532  ---------- ---- ---------------------
533  W. Robinson 31 Aug 2020 Original development
534 ********************************************************************/
535  {
536  int32_t ndat = pow( 2, ndim );
537 
538  //Compute the index by using the hash function
539  int index = hash_func( s, hash_tbl_siz );
540  //Search the linked list at that specific index for the index array
541  for( long unsigned int i = 0; i < hash_tbl[index].size(); i++)
542  {
543  // the == for the 2 valarrays make a valarray of booleans,
544  // basically all dims match (all 1), so min is not = 0
545  // if all dimensions match...
546  if( ( hash_tbl[index][i].ix_arr == s ).min() != 0 )
547  {
548  // interval is found, we can either return interval info or erase it
549  if( acc_mode == 2 ) // remove NOTE that underlying structures
550  // not handled here!!! so fix before use
551  {
552  hash_tbl[index].erase( hash_tbl[index].begin() + i );
553  cout << "Set is removed" << endl;
554  return (interval_struc *) NULL;
555  }
556  else // return interval struc for the interval
557  {
558  //cout << "Set is found!" << endl;
559  //cout << "position: " << i << endl;
560  return hash_tbl[index][i].int_str;
561  }
562  }
563  }
564  // if not found,
565  //cout << "Set is not found!" << endl;
566  if( acc_mode == 0 ) // add a new entry
567  {
568  // create the new entry
569  hash_entry_struc hash_entry;
570  interval_struc *insert;
571 
572  insert = (interval_struc *)malloc( sizeof(interval_struc) );
573  insert->dat_filled = 0;
574  insert->access_id = 0; // tenp setting, done later
575  insert->dat_info = (data_info_struc **)
576  calloc( ndat, sizeof(data_info_struc *) );
577  hash_entry.ix_arr = s;
578  hash_entry.int_str = insert;
579  // Insert the element in the linked list at the particular hash index
580 
581  hash_tbl[index].push_back(hash_entry);
582  //cout << "Inserting new interval, hash item\n";
583  return insert;
584  }
585  else
586  {
587  return (interval_struc *) NULL;
588  }
589  cout << "Code should not get here!/n";
590  return (interval_struc *)NULL;
591  }
592 
593 // New - add a data info structure to the grid point hash table
594 
595 int32_t dim_mgr::gpt_add( valarray<int> s, data_info_struc *dat_info )
596 /*-------------------------------------------------------------------
597  gpt_add - add a data info structure to the grid point hash table
598 
599  Returns: int 0 all OK, 1 trying to insert to a existing coordinate
600 
601  Parameters: (in calling order)
602  Type Name I/O Description
603  ---- ---- --- -----------
604  valarray<int> s I set of coordinates of the point
605  data_info_struc * dat_info I descriptor for the data at the
606  grid point
607 
608  Modification history:
609  Programmer Date Description of change
610  ---------- ---- ---------------------
611  W. Robinson 30 Nov 2021 replace interval searching with this
612 
613 -------------------------------------------------------------------*/
614  {
615  // as with access, Compute the index by using the hash function
616  // and check for this coordinate already (there should not be one)
617  int index = hash_func( s, hash_tbl_siz );
618 
619  for( long unsigned int i = 0; i < gpt_hash_tbl[index].size(); i++)
620  {
621  if( ( gpt_hash_tbl[index][i].ix_arr == s ).min() != 0 )
622  {
623  // we have a match, which should not happen as this is insert
624  cout << __FILE__ << __LINE__ <<
625  "Error: grid point is already in hash table, Exiting" << endl;
626  return 1;
627  }
628  }
629  // Normal branch, insert the new hash entry
630  gpt_hash_struc hash_entry;
631 
632  hash_entry.ix_arr = s;
633  hash_entry.dat_info = dat_info;
634 
635  gpt_hash_tbl[index].push_back( hash_entry );
636  /*
637  cout << __FILE__ << ", " << __LINE__ << ", " <<
638  "Just added a grid point to hash" << endl;
639  */
640  return 0;
641  }
642 
643 int dim_mgr::hash_func(valarray<int> s, int32_t hash_tbl_siz )
644 /********************************************************************
645  hash_func - from the grid coordinates, make a hash entry number
646  This is one of the more odd parts of using a hashtable - get a good
647  distribution of table entries or the hash is not as useful
648 
649  Returns:
650  interval_struc * pointer to the interval information
651 
652  Parameters: (in calling order)
653  Type Name I/O Description
654  ---- ---- --- -----------
655  valarray<int> s I set of coordinates of the point
656  int32_t hash_tbl_siz I size of hash table
657 
658  Modification history:
659  Programmer Date Description of change
660  ---------- ---- ---------------------
661  W. Robinson 31 Aug 2020 Original development
662 ********************************************************************/
663  {
664  int retval;
665  long sum = 0;
666 
667  if( hash_ifirst == 0 ) {
668  int32_t ndim = s.size();
669  hash_ifirst = 1;
670  hash_h_mult = hash_tbl_siz / ( 2 * ndim );
671  hash_h_mult = hash_h_mult - ndim / 2;
672  }
673 
674  for( long unsigned int i = 0; i < s.size(); i++ )
675  sum += ( hash_h_mult + i ) * s[i];
676  sum = sum % hash_tbl_siz;
677 
678  retval = sum;
679  return retval;
680  }
681 
682 int32_t dim_mgr::share_gpt( interval_struc *intvl, int32_t *ix )
683 /********************************************************************
684  share_gpt will find grid points that are already set up and share
685  them with the current interval
686 
687  Returns:
688  int32_t - 0 if all good
689 
690  Parameters: (in calling order)
691  Type Name I/O Description
692  ---- ---- --- -----------
693  interval_struc * intvl I/O a new interval structure to
694  find data for
695  int32_t * ix I start grid location of the
696  interval
697  Modification history:
698  Programmer Date Description of change
699  ---------- ---- ---------------------
700  W. Robinson 1 Dec 2021 to hopefully simplify the grid point
701  data sharing process, replacing the
702  iterative int_share_data
703 ********************************************************************/
704  {
705  int32_t *ix_off, i;
706  valarray<int> s(ndim);
707  int32_t npt = pow( 2, ndim );
708  ix_off = ( int32_t * ) malloc( ndim * sizeof(int32_t) );
709  //
710  // look at all the corners of this interval
711  for( int ipt = 0; ipt < npt; ipt++ )
712  {
713  // get the grid point location from base and offset to this point
714  linear_to_offset( ndim, ipt, ix_off );
715  for( i = 0; i < ndim; i++ )
716  {
717  ix_off[i] += ix[i];
718  s[i] = ix_off[i];
719  }
720 
721  // see if the point is in the grid point hash already
722  int index = hash_func( s, hash_tbl_siz );
723  for( i = 0; i < (int32_t)gpt_hash_tbl[index].size(); i++ )
724  {
725  if( ( gpt_hash_tbl[index][i].ix_arr == s ).min() != 0 )
726  {
727  // found matching pt it in hash table, point to it from the interval
728  intvl->dat_filled = 1;
729  intvl->dat_info[ipt] = gpt_hash_tbl[index][i].dat_info;
730  intvl->dat_info[ipt]->n_intervals++; // one more ref to the point
731  break;
732  }
733  }
734  // new points are handled in mng_pt
735  }
736  free( ix_off );
737  return 0;
738  }
739 
740 /********************************************************************
741  purge will completely remove all entries from the dimension manager
742 
743  Returns:
744  int32_t - 0 all good
745 
746 ********************************************************************/
747 int32_t dim_mgr::purge()
748  {
749  int32_t nhash = hash_tbl_siz;
750  int32_t ndat = pow( 2, ndim );
751  // go to hash entry
752  // loop over each hash bin
753  for( int ihash = 0; ihash < nhash; ihash++ )
754  {
755  int32_t nentry = hash_tbl[ihash].size();
756  for( int iint = 0; iint < nentry; iint++ )
757  {
758  // go to interval struc
759  hash_entry_struc hash_ent = hash_tbl[ihash][0];
760 
761  interval_struc *int_str = hash_ent.int_str;
762 
763  // go to data structures
764  for( int idat = 0; idat < ndat; idat++ )
765  {
766  // rid data if # intervals accessing is 1
767  if( int_str->dat_info[idat]->n_intervals > 1 )
768  {
769  int_str->dat_info[idat]->n_intervals--;
770  }
771  else
772  {
773  // no more intervals point to this data struct,
774  // so free the data info structure
775  free( int_str->dat_info[idat]->dat );
776  free( int_str->dat_info[idat]->ix_arr );
777  free( int_str->dat_info[idat] );
778  }
779  }
780 
781  // free the array with data info structure addresses
782  free( int_str->dat_info );
783 
784  // free the interval struc
785  free( int_str );
786  // rid the top hash entry for bin i
787  hash_tbl[ihash].erase(hash_tbl[ihash].begin() );
788  }
789  }
790 
791  // Clean up all the grid point hash table entries
792  // the dat_info is already gone from the interval purge above, so
793  // the only thing left is all the entries in each gpt_hash
794  for( int ihash = 0; ihash < nhash; ihash++ )
795  {
796  int32_t nentry = gpt_hash_tbl[ihash].size();
797  for( int iint = 0; iint < nentry; iint++ )
798  {
799  gpt_hash_tbl[ihash].erase( gpt_hash_tbl[ihash].begin() );
800  }
801  }
802 
803  // the previous interval pointer is invalid, say so
804  prev_int = NULL;
805  n_tot_dat_blobs = 0;
806  // The rest can stay - the destructor handles that (I think)
807  return 0;
808  }
809 
810 /********************************************************************
811  prune - Remove selected intervals from management
812 
813  Returns: int32_t - 0 all good
814  access_id I erase intervals with access_id lower than access_id
815 ********************************************************************/
816 int32_t dim_mgr::prune(int32_t access_id ) {
817 
818  // start at dim_mgr
819  int32_t nhash = hash_tbl_siz;
820  int32_t ndat = pow( 2, ndim );
821 
822  // go to hash entry, loop over each hash bin
823  for( int ihash = 0; ihash < nhash; ihash++ )
824  {
825  // prune from list end to start so next entry location is unchanged
826  // even if an entry is deleted
827  int32_t nentry = hash_tbl[ihash].size();
828  for( int iint = ( nentry - 1 ); iint >= 0; iint-- )
829  {
830  // go to interval struc
831  hash_entry_struc hash_ent = hash_tbl[ihash][iint];
832 
833  interval_struc *int_str = hash_ent.int_str;
834  if( int_str->access_id < access_id )
835  {
836  // go to data structures
837  for( int idat = 0; idat < ndat; idat++ )
838  {
839  // rid data if # intervals accessed is 1 else lower interval count
840  if( int_str->dat_info[idat]->n_intervals > 0 )
841  {
842  int_str->dat_info[idat]->n_intervals--;
843  }
844  else
845  {
846  // no more intervals point to this data struct,
847  // leave the data info struc around to be handled when
848  // cleaning up the grid point hash
849  }
850  }
851  // WDR *** MAY need to free( int_str->dat_info );
852  free( int_str->dat_info );
853  // free the interval struc
854  free( int_str );
855  // rid the hash entry for hash ihash, list entry iint
856  hash_tbl[ihash].erase(hash_tbl[ihash].begin() + iint);
857  }
858  }
859  }
860  // go through the grid point hash table and remove entries with
861  // no accesses
862  for( int ihash = 0; ihash < nhash; ihash++ )
863  {
864  // prune from list end to start as before
865  int32_t nentry = gpt_hash_tbl[ihash].size();
866  for( int iint = ( nentry - 1 ); iint >= 0; iint-- )
867  {
868  // go to data info struc
869  gpt_hash_struc hash_ent = gpt_hash_tbl[ihash][iint];
870  data_info_struc *lcl_info = hash_ent.dat_info;
871  if( lcl_info->n_intervals == 0 )
872  {
873  // as no intervals point to this data, remove it
874  free( lcl_info->dat );
875  free( lcl_info->ix_arr );
876  free( lcl_info );
877  n_tot_dat_blobs--; // one less managed data element
878  gpt_hash_tbl[ihash].erase( gpt_hash_tbl[ihash].begin() + iint );
879  }
880  }
881  }
882  // This is much like purge, but should work a bit slower
883  prev_int = NULL; // resetprevious interval in case we removed it
884  return 0;
885  }
886 
887 /********************************************************************
888  dump_mgr - report all info on all managed intervals
889 
890  double pt I depth of reporting: 0 do all, 1 - leave out interval info
891 ********************************************************************/
892 void dim_mgr::dump_mgr( double *pt ) {
893  // print # bins in hash table
894  int32_t idepth = (int32_t)pt[0];
895  printf( "\nCurrent manager state:\n" );
896  printf( " # of hash tbl bins: %d, # data blobs managed: %d\n",
897  hash_tbl_siz, n_tot_dat_blobs );
898 
899  // loop all hash bins
900  for( int ibin = 0; ibin < hash_tbl_siz; ibin++ ) {
901  // print bin # an entries inbin
902  int32_t n_entry = hash_tbl[ibin].size();
903  printf( " bin # %d, # entries: %d\n", ibin, n_entry );
904  // loop bin entries
905  for( int ient = 0; ient < n_entry; ient++ ) {
906  // print entry # and interval index associated with this entry
907  printf( " Entry %d, interval index for this entry:\n ",
908  ient );
909  for( int ix = 0; ix < ndim; ix++ )
910  printf( " %d,", hash_tbl[ibin][ient].ix_arr[ix] );
911  printf( "\n" );
912  if( idepth < 1 ) {
913  printf( "-------------------------\n" );
914  printf( "Interval Information:\n" );
915  // call the interval dumper
916  dump_interval( hash_tbl[ibin][ient].int_str );
917  printf( "-------------------------\n" );
918  }
919  }
920  }
921  // Add a report for the grid point hash bins
922  printf( "\n\nGrid point hash table summary:\n" );
923  for( int ibin = 0; ibin < hash_tbl_siz; ibin++ )
924  {
925  // print bin # an entries inbin
926  int32_t n_entry = gpt_hash_tbl[ibin].size();
927  printf( "-------------------------\n" );
928  printf( " bin # %d, # entries: %d\n", ibin, n_entry );
929  // loop bin entries
930  for( int ient = 0; ient < n_entry; ient++ ) {
931  // print entry #
932  printf( " Entry #: %d, Point coords follow\n", ient );
933  for( int ix = 0; ix < ndim; ix++ )
934  printf( " %d,", gpt_hash_tbl[ibin][ient].ix_arr[ix] );
935  printf( "\n" );
936  printf( "data info Point coords\n" );
937  for( int ix = 0; ix < ndim; ix++ )
938  printf( " %d,", gpt_hash_tbl[ibin][ient].dat_info->ix_arr[ix] );
939  printf( "\n" );
940  printf( "data info # intervals pointed to: %d\n",
941  gpt_hash_tbl[ibin][ient].dat_info->n_intervals );
942  printf( "data info status: %d\n",
943  gpt_hash_tbl[ibin][ient].dat_info->dat_status );
944  printf( "data info address: %ld\n",
945  (long int)gpt_hash_tbl[ibin][ient].dat_info->dat );
946  }
947  }
948  }
949 
950 /********************************************************************
951  dump_last_interval - report information about last interval
952  = a grid box's info
953 
954  interval_struc * interval I Interval structure for the
955 
956 ********************************************************************/
957 void dim_mgr::dump_last_interval() { dump_interval( prev_int ); }
958 
959 /********************************************************************
960  dump_interval - report information about an interval = a grid box's info
961 
962  interval_struc * interval I Interval structure for the
963 
964 ********************************************************************/
965 void dim_mgr::dump_interval( interval_struc *interval ) {
966  if( interval != NULL ) {
967  int32_t npt = pow( 2, ndim );
968  printf( "Interval address: %ld access ID: %d\n",(long int)interval,
969  interval->access_id );
970  printf( " Grid loc (%d dims): ", ndim );
971  for( int i = 0; i < ndim; i++ )
972  printf( " %d", interval->dat_info[0]->ix_arr[i] );
973  printf( "\n" );
974  for( int i = 0; i < npt; i++ )
975  {
976  printf(
977  "# %d data blob, address: %ld, # intervals pointing to it: %d\n", i,
978  (long int)interval->dat_info[i]->dat,
979  interval->dat_info[i]->n_intervals );
980  printf( " status: %d, grid point indexes: \n ",
981  interval->dat_info[i]->dat_status );
982  for( int j = 0; j < ndim; j++ )
983  printf( "%d, ", interval->dat_info[i]->ix_arr[j] );
984  printf( "\n" );
985  }
986  } else {
987  printf( "Sorry, last interval is NULL (no intervals added yet, " );
988  printf( "or purge or prune done)\n" );
989  }
990  }
991 
992  // information reporting
993  int dim_mgr::get_ndim() { return ndim; }
994  int dim_mgr::get_hdim() { return hash_tbl_siz; }
995 
996 // The linear_to_offset does not need to be in the class, in fact, it
997 // himders use from outside. So make it a non-member function here
998 
999 /********************************************************************
1000  linear_to_offset will convert a linear location in the data pointer
1001  array to a offset array
1002 
1003  Returns: int32_t - 0 if all good
1004 
1005  int32_t n_dim I # dimensions to use
1006  int32_t dat_ix I linear offset value
1007  int32_t * offset O offset array
1008 
1009 ********************************************************************/
1010 int32_t linear_to_offset( int32_t n_dim, int32_t dat_ix, int32_t *offset )
1011  {
1012  int32_t idim;
1013 
1014  for( idim = 0; idim < n_dim; idim++ )
1015  {
1016  /* the offset for that dim is the modulo 2 of the linear,
1017  then next time divide te linear offset by 2 to do the next dim offset */
1018  offset[idim] = dat_ix % 2;
1019  dat_ix /= 2;
1020  }
1021  return 0;
1022  }
int32_t init_dim(int32_t, int32_t, double *)
Definition: dim_mgr.cpp:172
an array had not been initialized Several spelling and grammar corrections were which is read from the appropriate MCF the above metadata values were hard coded A problem calculating the average background DN for SWIR bands when the moon is in the space view port was corrected The new algorithm used to calculate the average background DN for all reflective bands when the moon is in the space view port is now the same as the algorithm employed by the thermal bands For non SWIR changes in the averages are typically less than Also for non SWIR the black body DNs remain a backup in case the SV DNs are not available For SWIR the changes in computed averages were larger because the old which used the black body suffered from contamination by the micron leak As a consequence of the if SV DNs are not available for the SWIR the EV pixels will not be the granule time is used to identify the appropriate tables within the set given for one LUT the first two or last two tables respectively will be used for the interpolation If there is only one LUT in the set of it will be treated as a constant LUT The manner in which Earth View data is checked for saturation was changed Previously the raw Earth View DNs and Space View DNs were checked against the lookup table values contained in the table dn_sat The change made is to check the raw Earth and Space View DNs to be sure they are less than the maximum saturation value and to check the Space View subtracted Earth View dns against a set of values contained in the new lookup table dn_sat_ev The metadata configuration and ASSOCIATEDINSTRUMENTSHORTNAME from the MOD02HKM product The same metatdata with extensions and were removed from the MOD021KM and MOD02OBC products ASSOCIATEDSENSORSHORTNAME was set to MODIS in all products These changes are reflected in new File Specification which users may consult for exact the pow functions were eliminated in Emissive_Cal and Emissive bands replaced by more efficient code Other calculations throughout the code were also made more efficient Aside from a few round off there was no difference to the product The CPU time decreased by about for a day case and for a night case A minor bug in calculating the uncertainty index for emissive bands was corrected The frame index(0-based) was previously being used the frame number(1-based) should have been used. There were only a few minor changes to the uncertainty index(maximum of 1 digit). 3. Some inefficient arrays(Sigma_RVS_norm_sq) were eliminated and some code lines in Preprocess_L1A_Data were moved into Process_OBCEng_Emiss. There were no changes to the product. Required RAM was reduced by 20 MB. Now
void ** dat_ptrs
Definition: dim_mgr.hpp:70
int j
Definition: decode_rs.h:73
int status
Definition: l1_czcs_hdf.c:32
~dim_mgr()
Definition: dim_mgr.cpp:83
int32_t n_intervals
Definition: dim_mgr.hpp:24
These are used to scale the SD before writing it to the HDF4 file The default is and which means the product is not scaled at all Since the product is usually stored as a float inside of this is a way to write the float out as a integer l2prod min
double min
Definition: dim_mgr.hpp:14
double * wt
Definition: dim_mgr.hpp:68
#define NULL
Definition: decode_rs.h:63
valarray< int > ix_arr
Definition: dim_mgr.hpp:45
data_info_struc ** dat_info
Definition: dim_mgr.hpp:39
int32_t access_id
Definition: dim_mgr.hpp:33
int32_t prune(int32_t)
Definition: dim_mgr.cpp:816
valarray< int > ix_arr
Definition: dim_mgr.hpp:53
double * wt_pt
Definition: dim_mgr.hpp:69
int32_t * pt_status
Definition: dim_mgr.hpp:63
data_info_struc * dat_info
Definition: dim_mgr.hpp:54
void dump_last_interval()
Definition: dim_mgr.cpp:957
int32_t get_tot_blobs()
Definition: dim_mgr.cpp:123
int32_t nvals
Definition: dim_mgr.hpp:13
double * dim_coords
Definition: dim_mgr.hpp:18
int32_t get_hdim()
Definition: dim_mgr.cpp:994
void add_pts(int32_t)
Definition: dim_mgr.cpp:113
int32_t type
Definition: dim_mgr.hpp:17
int32_t * ix_arr
Definition: dim_mgr.hpp:27
pt_info_struc * mng_pt(double *, int32_t, int32_t *)
Definition: dim_mgr.cpp:241
Definition: dim_mgr.hpp:43
int32_t get_ndim()
Definition: dim_mgr.cpp:993
void update_new_data()
Definition: dim_mgr.cpp:202
int32_t interval_needs_data
Definition: dim_mgr.hpp:62
int32_t dat_status
Definition: dim_mgr.hpp:25
bool match(char *first, char *second)
Definition: l2qc_viirs.cpp:45
double max
Definition: dim_mgr.hpp:15
dim_mgr(int32_t)
Definition: dim_mgr.cpp:26
int32_t dat_filled
Definition: dim_mgr.hpp:37
int32_t linear_to_offset(int32_t n_dim, int32_t dat_ix, int32_t *offset)
Definition: dim_mgr.cpp:1010
void dump_mgr(double *)
Definition: dim_mgr.cpp:892
int32_t nvals
data_t s[NROOTS]
Definition: decode_rs.h:75
l2prod offset
int32_t * pt_base_loc
Definition: dim_mgr.hpp:66
interval_struc * int_str
Definition: dim_mgr.hpp:46
int32_t purge()
Definition: dim_mgr.cpp:747
double delta
Definition: dim_mgr.hpp:16
int i
Definition: decode_rs.h:71
l2prod max