1aae18fe415128a232186ba0034495e16a26306d
[u/mrichter/AliRoot.git] / RALICE / AliObjMatrix.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 // $Id$
17
18 ///////////////////////////////////////////////////////////////////////////
19 // Class AliObjMatrix
20 // Handling of a matrix structure of objects.
21 // All objects which are derived from TObject may be entered into the matrix 
22 // structure. This means that also TObjArray objects can be entered,
23 // which implies an increase of the dimension of the resulting structure.
24 //
25 // Example :
26 // =========
27 //
28 // AliObjMatrix* matrix=new AliObjMatrix();
29 // matrix->SetOwner();
30 // matrix->SetSwapMode();
31 //
32 // Float_t pos[3];
33 //
34 // AliSignal* s=0;
35 //
36 // s=new AliSignal();
37 // s->SetSignal(135);
38 // pos[0]=-120.4
39 // pos[1]=78.25
40 // pos[3]=12.93
41 // s->SetPosition(pos,"car");
42 // matrix->EnterObject(6,21,s);
43 //
44 // s=new AliSignal();
45 // s->SetSignal(25.84);
46 // pos[0]=68.7
47 // pos[1]=-53.88
48 // pos[3]=22.69
49 // s->SetPosition(pos,"car");
50 // matrix->EnterObject(8,13,s);
51 //
52 // s=new AliSignal();
53 // s->SetSignal(87.25);
54 // pos[0]=154.8
55 // pos[1]=932.576
56 // pos[3]=-1382.754
57 // s->SetPosition(pos,"car");
58 // matrix->EnterObject(64,3,s);
59 //
60 // Int_t nrows=matrix->GetMaxRow();
61 // Int_t ncols=matrix->GetMaxColumn();
62 //
63 //  cout << " Maxrow : " << nrows << " Maxcol : " << ncols
64 //       << " Nobjects : " << matrix->GetNobjects() << endl;
65 //
66 //  for (Int_t i=1; i<=nrows; i++)
67 //  {
68 //   for (Int_t j=1; j<=ncols; j++)
69 //   {
70 //    s=(AliSignal*)matrix->GetObject(i,j);
71 //    if (s) cout << " At (" << i << "," << j << ") Signal : " << s->GetSignal() << endl;
72 //   }
73 //  }
74 //
75 //--- Author: Nick van Eijndhoven 23-jan-2003 Utrecht University
76 //- Modified: NvE $Date$ Utrecht University
77 ///////////////////////////////////////////////////////////////////////////
78
79 #include "AliObjMatrix.h"
80 #include "Riostream.h"
81  
82 ClassImp(AliObjMatrix) // Class implementation to enable ROOT I/O
83  
84 AliObjMatrix::AliObjMatrix() : TNamed()
85 {
86 // Default constructor.
87 // Note : The owner and swap mode flags will be initialised to 0.
88 //        See the memberfunctions SetOwner() and SetSwapMode() for further
89 //        details. 
90  fRows=0;
91  fOwn=0;
92  fSwap=0;
93  fMaxrow=0;
94  fMaxcol=0;
95  fObjects=0;
96 }
97 ///////////////////////////////////////////////////////////////////////////
98 AliObjMatrix::~AliObjMatrix()
99 {
100 // Default destructor.
101  if (fRows)
102  {
103   delete fRows;
104   fRows=0;
105  }
106  if (fObjects)
107  {
108   delete fObjects;
109   fObjects=0;
110  }
111 }
112 ///////////////////////////////////////////////////////////////////////////
113 void AliObjMatrix::Reset()
114 {
115 // Reset the whole matrix structure.
116 // Note : The values of the owner and swap mode flags will not be modified.
117 //        To modify the ownership, use the memberfunction SetOwner(). 
118 //        To modify the swap mode, use the memberfunction SetSwapMode(). 
119  if (fRows)
120  {
121   delete fRows;
122   fRows=0;
123  }
124  if (fObjects)
125  {
126   delete fObjects;
127   fObjects=0;
128  }
129
130  fMaxrow=0;
131  fMaxcol=0;
132 }
133 ///////////////////////////////////////////////////////////////////////////
134 void AliObjMatrix::SetOwner(Int_t own)
135 {
136 // Set the owner flag (0/1) for the stored objects.
137 // When the owner flag is set to 1, all entered objects are owned by the
138 // matrix structure.
139 // At invokation of this memberfunction the default argument is own=1.
140 //
141  fOwn=own;
142
143  if (!fRows) return;
144
145  for (Int_t irow=0; irow<fRows->GetSize(); irow++)
146  {
147   TObjArray* mrow=(TObjArray*)fRows->At(irow);
148   if (mrow)
149   {
150    if (own)
151    {
152     mrow->SetOwner(kTRUE);
153    }
154    else
155    {
156     mrow->SetOwner(kFALSE);
157    }
158   }
159  }
160 }
161 ///////////////////////////////////////////////////////////////////////////
162 Int_t AliObjMatrix::GetOwner() const
163 {
164 // Provide the owner flag for the stored objects.
165  return fOwn;
166 }
167 ///////////////////////////////////////////////////////////////////////////
168 void AliObjMatrix::SetSwapMode(Int_t swap)
169 {
170 // Set the swap mode flag (0/1) for the internal matrix storage.
171 // In case the number of rows differs considerably from the number of columns,
172 // it might be more efficient (w.r.t. memory usage and/or output file size)
173 // to internally store the matrix with the rows and colums swapped.
174 // This swapping is only related with the internal storage and as such
175 // is completely hidden for the user.
176 // At invokation of this memberfunction the default argument is swap=1.
177 //
178 // Note : The swap mode can only be set as long as no objects have
179 //        been stored in the matrix structure (i.e. a new instance
180 //        of AliObjMatrix or after invokation of the Reset() function). 
181 //
182  if (!fRows)
183  {
184   fSwap=swap;
185  }
186  else
187  {
188   cout << " *AliObjMatrix::SetSwapMode* Matrix not empty ==> No action." << endl;
189  }
190 }
191 ///////////////////////////////////////////////////////////////////////////
192 Int_t AliObjMatrix::GetSwapMode() const
193 {
194 // Provide the swap mode flag for this matrix.
195  return fSwap;
196 }
197 ///////////////////////////////////////////////////////////////////////////
198 void AliObjMatrix::EnterObject(Int_t row,Int_t col,TObject* obj)
199 {
200 // Enter an object to the matrix structure at location (row,col).
201 // In case the location already contained an object, the existing object
202 // will first be removed before the new object is stored.
203 // According to the status of the owner flag (see the SetOwner() function)
204 // the existing object will also be deleted.
205 // Note : The first location in the matrix is indicated as (1,1).
206  if (row<1 || col<1)
207  {
208   cout << " *AliObjMatrix::AddObject* Invalid argument(s) (row,col) : ("
209        << row << "," << col << ")" << endl;
210   return;
211  }
212
213  if (row>fMaxrow) fMaxrow=row;
214  if (col>fMaxcol) fMaxcol=col;
215
216  Int_t rowx=row;
217  if (fSwap) rowx=col;
218  Int_t colx=col;
219  if (fSwap) colx=row;
220
221  if (!fRows)
222  {
223   fRows=new TObjArray(rowx);
224   fRows->SetOwner();
225  }
226  else
227  {
228   if (rowx > fRows->GetSize()) fRows->Expand(rowx);
229  }
230
231  TObjArray* mrow=(TObjArray*)fRows->At(rowx-1);
232
233  if (!mrow)
234  {
235   TObjArray* columns=new TObjArray(colx);
236   if (fOwn) columns->SetOwner();
237   fRows->AddAt(columns,rowx-1);
238   mrow=columns;
239  }
240  else
241  {
242   if (colx > mrow->GetSize()) mrow->Expand(colx);
243  }
244
245  TObject* old=(TObject*)mrow->At(colx-1);
246  if (old)
247  {
248   fObjects->Remove(old);
249   fObjects->Compress();
250   if (fOwn) delete old;
251  }
252
253  mrow->AddAt(obj,colx-1);
254
255  if (!fObjects) fObjects=new TObjArray();
256  fObjects->Add(obj);
257 }
258 ///////////////////////////////////////////////////////////////////////////
259 void AliObjMatrix::RemoveObject(Int_t row,Int_t col)
260 {
261 // Remove the object stored at the matrix location (row,col).
262 // In case the object was owned by the matrix, it will be deleted.
263 //
264 // Note : The first location in the matrix is indicated as (1,1).
265
266  TObject* obj=0;
267
268  if (!fRows || row<1 || col<1) return;
269
270
271  Int_t rowx=row;
272  if (fSwap) rowx=col;
273  Int_t colx=col;
274  if (fSwap) colx=row;
275
276  TObjArray* mrow=0;
277  if (rowx <= fRows->GetSize()) mrow=(TObjArray*)fRows->At(rowx-1);
278
279  if (!mrow) return;
280
281  if (colx <= mrow->GetSize()) obj=(TObject*)mrow->At(colx-1);
282
283  if (obj)
284  {
285   fObjects->Remove(obj);
286   fObjects->Compress();
287   mrow->Remove(obj);
288   if (fOwn) delete obj;
289  }
290 }
291 ///////////////////////////////////////////////////////////////////////////
292 void AliObjMatrix::RemoveObjects(TObject* obj,Int_t row,Int_t col)
293 {
294 // Remove object(s) from the matrix according to user specified selections.
295 // In case the object was owned by the matrix, it will be deleted.
296 //
297 // An object is only removed from the matrix if the stored reference matches
298 // the argument "obj".
299 // In case obj=0 no check on the matching of the stored reference is performed
300 // and the stored object is always removed in accordance with the other
301 // selection criteria.
302 //
303 // In case the argument "row" is specified, only the object references from
304 // that matrix row will be deleted.
305 // In case row=0 (default) no checking on the row index is performed.
306 //
307 // In case the argument "col" is specified, only the object references from
308 // that matrix column will be deleted.
309 // In case col=0 (default) no checking on the column index is performed.
310 //
311 // So, invokation of RemoveObjects(obj) will remove all references to the
312 // object "obj" from the total matrix, whereas RemoveObjects(obj,0,col)
313 // will remove all references to the object "obj" only from column "col".
314 //
315 // Notes :
316 // -------
317 // The first location in the matrix is indicated as (1,1).
318 //
319 // Invokation of RemoveObjects(0,row,col) is equivalent to invoking the
320 // memberfunction RemoveObject(row,col).
321 // Invoking the latter directly is slightly faster.
322 //
323 // Invokation of RemoveObjects(0) is equivalent to invoking Reset().
324 // Invoking the latter directly is slightly faster.
325 //
326  TArrayI rows;
327  TArrayI cols;
328  Int_t nrefs=0;
329
330  if (row && col)
331  {
332   if (!obj)
333   {
334    RemoveObject(row,col);
335   }
336   else
337   {
338    TObject* objx=GetObject(row,col);
339    if (objx==obj) RemoveObject(row,col);
340   }
341   return;
342  }
343
344  if (!row && !col)
345  {
346   if (!obj)
347   {
348    Reset();
349    return;
350   }
351   else
352   {
353    nrefs=GetIndices(obj,rows,cols);
354   }
355  }
356
357  if (row && !col) nrefs=GetIndices(obj,row,cols);
358  if (!row && col) nrefs=GetIndices(obj,rows,col);
359
360  // Remove the selected objects based on the obtained row and column indices
361  Int_t irow,icol;
362  for (Int_t i=0; i<nrefs; i++)
363  {
364   irow=row;
365   if (!irow) irow=rows.At(i);
366   icol=col;
367   if (!icol) icol=cols.At(i);
368   RemoveObject(irow,icol);
369  }
370 }
371 ///////////////////////////////////////////////////////////////////////////
372 TObject* AliObjMatrix::GetObject(Int_t row,Int_t col) const
373 {
374 // Provide a pointer to the object stored at the matrix location (row,col).
375 // In case no object was stored at the indicated location or the location
376 // would reside outside the matrix boundaries, a value 0 will be returned.
377 // Note : The first location in the matrix is indicated as (1,1).
378
379  TObject* obj=0;
380
381  if (!fRows || row<1 || col<1) return obj;
382
383
384  Int_t rowx=row;
385  if (fSwap) rowx=col;
386  Int_t colx=col;
387  if (fSwap) colx=row;
388
389  TObjArray* mrow=0;
390  if (rowx <= fRows->GetSize()) mrow=(TObjArray*)fRows->At(rowx-1);
391
392  if (!mrow) return obj;
393
394  if (colx <= mrow->GetSize()) obj=(TObject*)mrow->At(colx-1);
395
396  return obj;
397 }
398 ///////////////////////////////////////////////////////////////////////////
399 TObject* AliObjMatrix::GetObject(Int_t j) const
400 {
401 // Provide a pointer to the j-th stored object.
402 // In case the index j is invalid, a value 0 will be returned.
403 // The first stored object is indicated as j=1.
404 //
405 // Note : Do NOT delete the object.
406 //        To remove an object, the memberfunction RemoveObject() or
407 //        RemoveObjects() should be used.
408
409  TObject* obj=0;
410  Int_t nobj=0;
411  if (fObjects) nobj=fObjects->GetSize();
412
413  if (j>0 && j<=nobj) obj=(TObject*)fObjects->At(j-1);
414
415  return obj;
416 }
417 ///////////////////////////////////////////////////////////////////////////
418 TObjArray* AliObjMatrix::GetObjects()
419 {
420 // Provide references to all the stored objects.
421 // In case no objects are present, a value 0 will be returned.
422 //
423 // Note : Do NOT make any changes to the reference array apart from
424 //        changing the order of the pointers of the various objects.
425 //        For addition or removal of objects, the memberfunctions
426 //        EnterObject(), RemoveObject() or RemoveObjects() should be used.
427
428  return fObjects;
429 }
430 ///////////////////////////////////////////////////////////////////////////
431 Int_t AliObjMatrix::GetMaxRow() const
432 {
433 // Provide the maximum row number index.
434  return fMaxrow;
435 }
436 ///////////////////////////////////////////////////////////////////////////
437 Int_t AliObjMatrix::GetMaxColumn() const
438 {
439 // Provide the maximum column number index.
440  return fMaxcol;
441 }
442 ///////////////////////////////////////////////////////////////////////////
443 Int_t AliObjMatrix::GetNobjects() const
444 {
445 // Provide the number of stored objects.
446  Int_t nobj=0;
447  if (fObjects) nobj=fObjects->GetEntries();
448
449  return nobj;
450 }
451 ///////////////////////////////////////////////////////////////////////////
452 Int_t AliObjMatrix::GetNrefs(TObject* obj) const
453 {
454 // Provide the number of stored references to the specified object.
455 // If obj=0 the total number of stored references for all objects is returned.
456  Int_t nobjs=GetNobjects();
457
458  if (!obj) return nobjs;
459
460  Int_t nrefs=0;
461  for (Int_t i=1; i<=nobjs; i++)
462  {
463   TObject* objx=GetObject(i);
464   if (objx==obj) nrefs++;
465  }
466  return nrefs;
467 }
468 ///////////////////////////////////////////////////////////////////////////
469 Int_t AliObjMatrix::GetIndices(TObject* obj,TArrayI& rows,TArrayI& cols) const
470 {
471 // Provide the (row,col) indices of all the storage locations of the
472 // specified object.
473 // The row and column indices are returned in the two separate TArrayI arrays
474 // from which the (row,col) pairs can be obtained from the corresponding
475 // array indices like (row,col)=(rows.At(j),cols.At(j)).
476 // The integer return argument represents the number of (row,col) pairs which
477 // were encountered for the specified object.
478 //
479 // If obj=0 no object selection is performed and all (row,col) indices
480 // of the stored references for all objects are returned.
481 //
482 // Notes :
483 // -------
484 // As usual the convention is that row and column numbering starts at 1.
485 // 
486 // This memberfunction always resets the two TArrayI arrays at the start.
487 //
488 // This memberfunction can only be used to obtain the (row,col) indices
489 // of the object as stored via the EnterObject() memberfunction.
490 // This means that in case the user has entered a TObjArray as object
491 // (to increase the dimension of the resulting structure), the (row,col)
492 // indices of that TObjArray are obtained and NOT the indices of the
493 // actual objects contained in that TObjArray structure.
494 //
495  Int_t nrefs=GetNrefs(obj);
496  rows.Reset();
497  cols.Reset();
498  rows.Set(nrefs);
499  cols.Set(nrefs);
500  if (!nrefs) return 0;
501
502  Int_t irow,icol;
503  Int_t jref=0;
504  for (Int_t i=0; i<fRows->GetSize(); i++)
505  {
506   TObjArray* columns=(TObjArray*)fRows->At(i);
507   if (!columns) continue;
508
509   for (Int_t j=0; j<columns->GetSize(); j++)
510   {
511    TObject* objx=(TObject*)columns->At(j);
512    if (objx && (objx==obj || !obj))
513    {
514     irow=i+1;
515     if (fSwap) irow=j+1;
516     icol=j+1;
517     if (fSwap) icol=i+1;
518     rows.AddAt(irow,jref);
519     cols.AddAt(icol,jref);
520     jref++;
521    }
522    // All references found ==> Done
523    if (jref==nrefs) break;
524   }
525   // All references found ==> Done
526   if (jref==nrefs) break;
527  }
528  return nrefs;
529 }
530 ///////////////////////////////////////////////////////////////////////////
531 Int_t AliObjMatrix::GetIndices(TObject* obj,Int_t row,TArrayI& cols) const
532 {
533 // Provide the column indices of all the storage locations of the
534 // specified object in the specified row of the matrix.
535 // The column indices are returned in the TArrayI array.
536 // The integer return argument represents the number of storage locations which
537 // were encountered for the specified object in the specified matrix row.
538 //
539 // If obj=0 no object selection is performed and all column indices
540 // of the stored references for all objects in this specified matrix row
541 // are returned.
542 //
543 // If row=0 all rows will be scanned and all column indices matching the
544 // object selection are returned.
545 // Note that in this case multiple appearances of the same column index
546 // will only be recorded once in the returned TArrayI array.
547 //
548 // Notes :
549 // -------
550 // As usual the convention is that row and column numbering starts at 1.
551 // 
552 // This memberfunction always resets the TArrayI array at the start.
553 //
554 // This memberfunction can only be used to obtain the column indices
555 // of the object as stored via the EnterObject() memberfunction.
556 // This means that in case the user has entered a TObjArray as object
557 // (to increase the dimension of the resulting structure), the column
558 // indices of that TObjArray are obtained and NOT the indices of the
559 // actual objects contained in that TObjArray structure.
560 //
561  cols.Reset();
562
563  if (row<0 || row>GetMaxRow()) return 0;
564
565  Int_t nrefs=GetNrefs(obj);
566  cols.Set(nrefs);
567  if (!nrefs) return 0;
568
569  Int_t irow,icol;
570  Int_t jref=0;
571
572  // No specific row selection
573  if (!row)
574  {
575   TArrayI ar;
576   TArrayI ac;
577   Int_t n=GetIndices(obj,ar,ac);
578   Int_t found=0;
579   for (Int_t idx=0; idx<n; idx++)
580   {
581    icol=ac.At(idx);
582    found=0;
583    for (Int_t k=0; k<jref; k++)
584    {
585     if (icol==cols.At(k)) found=1;
586    }
587    if (!found)
588    {
589     cols.AddAt(icol,jref);
590     jref++;
591    }
592   }
593   // Set the array size to the actual number of different column indices
594   cols.Set(jref);
595
596   return jref;
597  }
598
599  // Specific row selection
600  for (Int_t i=0; i<fRows->GetSize(); i++)
601  {
602   TObjArray* columns=(TObjArray*)fRows->At(i);
603   if (!columns) continue;
604
605   for (Int_t j=0; j<columns->GetSize(); j++)
606   {
607    TObject* objx=(TObject*)columns->At(j);
608    if (objx && (objx==obj || !obj))
609    {
610     irow=i+1;
611     if (fSwap) irow=j+1;
612     icol=j+1;
613     if (fSwap) icol=i+1;
614     if (irow==row)
615     {
616      cols.AddAt(icol,jref);
617      jref++;
618     }
619    }
620    // All references found ==> Done
621    if (jref==nrefs) break;
622   }
623   // All references found ==> Done
624   if (jref==nrefs) break;
625  }
626  // Set the array size to the actual number of found occurrences
627  cols.Set(jref);
628
629  return jref;
630 }
631 ///////////////////////////////////////////////////////////////////////////
632 Int_t AliObjMatrix::GetIndices(TObject* obj,TArrayI& rows,Int_t col) const
633 {
634 // Provide the row indices of all the storage locations of the
635 // specified object in the specified column of the matrix.
636 // The row indices are returned in the TArrayI array.
637 // The integer return argument represents the number of storage locations which
638 // were encountered for the specified object in the specified matrix column.
639 //
640 // If obj=0 no object selection is performed and all row indices
641 // of the stored references for all objects in this specified matrix column
642 // are returned.
643 //
644 // If col=0 all columns will be scanned and all row indices matching the
645 // object selection are returned.
646 // Note that in this case multiple appearances of the same row index
647 // will only be recorded once in the returned TArrayI array.
648 //
649 // Notes :
650 // -------
651 // As usual the convention is that row and column numbering starts at 1.
652 // 
653 // This memberfunction always resets the TArrayI array at the start.
654 //
655 // This memberfunction can only be used to obtain the row indices
656 // of the object as stored via the EnterObject() memberfunction.
657 // This means that in case the user has entered a TObjArray as object
658 // (to increase the dimension of the resulting structure), the row
659 // indices of that TObjArray are obtained and NOT the indices of the
660 // actual objects contained in that TObjArray structure.
661 //
662  rows.Reset();
663
664  if (col<0 || col>GetMaxColumn()) return 0;
665
666  Int_t nrefs=GetNrefs(obj);
667  rows.Set(nrefs);
668  if (!nrefs) return 0;
669
670  Int_t irow,icol;
671  Int_t jref=0;
672
673  // No specific column selection
674  if (!col)
675  {
676   TArrayI ar;
677   TArrayI ac;
678   Int_t n=GetIndices(obj,ar,ac);
679   Int_t found=0;
680   for (Int_t idx=0; idx<n; idx++)
681   {
682    irow=ar.At(idx);
683    found=0;
684    for (Int_t k=0; k<jref; k++)
685    {
686     if (irow==rows.At(k)) found=1;
687    }
688    if (!found)
689    {
690     rows.AddAt(irow,jref);
691     jref++;
692    }
693   }
694   // Set the array size to the actual number of different row indices
695   rows.Set(jref);
696
697   return jref;
698  }
699
700  // Specific column selection
701  for (Int_t i=0; i<fRows->GetSize(); i++)
702  {
703   TObjArray* columns=(TObjArray*)fRows->At(i);
704   if (!columns) continue;
705
706   for (Int_t j=0; j<columns->GetSize(); j++)
707   {
708    TObject* objx=(TObject*)columns->At(j);
709    if (objx && (objx==obj || !obj))
710    {
711     irow=i+1;
712     if (fSwap) irow=j+1;
713     icol=j+1;
714     if (fSwap) icol=i+1;
715     if (icol==col)
716     {
717      rows.AddAt(irow,jref);
718      jref++;
719     }
720    }
721    // All references found ==> Done
722    if (jref==nrefs) break;
723   }
724   // All references found ==> Done
725   if (jref==nrefs) break;
726  }
727  // Set the array size to the actual number of found occurrences
728  rows.Set(jref);
729
730  return jref;
731 }
732 ///////////////////////////////////////////////////////////////////////////