ATLAS Offline Software
Loading...
Searching...
No Matches
Array.icc
Go to the documentation of this file.
1// This file's extension implies that it's C, but it's really -*- C++ -*-.
2
3/*
4 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
5*/
6
7/**
8 * @file Array.icc
9 * @author scott snyder <snyder@bnl.gov>
10 * @date June, 2004
11 * @brief Simple multidimensional arrays (inline and template implementations).
12 */
13
14
15#include "CxxUtils/unused.h"
16#include <ostream>
17#include <cassert>
18
19
20// cppcheck doesn't properly handle recursive templates like this.
21#ifndef __CPPCHECK__
22namespace CxxUtils {
23
24
25/**
26 * @brief Construct an @c Array<N>::const_iterator.
27 * @param rep @c Arrayrep from which to initialize the iterator.
28 * @param offs Offset of the first element referenced by the iterator
29 * within @a rep.
30 * @return The new iterator.
31 */
32template <unsigned int N>
33inline
34typename ArrayIteratorChooser<N>::const_iterator
35ArrayIteratorChooser<N>::make_iterator (const Arrayrep* rep,
36 unsigned int offs)
37{
38 return const_iterator (rep, offs);
39}
40
41
42/**
43 * @brief Construct an @c Array<1>::const_iterator.
44 * @param rep @c Arrayrep from which to initialize the iterator.
45 * @param offs Offset of the first element referenced by the iterator
46 * within @a rep.
47 * @return The new iterator.
48 */
49inline
50ArrayIteratorChooser<1>::const_iterator
51ArrayIteratorChooser<1>::make_iterator (const Arrayrep* rep,
52 unsigned int offs)
53{
54 return rep ? rep->m_data.data()+offs : 0;
55}
56
57
58//**********************************************************************
59
60
61/**
62 * @brief Default constructor.
63 *
64 * This produces an invalid @c Array that is not associated with
65 * an @c Arrayrep. @c valid() will return @c false for such an array.
66 * The only other thing that it is legal to do with an invalid array
67 * is to assign to it (which may make it valid).
68 */
69template <unsigned int N>
70Array<N>::Array ()
71 : m_rep (0),
72 m_offs (0)
73{
74}
75
76
77/**
78 * @brief Constructor.
79 * @param rep @c Arrayrep from which to initialize the array.
80 *
81 * Initialize an array from an @c Arrayrep. The new array will
82 * represent the entire @c Arrayrep. The dimension @c N must
83 * match the length of the @c Arrayrep's shape.
84 */
85template <unsigned int N>
86Array<N>::Array (const Arrayrep& rep)
87 : m_rep (&rep),
88 m_offs (0)
89{
90 assert (m_rep->m_shape.size() == N);
91 assert (m_rep->m_sizes.size() == m_rep->m_shape.size());
92}
93
94
95/**
96 * @brief Test for validity.
97 * @return True if the @c Array is associated with an @c Arrayrep,
98 * false if not.
99 */
100template <unsigned int N>
101bool Array<N>::valid() const
102{
103 return m_rep != 0;
104}
105
106
107/**
108 * @brief Return the array shape.
109 * @return The array shape.
110 *
111 * The array shape is vector with one element for each array dimension,
112 * giving the size of the array along that dimension.
113 */
114template <unsigned int N>
115std::vector<unsigned int> Array<N>::shape() const
116{
117 return std::vector<unsigned int>
118 (m_rep->m_shape.begin() + m_rep->m_shape.size() - N,
119 m_rep->m_shape.end());
120}
121
122
123/**
124 * @brief Return the size of the array along one dimension.
125 * @param dim The dimension of the size to retrieve.
126 * Must be less than the number of dimensions.
127 *
128 * As a special case, the size of an invalid array will always be 0.
129 * @return The array size along dimension @dim.
130 */
131template <unsigned int N>
132unsigned int Array<N>::size (unsigned int dim /*=0*/) const
133{
134 assert (dim < N);
135 if (!m_rep) return 0;
136 return m_rep->m_shape[m_rep->m_shape.size() - N + dim];
137}
138
139
140/**
141 * @brief Array indexing.
142 * @param i The desired index. Must be less than the array size
143 * along this dimension.
144 * @return The @a i'th @c N-1 dimensional subarray in the array.
145 *
146 * Note that this operation is not available if @c N is 0.
147 */
148template <unsigned int N>
149inline
150Array<N-1> Array<N>::operator[] (unsigned int i) const
151{
152 assert (i < m_rep->m_shape[m_rep->m_shape.size() - N]);
153 return Array<N-1> (*m_rep, m_offs + i * m_rep->m_sizes[N-1]);
154}
155
156
157/**
158 * @brief Return a direct pointer to array elements.
159 * @return A pointer to the first array elements.
160 *
161 * Subsequent elements follow in standard C indexing order.
162 */
163template <unsigned int N>
164inline
165const Arrayelt* Array<N>::ptr () const
166{
167 return &m_rep->m_data[m_offs];
168}
169
170
171/**
172 * @brief Return an iterator pointing at the beginning of the container.
173 * @return An iterator pointing at the beginning of the container.
174 */
175template <unsigned int N>
176inline
177typename Array<N>::const_iterator Array<N>::begin () const
178{
179 return ArrayIteratorChooser<N>::make_iterator (m_rep, m_offs);
180}
181
182
183/**
184 * @brief Return an iterator pointing past the end of the container.
185 * @return An iterator pointing past the end of the container.
186 */
187template <unsigned int N>
188inline
189typename Array<N>::const_iterator Array<N>::end () const
190{
191 unsigned int offs = m_rep ? m_offs + size() * m_rep->m_sizes[N-1] : 0;
192 return ArrayIteratorChooser<N>::make_iterator (m_rep, offs);
193}
194
195
196/**
197 * @brief Creates a text representation of the array content.
198 * @param std::ostream where the text should be written
199 *
200 * Writes the content of the array to a ostream. The sub-arrays are
201 * enclosed by square brackets and separated by commas.
202 */
203template <unsigned int N>
204inline
205void Array<N>::write_array (std::ostream& stream) const
206{
207 if (!m_rep) {
208 stream << "\"\"";
209 }
210 else {
211 m_rep->write_array (stream);
212 }
213}
214
215
216/**
217 * @brief Private constructor for array indexing.
218 * @param rep @c Arrayrep from which to initialize the array.
219 * @param offs Offset of the first element of the new array
220 * within @a rep.
221 *
222 * This is a private constructor used to make the @c Array
223 * instances returned from an indexing operation.
224 */
225template <unsigned int N>
226inline
227Array<N>::Array (const Arrayrep& rep, unsigned int offs)
228 : m_rep (&rep),
229 m_offs (offs)
230{
231}
232
233
234/**
235 * @brief Default constructor.
236 *
237 * This produces an invalid @c Array that is not associated with
238 * an @c Arrayrep. @c valid() will return @c false for such an array.
239 * The only other thing that it is legal to do with an invalid array
240 * is to assign to it (which may make it valid).
241 */
242inline
243Array<0>::Array ()
244 : m_elt (0)
245{
246}
247
248
249/**
250 * @brief Constructor.
251 * @param rep @c Arrayrep from which to initialize the array.
252 *
253 * Initialize an array from an @c Arrayrep. The new array will
254 * represent the entire @c Arrayrep. The dimension @c N must
255 * match the length of the @c Arrayrep's shape.
256 */
257inline
258Array<0>::Array (const Arrayrep& rep)
259 : m_elt (&rep.m_data[0])
260{
261 assert (rep.m_shape.size() == 0);
262 assert (rep.m_sizes.size() == rep.m_shape.size());
263}
264
265
266/**
267 * @brief Test for validity.
268 * @return True if the @c Array is associated with an @c Arrayrep,
269 * false if not.
270 */
271inline
272bool Array<0>::valid() const
273{
274 return m_elt != 0;
275}
276
277
278/**
279 * @brief Return the array shape.
280 * @return The array shape.
281 *
282 * The array shape is vector with one element for each array dimension,
283 * giving the size of the array along that dimension.
284 * For @c Array<0>, this will always be an empty array.
285 */
286inline
287std::vector<unsigned int> Array<0>::shape() const
288{
289 return std::vector<unsigned int> ();
290}
291
292
293/**
294 * @brief Return the size of the array along one dimension.
295 * @param dim The dimension of the size to retrieve.
296 * Must be less than the number of dimensions.
297 * @return The array size along dimension @dim.
298 *
299 * For @c Array<0>, @a dim must be 0, and the function
300 * will always return 1.
301 */
302inline
303unsigned int Array<0>::size ([[maybe_unused]] unsigned int dim /*=0*/) const
304{
305 assert (dim == 0);
306 return 1;
307}
308
309
310/**
311 * @brief Convert to a number.
312 * @return The @c Array<0> contents as a number.
313 */
314inline
315Array<0>::operator Arrayelt() const
316{
317 return *m_elt;
318}
319
320
321/**
322 * @brief Convert to an integer.
323 * @return The @c Array<0> contents as an integer.
324 */
325inline
326int Array<0>::asint() const
327{
328 return static_cast<int> (*m_elt);
329}
330
331
332/**
333 * @brief Creates a text representation of the array content.
334 * @param std::ostream where the text should be written
335 *
336 * Writes the content of the array to a ostream. The sub-arrays are
337 * enclosed by square brackets and separated by commas.
338 */
339inline
340void Array<0>::write_array (std::ostream& stream) const
341{
342 stream << *m_elt;
343}
344
345
346/**
347 * @brief Private constructor for array indexing.
348 * @param rep @c Arrayrep from which to initialize the array.
349 * @param offs Offset of the first element of the new array
350 * within @a rep.
351 *
352 * This is a private constructor used to make the @c Array
353 * instances returned from an indexing operation.
354 */
355inline
356Array<0>::Array (const Arrayrep& rep, unsigned int offs)
357 : m_elt (&rep.m_data[offs])
358{
359}
360
361
362template <unsigned int N>
363std::ostream& operator<< (std::ostream& s, const Array<N>& a)
364{
365 a.write_array (s);
366 return s;
367}
368
369
370//**********************************************************************
371
372
373/**
374 * @brief Proxy constructor.
375 * @param i The iterator that is being dereferenced.
376 */
377template <unsigned int N>
378ArrayIterator<N>::pointer::pointer (const ArrayIterator& i)
379 : m_a (*i)
380{
381}
382
383
384/**
385 * @brief Dereference the proxy.
386 * @return A copy of the @c Array proxy.
387 */
388template <unsigned int N>
389typename ArrayIterator<N>::value_type
390ArrayIterator<N>::pointer::operator* () const
391{
392 return m_a;
393}
394
395
396/**
397 * @brief Dereference the proxy.
398 * @return A pointer to the @c Array proxy.
399 * This proxy is only until the @c pointer instance
400 * is destroyed.
401 */
402template <unsigned int N>
403const typename ArrayIterator<N>::value_type*
404ArrayIterator<N>::pointer::operator-> () const
405{
406 return &m_a;
407}
408
409
410/**
411 * @brief Default constructor.
412 * Makes an invalid iterator.
413 */
414template <unsigned int N>
415ArrayIterator<N>::ArrayIterator ()
416 : m_rep (0),
417 m_offs (0)
418{
419}
420
421
422/**
423 * @brief Constructor from @c Arrayrep and offset.
424 * @param rep The underlying array representation.
425 * @param offs The offset in the representation of the
426 * first element referenced by this iterator.
427 */
428template <unsigned int N>
429ArrayIterator<N>::ArrayIterator (const Arrayrep* rep, unsigned int offs)
430 : m_rep (rep),
431 m_offs (offs)
432{
433}
434
435
436/**
437 * @brief Equality comparison.
438 * @param other The other object with which to compare.
439 * @return True if the iterators are equal.
440 */
441template <unsigned int N>
442bool ArrayIterator<N>::operator== (const ArrayIterator<N>& other) const
443{
444 return m_rep == other.m_rep && m_offs == other.m_offs;
445}
446
447
448/**
449 * @brief Inequality comparison.
450 * @param other The other object with which to compare.
451 * @return True if the iterators are not equal.
452 */
453template <unsigned int N>
454bool ArrayIterator<N>::operator!= (const ArrayIterator<N>& other) const
455{
456 return !(*this == other);
457}
458
459
460/**
461 * @brief Less-than comparison.
462 * @param other The other object with which to compare.
463 * @return True if this iterator is less than @a other.
464 * This will always return false for iterators
465 * over different arrays.
466 */
467template <unsigned int N>
468bool ArrayIterator<N>::operator< (const ArrayIterator<N>& other) const
469{
470 return m_rep == other.m_rep && m_offs < other.m_offs;
471}
472
473
474/**
475 * @brief Greater-than comparison.
476 * @param other The other object with which to compare.
477 * @return True if this iterator is greater than @a other.
478 * This will always return false for iterators
479 * over different arrays.
480 */
481template <unsigned int N>
482bool ArrayIterator<N>::operator> (const ArrayIterator<N>& other) const
483{
484 return other < *this;
485}
486
487
488/**
489 * @brief Less-than-or-equal comparison.
490 * @param other The other object with which to compare.
491 * @return True if this iterator is less than or equal to @a other.
492 * This will always return false for iterators
493 * over different arrays.
494 */
495template <unsigned int N>
496bool ArrayIterator<N>::operator<= (const ArrayIterator<N>& other) const
497{
498 return m_rep == other.m_rep && m_offs <= other.m_offs;
499}
500
501
502/**
503 * @brief Greater-than-or-equal comparison.
504 * @param other The other object with which to compare.
505 * @return True if this iterator is less than or equal to @a other.
506 * This will always return false for iterators
507 * over different arrays.
508 */
509template <unsigned int N>
510bool ArrayIterator<N>::operator>= (const ArrayIterator<N>& other) const
511{
512 return other <= *this;
513}
514
515
516/**
517 * @brief Dereference the iterator.
518 * @return The value that the iterator points to.
519 * Note that this method returns a @c value_type, not
520 * a @c reference. (Thus, this class does not quite
521 * conform to the iterator requirements.)
522 */
523template <unsigned int N>
524typename ArrayIterator<N>::value_type ArrayIterator<N>::operator* () const
525{
526 assert (m_offs < m_rep->m_data.size());
527 return Array<N-1> (*m_rep, m_offs);
528}
529
530
531/**
532 * @brief Dereference the iterator.
533 * @return A proxy for the iterator element.
534 *
535 * This method will return a proxy for the array, which you
536 * can then dereference. Note that if you get a C++ pointer
537 * from this, then it will be valid only until the proxy
538 * object gets destroyed.
539 */
540template <unsigned int N>
541typename ArrayIterator<N>::pointer ArrayIterator<N>::operator-> () const
542{
543 return pointer (*this);
544}
545
546
547/**
548 * @brief Advance the iterator.
549 * @returns This iterator.
550 */
551template <unsigned int N>
552ArrayIterator<N>& ArrayIterator<N>::operator++ ()
553{
554 m_offs += m_rep->m_sizes[N-1];
555 return *this;
556}
557
558
559/**
560 * @brief Advance the iterator.
561 * @returns The iterator before being advanced.
562 */
563template <unsigned int N>
564ArrayIterator<N> ArrayIterator<N>::operator++ (int)
565{
566 ArrayIterator tmp (*this);
567 m_offs += m_rep->m_sizes[N-1];
568 return tmp;
569}
570
571
572/**
573 * @brief Back up the iterator.
574 * @returns This iterator.
575 */
576template <unsigned int N>
577ArrayIterator<N>& ArrayIterator<N>::operator-- ()
578{
579 m_offs -= m_rep->m_sizes[N-1];
580 return *this;
581}
582
583
584/**
585 * @brief Back up the iterator.
586 * @returns The iterator before being backed up.
587 */
588template <unsigned int N>
589ArrayIterator<N> ArrayIterator<N>::operator-- (int)
590{
591 ArrayIterator tmp (*this);
592 m_offs -= m_rep->m_sizes[N-1];
593 return tmp;
594}
595
596
597/**
598 * @brief Array indexing relative to the iterator.
599 * @param n The array index.
600 * @return The array item at an offset of @a n from the
601 * current iterator position.
602 * Note that this method returns a @c value_type, not
603 * a @c reference. (Thus, this class does not quite
604 * conform to the iterator requirements.)
605 */
606template <unsigned int N>
607typename ArrayIterator<N>::value_type
608ArrayIterator<N>::operator[] (difference_type n) const
609{
610 unsigned int offs = m_offs + n * m_rep->m_sizes[N-1];
611 assert (offs < m_rep->m_data.size());
612 return Array<N-1> (*m_rep, offs);
613}
614
615
616/**
617 * @brief Advance the iterator.
618 * @param n Number of steps by which to advance the iterator.
619 * @return This iterator.
620 */
621template <unsigned int N>
622ArrayIterator<N>& ArrayIterator<N>::operator+= (difference_type n)
623{
624 m_offs += n * m_rep->m_sizes[N-1];
625 return *this;
626}
627
628
629/**
630 * @brief Return a new iterator pointing @a n steps ahead.
631 * @param n Number of steps by which to advance.
632 * @return The new iterator.
633 */
634template <unsigned int N>
635ArrayIterator<N> ArrayIterator<N>::operator+ (difference_type n) const
636{
637 return ArrayIterator (m_rep, m_offs + n * m_rep->m_sizes[N-1]);
638}
639
640
641/**
642 * @brief Back up the iterator.
643 * @param n Number of steps by which to advance the iterator.
644 * @return This iterator.
645 */
646template <unsigned int N>
647ArrayIterator<N>& ArrayIterator<N>::operator-= (difference_type n)
648{
649 m_offs -= n * m_rep->m_sizes[N-1];
650 return *this;
651}
652
653
654/**
655 * @brief Return a new iterator pointing @a n steps behind.
656 * @param n Number of steps by which to back up.
657 * @return The new iterator.
658 */
659template <unsigned int N>
660ArrayIterator<N> ArrayIterator<N>::operator- (difference_type n) const
661{
662 return ArrayIterator (m_rep, m_offs - n * m_rep->m_sizes[N-1]);
663}
664
665
666/**
667 * @brief Return the difference between two iterators.
668 * @param other The other iterator for the comparison.
669 * @return The number of elements difference between
670 * this iterator and @a other.
671 * Undefined if the two iterators do not point
672 * into the same array.
673 */
674template <unsigned int N>
675typename ArrayIterator<N>::difference_type
676ArrayIterator<N>::operator- (const ArrayIterator& other) const
677{
678 return (m_offs - other.m_offs) / m_rep->m_sizes[N-1];
679}
680
681
682//**********************************************************************
683
684
685/**
686 * @brief Constructor.
687 * @param rep @c Arrayrep from which to initialize the array.
688 *
689 * Initialize an array from an @c Arrayrep. The new array will
690 * represent the entire @c Arrayrep. The dimension @c N must
691 * match the length of the @c Arrayrep's shape.
692 */
693template <unsigned int N>
694inline
695WritableArray<N>::WritableArray (Arrayrep& rep)
696 : Array<N> (rep),
697 m_rep_nc (&rep)
698{
699}
700
701
702/**
703 * @brief Array indexing.
704 * @param i The desired index. Must be less than the array size
705 * along this dimension.
706 * @return The @a i'th @c N-1 dimensional subarray in the array.
707 *
708 * Note that this operation is not available if @c N is 0.
709 */
710template <unsigned int N>
711inline
712WritableArray<N-1> WritableArray<N>::operator[] (unsigned int i)
713{
714 assert (i < this->m_rep_nc->m_shape[this->m_rep_nc->m_shape.size() - N]);
715 return WritableArray<N-1> (*this->m_rep_nc,
716 this->m_offs + i * this->m_rep_nc->m_sizes[N-1]);
717}
718
719
720/**
721 * @brief Array indexing.
722 * @param i The desired index. Must be less than the array size
723 * along this dimension.
724 * @return The @a i'th @c N-1 dimensional subarray in the array.
725 *
726 * Note that this operation is not available if @c N is 0.
727 */
728template <unsigned int N>
729inline
730Array<N-1> WritableArray<N>::operator[] (unsigned int i) const
731{
732 assert (i < this->m_rep_nc->m_shape[this->m_rep_nc->m_shape.size() - N]);
733 return Array<N-1> (*this->m_rep_nc,
734 this->m_offs + i * this->m_rep_nc->m_sizes[N-1]);
735}
736
737
738/**
739 * @brief Return a direct pointer to array elements.
740 * @return A pointer to the first array elements.
741 *
742 * Subsequent elements follow in standard C indexing order.
743 */
744template <unsigned int N>
745inline
746Arrayelt* WritableArray<N>::ptr ()
747{
748 return &this->m_rep_nc->m_data[this->m_offs];
749}
750
751
752/**
753 * @brief Private constructor for array indexing.
754 * @param rep @c Arrayrep from which to initialize the array.
755 * @param offs Offset of the first element of the new array
756 * within @a rep.
757 *
758 * This is a private constructor used to make the @c Array
759 * instances returned from an indexing operation.
760 */
761template <unsigned int N>
762inline
763WritableArray<N>::WritableArray (Arrayrep& rep, unsigned int offs)
764 : Array<N> (rep, offs),
765 m_rep_nc (&rep)
766{
767}
768
769
770/**
771 * @brief Constructor.
772 * @param rep @c Arrayrep from which to initialize the array.
773 *
774 * Initialize an array from an @c Arrayrep. The new array will
775 * represent the entire @c Arrayrep. The dimension @c N must
776 * match the length of the @c Arrayrep's shape.
777 */
778inline
779WritableArray<0>::WritableArray (Arrayrep& rep)
780 : Array<0> (rep),
781 m_elt_nc (&rep.m_data[0])
782{
783}
784
785
786/**
787 * @brief Assignment.
788 * @param elt The RHS of the assignment.
789 * @return This object.
790 *
791 * Assign into the array.
792 */
793inline
794WritableArray<0>& WritableArray<0>::operator= (Arrayelt elt)
795{
796 *m_elt_nc = elt;
797 return *this;
798}
799
800
801/**
802 * @brief Private constructor for array indexing.
803 * @param rep @c Arrayrep from which to initialize the array.
804 * @param offs Offset of the first element of the new array
805 * within @a rep.
806 *
807 * This is a private constructor used to make the @c Array
808 * instances returned from an indexing operation.
809 */
810inline
811WritableArray<0>::WritableArray (Arrayrep& rep, unsigned int offs)
812 : Array<0> (rep, offs),
813 m_elt_nc (&rep.m_data[offs])
814{
815}
816
817
818//**********************************************************************
819
820
821/**
822 * @brief Constructor.
823 * @param shape The shape of the array, as a C array.
824 * Should be @c N elements long. \
825 *
826 * The shape is the size of the array along each dimension.
827 */
828template <unsigned int N>
829WritableArrayData<N>::WritableArrayData(const unsigned int shape[])
830 : Arrayrep (shape, N),
831 WritableArray<N> (*static_cast<Arrayrep*>(this))
832{
833}
834
835
836/**
837 * @brief Constructor.
838 * @param shape The shape of the array, as a std::vector.
839 * Should be @c N elements long.
840 *
841 * The shape is the size of the array along each dimension.
842 */
843template <unsigned int N>
844WritableArrayData<N>::WritableArrayData(const std::vector<unsigned int>& shape)
845 : Arrayrep (shape),
846 WritableArray<N> (*static_cast<Arrayrep*>(this))
847{
848 assert (shape.size() == N);
849}
850
851
852/**
853 * @brief Helper to convert from an @x Arrayrep to a scalar type.
854 * @param rep Representation object to convert.
855 * @param x[out] Result of the conversion.
856 */
857template <class T>
858 requires std::assignable_from<T&, float>
859void fromArrayrep (const CaloRec::Arrayrep& rep, T& x)
860{
861 x = rep.m_data[0];
862}
863
864
865/**
866 * @brief Helper to convert from an @x Arrayrep to an @c Array.
867 * @param rep Representation object to convert.
868 * @param x[out] Result of the conversion.
869 */
870template <unsigned int N>
871void fromArrayrep (const CaloRec::Arrayrep& rep, CxxUtils::Array<N>& x)
872{
873 x = CxxUtils::Array<N> (rep);
874}
875
876
877} // namespace CxxUtils
878#endif // not __CPPCHECK__