defects fixed
[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 AliObjMatrix::AliObjMatrix(const AliObjMatrix& m) : TNamed(m)
114 {
115 // Copy constructor
116
117  fRows=0;
118  fMaxrow=0;
119  fMaxcol=0;
120  fObjects=0;
121
122  fOwn=m.fOwn;
123  fSwap=m.fSwap;
124
125  Int_t maxrow=m.GetMaxRow();
126  Int_t maxcol=m.GetMaxColumn();
127  for (Int_t irow=1; irow<=maxrow; irow++)
128  {
129   for (Int_t icol=1; icol<=maxcol; icol++)
130   {
131    TObject* obj=m.GetObject(irow,icol);
132    if (obj)
133    {
134     if (!fOwn)
135     {
136      EnterObject(irow,icol,obj);
137     }
138     else
139     {
140      EnterObject(irow,icol,obj->Clone());
141     }
142    }
143   }
144  }
145 }
146 ///////////////////////////////////////////////////////////////////////////
147 void AliObjMatrix::Reset()
148 {
149 // Reset the whole matrix structure.
150 // Note : The values of the owner and swap mode flags will not be modified.
151 //        To modify the ownership, use the memberfunction SetOwner(). 
152 //        To modify the swap mode, use the memberfunction SetSwapMode(). 
153  if (fRows)
154  {
155   delete fRows;
156   fRows=0;
157  }
158  if (fObjects)
159  {
160   delete fObjects;
161   fObjects=0;
162  }
163
164  fMaxrow=0;
165  fMaxcol=0;
166 }
167 ///////////////////////////////////////////////////////////////////////////
168 void AliObjMatrix::SetOwner(Int_t own)
169 {
170 // Set the owner flag (0/1) for the stored objects.
171 // When the owner flag is set to 1, all entered objects are owned by the
172 // matrix structure.
173 // At invokation of this memberfunction the default argument is own=1.
174 //
175  fOwn=own;
176
177  if (!fRows) return;
178
179  for (Int_t irow=0; irow<fRows->GetSize(); irow++)
180  {
181   TObjArray* mrow=(TObjArray*)fRows->At(irow);
182   if (mrow)
183   {
184    if (own)
185    {
186     mrow->SetOwner(kTRUE);
187    }
188    else
189    {
190     mrow->SetOwner(kFALSE);
191    }
192   }
193  }
194 }
195 ///////////////////////////////////////////////////////////////////////////
196 Int_t AliObjMatrix::GetOwner() const
197 {
198 // Provide the owner flag for the stored objects.
199  return fOwn;
200 }
201 ///////////////////////////////////////////////////////////////////////////
202 void AliObjMatrix::SetSwapMode(Int_t swap)
203 {
204 // Set the swap mode flag (0/1) for the internal matrix storage.
205 // In case the number of rows differs considerably from the number of columns,
206 // it might be more efficient (w.r.t. memory usage and/or output file size)
207 // to internally store the matrix with the rows and colums swapped.
208 // This swapping is only related with the internal storage and as such
209 // is completely hidden for the user.
210 // At invokation of this memberfunction the default argument is swap=1.
211 //
212 // Note : The swap mode can only be set as long as no objects have
213 //        been stored in the matrix structure (i.e. a new instance
214 //        of AliObjMatrix or after invokation of the Reset() function). 
215 //
216  if (!fRows)
217  {
218   fSwap=swap;
219  }
220  else
221  {
222   cout << " *AliObjMatrix::SetSwapMode* Matrix not empty ==> No action." << endl;
223  }
224 }
225 ///////////////////////////////////////////////////////////////////////////
226 Int_t AliObjMatrix::GetSwapMode() const
227 {
228 // Provide the swap mode flag for this matrix.
229  return fSwap;
230 }
231 ///////////////////////////////////////////////////////////////////////////
232 void AliObjMatrix::EnterObject(Int_t row,Int_t col,TObject* obj)
233 {
234 // Enter an object to the matrix structure at location (row,col).
235 // In case the location already contained an object, the existing object
236 // will first be removed before the new object is stored.
237 // According to the status of the owner flag (see the SetOwner() function)
238 // the existing object will also be deleted.
239 // Note : The first location in the matrix is indicated as (1,1).
240  if (row<1 || col<1)
241  {
242   cout << " *AliObjMatrix::AddObject* Invalid argument(s) (row,col) : ("
243        << row << "," << col << ")" << endl;
244   return;
245  }
246
247  if (row>fMaxrow) fMaxrow=row;
248  if (col>fMaxcol) fMaxcol=col;
249
250  Int_t rowx=row;
251  if (fSwap) rowx=col;
252  Int_t colx=col;
253  if (fSwap) colx=row;
254
255  if (!fRows)
256  {
257   fRows=new TObjArray(rowx);
258   fRows->SetOwner();
259  }
260  else
261  {
262   if (rowx > fRows->GetSize()) fRows->Expand(rowx);
263  }
264
265  TObjArray* mrow=(TObjArray*)fRows->At(rowx-1);
266
267  if (!mrow)
268  {
269   TObjArray* columns=new TObjArray(colx);
270   if (fOwn) columns->SetOwner();
271   fRows->AddAt(columns,rowx-1);
272   mrow=columns;
273  }
274  else
275  {
276   if (colx > mrow->GetSize()) mrow->Expand(colx);
277  }
278
279  TObject* old=(TObject*)mrow->At(colx-1);
280  if (old)
281  {
282   fObjects->Remove(old);
283   fObjects->Compress();
284   if (fOwn) delete old;
285  }
286
287  mrow->AddAt(obj,colx-1);
288
289  if (!fObjects) fObjects=new TObjArray();
290  fObjects->Add(obj);
291 }
292 ///////////////////////////////////////////////////////////////////////////
293 void AliObjMatrix::RemoveObject(Int_t row,Int_t col)
294 {
295 // Remove the object stored at the matrix location (row,col).
296 // In case the object was owned by the matrix, it will be deleted.
297 //
298 // Note : The first location in the matrix is indicated as (1,1).
299
300  TObject* obj=0;
301
302  if (!fRows || row<1 || col<1) return;
303
304
305  Int_t rowx=row;
306  if (fSwap) rowx=col;
307  Int_t colx=col;
308  if (fSwap) colx=row;
309
310  TObjArray* mrow=0;
311  if (rowx <= fRows->GetSize()) mrow=(TObjArray*)fRows->At(rowx-1);
312
313  if (!mrow) return;
314
315  if (colx <= mrow->GetSize()) obj=(TObject*)mrow->At(colx-1);
316
317  if (obj)
318  {
319   fObjects->Remove(obj);
320   fObjects->Compress();
321   mrow->Remove(obj);
322   if (fOwn) delete obj;
323  }
324 }
325 ///////////////////////////////////////////////////////////////////////////
326 void AliObjMatrix::RemoveObjects(TObject* obj,Int_t row,Int_t col)
327 {
328 // Remove object(s) from the matrix according to user specified selections.
329 // In case the object was owned by the matrix, it will be deleted.
330 //
331 // An object is only removed from the matrix if the stored reference matches
332 // the argument "obj".
333 // In case obj=0 no check on the matching of the stored reference is performed
334 // and the stored object is always removed in accordance with the other
335 // selection criteria.
336 //
337 // In case the argument "row" is specified, only the object references from
338 // that matrix row will be deleted.
339 // In case row=0 (default) no checking on the row index is performed.
340 //
341 // In case the argument "col" is specified, only the object references from
342 // that matrix column will be deleted.
343 // In case col=0 (default) no checking on the column index is performed.
344 //
345 // So, invokation of RemoveObjects(obj) will remove all references to the
346 // object "obj" from the total matrix, whereas RemoveObjects(obj,0,col)
347 // will remove all references to the object "obj" only from column "col".
348 //
349 // Notes :
350 // -------
351 // The first location in the matrix is indicated as (1,1).
352 //
353 // Invokation of RemoveObjects(0,row,col) is equivalent to invoking the
354 // memberfunction RemoveObject(row,col).
355 // Invoking the latter directly is slightly faster.
356 //
357 // Invokation of RemoveObjects(0) is equivalent to invoking Reset().
358 // Invoking the latter directly is slightly faster.
359 //
360  TArrayI rows;
361  TArrayI cols;
362  Int_t nrefs=0;
363
364  if (row && col)
365  {
366   if (!obj)
367   {
368    RemoveObject(row,col);
369   }
370   else
371   {
372    TObject* objx=GetObject(row,col);
373    if (objx==obj) RemoveObject(row,col);
374   }
375   return;
376  }
377
378  if (!row && !col)
379  {
380   if (!obj)
381   {
382    Reset();
383    return;
384   }
385   else
386   {
387    nrefs=GetIndices(obj,rows,cols);
388   }
389  }
390
391  if (row && !col) nrefs=GetIndices(obj,row,cols);
392  if (!row && col) nrefs=GetIndices(obj,rows,col);
393
394  // Remove the selected objects based on the obtained row and column indices
395  Int_t irow,icol;
396  for (Int_t i=0; i<nrefs; i++)
397  {
398   irow=row;
399   if (!irow) irow=rows.At(i);
400   icol=col;
401   if (!icol) icol=cols.At(i);
402   RemoveObject(irow,icol);
403  }
404 }
405 ///////////////////////////////////////////////////////////////////////////
406 TObject* AliObjMatrix::GetObject(Int_t row,Int_t col) const
407 {
408 // Provide a pointer to the object stored at the matrix location (row,col).
409 // In case no object was stored at the indicated location or the location
410 // would reside outside the matrix boundaries, a value 0 will be returned.
411 // Note : The first location in the matrix is indicated as (1,1).
412
413  TObject* obj=0;
414
415  if (!fRows || row<1 || col<1) return obj;
416
417
418  Int_t rowx=row;
419  if (fSwap) rowx=col;
420  Int_t colx=col;
421  if (fSwap) colx=row;
422
423  TObjArray* mrow=0;
424  if (rowx <= fRows->GetSize()) mrow=(TObjArray*)fRows->At(rowx-1);
425
426  if (!mrow) return obj;
427
428  if (colx <= mrow->GetSize()) obj=(TObject*)mrow->At(colx-1);
429
430  return obj;
431 }
432 ///////////////////////////////////////////////////////////////////////////
433 TObject* AliObjMatrix::GetObject(Int_t j) const
434 {
435 // Provide a pointer to the j-th stored object.
436 // In case the index j is invalid, a value 0 will be returned.
437 // The first stored object is indicated as j=1.
438 //
439 // Note : Do NOT delete the object.
440 //        To remove an object, the memberfunction RemoveObject() or
441 //        RemoveObjects() should be used.
442
443  TObject* obj=0;
444  Int_t nobj=0;
445  if (fObjects) nobj=fObjects->GetSize();
446
447  if (j>0 && j<=nobj) obj=(TObject*)fObjects->At(j-1);
448
449  return obj;
450 }
451 ///////////////////////////////////////////////////////////////////////////
452 TObjArray* AliObjMatrix::GetObjects()
453 {
454 // Provide references to all the stored objects.
455 // In case no objects are present, a value 0 will be returned.
456 //
457 // Note : Do NOT make any changes to the reference array apart from
458 //        changing the order of the pointers of the various objects.
459 //        For addition or removal of objects, the memberfunctions
460 //        EnterObject(), RemoveObject() or RemoveObjects() should be used.
461
462  return fObjects;
463 }
464 ///////////////////////////////////////////////////////////////////////////
465 Int_t AliObjMatrix::GetMaxRow() const
466 {
467 // Provide the maximum row number index.
468  return fMaxrow;
469 }
470 ///////////////////////////////////////////////////////////////////////////
471 Int_t AliObjMatrix::GetMaxColumn() const
472 {
473 // Provide the maximum column number index.
474  return fMaxcol;
475 }
476 ///////////////////////////////////////////////////////////////////////////
477 Int_t AliObjMatrix::GetNobjects() const
478 {
479 // Provide the number of stored objects.
480  Int_t nobj=0;
481  if (fObjects) nobj=fObjects->GetEntries();
482
483  return nobj;
484 }
485 ///////////////////////////////////////////////////////////////////////////
486 Int_t AliObjMatrix::GetNrefs(TObject* obj) const
487 {
488 // Provide the number of stored references to the specified object.
489 // If obj=0 the total number of stored references for all objects is returned.
490  Int_t nobjs=GetNobjects();
491
492  if (!obj) return nobjs;
493
494  Int_t nrefs=0;
495  for (Int_t i=1; i<=nobjs; i++)
496  {
497   TObject* objx=GetObject(i);
498   if (objx==obj) nrefs++;
499  }
500  return nrefs;
501 }
502 ///////////////////////////////////////////////////////////////////////////
503 Int_t AliObjMatrix::GetIndices(TObject* obj,TArrayI& rows,TArrayI& cols) const
504 {
505 // Provide the (row,col) indices of all the storage locations of the
506 // specified object.
507 // The row and column indices are returned in the two separate TArrayI arrays
508 // from which the (row,col) pairs can be obtained from the corresponding
509 // array indices like (row,col)=(rows.At(j),cols.At(j)).
510 // The integer return argument represents the number of (row,col) pairs which
511 // were encountered for the specified object.
512 //
513 // If obj=0 no object selection is performed and all (row,col) indices
514 // of the stored references for all objects are returned.
515 //
516 // Notes :
517 // -------
518 // As usual the convention is that row and column numbering starts at 1.
519 // 
520 // This memberfunction always resets the two TArrayI arrays at the start.
521 //
522 // This memberfunction can only be used to obtain the (row,col) indices
523 // of the object as stored via the EnterObject() memberfunction.
524 // This means that in case the user has entered a TObjArray as object
525 // (to increase the dimension of the resulting structure), the (row,col)
526 // indices of that TObjArray are obtained and NOT the indices of the
527 // actual objects contained in that TObjArray structure.
528 //
529  Int_t nrefs=GetNrefs(obj);
530  rows.Reset();
531  cols.Reset();
532  rows.Set(nrefs);
533  cols.Set(nrefs);
534  if (!nrefs) return 0;
535
536  Int_t irow,icol;
537  Int_t jref=0;
538  for (Int_t i=0; i<fRows->GetSize(); i++)
539  {
540   TObjArray* columns=(TObjArray*)fRows->At(i);
541   if (!columns) continue;
542
543   for (Int_t j=0; j<columns->GetSize(); j++)
544   {
545    TObject* objx=(TObject*)columns->At(j);
546    if (objx && (objx==obj || !obj))
547    {
548     irow=i+1;
549     if (fSwap) irow=j+1;
550     icol=j+1;
551     if (fSwap) icol=i+1;
552     rows.AddAt(irow,jref);
553     cols.AddAt(icol,jref);
554     jref++;
555    }
556    // All references found ==> Done
557    if (jref==nrefs) break;
558   }
559   // All references found ==> Done
560   if (jref==nrefs) break;
561  }
562  return nrefs;
563 }
564 ///////////////////////////////////////////////////////////////////////////
565 Int_t AliObjMatrix::GetIndices(TObject* obj,Int_t row,TArrayI& cols) const
566 {
567 // Provide the column indices of all the storage locations of the
568 // specified object in the specified row of the matrix.
569 // The column indices are returned in the TArrayI array.
570 // The integer return argument represents the number of storage locations which
571 // were encountered for the specified object in the specified matrix row.
572 //
573 // If obj=0 no object selection is performed and all column indices
574 // of the stored references for all objects in this specified matrix row
575 // are returned.
576 //
577 // If row=0 all rows will be scanned and all column indices matching the
578 // object selection are returned.
579 // Note that in this case multiple appearances of the same column index
580 // will only be recorded once in the returned TArrayI array.
581 //
582 // Notes :
583 // -------
584 // As usual the convention is that row and column numbering starts at 1.
585 // 
586 // This memberfunction always resets the TArrayI array at the start.
587 //
588 // This memberfunction can only be used to obtain the column indices
589 // of the object as stored via the EnterObject() memberfunction.
590 // This means that in case the user has entered a TObjArray as object
591 // (to increase the dimension of the resulting structure), the column
592 // indices of that TObjArray are obtained and NOT the indices of the
593 // actual objects contained in that TObjArray structure.
594 //
595  cols.Reset();
596
597  if (row<0 || row>GetMaxRow()) return 0;
598
599  Int_t nrefs=GetNrefs(obj);
600  cols.Set(nrefs);
601  if (!nrefs) return 0;
602
603  Int_t irow,icol;
604  Int_t jref=0;
605
606  // No specific row selection
607  if (!row)
608  {
609   TArrayI ar;
610   TArrayI ac;
611   Int_t n=GetIndices(obj,ar,ac);
612   Int_t found=0;
613   for (Int_t idx=0; idx<n; idx++)
614   {
615    icol=ac.At(idx);
616    found=0;
617    for (Int_t k=0; k<jref; k++)
618    {
619     if (icol==cols.At(k)) found=1;
620    }
621    if (!found)
622    {
623     cols.AddAt(icol,jref);
624     jref++;
625    }
626   }
627   // Set the array size to the actual number of different column indices
628   cols.Set(jref);
629
630   return jref;
631  }
632
633  // Specific row selection
634  for (Int_t i=0; i<fRows->GetSize(); i++)
635  {
636   TObjArray* columns=(TObjArray*)fRows->At(i);
637   if (!columns) continue;
638
639   for (Int_t j=0; j<columns->GetSize(); j++)
640   {
641    TObject* objx=(TObject*)columns->At(j);
642    if (objx && (objx==obj || !obj))
643    {
644     irow=i+1;
645     if (fSwap) irow=j+1;
646     icol=j+1;
647     if (fSwap) icol=i+1;
648     if (irow==row)
649     {
650      cols.AddAt(icol,jref);
651      jref++;
652     }
653    }
654    // All references found ==> Done
655    if (jref==nrefs) break;
656   }
657   // All references found ==> Done
658   if (jref==nrefs) break;
659  }
660  // Set the array size to the actual number of found occurrences
661  cols.Set(jref);
662
663  return jref;
664 }
665 ///////////////////////////////////////////////////////////////////////////
666 Int_t AliObjMatrix::GetIndices(TObject* obj,TArrayI& rows,Int_t col) const
667 {
668 // Provide the row indices of all the storage locations of the
669 // specified object in the specified column of the matrix.
670 // The row indices are returned in the TArrayI array.
671 // The integer return argument represents the number of storage locations which
672 // were encountered for the specified object in the specified matrix column.
673 //
674 // If obj=0 no object selection is performed and all row indices
675 // of the stored references for all objects in this specified matrix column
676 // are returned.
677 //
678 // If col=0 all columns will be scanned and all row indices matching the
679 // object selection are returned.
680 // Note that in this case multiple appearances of the same row index
681 // will only be recorded once in the returned TArrayI array.
682 //
683 // Notes :
684 // -------
685 // As usual the convention is that row and column numbering starts at 1.
686 // 
687 // This memberfunction always resets the TArrayI array at the start.
688 //
689 // This memberfunction can only be used to obtain the row indices
690 // of the object as stored via the EnterObject() memberfunction.
691 // This means that in case the user has entered a TObjArray as object
692 // (to increase the dimension of the resulting structure), the row
693 // indices of that TObjArray are obtained and NOT the indices of the
694 // actual objects contained in that TObjArray structure.
695 //
696  rows.Reset();
697
698  if (col<0 || col>GetMaxColumn()) return 0;
699
700  Int_t nrefs=GetNrefs(obj);
701  rows.Set(nrefs);
702  if (!nrefs) return 0;
703
704  Int_t irow,icol;
705  Int_t jref=0;
706
707  // No specific column selection
708  if (!col)
709  {
710   TArrayI ar;
711   TArrayI ac;
712   Int_t n=GetIndices(obj,ar,ac);
713   Int_t found=0;
714   for (Int_t idx=0; idx<n; idx++)
715   {
716    irow=ar.At(idx);
717    found=0;
718    for (Int_t k=0; k<jref; k++)
719    {
720     if (irow==rows.At(k)) found=1;
721    }
722    if (!found)
723    {
724     rows.AddAt(irow,jref);
725     jref++;
726    }
727   }
728   // Set the array size to the actual number of different row indices
729   rows.Set(jref);
730
731   return jref;
732  }
733
734  // Specific column selection
735  for (Int_t i=0; i<fRows->GetSize(); i++)
736  {
737   TObjArray* columns=(TObjArray*)fRows->At(i);
738   if (!columns) continue;
739
740   for (Int_t j=0; j<columns->GetSize(); j++)
741   {
742    TObject* objx=(TObject*)columns->At(j);
743    if (objx && (objx==obj || !obj))
744    {
745     irow=i+1;
746     if (fSwap) irow=j+1;
747     icol=j+1;
748     if (fSwap) icol=i+1;
749     if (icol==col)
750     {
751      rows.AddAt(irow,jref);
752      jref++;
753     }
754    }
755    // All references found ==> Done
756    if (jref==nrefs) break;
757   }
758   // All references found ==> Done
759   if (jref==nrefs) break;
760  }
761  // Set the array size to the actual number of found occurrences
762  rows.Set(jref);
763
764  return jref;
765 }
766 ///////////////////////////////////////////////////////////////////////////
767 TObject* AliObjMatrix::Clone(const char* name) const
768 {
769 // Make a deep copy of the current object and provide the pointer to the copy.
770 // This memberfunction enables automatic creation of new objects of the
771 // correct type depending on the object type, a feature which may be very useful
772 // for containers when adding objects in case the container owns the objects.
773
774  AliObjMatrix* m=new AliObjMatrix(*this);
775  if (name)
776  {
777   if (strlen(name)) m->SetName(name);
778  }
779  return m;
780 }
781 ///////////////////////////////////////////////////////////////////////////