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