Overture  Version 25
ArraySimple.h
Go to the documentation of this file.
1 #ifndef __OV_ArraySimple_H__
2 #define __OV_ArraySimple_H__
3 
4 #define WAS_NOT_DETEMPLIFIED
5 
6 // include overturetypes to make sure we get bool!
7 #include "OvertureTypes.h"
8 
9 #include "ArraySimpleCommon.h"
10 //#include "VectorSimple.h"
11 #ifndef WAS_DETEMPLIFIED
12 #include "ArraySimpleFixed.h"
13 #endif
14 
15 // // //
18 
19 public:
20  AS_ReferenceCounting( bool startCounting=TRUE ) : r(NULL)
21  {
22 
23 #ifdef TEST_AS_REFCOUNTING
24  cout<<"building referenced object at "<<long(this)<<endl;
25 #endif
26 
27  if (startCounting) increment();
28  }
29 
31  {
32 #ifdef TEST_AS_REFCOUNTING
33  cout<<"copy constructor called for object at "<<long(this)<<endl;
34 #endif
35 
36  *this=ref;
37  }
38 
40  decrement();
41 #ifdef TEST_AS_REFCOUNTING
42  cout<<"destructor called for object at "<<long(this)<<endl;
43  cout<<" ncreated = "<<ncreated<<" ndeleted = "<<ndeleted<<endl;
44 #endif
45  }
46 
47  int numberOfReferences() const { return r ? *r : 0; }
48 
50 
51 #ifdef TEST_AS_REFCOUNTING
52  cout<<"operator= called for object at "<<long(this)<<endl;
53 #endif
54 
55  if ( ref.r!=r )
56  {
57  // we are changing the reference or it is a brand new reference
58  if ( r )
59  if ( !decrement() ) delete r;
60  r = ref.r;
61 
62  // if counting is on on both instances, increment the reference count
63  if ( r ) increment();
64 
65  }
66 
67  return *this;
68  }
69 
71  {
72  int n = numberOfReferences();
73  if (n)
74  {
75  decrement();
76  r=0;
77  increment();
78  }
79  return n;
80  }
81 
82 protected:
83 
84  int decrement() {
85 #ifdef TEST_AS_REFCOUNTING
86  if ( r )
87  cout<<"decrementing object at "<<long(this)<<" to "<<*r-1<<" counts"<<endl;
88  else
89  cout<<"decrement called on non-counted object at "<<long(this)<<endl;
90 #endif
91  if ( r )
92  if ( ! --*r )
93  {
94  delete r;
95  r=0;
96 #ifdef TEST_AS_REFCOUNTING
97  ndeleted++;
98 #endif
99  }
100 
101  return r ? *r : 0;
102  }
103 
104  int increment() {
105 
106  if ( r )
107  ++*r;
108  else
109  {
110  // begin reference counting the object
111  r = new int;
112  *r = 1;
113 
114 #ifdef TEST_AS_REFCOUNTING
115  ncreated++;
116 #endif
117  }
118 
119 #ifdef TEST_AS_REFCOUNTING
120  cout<<"incrementing object at "<<long(this)<<" to "<<*r<<" counts"<<endl;
121 #endif
122 
123  return *r;
124  }
125 
126 
127 #ifdef TEST_AS_REFCOUNTING
128 public:
129  static int ncreated, ndeleted;
130 #endif
131 
132 private:
133  int *r;
134 
135 };
136 
137 // // //
139 
148 template <class T>
150 public:
151 
153 
155  inline ArraySimple() : AS_ReferenceCounting(FALSE), data(0), nrank(0)
156  {
157  for ( int r=0; r<MAXRANK; r++ ) n[r] = 0;
158  }
159 
161  inline ArraySimple( const ArraySimple<T> &a ) : AS_ReferenceCounting(FALSE), data(0), nrank(0)
162  {
163 
164 #if 0
165  // shallow copy
166  *this = a;
167 
168 #else
169  // deep copy
170  nrank = a.nrank;
171  for ( int r=0; r<MAXRANK; r++ ) n[r] = a.n[r];
172  allocate();
173 
174  for ( int i=0; i<size(); i++ ) data[i] = a.data[i];
175 #endif
176 
177  }
178 
179 #ifndef WAS_DETEMPLIFIED
180 #ifndef OV_NO_DEFAULT_TEMPL_ARGS
181 
182  template<int d1, int d2, int d3, int d4,int d5>
184  {
185 
186  n[0] = d1;
187  n[1] = d2;
188  n[2] = d3;
189  n[3] = d4;
190  n[4] = d5;
191 
192  if ( n[1]==1 && n[2]==1 && n[3]==1 && n[4]==1 ) nrank = 1;
193  else if ( n[2]==1 && n[3]==1 && n[4]==1 ) nrank = 2;
194  else if ( n[3]==1 && n[4]==1 ) nrank = 3;
195  else if ( n[4]==1 ) nrank = 4;
196  else nrank = 5;
197 
198  allocate();
199  for ( int s=0; s<size(); s++ )
200  data[s] = a[s];
201 
202  }
203 #endif
204 #endif
205  //
206  // Basic constructors for the various rank arrays
207  // The arguments are the sizes of each dimension
208  //
209  EXPLICIT ArraySimple(int n1) : AS_ReferenceCounting(FALSE), data(0), nrank(0)
210  {
211  nrank = 1;
212  n[0] = n1;
213  for ( int r=1; r<MAXRANK; r++ ) n[r] = 1;
214  allocate();
215  }
216 
217  EXPLICIT ArraySimple(int n1, int n2) : AS_ReferenceCounting(FALSE), data(0), nrank(0)
218  {
219  nrank = 2;
220  n[0] = n1;
221  n[1] = n2;
222  for ( int r=2; r<MAXRANK; r++ ) n[r] = 1;
223  allocate();
224  }
225 
226  EXPLICIT ArraySimple(int n1, int n2, int n3) : AS_ReferenceCounting(FALSE), data(0), nrank(0)
227  {
228  nrank = 3;
229  n[0] = n1;
230  n[1] = n2;
231  n[2] = n3;
232  for ( int r=3; r<MAXRANK; r++ ) n[r] = 1;
233  allocate();
234  }
235 
236  EXPLICIT ArraySimple(int n1, int n2, int n3, int n4) : AS_ReferenceCounting(FALSE), data(0), nrank(0)
237  {
238  nrank = 4;
239  n[0] = n1;
240  n[1] = n2;
241  n[2] = n3;
242  n[3] = n4;
243  for ( int r=4; r<MAXRANK; r++ ) n[r] = 1;
244  allocate();
245  }
246 
247  EXPLICIT ArraySimple(int n1, int n2, int n3, int n4, int n5) : AS_ReferenceCounting(FALSE), data(0), nrank(0)
248  {
249  nrank = 5;
250  n[0] = n1;
251  n[1] = n2;
252  n[2] = n3;
253  n[3] = n4;
254  n[4] = n5;
255  for ( int r=5; r<MAXRANK; r++ ) n[r] = 1;
256  allocate();
257  }
258 
259  // destructor
260  inline ~ArraySimple() { if (numberOfReferences()<2) destroy(); }
261 
262  // size
263  inline int size() const
264  {
265  // /Description : return the total size of the array
266  int s = 1;
267  for ( int r=0; r<nrank; r++ )
268  s *= n[r];
269 
270  return nrank==0 ? 0 : s;
271  }
272 
273  // size (int)
274  inline int size( const int &r_ ) const
275  {
276  // /Description : return the size of one dimension
277  assert(RANGE_CHK(r_>=0 && r_<nrank));
278 
279  return n[r_];
280  }
281 
282  // rank
283  inline int rank() const
284  {
285  // /Description : return the rank of the array
286  return nrank;
287  }
288 
289  // deep copy
290  inline void copy(const ArraySimple<T> &a)
291  {
292  // /Description : create a deep copy of array a
293 
294  int s = size();
295  int as = a.size();
296 
297  if ( breakReference()<2 && s!=as )
298  destroy();
299 
300  nrank = a.nrank;
301  for (int r=0; r<MAXRANK; r++ ) n[r] = a.n[r];
302 
303  if ( s!=as )
304  {
305  data = 0;
306  allocate();
307  }
308 
309  for ( int i=0; i<s; i++ ) data[i] = a.data[i];
310 
311  }
312 
313  // shallow copy
314  inline void reference(ArraySimple<T> &a)
315  {
316 #ifdef TEST_AS_REFCOUNTING
317  cout<<"instance at "<<long(this)<<" is referencing instance at "<<long(&a)<<endl;
318 #endif
319 
320  // /Description : create a reference to the data in a (shallow copy)
321  if ( a.numberOfReferences()==0 ) a.increment(); // start the counting if needed
322 
323  (AS_ReferenceCounting &)(*this) = a;
324  nrank = a.nrank;
325  for ( int r=0; r<MAXRANK; r++ ) n[r] = a.n[r];
326  data = a.data;
327 
328  }
329 
330  // ptr
331  inline T * ptr()
332  {
333  // /Description : returns the data pointer
334  return data;
335  }
336 
338  {
339 
340 #if 0
341  // /Description : perform a shallow copy
342 
343  (AS_ReferenceCounting &)(*this) = a;
344  nrank = a.nrank;
345  for ( int r=0; r<MAXRANK; r++ ) n[r] = a.n[r];
346  data = a.data;
347 
348  return *this;
349 
350 #else
351  // /Description : perform a deep copy
352  if ( numberOfReferences()>1 )
353  {
354  breakReference();
355  decrement(); // turn off the reference counting
356  data = 0;
357  }
358 
359  int s=size();
360  int sa=a.size();
361 
362  if ( s != sa )
363  destroy();
364 
365  nrank = a.nrank;
366  for ( int r=0; r<MAXRANK; r++ ) n[r] = a.n[r];
367 
368  if ( s!=sa )
369  allocate();
370 
371  for ( int i=0; i<size(); i++ ) data[i] = a.data[i];
372  return *this;
373 #endif
374 
375  }
376 
377  inline ArraySimple<T> & operator= ( const T &a )
378  {
379  // /Description : set all array values equal to a const value
380  for ( int i=0; i<size(); i++ ) data[i] = a;
381  return *this;
382  }
383 
384  // operator[]
385  inline T & operator[] (const int &i)
386  {
387  // /Description : indexes the data using 1d indexing (no range checks along each axis)
388  assert(RANGE_CHK( i>=0 && i<size() ) );
389  return data[i];
390  }
391 
392  // operator[]
393  inline const T & operator[] (const int &i) const
394  {
395  // /Description : indexes the data using 1d indexing (no range checks along each axis)
396  assert(RANGE_CHK( i>=0 && i<size() ) );
397  return data[i];
398  }
399 
400  //
401  // index operators
402  // for each rank, an index operator is specified. Range checking is performed if
403  // OV_DEBUG is defined (using RANGE_CHK)
404  //
405  inline T & operator() (const int &i0)
406  {
407  assert(RANGE_CHK( nrank==1 && i0>-1 && i0<n[0] ));
408  return data[ i0 ];
409  }
410 
411  inline const T & operator() (const int &i0) const
412  {
413  assert(RANGE_CHK( nrank==1 && i0>-1 && i0<n[0] ));
414  return data[ i0 ];
415  }
416 
417  inline T & operator() (const int &i0, const int &i1)
418  {
419  assert(RANGE_CHK( nrank==2 &&
420  i0>-1 && i0<n[0] &&
421  i1>-1 && i1<n[1] ));
422  return data[ i0 + i1*n[0] ];
423  }
424 
425  inline const T & operator() (const int &i0, const int &i1) const
426  {
427  assert(RANGE_CHK( nrank==2 &&
428  i0>-1 && i0<n[0] &&
429  i1>-1 && i1<n[1] ));
430  return data[ i0 + i1*n[0] ];
431  }
432 
433  inline T & operator() (int i0, int i1, int i2)
434  {
435  assert(RANGE_CHK( nrank==3 &&
436  i0>-1 && i0<n[0] &&
437  i1>-1 && i1<n[1] &&
438  i2>-1 && i2<n[2] ));
439  return data[ i0 + n[0]*(i1 + i2*n[1]) ];
440 
441  }
442 
443  inline const T & operator() (int i0, int i1, int i2) const
444  {
445  assert(RANGE_CHK( nrank==3 &&
446  i0>-1 && i0<n[0] &&
447  i1>-1 && i1<n[1] &&
448  i2>-1 && i2<n[2] ));
449  return data[ i0 + n[0]*(i1 + i2*n[1]) ];
450 
451  }
452 
453  inline T & operator() (int i0, int i1, int i2, int i3)
454  {
455  assert(RANGE_CHK( nrank==4 &&
456  i0>-1 && i0<n[0] &&
457  i1>-1 && i1<n[1] &&
458  i2>-1 && i2<n[2] &&
459  i3>-1 && i3<n[3] ));
460  return data[ i0 + n[0]*(i1 + n[1]*(i2 + i3*n[2])) ];
461 
462  }
463 
464  inline const T & operator() (int i0, int i1, int i2, int i3) const
465  {
466  assert(RANGE_CHK( nrank==4 &&
467  i0>-1 && i0<n[0] &&
468  i1>-1 && i1<n[1] &&
469  i2>-1 && i2<n[2] &&
470  i3>-1 && i3<n[3] ));
471  return data[ i0 + n[0]*(i1 + n[1]*(i2 + i3*n[2])) ];
472 
473  }
474 
475  inline T & operator() (int i0, int i1, int i2, int i3, int i4)
476  {
477  assert(RANGE_CHK( nrank==4 &&
478  i0>-1 && i0<n[0] &&
479  i1>-1 && i1<n[1] &&
480  i2>-1 && i2<n[2] &&
481  i3>-1 && i3<n[3] &&
482  i4>-1 && i4<n[4] ));
483  return data[ i0 + n[0]*(i1 + n[1]*(i2 + n[2]*(i3 + n[3]*i4))) ];
484 // return data[ i0 + n[0]*(i1 + n[1]*(i2 + i3*n[2])) ];
485 
486  }
487 
488  inline const T & operator() (int i0, int i1, int i2, int i3, int i4) const
489  {
490  assert(RANGE_CHK( nrank==4 &&
491  i0>-1 && i0<n[0] &&
492  i1>-1 && i1<n[1] &&
493  i2>-1 && i2<n[2] &&
494  i3>-1 && i3<n[3] &&
495  i4>-1 && i4<n[4] ));
496  return data[ i0 + n[0]*(i1 + n[1]*(i2 + n[2]*(i3 + n[3]*i4))) ];
497 
498  }
499 
501  void resize(int n1, int n2=-1, int n3=-1, int n4=-1, int n5=-1)
502  {
503  int oldRefs = numberOfReferences();
504  if ( oldRefs )
505  {
506  breakReference();
507  decrement(); // turn off ref counting
508  }
509 
510  T *tmp_data = data;
511  int tmp_size = size();
512 
513  int i=0;
514  n[0] = n1;
515  n[1] = n2;
516  n[2] = n3;
517  n[3] = n4;
518  n[4] = n5;
519  while ( n[i]>0 && i<MAXRANK ) i++;
520  nrank = i;
521 
522  for ( i=nrank; i<MAXRANK; i++ ) n[i] = 1;
523 
524  data = 0;
525  allocate();
526 
527  for ( int i=0; i<min(tmp_size,size()); i++ )
528  data[i] = tmp_data[i];
529 
530  if ( oldRefs<2 && tmp_data )
531  {
532  delete [] tmp_data;
533 #ifdef TEST_AS_REFCOUNTING
534  cout<<"DELETING ARRAY DATA DURING RESIZE FOR INSTANCE "<<long(this)<<endl;
535  ndel++;
536  cout<<" nalloc = "<<nalloc<<" ndel "<<ndel<<endl;
537 #endif
538  }
539  }
540 
541  void redim(int n1, int n2=-1, int n3=-1, int n4=-1, int n5=-1)
542  {
543  int oldRefs = numberOfReferences();
544  if ( oldRefs )
545  {
546  breakReference();
547  decrement(); // turn off ref counting
548  }
549 
550  destroy();
551 
552  n[0] = n1;
553  n[1] = n2;
554  n[2] = n3;
555  n[3] = n4;
556  n[4] = n5;
557 
558  int i=0;
559  while ( n[i]>0 && i<MAXRANK ) i++;
560  nrank = i;
561 
562  for ( i=nrank; i<MAXRANK; i++ ) n[i] = 1;
563 
564  data = 0;
565  allocate();
566 
567  }
568 
569 #ifdef TEST_AS_REFCOUNTING
570  static int nalloc, ndel;
571 #endif
572 
573 protected:
574 
575  inline void allocate()
576  {
577  int s = size();
578 
579  assert(data==0);
580  assert(RANGE_CHK(s>=0));
581 
582 #ifdef TEST_AS_REFCOUNTING
583  if ( s )
584  {
585  cout<<"ALLOCATING ARRAY DATA FOR INSTANCE "<<long(this)<<endl;
586  nalloc++;
587  cout<<" nalloc = "<<nalloc<<" ndel "<<ndel<<endl;
588  }
589 #endif
590 
591  if ( s>0 )
592  {
593  data = new T[s];
594  assert(data != 0);
595  }
596  else
597  data = 0;
598  }
599 
600  inline void destroy()
601  {
602 #ifdef TEST_AS_REFCOUNTING
603  if ( data )
604  {
605  cout<<"DESTROYING ARRAY DATA FOR INSTANCE "<<long(this)<<endl;
606  ndel++;
607  cout<<" nalloc = "<<nalloc<<" ndel "<<ndel<<endl;
608  }
609 #endif
610 
611  if ( data!=0 ) delete [] data;
612  for ( int r=0; r<MAXRANK; r++ ) n[r] = 0;
613  data = 0;
614  nrank = 0;
615  }
616 
617 private:
618  T *data;
619  int n[MAXRANK];
620  short nrank;
621 
622 };
623 //
624 // end of ArraySimple
625 // // //
626 
627 #ifndef WAS_DETEMPLIFIED
631 #endif
632 
633 template<class T>
634 ostream & operator<< (ostream &os, ArraySimple<T> &sa)
635 {
636  // /Description : overloading for ostream to make printing ArraySimples easier
637 
638  int rank = sa.rank();
639 
640  os<<"********** ArraySimple( ";
641 
642  for ( int r=0; r<rank-1; r++ )
643  os<<sa.size(r)<<", ";
644  if ( rank!=0 )
645  os<<sa.size(rank-1);
646  else
647  os<<"UNINITIALIZED";
648 
649  os<<" ) **********\n";
650 
651  if ( rank != 0 )
652  {
653  switch (rank)
654  {
655  case 1:
656  {
657  for ( int i=0; i<sa.size(); i++ )
658  os<<"a( "<<i<<" ) = "<<sa(i)<<endl;
659  break;
660  }
661  case 2:
662  {
663  for ( int i1=0; i1<sa.size(0); i1++ )
664  for ( int i2=0; i2<sa.size(1); i2++ )
665  os<<"a( "<<i1<<", "<<i2<<" ) = "<<sa(i1,i2)<<endl;
666  break;
667  }
668  case 3:
669  {
670  for ( int i1=0; i1<sa.size(0); i1++ )
671  for ( int i2=0; i2<sa.size(1); i2++ )
672  for ( int i3=0; i3<sa.size(2); i3++ )
673  os<<"a( "<<i1<<", "<<i2<<", "<<i3<<" ) = "<<sa(i1,i2,i3)<<endl;
674  break;
675  }
676  case 4:
677  {
678  for ( int i1=0; i1<sa.size(0); i1++ )
679  for ( int i2=0; i2<sa.size(1); i2++ )
680  for ( int i3=0; i3<sa.size(2); i3++ )
681  for ( int i4=0; i4<sa.size(3); i4++ )
682  os<<"a( "<<i1<<", "<<i2<<", "<<i3<<", "<<i4<<" ) = "<<sa(i1,i2,i3,i4)<<endl;
683  break;
684  }
685  case 5:
686  {
687  for ( int i1=0; i1<sa.size(0); i1++ )
688  for ( int i2=0; i2<sa.size(1); i2++ )
689  for ( int i3=0; i3<sa.size(2); i3++ )
690  for ( int i4=0; i4<sa.size(3); i4++ )
691  for ( int i5=0; i5<sa.size(4); i5++ )
692  os<<"a( "<<i1<<", "<<i2<<", "<<i3<<", "<<i4<<", "<<i5<<" ) = "<<sa(i1,i2,i3,i4,i5)<<endl;
693  break;
694  }
695  default:
696  {
697  os<<"RANK "<<rank<<" ARRAYS ARE NOT SUPPORTED"<<endl;
698  }
699  }
700  }
701 
702  return os;
703 }
704 
705 #endif