1 /*! \file
2
3 \verbatim
4
5 Copyright (c) 2004, Sylvain Paris and Francois Sillion
6 All rights reserved.
7
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions are
10 met:
11
12 * Redistributions of source code must retain the above copyright
13 notice, this list of conditions and the following disclaimer.
14
15 * Redistributions in binary form must reproduce the above
16 copyright notice, this list of conditions and the following
17 disclaimer in the documentation and/or other materials provided
18 with the distribution.
19
20 * Neither the name of ARTIS, GRAVIR-IMAG nor the names of its
21 contributors may be used to endorse or promote products derived
22 from this software without specific prior written permission.
23
24 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35
36 \endverbatim
37
38
39 * This file contains code made by Sylvain Paris under supervision of
40 * Fran�ois Sillion for his PhD work with <a
41 * href="http://www-artis.imag.fr">ARTIS project</a>. ARTIS is a
42 * research project in the GRAVIR/IMAG laboratory, a joint unit of
43 * CNRS, INPG, INRIA and UJF.
44 *
45 * Use <a href="http://www.stack.nl/~dimitri/doxygen/">Doxygen</a>
46 * with DISTRIBUTE_GROUP_DOC option to produce an nice html
47 * documentation.
48 *
49 * Most of STL conventions are used -- like std::vector. The main
50 * difference is the use the () operator to access the elements. Since
51 * the operator [] accepts only one argument, it is kept for the
52 * access through a vector variable.
53 */
54
55 #ifndef __ARRAY__
56 #define __ARRAY__
57
58
59 #ifdef ARRAY_EXCEPTION
60 # include <stdexcept>
61 #else
62 # include <iostream>
63 #endif
64
65 #include <vector>
66
67 //~ #ifndef NO_XML
68 //~ #include <sstream>
69
70 //~ #include <qdom.h>
71 //~ #endif
72
73 /*
74
75 ##################
76 # class Array_2D #
77 ##################
78
79 */
80
81
82
83 //! Class representing a 2D array.
84 /*!
85 Optimised for an access in order :
86 \code
87 for(x=...){ for(y=...){...} }
88 \endcode
89
90 at() and the operator[]() also accept a vector that provides an
91 access to its elements through an [] operator.
92 */
93 template<typename T,typename A = std::allocator<T> >
94 class Array_2D{
95
96 private:
97 //! Type of the storage structure.
98 typedef std::vector<T,A> Storage;
99
100 public:
101
102 //@{
103 //! Standard type.
104
105 typedef typename Storage::value_type value_type;
106 typedef typename Storage::allocator_type allocator_type;
107
108 typedef typename Storage::size_type size_type;
109 typedef typename Storage::difference_type difference_type;
110
111 typedef typename Storage::iterator iterator;
112 typedef typename Storage::const_iterator const_iterator;
113
114 typedef typename Storage::reverse_iterator reverse_iterator;
115 typedef typename Storage::const_reverse_iterator const_reverse_iterator;
116
117 typedef typename Storage::reference reference;
118 typedef typename Storage::const_reference const_reference;
119 //@}
120
121 //@{
122 //! Classical constructor.
123
124 explicit inline Array_2D(const A& a = A());
125
126 explicit inline Array_2D(const size_type nx,
127 const size_type ny,
128 const T& val = T(),const A& a = A());
129
130 template<typename Element_iterator>
131 inline Array_2D(Element_iterator begin_elt,
132 Element_iterator end_elt,
133 const size_type nx,
134 const size_type ny,
135 const A& a = A());
136
137 inline Array_2D(const Array_2D<T,A>& a);
138 //@}
139
140 //! Assignement of a default value.
141 void assign(const size_type nx,
142 const size_type ny,
143 const T& val);
144
145 //@{
146 //! Handle the array dimension.
147
148 inline bool empty() const;
149
150 inline size_type x_size() const;
151 inline size_type width() const;
152 inline size_type y_size() const;
153 inline size_type height() const;
154 inline size_type size() const;
155
156 inline size_type max_size() const;
157
158 inline void resize(const size_type nx,
159 const size_type ny);
160 //@}
161
162 //! Efficient swapping of two 2D arrays.
163 inline void swap(Array_2D<T,A>& a); /* A reference is used as in the STL. */
164
165 //! Gives the memory allocator.
166 inline allocator_type get_allocator() const;
167
168 //@{
169 //! Classical operator.
170
171 inline Array_2D<T,A>& operator=(const Array_2D<T,A>& a);
172 inline bool operator==(const Array_2D<T,A>& a);
173 inline bool operator!=(const Array_2D<T,A>& a);
174 //@}
175
176 //@{
177 //! Access operator.
178
179 template<typename Vector_position>
180 inline reference operator[](const Vector_position& v);
181
182 template<typename Vector_position>
183 inline const_reference operator[](const Vector_position& v) const;
184
185 inline reference operator()(const size_type x,
186 const size_type y);
187
188 inline const_reference operator()(const size_type x,
189 const size_type y) const;
190
191 template<typename Vector_position>
192 inline reference at(const Vector_position& v);
193
194 template<typename Vector_position>
195 inline const_reference at(const Vector_position& v) const;
196
197 inline reference at(const size_type x,
198 const size_type y);
199
200 inline const_reference at(const size_type x,
201 const size_type y) const;
202 //@}
203
204 //@{
205 //! Points on the (0,0) element.
206 /*!
207 Goes through the array in the order
208 \code
209 for(x=...){ for(y=...){...} }.
210 \endcode
211 */
212
213 inline iterator begin();
214 inline const_iterator begin() const;
215 //@}
216
217 //@{
218 //! Points on the element after (x_size()-1,y_size()-1).
219 /*!
220 Goes through the array in the order
221 \code
222 for(x=...){ for(y=...){...} }.
223 \endcode
224 */
225
226 inline iterator end();
227 inline const_iterator end() const;
228 //@}
229
230 //@{
231 //! Reverse iterator.
232
233 inline reverse_iterator rbegin();
234 inline const_reverse_iterator rbegin() const;
235 inline reverse_iterator rend();
236 inline const_reverse_iterator rend() const;
237 //@}
238
239 //~ #ifndef NO_XML
240 //~ inline QDomElement to_DOM_element(const QString& name,
241 //~ QDomDocument& document) const;
242 //~ inline void from_DOM_element(const QDomElement& element);
243 //~ #endif
244
245 private:
246 //@{
247 //! Dimension of the array.
248
249 int x_dim,y_dim;
250 //@}
251
252 //! Storage structure.
253 Storage storage;
254
255 //@{
256 //! Computation of the position in the storage structure.
257
258 template<typename Vector_position>
259 inline size_type offset(const Vector_position& v) const;
260
261 inline size_type offset(const size_type& x,
262 const size_type& y) const;
263 //@}
264 };
265
266
267
268
269
270
271
272
273
274 /*
275
276 ##################
277 # class Array_3D #
278 ##################
279
280 */
281
282
283
284
285
286
287
288
289
290 //! Class representing a 3D array.
291 /*!
292 Optimised for an access in order :
293 \code
294 for(x=...){ for(y=...){for(z=...){...} } }
295 \endcode
296
297 at() and the operator[]() also accept a vector that provides an
298 access to its elements through an [] operator.
299 */
300 template<typename T,typename A = std::allocator<T> >
301 class Array_3D{
302
303 private:
304 //! Type of the storage structure.
305 typedef std::vector<T,A> Storage;
306
307 public:
308
309 //@{
310 //! Standard type.
311
312 typedef typename Storage::value_type value_type;
313 typedef typename Storage::allocator_type allocator_type;
314
315 typedef typename Storage::size_type size_type;
316 typedef typename Storage::difference_type difference_type;
317
318 typedef typename Storage::iterator iterator;
319 typedef typename Storage::const_iterator const_iterator;
320
321 typedef typename Storage::reverse_iterator reverse_iterator;
322 typedef typename Storage::const_reverse_iterator const_reverse_iterator;
323
324 typedef typename Storage::reference reference;
325 typedef typename Storage::const_reference const_reference;
326 //@}
327
328 //@{
329 //! Classical constructor.
330
331 explicit inline Array_3D(const A& a = A());
332
333 explicit inline Array_3D(const size_type nx,
334 const size_type ny,
335 const size_type nz,
336 const T& val = T(),
337 const A& a = A());
338
339 template<typename Element_iterator>
340 inline Array_3D(Element_iterator begin_elt,
341 Element_iterator end_elt,
342 const size_type nx,
343 const size_type ny,
344 const size_type nz,
345 const A& a = A());
346
347 inline Array_3D(const Array_3D<T,A>& a);
348 //@}
349
350 //! Assignement of a default value.
351 void assign(const size_type nx,
352 const size_type ny,
353 const size_type nz,
354 const T& val);
355
356 //@{
357 //! Handle the array dimension.
358
359 inline bool empty() const;
360
361 inline size_type x_size() const;
362 inline size_type width() const;
363 inline size_type y_size() const;
364 inline size_type height() const;
365 inline size_type z_size() const;
366 inline size_type depth() const;
367 inline size_type size() const;
368
369 inline size_type max_size() const;
370
371 inline void resize(const size_type nx,
372 const size_type ny,
373 const size_type nz);
374 //@}
375
376 //! Efficient swapping of two 2D arrays.
377 inline void swap(Array_3D<T,A>& a); /* A reference is used as in the STL. */
378
379 //! Renvoie l'allocateur.
380 inline allocator_type get_allocator() const;
381
382 //@{
383 //! Classical operator.
384
385 inline Array_3D<T,A>& operator=(const Array_3D<T,A>& a);
386 inline bool operator==(const Array_3D<T,A>& a);
387 inline bool operator!=(const Array_3D<T,A>& a);
388 //@}
389
390 //@{
391 //! Access operator.
392
393 template<typename Vector_position>
394 inline reference operator[](const Vector_position& v);
395
396 template<typename Vector_position>
397 inline const_reference operator[](const Vector_position& v) const;
398
399 inline reference operator()(const size_type x,
400 const size_type y,
401 const size_type z);
402
403 inline const_reference operator()(const size_type x,
404 const size_type y,
405 const size_type z) const;
406
407 template<typename Vector_position>
408 inline reference at(const Vector_position& v);
409
410 template<typename Vector_position>
411 inline const_reference at(const Vector_position& v) const;
412
413 inline reference at(const size_type x,
414 const size_type y,
415 const size_type z);
416
417 inline const_reference at(const size_type x,
418 const size_type y,
419 const size_type z) const;
420 //@}
421
422 //@{
423 //! Points on the (0,0,0) element.
424 /*!
425 Goes through the array in the order
426 \code
427 for(x=...){ for(y=...){ for(z=...){...} } }.
428 \endcode
429 */
430
431 inline iterator begin();
432 inline const_iterator begin() const;
433 //@}
434
435 //@{
436 //! Points on the element after (x_size()-1,y_size()-1,z_size()-1).
437 /*!
438 Goes through the array in the order
439 \code
440 for(x=...){ for(y=...){ for(z=...){...} } }.
441 \endcode
442 */
443
444 inline iterator end();
445 inline const_iterator end() const;
446 //@}
447
448 //@{
449 //! Reverse iterator.
450
451 inline reverse_iterator rbegin();
452 inline const_reverse_iterator rbegin() const;
453 inline reverse_iterator rend();
454 inline const_reverse_iterator rend() const;
455 //@}
456
457
458 private:
459 //@{
460 //! Dimension of the array.
461
462 int x_dim,y_dim,z_dim;
463 //@}
464
465 //! Storage structure.
466 Storage storage;
467
468 //@{
469 //! Computation of the position in the storage structure.
470
471 template<typename Vector_position>
472 inline size_type offset(const Vector_position& v) const;
473
474 inline size_type offset(const size_type& x,
475 const size_type& y,
476 const size_type& z) const;
477 //@}
478 };
479
480
481
482
483
484
485
486
487
488 /*
489
490 #############################################
491 #############################################
492 #############################################
493 ###### ######
494 ###### I M P L E M E N T A T I O N ######
495 ###### ######
496 #############################################
497 #############################################
498 #############################################
499
500 */
501
502
503
504
505
506
507
508 /*
509
510 ##################
511 # class Array_2D #
512 ##################
513
514 */
515
516
517
518
519
520 template<typename T,typename A>
Array_2D(const A & a)521 Array_2D<T,A>::Array_2D(const A& a)
522 :x_dim(0),y_dim(0),storage(a){}
523
524
525 template<typename T,typename A>
Array_2D(const size_type nx,const size_type ny,const T & val,const A & a)526 Array_2D<T,A>::Array_2D(const size_type nx,
527 const size_type ny,
528 const T& val,
529 const A& a)
530 :x_dim(nx),y_dim(ny),storage(nx*ny,val,a){}
531
532
533 /*!
534 Fills in the array with the elements between \p begin_elt and
535 \p \e end_elt.
536
537 Throw the length_error() exception if not enough elements.
538 */
539 template<typename T,typename A>
540 template<typename Element_iterator>
Array_2D(Element_iterator begin_elt,Element_iterator end_elt,const size_type nx,const size_type ny,const A & a)541 Array_2D<T,A>::Array_2D(Element_iterator begin_elt,
542 Element_iterator end_elt,
543 const size_type nx,
544 const size_type ny,
545 const A& a)
546 :x_dim(nx),y_dim(ny),storage(a){
547
548 const size_type s = x_dim*y_dim;
549 storage.reserve(s);
550
551 Element_iterator elt;
552 size_type index;
553 for(elt=begin_elt,index=0;(elt!=end_elt)&&(index<s);elt++,index++){
554 storage.push_back(*elt);
555 }
556
557 if (index!=s) {
558 storage.clear();
559 storage.reserve(0);
560 #ifdef ARRAY_EXCEPTION
561 throw std::length_error("Not enough elements to initialize the array");
562 #else
563 std::cerr<<"[Array_2D<T,A>::Array_2D] Not enough elements to initialize the array"<<std::endl;
564 exit(1);
565 #endif
566 }
567 }
568
569
570 template<typename T,typename A>
Array_2D(const Array_2D<T,A> & a)571 Array_2D<T,A>::Array_2D(const Array_2D<T,A>& a)
572 :x_dim(a.x_dim),y_dim(a.y_dim),storage(a.storage){}
573
574
575 template<typename T,typename A>
576 void
assign(const size_type nx,const size_type ny,const T & val)577 Array_2D<T,A>::assign(const size_type nx,
578 const size_type ny,
579 const T& val){
580 x_dim = nx;
581 y_dim = ny;
582 storage.assign(x_dim*y_dim,val);;
583 }
584
585
586 template<typename T,typename A>
587 bool
empty()588 Array_2D<T,A>::empty() const{
589 return storage.empty();
590 }
591
592
593 template<typename T,typename A>
594 typename Array_2D<T,A>::size_type
x_size()595 Array_2D<T,A>::x_size() const{
596 return x_dim;
597 }
598
599 template<typename T,typename A>
600 typename Array_2D<T,A>::size_type
width()601 Array_2D<T,A>::width() const{
602 return x_dim;
603 }
604
605
606 template<typename T,typename A>
607 typename Array_2D<T,A>::size_type
y_size()608 Array_2D<T,A>::y_size() const{
609 return y_dim;
610 }
611
612 template<typename T,typename A>
613 typename Array_2D<T,A>::size_type
height()614 Array_2D<T,A>::height() const{
615 return y_dim;
616 }
617
618
619 template<typename T,typename A>
620 typename Array_2D<T,A>::size_type
size()621 Array_2D<T,A>::size() const{
622 return storage.size();
623 }
624
625
626 template<typename T,typename A>
627 typename Array_2D<T,A>::size_type
max_size()628 Array_2D<T,A>::max_size() const{
629 return storage.max_size();
630 }
631
632
633 template<typename T,typename A>
634 void
resize(const size_type nx,const size_type ny)635 Array_2D<T,A>::resize(const size_type nx,
636 const size_type ny){
637 x_dim = nx;
638 y_dim = ny;
639 storage.resize(x_dim * y_dim);
640 }
641
642
643 template<typename T,typename A>
644 void
swap(Array_2D<T,A> & a)645 Array_2D<T,A>::swap(Array_2D<T,A>& a){
646 size_type x_buf = x_dim;
647 size_type y_buf = y_dim;
648
649 x_dim = a.x_dim;
650 y_dim = a.y_dim;
651
652 a.x_dim = x_buf;
653 a.y_dim = y_buf;
654
655 storage.swap(a.storage);
656 }
657
658
659 template<typename T,typename A>
660 typename Array_2D<T,A>::allocator_type
get_allocator()661 Array_2D<T,A>::get_allocator() const{
662 return storage.get_allocator();
663 }
664
665
666 template<typename T,typename A>
667 Array_2D<T,A>&
668 Array_2D<T,A>::operator=(const Array_2D<T,A>& a){
669
670 if (&a!=this){
671 x_dim = a.x_dim;
672 y_dim = a.y_dim;
673 storage = a.storage;
674 }
675
676 return *this;
677 }
678
679
680 template<typename T,typename A>
681 bool
682 Array_2D<T,A>::operator==(const Array_2D<T,A>& a){
683 return ((x_dim==a.x_dim)&&(y_dim==a.y_dim)&&(storage==a.storage));
684 }
685
686
687 template<typename T,typename A>
688 bool
689 Array_2D<T,A>::operator!=(const Array_2D<T,A>& a){
690 return !(*this==a);
691 }
692
693
694 template<typename T,typename A>
695 template<typename Vector_position>
696 typename Array_2D<T,A>::reference
697 Array_2D<T,A>::operator[](const Vector_position& v){
698 return storage[offset(v)];
699 }
700
701
702 template<typename T,typename A>
703 template<typename Vector_position>
704 typename Array_2D<T,A>::const_reference
705 Array_2D<T,A>::operator[](const Vector_position& v) const{
706 return storage[offset(v)];
707 }
708
709
710 template<typename T,typename A>
711 typename Array_2D<T,A>::reference
operator()712 Array_2D<T,A>::operator()(const size_type x,const size_type y){
713 return storage[offset(x,y)];
714 }
715
716
717 template<typename T,typename A>
718 typename Array_2D<T,A>::const_reference
operator()719 Array_2D<T,A>::operator()(const size_type x,const size_type y) const{
720 return storage[offset(x,y)];
721 }
722
723
724 template<typename T,typename A>
725 template<typename Vector_position>
726 typename Array_2D<T,A>::reference
at(const Vector_position & v)727 Array_2D<T,A>::at(const Vector_position& v){
728
729 if ((v[0]>=x_dim)||(v[1]>=y_dim)){
730 #ifdef ARRAY_EXCEPTION
731 if (v[0]>=x_dim) {
732 throw std::out_of_range("Out of range X");
733 }
734 else{
735 throw std::out_of_range("Out of range Y");
736 }
737 #else
738 std::cerr<<"[Array_2D<T,A>::at] Out of range"<<std::endl;
739 exit(1);
740 #endif
741 }
742
743 return storage[offset(v)];
744 }
745
746
747 template<typename T,typename A>
748 template<typename Vector_position>
749 typename Array_2D<T,A>::const_reference
at(const Vector_position & v)750 Array_2D<T,A>::at(const Vector_position& v) const{
751
752 if ((v[0]>=x_dim)||(v[1]>=y_dim)){
753 #ifdef ARRAY_EXCEPTION
754 if (v[0]>=x_dim) {
755 throw std::out_of_range("Out of range X");
756 }
757 else{
758 throw std::out_of_range("Out of range Y");
759 }
760 #else
761 std::cerr<<"[Array_2D<T,A>::at] Out of range"<<std::endl;
762 exit(1);
763 #endif
764 }
765
766 return storage[offset(v)];
767 }
768
769
770 template<typename T,typename A>
771 typename Array_2D<T,A>::reference
at(const size_type x,const size_type y)772 Array_2D<T,A>::at(const size_type x,const size_type y){
773
774 if ((x>=x_dim)||(y>=y_dim)){
775 #ifdef ARRAY_EXCEPTION
776 if (x>=x_dim) {
777 throw std::out_of_range("Out of range X");
778 }
779 else{
780 throw std::out_of_range("Out of range Y");
781 }
782 #else
783 std::cerr<<"[Array_2D<T,A>::at] Out of range"<<std::endl;
784 exit(1);
785 #endif
786 }
787
788 return storage[offset(x,y)];
789 }
790
791
792 template<typename T,typename A>
793 typename Array_2D<T,A>::const_reference
at(const size_type x,const size_type y)794 Array_2D<T,A>::at(const size_type x,const size_type y) const{
795
796 if ((x>=x_dim)||(y>=y_dim)){
797 #ifdef ARRAY_EXCEPTION
798 if (x>=x_dim) {
799 throw std::out_of_range("Out of range X");
800 }
801 else{
802 throw std::out_of_range("Out of range Y");
803 }
804 #else
805 std::cerr<<"[Array_2D<T,A>::at] Out of range"<<std::endl;
806 exit(1);
807 #endif
808 }
809
810 return storage[offset(x,y)];
811 }
812
813
814 template<typename T,typename A>
815 typename Array_2D<T,A>::iterator
begin()816 Array_2D<T,A>::begin(){
817 return storage.begin();
818 }
819
820
821 template<typename T,typename A>
822 typename Array_2D<T,A>::const_iterator
begin()823 Array_2D<T,A>::begin() const{
824 return storage.begin();
825 }
826
827
828 template<typename T,typename A>
829 typename Array_2D<T,A>::iterator
end()830 Array_2D<T,A>::end(){
831 return storage.end();
832 }
833
834
835 template<typename T,typename A>
836 typename Array_2D<T,A>::const_iterator
end()837 Array_2D<T,A>::end() const{
838 return storage.end();
839 }
840
841
842 template<typename T,typename A>
843 typename Array_2D<T,A>::reverse_iterator
rbegin()844 Array_2D<T,A>::rbegin(){
845 return storage.rbegin();
846 }
847
848
849 template<typename T,typename A>
850 typename Array_2D<T,A>::const_reverse_iterator
rbegin()851 Array_2D<T,A>::rbegin() const{
852 return storage.rbegin();
853 }
854
855
856 template<typename T,typename A>
857 typename Array_2D<T,A>::reverse_iterator
rend()858 Array_2D<T,A>::rend(){
859 return storage.rend();
860 }
861
862
863 template<typename T,typename A>
864 typename Array_2D<T,A>::const_reverse_iterator
rend()865 Array_2D<T,A>::rend() const{
866 return storage.rend();
867 }
868
869
870 template<typename T,typename A>
871 template<typename Vector_position>
872 typename Array_2D<T,A>::size_type
offset(const Vector_position & v)873 Array_2D<T,A>::offset(const Vector_position& v) const{
874
875 #ifdef CHECK_ARRAY_ACCESS
876 if ((v[0] >= x_dim) || (v[1] >= y_dim)){
877 std::cerr<<"Array_2D: Out of range ("<<v[0]<<","<<v[1]<<"), actual size is "<<x_dim<<"x"<<y_dim<<std::endl;
878 }
879 exit(1);
880 #endif
881
882 return v[0]*y_dim + v[1];
883 }
884
885
886 template<typename T,typename A>
887 typename Array_2D<T,A>::size_type
offset(const size_type & x,const size_type & y)888 Array_2D<T,A>::offset(const size_type& x,const size_type& y) const{
889
890 #ifdef CHECK_ARRAY_ACCESS
891 if ((x >= x_dim) || (y >= y_dim)){
892 std::cerr<<"Array_2D: Out of range ("<<x<<","<<y<<"), actual size is "<<x_dim<<"x"<<y_dim<<std::endl;
893 }
894 exit(1);
895 #endif
896
897 return x*y_dim + y;
898 }
899
900
901 //~ #ifndef NO_XML
902
903 //~ template<typename T,typename A>
904 //~ QDomElement Array_2D<T,A>::to_DOM_element(const QString& name,
905 //~ QDomDocument& document) const{
906
907 //~ QDomElement main_element = document.createElement(name);
908 //~ main_element.setAttribute("width",QString::number(width()));
909 //~ main_element.setAttribute("height",QString::number(height()));
910
911 //~ std::ostringstream out;
912
913 //~ for(const_iterator i=begin(),i_end=end();i!=i_end;i++){
914 //~ out<<(*i)<<' ';
915 //~ }
916
917 //~ main_element.appendChild(document.createTextNode(out.str()));
918 //~ return main_element;
919 //~ }
920
921
922 //~ template<typename T,typename A>
923 //~ void Array_2D<T,A>::from_DOM_element(const QDomElement& element){
924
925 //~ QDomElement& elt = const_cast<QDomElement&>(element);
926
927 //~ const size_type width = elt.attributeNode("width").value().toUInt();
928 //~ const size_type height = elt.attributeNode("height").value().toUInt();
929
930 //~ resize(width,height);
931
932 //~ std::istringstream in(elt.text());
933
934 //~ for(iterator i=begin(),i_end=end();i!=i_end;i++){
935 //~ in>>(*i);
936 //~ }
937 //~ }
938
939 //~ #endif
940
941
942
943
944
945
946 /*
947
948 ##################
949 # class Array_3D #
950 ##################
951
952 */
953
954
955
956
957
958
959
960
961
962
963 template<typename T,typename A>
Array_3D(const A &)964 Array_3D<T,A>::Array_3D(const A&)
965 :x_dim(0),y_dim(0),z_dim(0),storage(){}
966
967
968 template<typename T,typename A>
Array_3D(const size_type nx,const size_type ny,const size_type nz,const T & val,const A & a)969 Array_3D<T,A>::Array_3D(const size_type nx,
970 const size_type ny,
971 const size_type nz,
972 const T& val,
973 const A& a)
974 :x_dim(nx),y_dim(ny),z_dim(nz),storage(nx*ny*nz,val,a){}
975
976
977 /*!
978 Fills in the array with the elements between \p begin_elt and
979 \p \e end_elt.
980
981 Throw the length_error() exception if not enough elements.
982 */
983 template<typename T,typename A>
984 template<typename Element_iterator>
Array_3D(Element_iterator begin_elt,Element_iterator end_elt,const size_type nx,const size_type ny,const size_type nz,const A & a)985 Array_3D<T,A>::Array_3D(Element_iterator begin_elt,
986 Element_iterator end_elt,
987 const size_type nx,
988 const size_type ny,
989 const size_type nz,
990 const A& a)
991 :x_dim(nx),y_dim(ny),z_dim(nz),storage(a){
992
993 const size_type s = x_dim*y_dim*z_dim;
994 storage.reserve(s);
995
996 Element_iterator elt;
997 size_type index;
998 for(elt=begin_elt,index=0;(elt!=end_elt)&&(index<s);elt++,index++){
999 storage.push_back(*elt);
1000 }
1001
1002 if (index!=s) {
1003 storage.clear();
1004 storage.reserve(0);
1005 #ifdef ARRAY_EXCEPTION
1006 throw std::length_error("Not enough elements to initialize the array");
1007 #else
1008 std::cerr<<"[Array_3D<T,A>::Array_3D] Not enough elements to initialize the array"<<std::endl;
1009 exit(1);
1010 #endif
1011 }
1012 }
1013
1014
1015 template<typename T,typename A>
Array_3D(const Array_3D<T,A> & a)1016 Array_3D<T,A>::Array_3D(const Array_3D<T,A>& a)
1017 :x_dim(a.x_dim),y_dim(a.y_dim),z_dim(a.z_dim),storage(a.storage){}
1018
1019
1020 template<typename T,typename A>
1021 void
assign(const size_type nx,const size_type ny,const size_type nz,const T & val)1022 Array_3D<T,A>::assign(const size_type nx,
1023 const size_type ny,
1024 const size_type nz,
1025 const T& val){
1026 x_dim = nx;
1027 y_dim = ny;
1028 z_dim = nz;
1029 storage.assign(x_dim*y_dim*z_dim,val);;
1030 }
1031
1032
1033 template<typename T,typename A>
1034 bool
empty()1035 Array_3D<T,A>::empty() const{
1036 return storage.empty();
1037 }
1038
1039
1040 template<typename T,typename A>
1041 typename Array_3D<T,A>::size_type
x_size()1042 Array_3D<T,A>::x_size() const{
1043 return x_dim;
1044 }
1045
1046
1047 template<typename T,typename A>
1048 typename Array_3D<T,A>::size_type
width()1049 Array_3D<T,A>::width() const{
1050 return x_dim;
1051 }
1052
1053
1054 template<typename T,typename A>
1055 typename Array_3D<T,A>::size_type
y_size()1056 Array_3D<T,A>::y_size() const{
1057 return y_dim;
1058 }
1059
1060
1061 template<typename T,typename A>
1062 typename Array_3D<T,A>::size_type
height()1063 Array_3D<T,A>::height() const{
1064 return y_dim;
1065 }
1066
1067
1068 template<typename T,typename A>
1069 typename Array_3D<T,A>::size_type
z_size()1070 Array_3D<T,A>::z_size() const{
1071 return z_dim;
1072 }
1073
1074
1075 template<typename T,typename A>
1076 typename Array_3D<T,A>::size_type
depth()1077 Array_3D<T,A>::depth() const{
1078 return z_dim;
1079 }
1080
1081
1082 template<typename T,typename A>
1083 typename Array_3D<T,A>::size_type
size()1084 Array_3D<T,A>::size() const{
1085 return storage.size();
1086 }
1087
1088
1089 template<typename T,typename A>
1090 typename Array_3D<T,A>::size_type
max_size()1091 Array_3D<T,A>::max_size() const{
1092 return storage.max_size();
1093 }
1094
1095
1096 template<typename T,typename A>
1097 void
resize(const size_type nx,const size_type ny,const size_type nz)1098 Array_3D<T,A>::resize(const size_type nx,
1099 const size_type ny,
1100 const size_type nz){
1101 x_dim = nx;
1102 y_dim = ny;
1103 z_dim = nz;
1104 storage.resize(x_dim * y_dim * z_dim);
1105 }
1106
1107
1108 template<typename T,typename A>
1109 void
swap(Array_3D<T,A> & a)1110 Array_3D<T,A>::swap(Array_3D<T,A>& a){
1111 size_type x_buf = x_dim;
1112 size_type y_buf = y_dim;
1113 size_type z_buf = z_dim;
1114
1115 x_dim = a.x_dim;
1116 y_dim = a.y_dim;
1117 z_dim = a.z_dim;
1118
1119 a.x_dim = x_buf;
1120 a.y_dim = y_buf;
1121 a.z_dim = z_buf;
1122
1123 storage.swap(a.storage);
1124 }
1125
1126
1127 template<typename T,typename A>
1128 typename Array_3D<T,A>::allocator_type
get_allocator()1129 Array_3D<T,A>::get_allocator() const{
1130 return storage.get_allocator();
1131 }
1132
1133
1134 template<typename T,typename A>
1135 Array_3D<T,A>&
1136 Array_3D<T,A>::operator=(const Array_3D<T,A>& a){
1137
1138 if (&a!=this){
1139 x_dim = a.x_dim;
1140 y_dim = a.y_dim;
1141 z_dim = a.z_dim;
1142 storage = a.storage;
1143 }
1144
1145 return *this;
1146 }
1147
1148
1149 template<typename T,typename A>
1150 bool
1151 Array_3D<T,A>::operator==(const Array_3D<T,A>& a){
1152 return ((x_dim==a.x_dim)
1153 &&(y_dim==a.y_dim)
1154 &&(z_dim==a.z_dim)
1155 &&(storage==a.storage));
1156 }
1157
1158
1159 template<typename T,typename A>
1160 bool
1161 Array_3D<T,A>::operator!=(const Array_3D<T,A>& a){
1162 return !(*this==a);
1163 }
1164
1165
1166 template<typename T,typename A>
1167 template<typename Vector_position>
1168 typename Array_3D<T,A>::reference
1169 Array_3D<T,A>::operator[](const Vector_position& v){
1170 return storage[offset(v)];
1171 }
1172
1173
1174 template<typename T,typename A>
1175 template<typename Vector_position>
1176 typename Array_3D<T,A>::const_reference
1177 Array_3D<T,A>::operator[](const Vector_position& v) const{
1178 return storage[offset(v)];
1179 }
1180
1181
1182 template<typename T,typename A>
1183 typename Array_3D<T,A>::reference
operator()1184 Array_3D<T,A>::operator()(const size_type x,
1185 const size_type y,
1186 const size_type z){
1187
1188 return storage[offset(x,y,z)];
1189 }
1190
1191
1192 template<typename T,typename A>
1193 typename Array_3D<T,A>::const_reference
operator()1194 Array_3D<T,A>::operator()(const size_type x,
1195 const size_type y,
1196 const size_type z) const{
1197
1198 return storage[offset(x,y,z)];
1199 }
1200
1201
1202 template<typename T,typename A>
1203 template<typename Vector_position>
1204 typename Array_3D<T,A>::reference
at(const Vector_position & v)1205 Array_3D<T,A>::at(const Vector_position& v){
1206
1207 if ((v[0]>=x_dim)||(v[1]>=y_dim)||(v[2]>=z_dim)){
1208 #ifdef ARRAY_EXCEPTION
1209 if (v[0]>=x_dim) {
1210 throw std::out_of_range("Out of range X");
1211 }
1212 else if (v[1]>=y_dim) {
1213 throw std::out_of_range("Out of range Y");
1214 }
1215 else {
1216 throw std::out_of_range("Out of range Z");
1217 }
1218 #else
1219 std::cerr<<"[Array_3D<T,A>::at] Out of range"<<std::endl;
1220 exit(1);
1221 #endif
1222 }
1223
1224 return storage[offset(v)];
1225 }
1226
1227
1228 template<typename T,typename A>
1229 template<typename Vector_position>
1230 typename Array_3D<T,A>::const_reference
at(const Vector_position & v)1231 Array_3D<T,A>::at(const Vector_position& v) const{
1232
1233 if ((v[0]>=x_dim)||(v[1]>=y_dim)||(v[2]>=z_dim)){
1234 #ifdef ARRAY_EXCEPTION
1235 if (v[0]>=x_dim) {
1236 throw std::out_of_range("Out of range X");
1237 }
1238 else if (v[1]>=y_dim) {
1239 throw std::out_of_range("Out of range Y");
1240 }
1241 else {
1242 throw std::out_of_range("Out of range Z");
1243 }
1244 #else
1245 std::cerr<<"[Array_3D<T,A>::at] Out of range"<<std::endl;
1246 exit(1);
1247 #endif
1248 }
1249
1250 return storage[offset(v)];
1251 }
1252
1253
1254 template<typename T,typename A>
1255 typename Array_3D<T,A>::reference
at(const size_type x,const size_type y,const size_type z)1256 Array_3D<T,A>::at(const size_type x,
1257 const size_type y,
1258 const size_type z){
1259
1260 if ((x>=x_dim)||(y>=y_dim)||(z>=z_dim)){
1261 #ifdef ARRAY_EXCEPTION
1262 if (x>=x_dim) {
1263 throw std::out_of_range("Out of range X");
1264 }
1265 else if (y>=y_dim) {
1266 throw std::out_of_range("Out of range Y");
1267 }
1268 else {
1269 throw std::out_of_range("Out of range Z");
1270 }
1271 #else
1272 std::cerr<<"[Array_3D<T,A>::at] Out of range"<<std::endl;
1273 #endif
1274 }
1275
1276 return storage[offset(x,y,z)];
1277 }
1278
1279
1280 template<typename T,typename A>
1281 typename Array_3D<T,A>::const_reference
at(const size_type x,const size_type y,const size_type z)1282 Array_3D<T,A>::at(const size_type x,
1283 const size_type y,
1284 const size_type z) const{
1285
1286 if ((x>=x_dim)||(y>=y_dim)||(z>=z_dim)){
1287 #ifdef ARRAY_EXCEPTION
1288 if (x>=x_dim) {
1289 throw std::out_of_range("Out of range X");
1290 }
1291 else if (y>=y_dim) {
1292 throw std::out_of_range("Out of range Y");
1293 }
1294 else {
1295 throw std::out_of_range("Out of range Z");
1296 }
1297 #else
1298 std::cerr<<"[Array_3D<T,A>::at] Out of range"<<std::endl;
1299 #endif
1300 }
1301
1302 return storage[offset(x,y,z)];
1303 }
1304
1305
1306 template<typename T,typename A>
1307 typename Array_3D<T,A>::iterator
begin()1308 Array_3D<T,A>::begin(){
1309 return storage.begin();
1310 }
1311
1312
1313 template<typename T,typename A>
1314 typename Array_3D<T,A>::const_iterator
begin()1315 Array_3D<T,A>::begin() const{
1316 return storage.begin();
1317 }
1318
1319
1320 template<typename T,typename A>
1321 typename Array_3D<T,A>::iterator
end()1322 Array_3D<T,A>::end(){
1323 return storage.end();
1324 }
1325
1326
1327 template<typename T,typename A>
1328 typename Array_3D<T,A>::const_iterator
end()1329 Array_3D<T,A>::end() const{
1330 return storage.end();
1331 }
1332
1333
1334 template<typename T,typename A>
1335 typename Array_3D<T,A>::reverse_iterator
rbegin()1336 Array_3D<T,A>::rbegin(){
1337 return storage.rbegin();
1338 }
1339
1340
1341 template<typename T,typename A>
1342 typename Array_3D<T,A>::const_reverse_iterator
rbegin()1343 Array_3D<T,A>::rbegin() const{
1344 return storage.rbegin();
1345 }
1346
1347
1348 template<typename T,typename A>
1349 typename Array_3D<T,A>::reverse_iterator
rend()1350 Array_3D<T,A>::rend(){
1351 return storage.rend();
1352 }
1353
1354
1355 template<typename T,typename A>
1356 typename Array_3D<T,A>::const_reverse_iterator
rend()1357 Array_3D<T,A>::rend() const{
1358 return storage.rend();
1359 }
1360
1361
1362 template<typename T,typename A>
1363 template<typename Vector_position>
1364 typename Array_3D<T,A>::size_type
offset(const Vector_position & v)1365 Array_3D<T,A>::offset(const Vector_position& v) const{
1366
1367 #ifdef CHECK_ARRAY_ACCESS
1368 if ((v[0] >= x_dim) || (v[1] >= y_dim) || (v[2] >= z_dim)){
1369 std::cerr<<"Array_3D: Out of range ("<<v[0]<<","<<v[1]<<","<<v[2]<<"), actual size is "<<x_dim<<"x"<<y_dim<<"x"<<z_dim<<std::endl;
1370 }
1371 #endif
1372
1373 return (v[0]*y_dim + v[1])*z_dim + v[2];
1374 }
1375
1376
1377 template<typename T,typename A>
1378 typename Array_3D<T,A>::size_type
offset(const size_type & x,const size_type & y,const size_type & z)1379 Array_3D<T,A>::offset(const size_type& x,
1380 const size_type& y,
1381 const size_type& z) const{
1382
1383 #ifdef CHECK_ARRAY_ACCESS
1384 if ((x >= x_dim) || (y >= y_dim) || (z >= z_dim)){
1385 std::cerr<<"Array_3D: Out of range ("<<x<<","<<y<<","<<z<<"), actual size is "<<x_dim<<"x"<<y_dim<<"x"<<z_dim<<std::endl;
1386 }
1387 #endif
1388
1389 return (x*y_dim + y)*z_dim + z;
1390 }
1391
1392 #endif
1393