Salome HOME
Some useful tools for MEDCouplingMappedExtrudedMesh users that needs to store it...
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingMemArray.txx
1 // Copyright (C) 2007-2016  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (CEA/DEN)
20
21 #ifndef __PARAMEDMEM_MEDCOUPLINGMEMARRAY_TXX__
22 #define __PARAMEDMEM_MEDCOUPLINGMEMARRAY_TXX__
23
24 #include "MEDCouplingMemArray.hxx"
25 #include "NormalizedUnstructuredMesh.hxx"
26 #include "InterpKernelException.hxx"
27 #include "InterpolationUtils.hxx"
28 #include "MCAuto.hxx"
29
30 #include <sstream>
31 #include <cstdlib>
32 #include <algorithm>
33
34 namespace MEDCoupling
35 {
36   template<class T>
37   void MEDCouplingPointer<T>::setInternal(T *pointer)
38   {
39     _internal=pointer;
40     _external=0;
41   }
42
43   template<class T>
44   void MEDCouplingPointer<T>::setExternal(const T *pointer)
45   {
46     _external=pointer;
47     _internal=0;
48   }
49
50   template<class T>
51   MemArray<T>::MemArray(const MemArray<T>& other):_nb_of_elem(0),_nb_of_elem_alloc(0),_ownership(false),_dealloc(0),_param_for_deallocator(0)
52   {
53     if(!other._pointer.isNull())
54       {
55         _nb_of_elem_alloc=other._nb_of_elem;
56         T *pointer=(T*)malloc(_nb_of_elem_alloc*sizeof(T));
57         std::copy(other._pointer.getConstPointer(),other._pointer.getConstPointer()+other._nb_of_elem,pointer);
58         useArray(pointer,true,C_DEALLOC,other._nb_of_elem);
59       }
60   }
61
62   template<class T>
63   void MemArray<T>::useArray(const T *array, bool ownership, DeallocType type, std::size_t nbOfElem)
64   {
65     destroy();
66     _nb_of_elem=nbOfElem;
67     _nb_of_elem_alloc=nbOfElem;
68     if(ownership)
69       _pointer.setInternal(const_cast<T *>(array));
70     else
71       _pointer.setExternal(array);
72     _ownership=ownership;
73     _dealloc=BuildFromType(type);
74   }
75
76   template<class T>
77   void MemArray<T>::useExternalArrayWithRWAccess(const T *array, std::size_t nbOfElem)
78   {
79     destroy();
80     _nb_of_elem=nbOfElem;
81     _nb_of_elem_alloc=nbOfElem;
82     _pointer.setInternal(const_cast<T *>(array));
83     _ownership=false;
84     _dealloc=CPPDeallocator;
85   }
86
87   template<class T>
88   void MemArray<T>::writeOnPlace(std::size_t id, T element0, const T *others, std::size_t sizeOfOthers)
89   {
90     if(id+sizeOfOthers>=_nb_of_elem_alloc)
91       reserve(2*_nb_of_elem+sizeOfOthers+1);
92     T *pointer=_pointer.getPointer();
93     pointer[id]=element0;
94     std::copy(others,others+sizeOfOthers,pointer+id+1);
95     _nb_of_elem=std::max<std::size_t>(_nb_of_elem,id+sizeOfOthers+1);
96   }
97
98   template<class T>
99   template<class InputIterator>
100   void MemArray<T>::insertAtTheEnd(InputIterator first, InputIterator last)
101   {
102     T *pointer=_pointer.getPointer();
103     while(first!=last)
104       {
105         if(_nb_of_elem>=_nb_of_elem_alloc)
106           {
107             reserve(_nb_of_elem_alloc>0?2*_nb_of_elem_alloc:1);
108             pointer=_pointer.getPointer();
109           }
110         pointer[_nb_of_elem++]=*first++;
111       }
112   }
113
114   template<class T>
115   void MemArray<T>::pushBack(T elem)
116   {
117     if(_nb_of_elem>=_nb_of_elem_alloc)
118       reserve(_nb_of_elem_alloc>0?2*_nb_of_elem_alloc:1);
119     T *pt=getPointer();
120     pt[_nb_of_elem++]=elem;
121   }
122
123   template<class T>
124   T MemArray<T>::popBack()
125   {
126     if(_nb_of_elem>0)
127       {
128         const T *pt=getConstPointer();
129         return pt[--_nb_of_elem];
130       }
131     throw INTERP_KERNEL::Exception("MemArray::popBack : nothing to pop in array !");
132   }
133
134   template<class T>
135   void MemArray<T>::pack() const
136   {
137     (const_cast<MemArray<T> * >(this))->reserve(_nb_of_elem);
138   }
139
140   template<class T>
141   bool MemArray<T>::isEqual(const MemArray<T>& other, T prec, std::string& reason) const
142   {
143     std::ostringstream oss; oss.precision(15);
144     if(_nb_of_elem!=other._nb_of_elem)
145       {
146         oss << "Number of elements in coarse data of DataArray mismatch : this=" << _nb_of_elem << " other=" << other._nb_of_elem;
147         reason=oss.str();
148         return false;
149       }
150     const T *pt1=_pointer.getConstPointer();
151     const T *pt2=other._pointer.getConstPointer();
152     if(pt1==0 && pt2==0)
153       return true;
154     if(pt1==0 || pt2==0)
155       {
156         oss << "coarse data pointer is defined for only one DataArray instance !";
157         reason=oss.str();
158         return false;
159       }
160     if(pt1==pt2)
161       return true;
162     for(std::size_t i=0;i<_nb_of_elem;i++)
163       if(pt1[i]-pt2[i]<-prec || (pt1[i]-pt2[i])>prec)
164         {
165           oss << "The content of data differs at pos #" << i << " of coarse data ! this[i]=" << pt1[i] << " other[i]=" << pt2[i];
166           reason=oss.str();
167           return false;
168         }
169     return true;
170   }
171
172   /*!
173    * \param [in] sl is typically the number of components
174    * \return True if a not null pointer is present, False if not.
175    */
176   template<class T>
177   bool MemArray<T>::reprHeader(int sl, std::ostream& stream) const
178   {
179     stream << "Number of tuples : ";
180     if(!_pointer.isNull())
181       {
182         if(sl!=0)
183           stream << _nb_of_elem/sl << std::endl << "Internal memory facts : " << _nb_of_elem << "/" << _nb_of_elem_alloc;
184         else
185           stream << "Empty Data";
186       }
187     else
188       stream << "No data";
189     stream << "\n";
190     stream << "Data content :\n";
191     bool ret=!_pointer.isNull();
192     if(!ret)
193       stream << "No data !\n";
194     return ret;
195   }
196
197   /*!
198    * \param [in] sl is typically the number of components
199    */
200   template<class T>
201   void MemArray<T>::repr(int sl, std::ostream& stream) const
202   {
203     if(reprHeader(sl,stream))
204       {
205         const T *data=getConstPointer();
206         if(_nb_of_elem!=0 && sl!=0)
207           {
208             std::size_t nbOfTuples=_nb_of_elem/std::abs(sl);
209             for(std::size_t i=0;i<nbOfTuples;i++)
210               {
211                 stream << "Tuple #" << i << " : ";
212                 std::copy(data,data+sl,std::ostream_iterator<T>(stream," "));
213                 stream << "\n";
214                 data+=sl;
215               }
216           }
217         else
218           stream << "Empty Data\n";
219       }
220   }
221
222   /*!
223    * \param [in] sl is typically the number of components
224    */
225   template<class T>
226   void MemArray<T>::reprZip(int sl, std::ostream& stream) const
227   {
228     stream << "Number of tuples : ";
229     if(!_pointer.isNull())
230       {
231         if(sl!=0)
232           stream << _nb_of_elem/sl;
233         else
234           stream << "Empty Data";
235       }
236     else
237       stream << "No data";
238     stream << "\n";
239     stream << "Data content : ";
240     const T *data=getConstPointer();
241     if(!_pointer.isNull())
242       {
243         if(_nb_of_elem!=0 && sl!=0)
244           {
245             std::size_t nbOfTuples=_nb_of_elem/std::abs(sl);
246             for(std::size_t i=0;i<nbOfTuples;i++)
247               {
248                 stream << "|";
249                 std::copy(data,data+sl,std::ostream_iterator<T>(stream," "));
250                 stream << "| ";
251                 data+=sl;
252               }
253             stream << "\n";
254           }
255         else
256           stream << "Empty Data\n";
257       }
258     else
259       stream << "No data !\n";
260   }
261
262   /*!
263    * \param [in] sl is typically the number of components
264    */
265   template<class T>
266   void MemArray<T>::reprNotTooLong(int sl, std::ostream& stream) const
267   {
268     if(reprHeader(sl,stream))
269       {
270         const T *data=getConstPointer();
271         if(_nb_of_elem!=0 && sl!=0)
272           {
273             std::size_t nbOfTuples=_nb_of_elem/std::abs(sl);
274             if(nbOfTuples<=1000)
275               {
276                 for(std::size_t i=0;i<nbOfTuples;i++)
277                   {
278                     stream << "Tuple #" << i << " : ";
279                     std::copy(data,data+sl,std::ostream_iterator<T>(stream," "));
280                     stream << "\n";
281                     data+=sl;
282                   }
283               }
284             else
285               {// too much tuples -> print the 3 first tuples and 3 last.
286                 stream << "Tuple #0 : ";
287                 std::copy(data,data+sl,std::ostream_iterator<T>(stream," ")); stream << "\n";
288                 stream << "Tuple #1 : ";
289                 std::copy(data+sl,data+2*sl,std::ostream_iterator<T>(stream," ")); stream << "\n";
290                 stream << "Tuple #2 : ";
291                 std::copy(data+2*sl,data+3*sl,std::ostream_iterator<T>(stream," ")); stream << "\n";
292                 stream << "...\n";
293                 stream << "Tuple #" << nbOfTuples-3 << " : ";
294                 std::copy(data+(nbOfTuples-3)*sl,data+(nbOfTuples-2)*sl,std::ostream_iterator<T>(stream," ")); stream << "\n";
295                 stream << "Tuple #" << nbOfTuples-2 << " : ";
296                 std::copy(data+(nbOfTuples-2)*sl,data+(nbOfTuples-1)*sl,std::ostream_iterator<T>(stream," ")); stream << "\n";
297                 stream << "Tuple #" << nbOfTuples-1 << " : ";
298                 std::copy(data+(nbOfTuples-1)*sl,data+nbOfTuples*sl,std::ostream_iterator<T>(stream," ")); stream << "\n";
299               }
300           }
301         else
302           stream << "Empty Data\n";
303       }
304   }
305
306   template<class T>
307   void MemArray<T>::fillWithValue(const T& val)
308   {
309     T *pt=_pointer.getPointer();
310     std::fill(pt,pt+_nb_of_elem,val);
311   }
312
313   template<class T>
314   T *MemArray<T>::fromNoInterlace(int nbOfComp) const
315   {
316     if(nbOfComp<1)
317       throw INTERP_KERNEL::Exception("MemArray<T>::fromNoInterlace : number of components must be > 0 !");
318     const T *pt=_pointer.getConstPointer();
319     std::size_t nbOfTuples=_nb_of_elem/nbOfComp;
320     T *ret=(T*)malloc(_nb_of_elem*sizeof(T));
321     T *w=ret;
322     for(std::size_t i=0;i<nbOfTuples;i++)
323       for(int j=0;j<nbOfComp;j++,w++)
324         *w=pt[j*nbOfTuples+i];
325     return ret;
326   }
327
328   template<class T>
329   T *MemArray<T>::toNoInterlace(int nbOfComp) const
330   {
331     if(nbOfComp<1)
332       throw INTERP_KERNEL::Exception("MemArray<T>::toNoInterlace : number of components must be > 0 !");
333     const T *pt=_pointer.getConstPointer();
334     std::size_t nbOfTuples=_nb_of_elem/nbOfComp;
335     T *ret=(T*)malloc(_nb_of_elem*sizeof(T));
336     T *w=ret;
337     for(int i=0;i<nbOfComp;i++)
338       for(std::size_t j=0;j<nbOfTuples;j++,w++)
339         *w=pt[j*nbOfComp+i];
340     return ret;
341   }
342
343   template<class T>
344   void MemArray<T>::sort(bool asc)
345   {
346     T *pt=_pointer.getPointer();
347     if(asc)
348       std::sort(pt,pt+_nb_of_elem);
349     else
350       {
351         typename std::reverse_iterator<T *> it1(pt+_nb_of_elem);
352         typename std::reverse_iterator<T *> it2(pt);
353         std::sort(it1,it2);
354       }
355   }
356
357   template<class T>
358   void MemArray<T>::reverse(int nbOfComp)
359   {
360     if(nbOfComp<1)
361       throw INTERP_KERNEL::Exception("MemArray<T>::reverse : only supported with 'this' array with ONE or more than ONE component !");
362     T *pt=_pointer.getPointer();
363     if(nbOfComp==1)
364       {
365         std::reverse(pt,pt+_nb_of_elem);
366         return ;
367       }
368     else
369       {
370         T *pt2=pt+_nb_of_elem-nbOfComp;
371         std::size_t nbOfTuples=_nb_of_elem/nbOfComp;
372         for(std::size_t i=0;i<nbOfTuples/2;i++,pt+=nbOfComp,pt2-=nbOfComp)
373           {
374             for(int j=0;j<nbOfComp;j++)
375               std::swap(pt[j],pt2[j]);
376           }
377       }
378   }
379
380   template<class T>
381   void MemArray<T>::alloc(std::size_t nbOfElements)
382   {
383     destroy();
384     _nb_of_elem=nbOfElements;
385     _nb_of_elem_alloc=nbOfElements;
386     _pointer.setInternal((T*)malloc(_nb_of_elem_alloc*sizeof(T)));
387     _ownership=true;
388     _dealloc=CDeallocator;
389   }
390
391   /*!
392    * This method performs systematically an allocation of \a newNbOfElements elements in \a this.
393    * \a _nb_of_elem and \a _nb_of_elem_alloc will \b NOT be systematically equal (contrary to MemArray<T>::reAlloc method.
394    * So after the call of this method \a _nb_of_elem will be equal tostd::min<std::size_t>(_nb_of_elem,newNbOfElements) and \a _nb_of_elem_alloc equal to 
395    * \a newNbOfElements. This method is typically used to perform a pushBack to avoid systematic allocations-copy-deallocation.
396    * So after the call of this method the accessible content is perfectly set.
397    * 
398    * So this method should not be confused with MemArray<T>::reserve that is close to MemArray<T>::reAlloc but not same.
399    */
400   template<class T>
401   void MemArray<T>::reserve(std::size_t newNbOfElements)
402   {
403     if(_nb_of_elem_alloc==newNbOfElements)
404       return ;
405     T *pointer=(T*)malloc(newNbOfElements*sizeof(T));
406     std::copy(_pointer.getConstPointer(),_pointer.getConstPointer()+std::min<std::size_t>(_nb_of_elem,newNbOfElements),pointer);
407     if(_ownership)
408       DestroyPointer(const_cast<T *>(_pointer.getConstPointer()),_dealloc,_param_for_deallocator);//Do not use getPointer because in case of _external
409     _pointer.setInternal(pointer);
410     _nb_of_elem=std::min<std::size_t>(_nb_of_elem,newNbOfElements);
411     _nb_of_elem_alloc=newNbOfElements;
412     _ownership=true;
413     _dealloc=CDeallocator;
414     _param_for_deallocator=0;
415   }
416
417   /*!
418    * This method performs systematically an allocation of \a newNbOfElements elements in \a this.
419    * \a _nb_of_elem and \a _nb_of_elem_alloc will be equal even if only std::min<std::size_t>(_nb_of_elem,newNbOfElements) come from the .
420    * The remaing part of the new allocated chunk are available but not set previouly !
421    * 
422    * So this method should not be confused with MemArray<T>::reserve that is close to MemArray<T>::reAlloc but not same.
423    */
424   template<class T>
425   void MemArray<T>::reAlloc(std::size_t newNbOfElements)
426   {
427     if(_nb_of_elem==newNbOfElements)
428       return ;
429     T *pointer=(T*)malloc(newNbOfElements*sizeof(T));
430     std::copy(_pointer.getConstPointer(),_pointer.getConstPointer()+std::min<std::size_t>(_nb_of_elem,newNbOfElements),pointer);
431     if(_ownership)
432       DestroyPointer(const_cast<T *>(_pointer.getConstPointer()),_dealloc,_param_for_deallocator);//Do not use getPointer because in case of _external
433     _pointer.setInternal(pointer);
434     _nb_of_elem=newNbOfElements;
435     _nb_of_elem_alloc=newNbOfElements;
436     _ownership=true;
437     _dealloc=CDeallocator;
438     _param_for_deallocator=0;
439   }
440
441   template<class T>
442   void MemArray<T>::CPPDeallocator(void *pt, void *param)
443   {
444     delete [] reinterpret_cast<T*>(pt);
445   }
446
447   template<class T>
448   void MemArray<T>::CDeallocator(void *pt, void *param)
449   {
450     free(pt);
451   }
452
453   template<class T>
454   typename MemArray<T>::Deallocator MemArray<T>::BuildFromType(DeallocType type)
455   {
456     switch(type)
457     {
458       case CPP_DEALLOC:
459         return CPPDeallocator;
460       case C_DEALLOC:
461         return CDeallocator;
462       default:
463         throw INTERP_KERNEL::Exception("Invalid deallocation requested ! Unrecognized enum DeallocType !");
464     }
465   }
466
467   template<class T>
468   void MemArray<T>::DestroyPointer(T *pt, typename MemArray<T>::Deallocator dealloc, void *param)
469   {
470     if(dealloc)
471       dealloc(pt,param);
472   }
473
474   template<class T>
475   void MemArray<T>::destroy()
476   {
477     if(_ownership)
478       DestroyPointer(const_cast<T *>(_pointer.getConstPointer()),_dealloc,_param_for_deallocator);//Do not use getPointer because in case of _external
479     _pointer.null();
480     _ownership=false;
481     _dealloc=NULL;
482     _param_for_deallocator=NULL;
483     _nb_of_elem=0;
484     _nb_of_elem_alloc=0;
485   }
486
487   template<class T>
488   MemArray<T> &MemArray<T>::operator=(const MemArray<T>& other)
489   {
490     alloc(other._nb_of_elem);
491     std::copy(other._pointer.getConstPointer(),other._pointer.getConstPointer()+_nb_of_elem,_pointer.getPointer());
492     return *this;
493   }
494
495   //////////////////////////////////
496   
497   template<class T>
498   std::size_t DataArrayTemplate<T>::getHeapMemorySizeWithoutChildren() const
499   {
500     std::size_t sz(_mem.getNbOfElemAllocated());
501     sz*=sizeof(T);
502     return DataArray::getHeapMemorySizeWithoutChildren()+sz;
503   }
504   
505   /*!
506    * Allocates the raw data in memory. If the memory was already allocated, then it is
507    * freed and re-allocated. See an example of this method use
508    * \ref MEDCouplingArraySteps1WC "here".
509    *  \param [in] nbOfTuple - number of tuples of data to allocate.
510    *  \param [in] nbOfCompo - number of components of data to allocate.
511    *  \throw If \a nbOfTuple < 0 or \a nbOfCompo < 0.
512    */
513   template<class T>
514   void DataArrayTemplate<T>::alloc(int nbOfTuple, int nbOfCompo)
515   {
516     if(nbOfTuple<0 || nbOfCompo<0)
517       {
518         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::alloc : request for negative length of data !";
519         throw INTERP_KERNEL::Exception(oss.str().c_str());
520       }
521     _info_on_compo.resize(nbOfCompo);
522     _mem.alloc(nbOfCompo*(std::size_t)nbOfTuple);
523     declareAsNew();
524   }
525
526   /*!
527    * Sets a C array to be used as raw data of \a this. The previously set info
528    *  of components is retained and re-sized. 
529    * For more info see \ref MEDCouplingArraySteps1.
530    *  \param [in] array - the C array to be used as raw data of \a this.
531    *  \param [in] ownership - if \a true, \a array will be deallocated at destruction of \a this.
532    *  \param [in] type - specifies how to deallocate \a array. If \a type == MEDCoupling::CPP_DEALLOC,
533    *                     \c delete [] \c array; will be called. If \a type == MEDCoupling::C_DEALLOC,
534    *                     \c free(\c array ) will be called.
535    *  \param [in] nbOfTuple - new number of tuples in \a this.
536    *  \param [in] nbOfCompo - new number of components in \a this.
537    */
538   template<class T>
539   void DataArrayTemplate<T>::useArray(const T *array, bool ownership, DeallocType type, int nbOfTuple, int nbOfCompo)
540   {
541     _info_on_compo.resize(nbOfCompo);
542     _mem.useArray(array,ownership,type,(std::size_t)nbOfTuple*nbOfCompo);
543     declareAsNew();
544   }
545   
546   template<class T>
547   void DataArrayTemplate<T>::useExternalArrayWithRWAccess(const T *array, int nbOfTuple, int nbOfCompo)
548   {
549     _info_on_compo.resize(nbOfCompo);
550     _mem.useExternalArrayWithRWAccess(array,(std::size_t)nbOfTuple*nbOfCompo);
551     declareAsNew();
552   }
553
554   /*!
555    * Returns a value located at specified tuple and component.
556    * This method is equivalent to DataArrayTemplate<T>::getIJ() except that validity of
557    * parameters is checked. So this method is safe but expensive if used to go through
558    * all values of \a this.
559    *  \param [in] tupleId - index of tuple of interest.
560    *  \param [in] compoId - index of component of interest.
561    *  \return double - value located by \a tupleId and \a compoId.
562    *  \throw If \a this is not allocated.
563    *  \throw If condition <em>( 0 <= tupleId < this->getNumberOfTuples() )</em> is violated.
564    *  \throw If condition <em>( 0 <= compoId < this->getNumberOfComponents() )</em> is violated.
565    */
566   template<class T>
567   T DataArrayTemplate<T>::getIJSafe(int tupleId, int compoId) const
568   {
569     checkAllocated();
570     if(tupleId<0 || tupleId>=getNumberOfTuples())
571       {
572         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::getIJSafe : request for tupleId " << tupleId << " should be in [0," << getNumberOfTuples() << ") !";
573         throw INTERP_KERNEL::Exception(oss.str().c_str());
574       }
575     if(compoId<0 || compoId>=getNumberOfComponents())
576       {
577         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::getIJSafe : request for compoId " << compoId << " should be in [0," << getNumberOfComponents() << ") !";
578         throw INTERP_KERNEL::Exception(oss.str().c_str());
579       }
580     return _mem[tupleId*_info_on_compo.size()+compoId];
581   }
582
583   /*!
584    * This method \b do \b not modify content of \a this. It only modify its memory footprint if the allocated memory is to high regarding real data to store.
585    *
586    * \sa DataArray::getHeapMemorySizeWithoutChildren, DataArrayTemplate<T>::reserve
587    */
588   template<class T>
589   void DataArrayTemplate<T>::pack() const
590   {
591     _mem.pack();
592   }
593
594   /*!
595    * Checks if raw data is allocated. Read more on the raw data
596    * in \ref MEDCouplingArrayBasicsTuplesAndCompo "DataArrays infos" for more information.
597    *  \return bool - \a true if the raw data is allocated, \a false else.
598    */
599   template<class T>
600   bool DataArrayTemplate<T>::isAllocated() const
601   {
602     return getConstPointer()!=0;
603   }
604   
605   /*!
606    * Checks if raw data is allocated and throws an exception if it is not the case.
607    *  \throw If the raw data is not allocated.
608    */
609   template<class T>
610   void DataArrayTemplate<T>::checkAllocated() const
611   {
612     if(!isAllocated())
613       {
614         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::checkAllocated : Array is defined but not allocated ! Call alloc or setValues method first !";
615         throw INTERP_KERNEL::Exception(oss.str().c_str());
616       }
617   }
618   
619   /*!
620    * This method desallocated \a this without modification of informations relative to the components.
621    * After call of this method, DataArrayDouble::isAllocated will return false.
622    * If \a this is already not allocated, \a this is let unchanged.
623    */
624   template<class T>
625   void DataArrayTemplate<T>::desallocate()
626   {
627     _mem.destroy();
628   }
629
630   /*!
631    * This method reserve nbOfElems elements in memory ( nbOfElems*8 bytes ) \b without impacting the number of tuples in \a this.
632    * If \a this has already been allocated, this method checks that \a this has only one component. If not an INTERP_KERNEL::Exception will be thrown.
633    * If \a this has not already been allocated, number of components is set to one.
634    * This method allows to reduce number of reallocations on invokation of DataArrayDouble::pushBackSilent and DataArrayDouble::pushBackValsSilent on \a this.
635    * 
636    * \sa DataArrayDouble::pack, DataArrayDouble::pushBackSilent, DataArrayDouble::pushBackValsSilent
637    */
638   template<class T>
639   void DataArrayTemplate<T>::reserve(std::size_t nbOfElems)
640   {
641     int nbCompo(getNumberOfComponents());
642     if(nbCompo==1)
643       {
644         _mem.reserve(nbOfElems);
645       }
646     else if(nbCompo==0)
647       {
648         _mem.reserve(nbOfElems);
649         _info_on_compo.resize(1);
650       }
651     else
652       {
653         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::reserve : not available for DataArrayDouble with number of components different than 1 !";
654         throw INTERP_KERNEL::Exception(oss.str().c_str());
655       }
656   }
657   
658   /*!
659    * This method adds at the end of \a this the single value \a val. This method do \b not update its time label to avoid useless incrementation
660    * of counter. So the caller is expected to call TimeLabel::declareAsNew on \a this at the end of the push session.
661    *
662    * \param [in] val the value to be added in \a this
663    * \throw If \a this has already been allocated with number of components different from one.
664    * \sa DataArrayDouble::pushBackValsSilent
665    */
666   template<class T>
667   void DataArrayTemplate<T>::pushBackSilent(T val)
668   {
669     int nbCompo(getNumberOfComponents());
670     if(nbCompo==1)
671       _mem.pushBack(val);
672     else if(nbCompo==0)
673       {
674         _info_on_compo.resize(1);
675         _mem.pushBack(val);
676       }
677     else
678       {
679         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::pushBackSilent : not available for DataArrayDouble with number of components different than 1 !";
680         throw INTERP_KERNEL::Exception(oss.str().c_str());
681       }
682   }
683   
684   /*!
685    * This method adds at the end of \a this a serie of values [\c valsBg,\c valsEnd). This method do \b not update its time label to avoid useless incrementation
686    * of counter. So the caller is expected to call TimeLabel::declareAsNew on \a this at the end of the push session.
687    *
688    *  \param [in] valsBg - an array of values to push at the end of \c this.
689    *  \param [in] valsEnd - specifies the end of the array \a valsBg, so that
690    *              the last value of \a valsBg is \a valsEnd[ -1 ].
691    * \throw If \a this has already been allocated with number of components different from one.
692    * \sa DataArrayDouble::pushBackSilent
693    */
694   template<class T>
695   void DataArrayTemplate<T>::pushBackValsSilent(const T *valsBg, const T *valsEnd)
696   {
697     int nbCompo(getNumberOfComponents());
698     if(nbCompo==1)
699       _mem.insertAtTheEnd(valsBg,valsEnd);
700     else if(nbCompo==0)
701       {
702         _info_on_compo.resize(1);
703         _mem.insertAtTheEnd(valsBg,valsEnd);
704       }
705     else
706       {
707         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::pushBackValsSilent : not available for DataArrayDouble with number of components different than 1 !";
708         throw INTERP_KERNEL::Exception(oss.str().c_str());
709       }
710   }
711   
712   /*!
713    * This method returns silently ( without updating time label in \a this ) the last value, if any and suppress it.
714    * \throw If \a this is already empty.
715    * \throw If \a this has number of components different from one.
716    */
717   template<class T>
718   T DataArrayTemplate<T>::popBackSilent()
719   {
720     if(getNumberOfComponents()==1)
721       return _mem.popBack();
722     else
723       {
724         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::popBackSilent : not available for DataArrayDouble with number of components different than 1 !";
725         throw INTERP_KERNEL::Exception(oss.str().c_str());
726       }
727   }
728   
729   /*!
730    * Allocates the raw data in memory. If exactly same memory as needed already
731    * allocated, it is not re-allocated.
732    *  \param [in] nbOfTuple - number of tuples of data to allocate.
733    *  \param [in] nbOfCompo - number of components of data to allocate.
734    *  \throw If \a nbOfTuple < 0 or \a nbOfCompo < 0.
735    */
736   template<class T>
737   void DataArrayTemplate<T>::allocIfNecessary(int nbOfTuple, int nbOfCompo)
738   {
739     if(isAllocated())
740       {
741         if(nbOfTuple!=getNumberOfTuples() || nbOfCompo!=getNumberOfComponents())
742           alloc(nbOfTuple,nbOfCompo);
743       }
744     else
745       alloc(nbOfTuple,nbOfCompo);
746   }
747
748   /*!
749    * Checks the number of tuples.
750    *  \return bool - \a true if getNumberOfTuples() == 0, \a false else.
751    *  \throw If \a this is not allocated.
752    */
753   template<class T>
754   bool DataArrayTemplate<T>::empty() const
755   {
756     checkAllocated();
757     return getNumberOfTuples()==0;
758   }
759
760   /*!
761    * Copies all the data from another DataArrayDouble. For more info see
762    * \ref MEDCouplingArrayBasicsCopyDeepAssign.
763    *  \param [in] other - another instance of DataArrayDouble to copy data from.
764    *  \throw If the \a other is not allocated.
765    */
766   template<class T>
767   void DataArrayTemplate<T>::deepCopyFrom(const DataArrayTemplate<T>& other)
768   {
769     other.checkAllocated();
770     int nbOfTuples(other.getNumberOfTuples()),nbOfComp(other.getNumberOfComponents());
771     allocIfNecessary(nbOfTuples,nbOfComp);
772     std::size_t nbOfElems((std::size_t)nbOfTuples*nbOfComp);
773     T *pt(getPointer());
774     const T *ptI(other.begin());
775     for(std::size_t i=0;i<nbOfElems;i++)
776       pt[i]=ptI[i];
777     copyStringInfoFrom(other);
778   }
779
780   /*!
781    * Reverse the array values.
782    *  \throw If \a this->getNumberOfComponents() < 1.
783    *  \throw If \a this is not allocated.
784    */
785   template<class T>
786   void DataArrayTemplate<T>::reverse()
787   {
788     checkAllocated();
789     _mem.reverse(getNumberOfComponents());
790     declareAsNew();
791   }
792
793   /*!
794    * Assign \a val to all values in \a this array. To know more on filling arrays see
795    * \ref MEDCouplingArrayFill.
796    *  \param [in] val - the value to fill with.
797    *  \throw If \a this is not allocated.
798    */
799   template<class T>
800   void DataArrayTemplate<T>::fillWithValue(T val)
801   {
802     checkAllocated();
803     _mem.fillWithValue(val);
804     declareAsNew();
805   }
806
807   /*!
808    * Changes number of tuples in the array. If the new number of tuples is smaller
809    * than the current number the array is truncated, otherwise the array is extended.
810    *  \param [in] nbOfTuples - new number of tuples. 
811    *  \throw If \a this is not allocated.
812    *  \throw If \a nbOfTuples is negative.
813    */
814   template<class T>
815   void DataArrayTemplate<T>::reAlloc(int nbOfTuples)
816   {
817     if(nbOfTuples<0)
818       {
819         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::reAlloc : input new number of tuples should be >=0 !";
820         throw INTERP_KERNEL::Exception(oss.str().c_str());
821       }
822     checkAllocated();
823     _mem.reAlloc(getNumberOfComponents()*(std::size_t)nbOfTuples);
824     declareAsNew();
825   }
826
827   /*!
828    * Permutes values of \a this array as required by \a old2New array. The values are
829    * permuted so that \c new[ \a old2New[ i ]] = \c old[ i ]. Number of tuples remains
830    * the same as in \c this one.
831    * If a permutation reduction is needed, subArray() or selectByTupleId() should be used.
832    * For more info on renumbering see \ref numbering.
833    *  \param [in] old2New - C array of length equal to \a this->getNumberOfTuples()
834    *     giving a new position for i-th old value.
835    */
836   template<class T>
837   void DataArrayTemplate<T>::renumberInPlace(const int *old2New)
838   {
839     checkAllocated();
840     int nbTuples(getNumberOfTuples()),nbOfCompo(getNumberOfComponents());
841     T *tmp(new T[nbTuples*nbOfCompo]);
842     const T *iptr(begin());
843     for(int i=0;i<nbTuples;i++)
844       {
845         int v=old2New[i];
846         if(v>=0 && v<nbTuples)
847           std::copy(iptr+nbOfCompo*i,iptr+nbOfCompo*(i+1),tmp+nbOfCompo*v);
848         else
849           {
850             std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::renumberInPlace : At place #" << i << " value is " << v << " ! Should be in [0," << nbTuples << ") !";
851             throw INTERP_KERNEL::Exception(oss.str().c_str());
852           }
853       }
854     std::copy(tmp,tmp+nbTuples*nbOfCompo,getPointer());
855     delete [] tmp;
856     declareAsNew();
857   }
858
859
860   /*!
861    * Permutes values of \a this array as required by \a new2Old array. The values are
862    * permuted so that \c new[ i ] = \c old[ \a new2Old[ i ]]. Number of tuples remains
863    * the same as in \c this one.
864    * For more info on renumbering see \ref numbering.
865    *  \param [in] new2Old - C array of length equal to \a this->getNumberOfTuples()
866    *     giving a previous position of i-th new value.
867    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
868    *          is to delete using decrRef() as it is no more needed.
869    */
870   template<class T>
871   void DataArrayTemplate<T>::renumberInPlaceR(const int *new2Old)
872   {
873     checkAllocated();
874     int nbTuples(getNumberOfTuples()),nbOfCompo(getNumberOfComponents());
875     T *tmp(new T[nbTuples*nbOfCompo]);
876     const T *iptr(begin());
877     for(int i=0;i<nbTuples;i++)
878       {
879         int v=new2Old[i];
880         if(v>=0 && v<nbTuples)
881           std::copy(iptr+nbOfCompo*v,iptr+nbOfCompo*(v+1),tmp+nbOfCompo*i);
882         else
883           {
884             std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::renumberInPlaceR : At place #" << i << " value is " << v << " ! Should be in [0," << nbTuples << ") !";
885             throw INTERP_KERNEL::Exception(oss.str().c_str());
886           }
887       }
888     std::copy(tmp,tmp+nbTuples*nbOfCompo,getPointer());
889     delete [] tmp;
890     declareAsNew();
891   }
892
893   /*!
894    * Sorts values of the array.
895    *  \param [in] asc - \a true means ascending order, \a false, descending.
896    *  \throw If \a this is not allocated.
897    *  \throw If \a this->getNumberOfComponents() != 1.
898    */
899   template<class T>
900   void DataArrayTemplate<T>::sort(bool asc)
901   {
902     checkAllocated();
903     if(getNumberOfComponents()!=1)
904       {
905         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::sort : only supported with 'this' array with ONE component !";
906         throw INTERP_KERNEL::Exception(oss.str().c_str());
907       }
908     _mem.sort(asc);
909     declareAsNew();
910   }
911
912   /*!
913    * Returns a copy of \a this array with values permuted as required by \a old2New array.
914    * The values are permuted so that  \c new[ \a old2New[ i ]] = \c old[ i ].
915    * Number of tuples in the result array remains the same as in \c this one.
916    * If a permutation reduction is needed, renumberAndReduce() should be used.
917    * For more info on renumbering see \ref numbering.
918    *  \param [in] old2New - C array of length equal to \a this->getNumberOfTuples()
919    *          giving a new position for i-th old value.
920    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
921    *          is to delete using decrRef() as it is no more needed.
922    *  \throw If \a this is not allocated.
923    */
924   template<class T>
925   typename Traits<T>::ArrayType *DataArrayTemplate<T>::renumber(const int *old2New) const
926   {
927     checkAllocated();
928     int nbTuples(getNumberOfTuples()),nbOfCompo(getNumberOfComponents());
929     MCAuto<DataArray> ret0(buildNewEmptyInstance());
930     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
931     ret->alloc(nbTuples,nbOfCompo);
932     ret->copyStringInfoFrom(*this);
933     const T *iptr(begin());
934     T *optr(ret->getPointer());
935     for(int i=0;i<nbTuples;i++)
936       std::copy(iptr+nbOfCompo*i,iptr+nbOfCompo*(i+1),optr+nbOfCompo*old2New[i]);
937     ret->copyStringInfoFrom(*this);
938     return ret.retn();
939   }
940
941   /*!
942    * Returns a copy of \a this array with values permuted as required by \a new2Old array.
943    * The values are permuted so that  \c new[ i ] = \c old[ \a new2Old[ i ]]. Number of
944    * tuples in the result array remains the same as in \c this one.
945    * If a permutation reduction is needed, subArray() or selectByTupleId() should be used.
946    * For more info on renumbering see \ref numbering.
947    *  \param [in] new2Old - C array of length equal to \a this->getNumberOfTuples()
948    *     giving a previous position of i-th new value.
949    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
950    *          is to delete using decrRef() as it is no more needed.
951    */
952   template<class T>
953   typename Traits<T>::ArrayType *DataArrayTemplate<T>::renumberR(const int *new2Old) const
954   {
955     checkAllocated();
956     int nbTuples(getNumberOfTuples()),nbOfCompo(getNumberOfComponents());
957     MCAuto<DataArray> ret0(buildNewEmptyInstance());
958     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
959     ret->alloc(nbTuples,nbOfCompo);
960     ret->copyStringInfoFrom(*this);
961     const T *iptr(getConstPointer());
962     T *optr(ret->getPointer());
963     for(int i=0;i<nbTuples;i++)
964       std::copy(iptr+nbOfCompo*new2Old[i],iptr+nbOfCompo*(new2Old[i]+1),optr+i*nbOfCompo);
965     ret->copyStringInfoFrom(*this);
966     return ret.retn();
967   }
968
969   /*!
970    * Returns a shorten and permuted copy of \a this array. The new DataArrayDouble is
971    * of size \a newNbOfTuple and it's values are permuted as required by \a old2New array.
972    * The values are permuted so that  \c new[ \a old2New[ i ]] = \c old[ i ] for all
973    * \a old2New[ i ] >= 0. In other words every i-th tuple in \a this array, for which 
974    * \a old2New[ i ] is negative, is missing from the result array.
975    * For more info on renumbering see \ref numbering.
976    *  \param [in] old2New - C array of length equal to \a this->getNumberOfTuples()
977    *     giving a new position for i-th old tuple and giving negative position for
978    *     for i-th old tuple that should be omitted.
979    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
980    *          is to delete using decrRef() as it is no more needed.
981    */
982   template<class T>
983   typename Traits<T>::ArrayType *DataArrayTemplate<T>::renumberAndReduce(const int *old2New, int newNbOfTuple) const
984   {
985     checkAllocated();
986     int nbTuples(getNumberOfTuples()),nbOfCompo(getNumberOfComponents());
987     MCAuto<DataArray> ret0(buildNewEmptyInstance());
988     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
989     ret->alloc(newNbOfTuple,nbOfCompo);
990     const T *iptr=getConstPointer();
991     T *optr=ret->getPointer();
992     for(int i=0;i<nbTuples;i++)
993       {
994         int w=old2New[i];
995         if(w>=0)
996           std::copy(iptr+i*nbOfCompo,iptr+(i+1)*nbOfCompo,optr+w*nbOfCompo);
997       }
998     ret->copyStringInfoFrom(*this);
999     return ret.retn();
1000   }
1001
1002   /*!
1003    * Returns a shorten and permuted copy of \a this array. The new DataArrayDouble is
1004    * of size \a new2OldEnd - \a new2OldBg and it's values are permuted as required by
1005    * \a new2OldBg array.
1006    * The values are permuted so that  \c new[ i ] = \c old[ \a new2OldBg[ i ]].
1007    * This method is equivalent to renumberAndReduce() except that convention in input is
1008    * \c new2old and \b not \c old2new.
1009    * For more info on renumbering see \ref numbering.
1010    *  \param [in] new2OldBg - pointer to the beginning of a permutation array that gives a
1011    *              tuple index in \a this array to fill the i-th tuple in the new array.
1012    *  \param [in] new2OldEnd - specifies the end of the permutation array that starts at
1013    *              \a new2OldBg, so that pointer to a tuple index (\a pi) varies as this:
1014    *              \a new2OldBg <= \a pi < \a new2OldEnd.
1015    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1016    *          is to delete using decrRef() as it is no more needed.
1017    */
1018   template<class T>
1019   typename Traits<T>::ArrayType *DataArrayTemplate<T>::mySelectByTupleId(const int *new2OldBg, const int *new2OldEnd) const
1020   {
1021     checkAllocated();
1022     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1023     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1024     int nbComp(getNumberOfComponents());
1025     ret->alloc((int)std::distance(new2OldBg,new2OldEnd),nbComp);
1026     ret->copyStringInfoFrom(*this);
1027     T *pt(ret->getPointer());
1028     const T *srcPt(getConstPointer());
1029     int i(0);
1030     for(const int *w=new2OldBg;w!=new2OldEnd;w++,i++)
1031       std::copy(srcPt+(*w)*nbComp,srcPt+((*w)+1)*nbComp,pt+i*nbComp);
1032     ret->copyStringInfoFrom(*this);
1033     return ret.retn();
1034   }
1035
1036   template<class T>
1037   typename Traits<T>::ArrayType *DataArrayTemplate<T>::mySelectByTupleId(const DataArrayInt& di) const
1038   {
1039     return DataArrayTemplate<T>::mySelectByTupleId(di.begin(),di.end());
1040   }
1041   
1042   /*!
1043    * Returns a shorten and permuted copy of \a this array. The new DataArrayDouble is
1044    * of size \a new2OldEnd - \a new2OldBg and it's values are permuted as required by
1045    * \a new2OldBg array.
1046    * The values are permuted so that  \c new[ i ] = \c old[ \a new2OldBg[ i ]].
1047    * This method is equivalent to renumberAndReduce() except that convention in input is
1048    * \c new2old and \b not \c old2new.
1049    * This method is equivalent to selectByTupleId() except that it prevents coping data
1050    * from behind the end of \a this array.
1051    * For more info on renumbering see \ref numbering.
1052    *  \param [in] new2OldBg - pointer to the beginning of a permutation array that gives a
1053    *              tuple index in \a this array to fill the i-th tuple in the new array.
1054    *  \param [in] new2OldEnd - specifies the end of the permutation array that starts at
1055    *              \a new2OldBg, so that pointer to a tuple index (\a pi) varies as this:
1056    *              \a new2OldBg <= \a pi < \a new2OldEnd.
1057    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1058    *          is to delete using decrRef() as it is no more needed.
1059    *  \throw If \a new2OldEnd - \a new2OldBg > \a this->getNumberOfTuples().
1060    */
1061   template<class T>
1062   typename Traits<T>::ArrayType *DataArrayTemplate<T>::mySelectByTupleIdSafe(const int *new2OldBg, const int *new2OldEnd) const
1063   {
1064     checkAllocated();
1065     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1066     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1067     int nbComp(getNumberOfComponents()),oldNbOfTuples(getNumberOfTuples());
1068     ret->alloc((int)std::distance(new2OldBg,new2OldEnd),nbComp);
1069     ret->copyStringInfoFrom(*this);
1070     T *pt(ret->getPointer());
1071     const T *srcPt(getConstPointer());
1072     int i(0);
1073     for(const int *w=new2OldBg;w!=new2OldEnd;w++,i++)
1074       if(*w>=0 && *w<oldNbOfTuples)
1075         std::copy(srcPt+(*w)*nbComp,srcPt+((*w)+1)*nbComp,pt+i*nbComp);
1076       else
1077         {
1078           std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::selectByTupleIdSafe : some ids has been detected to be out of [0,this->getNumberOfTuples) !";
1079           throw INTERP_KERNEL::Exception(oss.str().c_str());
1080         }
1081     ret->copyStringInfoFrom(*this);
1082     return ret.retn();
1083   }
1084
1085   /*!
1086    * Changes the number of components within \a this array so that its raw data **does
1087    * not** change, instead splitting this data into tuples changes.
1088    *  \warning This method erases all (name and unit) component info set before!
1089    *  \param [in] newNbOfComp - number of components for \a this array to have.
1090    *  \throw If \a this is not allocated
1091    *  \throw If getNbOfElems() % \a newNbOfCompo != 0.
1092    *  \throw If \a newNbOfCompo is lower than 1.
1093    *  \throw If the rearrange method would lead to a number of tuples higher than 2147483647 (maximal capacity of int32 !).
1094    *  \warning This method erases all (name and unit) component info set before!
1095    */
1096   template<class T>
1097   void DataArrayTemplate<T>::rearrange(int newNbOfCompo)
1098   {
1099     checkAllocated();
1100     if(newNbOfCompo<1)
1101       {
1102         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::rearrange : input newNbOfCompo must be > 0 !";
1103         throw INTERP_KERNEL::Exception(oss.str().c_str());
1104       }
1105     std::size_t nbOfElems=getNbOfElems();
1106     if(nbOfElems%newNbOfCompo!=0)
1107       {
1108         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::rearrange : nbOfElems%newNbOfCompo!=0 !";
1109         throw INTERP_KERNEL::Exception(oss.str().c_str());
1110       }
1111     if(nbOfElems/newNbOfCompo>(std::size_t)std::numeric_limits<int>::max())
1112       {
1113         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::rearrange : the rearrangement leads to too high number of tuples (> 2147483647) !";
1114         throw INTERP_KERNEL::Exception(oss.str().c_str());
1115       }
1116     _info_on_compo.clear();
1117     _info_on_compo.resize(newNbOfCompo);
1118     declareAsNew();
1119   }
1120
1121   /*!
1122    * Changes the number of components within \a this array to be equal to its number
1123    * of tuples, and inversely its number of tuples to become equal to its number of 
1124    * components. So that its raw data **does not** change, instead splitting this
1125    * data into tuples changes.
1126    *  \warning This method erases all (name and unit) component info set before!
1127    *  \warning Do not confuse this method with fromNoInterlace() and toNoInterlace()!
1128    *  \throw If \a this is not allocated.
1129    *  \sa rearrange()
1130    */
1131   template<class T>
1132   void DataArrayTemplate<T>::transpose()
1133   {
1134     checkAllocated();
1135     int nbOfTuples(getNumberOfTuples());
1136     rearrange(nbOfTuples);
1137   }
1138
1139   /*!
1140    * Returns a shorten or extended copy of \a this array. If \a newNbOfComp is less
1141    * than \a this->getNumberOfComponents() then the result array is shorten as each tuple
1142    * is truncated to have \a newNbOfComp components, keeping first components. If \a
1143    * newNbOfComp is more than \a this->getNumberOfComponents() then the result array is
1144    * expanded as each tuple is populated with \a dftValue to have \a newNbOfComp
1145    * components.  
1146    *  \param [in] newNbOfComp - number of components for the new array to have.
1147    *  \param [in] dftValue - value assigned to new values added to the new array.
1148    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1149    *          is to delete using decrRef() as it is no more needed.
1150    *  \throw If \a this is not allocated.
1151    */
1152   template<class T>
1153   typename Traits<T>::ArrayType *DataArrayTemplate<T>::changeNbOfComponents(int newNbOfComp, T dftValue) const
1154   {
1155     checkAllocated();
1156     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1157     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1158     ret->alloc(getNumberOfTuples(),newNbOfComp);
1159     const T *oldc(getConstPointer());
1160     T *nc(ret->getPointer());
1161     int nbOfTuples(getNumberOfTuples()),oldNbOfComp(getNumberOfComponents());
1162     int dim(std::min(oldNbOfComp,newNbOfComp));
1163     for(int i=0;i<nbOfTuples;i++)
1164       {
1165         int j=0;
1166         for(;j<dim;j++)
1167           nc[newNbOfComp*i+j]=oldc[i*oldNbOfComp+j];
1168         for(;j<newNbOfComp;j++)
1169           nc[newNbOfComp*i+j]=dftValue;
1170       }
1171     ret->setName(getName());
1172     for(int i=0;i<dim;i++)
1173       ret->setInfoOnComponent(i,getInfoOnComponent(i));
1174     ret->setName(getName());
1175     return ret.retn();
1176   }
1177
1178   /*!
1179    * Returns a copy of \a this array composed of selected components.
1180    * The new DataArrayDouble has the same number of tuples but includes components
1181    * specified by \a compoIds parameter. So that getNbOfElems() of the result array
1182    * can be either less, same or more than \a this->getNbOfElems().
1183    *  \param [in] compoIds - sequence of zero based indices of components to include
1184    *              into the new array.
1185    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1186    *          is to delete using decrRef() as it is no more needed.
1187    *  \throw If \a this is not allocated.
1188    *  \throw If a component index (\a i) is not valid: 
1189    *         \a i < 0 || \a i >= \a this->getNumberOfComponents().
1190    *
1191    *  \if ENABLE_EXAMPLES
1192    *  \ref py_mcdataarraydouble_KeepSelectedComponents "Here is a Python example".
1193    *  \endif
1194    */
1195   template<class T>
1196   typename Traits<T>::ArrayType *DataArrayTemplate<T>::myKeepSelectedComponents(const std::vector<int>& compoIds) const
1197   {
1198     checkAllocated();
1199     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1200     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1201     std::size_t newNbOfCompo(compoIds.size());
1202     int oldNbOfCompo(getNumberOfComponents());
1203     for(std::vector<int>::const_iterator it=compoIds.begin();it!=compoIds.end();it++)
1204       if((*it)<0 || (*it)>=oldNbOfCompo)
1205         {
1206           std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::keepSelectedComponents : invalid requested component : " << *it << " whereas it should be in [0," << oldNbOfCompo << ") !";
1207           throw INTERP_KERNEL::Exception(oss.str().c_str());
1208         }
1209     int nbOfTuples(getNumberOfTuples());
1210     ret->alloc(nbOfTuples,(int)newNbOfCompo);
1211     ret->copyPartOfStringInfoFrom(*this,compoIds);
1212     const T *oldc(getConstPointer());
1213     T *nc(ret->getPointer());
1214     for(int i=0;i<nbOfTuples;i++)
1215       for(std::size_t j=0;j<newNbOfCompo;j++,nc++)
1216         *nc=oldc[i*oldNbOfCompo+compoIds[j]];
1217     return ret.retn();
1218   }
1219
1220   /*!
1221    * Returns a shorten copy of \a this array. The new DataArrayDouble contains all
1222    * tuples starting from the \a tupleIdBg-th tuple and including all tuples located before
1223    * the \a tupleIdEnd-th one. This methods has a similar behavior as std::string::substr().
1224    * This method is a specialization of selectByTupleIdSafeSlice().
1225    *  \param [in] tupleIdBg - index of the first tuple to copy from \a this array.
1226    *  \param [in] tupleIdEnd - index of the tuple before which the tuples to copy are located.
1227    *          If \a tupleIdEnd == -1, all the tuples till the end of \a this array are copied.
1228    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1229    *          is to delete using decrRef() as it is no more needed.
1230    *  \throw If \a tupleIdBg < 0.
1231    *  \throw If \a tupleIdBg > \a this->getNumberOfTuples().
1232    *  \throw If \a tupleIdEnd != -1 && \a tupleIdEnd < \a this->getNumberOfTuples().
1233    *  \sa DataArrayDouble::selectByTupleIdSafeSlice
1234    */
1235   template<class T>
1236   typename Traits<T>::ArrayType *DataArrayTemplate<T>::subArray(int tupleIdBg, int tupleIdEnd) const
1237   {
1238     checkAllocated();
1239     int nbt(getNumberOfTuples());
1240     if(tupleIdBg<0)
1241       {
1242         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::subArray : The tupleIdBg parameter must be greater than 0 !";
1243         throw INTERP_KERNEL::Exception(oss.str().c_str());
1244       }
1245     if(tupleIdBg>nbt)
1246       {
1247         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << ":subArray : The tupleIdBg parameter is greater than number of tuples !";
1248         throw INTERP_KERNEL::Exception(oss.str().c_str());
1249       }
1250     int trueEnd=tupleIdEnd;
1251     if(tupleIdEnd!=-1)
1252       {
1253         if(tupleIdEnd>nbt)
1254           {
1255             std::ostringstream oss; oss << Traits<T>::ArrayTypeName << ":subArray : The tupleIdBg parameter is greater than number of tuples !";
1256             throw INTERP_KERNEL::Exception(oss.str().c_str());
1257           }
1258       }
1259     else
1260       trueEnd=nbt;
1261     int nbComp(getNumberOfComponents());
1262     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1263     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1264     ret->alloc(trueEnd-tupleIdBg,nbComp);
1265     ret->copyStringInfoFrom(*this);
1266     std::copy(getConstPointer()+tupleIdBg*nbComp,getConstPointer()+trueEnd*nbComp,ret->getPointer());
1267     return ret.retn();
1268   }
1269
1270   /*!
1271    * Returns a shorten copy of \a this array. The new DataArrayDouble contains every
1272    * (\a bg + \c i * \a step)-th tuple of \a this array located before the \a end2-th
1273    * tuple. Indices of the selected tuples are the same as ones returned by the Python
1274    * command \c range( \a bg, \a end2, \a step ).
1275    * This method is equivalent to selectByTupleIdSafe() except that the input array is
1276    * not constructed explicitly.
1277    * For more info on renumbering see \ref numbering.
1278    *  \param [in] bg - index of the first tuple to copy from \a this array.
1279    *  \param [in] end2 - index of the tuple before which the tuples to copy are located.
1280    *  \param [in] step - index increment to get index of the next tuple to copy.
1281    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1282    *          is to delete using decrRef() as it is no more needed.
1283    *  \sa DataArrayDouble::subArray.
1284    */
1285   template<class T>
1286   typename Traits<T>::ArrayType *DataArrayTemplate<T>::mySelectByTupleIdSafeSlice(int bg, int end2, int step) const
1287   {
1288     checkAllocated();
1289     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1290     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1291     int nbComp(getNumberOfComponents());
1292     std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::selectByTupleIdSafeSlice : ";
1293     int newNbOfTuples(GetNumberOfItemGivenBESRelative(bg,end2,step,oss.str()));
1294     ret->alloc(newNbOfTuples,nbComp);
1295     T *pt(ret->getPointer());
1296     const T *srcPt(getConstPointer()+bg*nbComp);
1297     for(int i=0;i<newNbOfTuples;i++,srcPt+=step*nbComp)
1298       std::copy(srcPt,srcPt+nbComp,pt+i*nbComp);
1299     ret->copyStringInfoFrom(*this);
1300     return ret.retn();
1301   }
1302   
1303   /*!
1304    * Copy all values from another DataArrayDouble into specified tuples and components
1305    * of \a this array. Textual data is not copied.
1306    * The tree parameters defining set of indices of tuples and components are similar to
1307    * the tree parameters of the Python function \c range(\c start,\c stop,\c step).
1308    *  \param [in] a - the array to copy values from.
1309    *  \param [in] bgTuples - index of the first tuple of \a this array to assign values to.
1310    *  \param [in] endTuples - index of the tuple before which the tuples to assign to
1311    *              are located.
1312    *  \param [in] stepTuples - index increment to get index of the next tuple to assign to.
1313    *  \param [in] bgComp - index of the first component of \a this array to assign values to.
1314    *  \param [in] endComp - index of the component before which the components to assign
1315    *              to are located.
1316    *  \param [in] stepComp - index increment to get index of the next component to assign to.
1317    *  \param [in] strictCompoCompare - if \a true (by default), then \a a->getNumberOfComponents() 
1318    *              must be equal to the number of columns to assign to, else an
1319    *              exception is thrown; if \a false, then it is only required that \a
1320    *              a->getNbOfElems() equals to number of values to assign to (this condition
1321    *              must be respected even if \a strictCompoCompare is \a true). The number of 
1322    *              values to assign to is given by following Python expression:
1323    *              \a nbTargetValues = 
1324    *              \c len(\c range(\a bgTuples,\a endTuples,\a stepTuples)) *
1325    *              \c len(\c range(\a bgComp,\a endComp,\a stepComp)).
1326    *  \throw If \a a is NULL.
1327    *  \throw If \a a is not allocated.
1328    *  \throw If \a this is not allocated.
1329    *  \throw If parameters specifying tuples and components to assign to do not give a
1330    *            non-empty range of increasing indices.
1331    *  \throw If \a a->getNbOfElems() != \a nbTargetValues.
1332    *  \throw If \a strictCompoCompare == \a true && \a a->getNumberOfComponents() !=
1333    *            \c len(\c range(\a bgComp,\a endComp,\a stepComp)).
1334    *
1335    *  \if ENABLE_EXAMPLES
1336    *  \ref py_mcdataarraydouble_setpartofvalues1 "Here is a Python example".
1337    *  \endif
1338    */
1339   template<class T>
1340   void DataArrayTemplate<T>::setPartOfValues1(const typename Traits<T>::ArrayType *a, int bgTuples, int endTuples, int stepTuples, int bgComp, int endComp, int stepComp, bool strictCompoCompare)
1341   {
1342     if(!a)
1343       {
1344         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::setPartOfValues1 : input DataArrayDouble is NULL !";
1345         throw INTERP_KERNEL::Exception(oss.str().c_str());
1346       }
1347     const char msg[]="DataArrayTemplate::setPartOfValues1";
1348     checkAllocated();
1349     a->checkAllocated();
1350     int newNbOfTuples(DataArray::GetNumberOfItemGivenBES(bgTuples,endTuples,stepTuples,msg));
1351     int newNbOfComp(DataArray::GetNumberOfItemGivenBES(bgComp,endComp,stepComp,msg));
1352     int nbComp(getNumberOfComponents()),nbOfTuples(getNumberOfTuples());
1353     DataArray::CheckValueInRangeEx(nbOfTuples,bgTuples,endTuples,"invalid tuple value");
1354     DataArray::CheckValueInRangeEx(nbComp,bgComp,endComp,"invalid component value");
1355     bool assignTech(true);
1356     if(a->getNbOfElems()==(std::size_t)newNbOfTuples*newNbOfComp)
1357       {
1358         if(strictCompoCompare)
1359           a->checkNbOfTuplesAndComp(newNbOfTuples,newNbOfComp,msg);
1360       }
1361     else
1362       {
1363         a->checkNbOfTuplesAndComp(1,newNbOfComp,msg);
1364         assignTech=false;
1365       }
1366     const T *srcPt(a->getConstPointer());
1367     T *pt(getPointer()+bgTuples*nbComp+bgComp);
1368     if(assignTech)
1369       {
1370         for(int i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
1371           for(int j=0;j<newNbOfComp;j++,srcPt++)
1372             pt[j*stepComp]=*srcPt;
1373       }
1374     else
1375       {
1376         for(int i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
1377           {
1378             const T*srcPt2=srcPt;
1379             for(int j=0;j<newNbOfComp;j++,srcPt2++)
1380               pt[j*stepComp]=*srcPt2;
1381           }
1382       }
1383   }
1384   
1385   /*!
1386  * Assign a given value to values at specified tuples and components of \a this array.
1387  * The tree parameters defining set of indices of tuples and components are similar to
1388  * the tree parameters of the Python function \c range(\c start,\c stop,\c step)..
1389  *  \param [in] a - the value to assign.
1390  *  \param [in] bgTuples - index of the first tuple of \a this array to assign to.
1391  *  \param [in] endTuples - index of the tuple before which the tuples to assign to
1392  *              are located.
1393  *  \param [in] stepTuples - index increment to get index of the next tuple to assign to.
1394  *  \param [in] bgComp - index of the first component of \a this array to assign to.
1395  *  \param [in] endComp - index of the component before which the components to assign
1396  *              to are located.
1397  *  \param [in] stepComp - index increment to get index of the next component to assign to.
1398  *  \throw If \a this is not allocated.
1399  *  \throw If parameters specifying tuples and components to assign to, do not give a
1400  *            non-empty range of increasing indices or indices are out of a valid range
1401  *            for \c this array.
1402  *
1403  *  \if ENABLE_EXAMPLES
1404  *  \ref py_mcdataarraydouble_setpartofvaluessimple1 "Here is a Python example".
1405  *  \endif
1406  */
1407   template<class T>
1408   void DataArrayTemplate<T>::setPartOfValuesSimple1(T a, int bgTuples, int endTuples, int stepTuples, int bgComp, int endComp, int stepComp)
1409   {
1410     const char msg[]="DataArrayTemplate::setPartOfValuesSimple1";
1411     checkAllocated();
1412     int newNbOfTuples(DataArray::GetNumberOfItemGivenBES(bgTuples,endTuples,stepTuples,msg));
1413     int newNbOfComp(DataArray::GetNumberOfItemGivenBES(bgComp,endComp,stepComp,msg));
1414     int nbComp(getNumberOfComponents()),nbOfTuples(getNumberOfTuples());
1415     DataArray::CheckValueInRangeEx(nbOfTuples,bgTuples,endTuples,"invalid tuple value");
1416     DataArray::CheckValueInRangeEx(nbComp,bgComp,endComp,"invalid component value");
1417     T *pt=getPointer()+bgTuples*nbComp+bgComp;
1418     for(int i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
1419       for(int j=0;j<newNbOfComp;j++)
1420         pt[j*stepComp]=a;
1421   }
1422   
1423   /*!
1424    * Copy all values from another DataArrayDouble (\a a) into specified tuples and 
1425    * components of \a this array. Textual data is not copied.
1426    * The tuples and components to assign to are defined by C arrays of indices.
1427    * There are two *modes of usage*:
1428    * - If \a a->getNbOfElems() equals to number of values to assign to, then every value
1429    *   of \a a is assigned to its own location within \a this array. 
1430    * - If \a a includes one tuple, then all values of \a a are assigned to the specified
1431    *   components of every specified tuple of \a this array. In this mode it is required
1432    *   that \a a->getNumberOfComponents() equals to the number of specified components.
1433    *
1434    *  \param [in] a - the array to copy values from.
1435    *  \param [in] bgTuples - pointer to an array of tuple indices of \a this array to
1436    *              assign values of \a a to.
1437    *  \param [in] endTuples - specifies the end of the array \a bgTuples, so that
1438    *              pointer to a tuple index <em>(pi)</em> varies as this: 
1439    *              \a bgTuples <= \a pi < \a endTuples.
1440    *  \param [in] bgComp - pointer to an array of component indices of \a this array to
1441    *              assign values of \a a to.
1442    *  \param [in] endComp - specifies the end of the array \a bgTuples, so that
1443    *              pointer to a component index <em>(pi)</em> varies as this: 
1444    *              \a bgComp <= \a pi < \a endComp.
1445    *  \param [in] strictCompoCompare - this parameter is checked only if the
1446    *               *mode of usage* is the first; if it is \a true (default), 
1447    *               then \a a->getNumberOfComponents() must be equal 
1448    *               to the number of specified columns, else this is not required.
1449    *  \throw If \a a is NULL.
1450    *  \throw If \a a is not allocated.
1451    *  \throw If \a this is not allocated.
1452    *  \throw If any index of tuple/component given by <em>bgTuples / bgComp</em> is
1453    *         out of a valid range for \a this array.
1454    *  \throw In the first *mode of usage*, if <em>strictCompoCompare == true </em> and
1455    *         if <em> a->getNumberOfComponents() != (endComp - bgComp) </em>.
1456    *  \throw In the second *mode of usage*, if \a a->getNumberOfTuples() != 1 or
1457    *         <em> a->getNumberOfComponents() != (endComp - bgComp)</em>.
1458    *
1459    *  \if ENABLE_EXAMPLES
1460    *  \ref py_mcdataarraydouble_setpartofvalues2 "Here is a Python example".
1461    *  \endif
1462    */
1463   template<class T>
1464   void DataArrayTemplate<T>::setPartOfValues2(const typename Traits<T>::ArrayType *a, const int *bgTuples, const int *endTuples, const int *bgComp, const int *endComp, bool strictCompoCompare)
1465   {
1466     if(!a)
1467       throw INTERP_KERNEL::Exception("DataArrayDouble::setPartOfValues2 : input DataArrayDouble is NULL !");
1468     const char msg[]="DataArrayTemplate::setPartOfValues2";
1469     checkAllocated();
1470     a->checkAllocated();
1471     int nbComp(getNumberOfComponents()),nbOfTuples(getNumberOfTuples());
1472     for(const int *z=bgComp;z!=endComp;z++)
1473       DataArray::CheckValueInRange(nbComp,*z,"invalid component id");
1474     int newNbOfTuples((int)std::distance(bgTuples,endTuples));
1475     int newNbOfComp((int)std::distance(bgComp,endComp));
1476     bool assignTech(true);
1477     if(a->getNbOfElems()==(std::size_t)newNbOfTuples*newNbOfComp)
1478       {
1479         if(strictCompoCompare)
1480           a->checkNbOfTuplesAndComp(newNbOfTuples,newNbOfComp,msg);
1481       }
1482     else
1483       {
1484         a->checkNbOfTuplesAndComp(1,newNbOfComp,msg);
1485         assignTech=false;
1486       }
1487     T *pt(getPointer());
1488     const T *srcPt(a->getConstPointer());
1489     if(assignTech)
1490       {    
1491         for(const int *w=bgTuples;w!=endTuples;w++)
1492           {
1493             DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1494             for(const int *z=bgComp;z!=endComp;z++,srcPt++)
1495               {    
1496                 pt[(std::size_t)(*w)*nbComp+(*z)]=*srcPt;
1497               }
1498           }
1499       }
1500     else
1501       {
1502         for(const int *w=bgTuples;w!=endTuples;w++)
1503           {
1504             const T *srcPt2=srcPt;
1505             DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1506             for(const int *z=bgComp;z!=endComp;z++,srcPt2++)
1507               {    
1508                 pt[(std::size_t)(*w)*nbComp+(*z)]=*srcPt2;
1509               }
1510           }
1511       }
1512   }
1513   
1514   /*!
1515    * Assign a given value to values at specified tuples and components of \a this array.
1516    * The tuples and components to assign to are defined by C arrays of indices.
1517    *  \param [in] a - the value to assign.
1518    *  \param [in] bgTuples - pointer to an array of tuple indices of \a this array to
1519    *              assign \a a to.
1520    *  \param [in] endTuples - specifies the end of the array \a bgTuples, so that
1521    *              pointer to a tuple index (\a pi) varies as this: 
1522    *              \a bgTuples <= \a pi < \a endTuples.
1523    *  \param [in] bgComp - pointer to an array of component indices of \a this array to
1524    *              assign \a a to.
1525    *  \param [in] endComp - specifies the end of the array \a bgTuples, so that
1526    *              pointer to a component index (\a pi) varies as this: 
1527    *              \a bgComp <= \a pi < \a endComp.
1528    *  \throw If \a this is not allocated.
1529    *  \throw If any index of tuple/component given by <em>bgTuples / bgComp</em> is
1530    *         out of a valid range for \a this array.
1531    *
1532    *  \if ENABLE_EXAMPLES
1533    *  \ref py_mcdataarraydouble_setpartofvaluessimple2 "Here is a Python example".
1534    *  \endif
1535    */
1536   template<class T>
1537   void DataArrayTemplate<T>::setPartOfValuesSimple2(T a, const int *bgTuples, const int *endTuples, const int *bgComp, const int *endComp)
1538   {
1539     checkAllocated();
1540     int nbComp(getNumberOfComponents()),nbOfTuples(getNumberOfTuples());
1541     for(const int *z=bgComp;z!=endComp;z++)
1542       DataArray::CheckValueInRange(nbComp,*z,"invalid component id");
1543     T *pt(getPointer());
1544     for(const int *w=bgTuples;w!=endTuples;w++)
1545       for(const int *z=bgComp;z!=endComp;z++)
1546         {
1547           DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1548           pt[(std::size_t)(*w)*nbComp+(*z)]=a;
1549         }
1550   }
1551   
1552   /*!
1553    * Copy all values from another DataArrayDouble (\a a) into specified tuples and 
1554    * components of \a this array. Textual data is not copied.
1555    * The tuples to assign to are defined by a C array of indices.
1556    * The components to assign to are defined by three values similar to parameters of
1557    * the Python function \c range(\c start,\c stop,\c step).
1558    * There are two *modes of usage*:
1559    * - If \a a->getNbOfElems() equals to number of values to assign to, then every value
1560    *   of \a a is assigned to its own location within \a this array. 
1561    * - If \a a includes one tuple, then all values of \a a are assigned to the specified
1562    *   components of every specified tuple of \a this array. In this mode it is required
1563    *   that \a a->getNumberOfComponents() equals to the number of specified components.
1564    *
1565    *  \param [in] a - the array to copy values from.
1566    *  \param [in] bgTuples - pointer to an array of tuple indices of \a this array to
1567    *              assign values of \a a to.
1568    *  \param [in] endTuples - specifies the end of the array \a bgTuples, so that
1569    *              pointer to a tuple index <em>(pi)</em> varies as this: 
1570    *              \a bgTuples <= \a pi < \a endTuples.
1571    *  \param [in] bgComp - index of the first component of \a this array to assign to.
1572    *  \param [in] endComp - index of the component before which the components to assign
1573    *              to are located.
1574    *  \param [in] stepComp - index increment to get index of the next component to assign to.
1575    *  \param [in] strictCompoCompare - this parameter is checked only in the first
1576    *               *mode of usage*; if \a strictCompoCompare is \a true (default), 
1577    *               then \a a->getNumberOfComponents() must be equal 
1578    *               to the number of specified columns, else this is not required.
1579    *  \throw If \a a is NULL.
1580    *  \throw If \a a is not allocated.
1581    *  \throw If \a this is not allocated.
1582    *  \throw If any index of tuple given by \a bgTuples is out of a valid range for 
1583    *         \a this array.
1584    *  \throw In the first *mode of usage*, if <em>strictCompoCompare == true </em> and
1585    *         if <em> a->getNumberOfComponents()</em> is unequal to the number of components
1586    *         defined by <em>(bgComp,endComp,stepComp)</em>.
1587    *  \throw In the second *mode of usage*, if \a a->getNumberOfTuples() != 1 or
1588    *         <em> a->getNumberOfComponents()</em> is unequal to the number of components
1589    *         defined by <em>(bgComp,endComp,stepComp)</em>.
1590    *  \throw If parameters specifying components to assign to, do not give a
1591    *            non-empty range of increasing indices or indices are out of a valid range
1592    *            for \c this array.
1593    *
1594    *  \if ENABLE_EXAMPLES
1595    *  \ref py_mcdataarraydouble_setpartofvalues3 "Here is a Python example".
1596    *  \endif
1597    */
1598   template<class T>
1599   void DataArrayTemplate<T>::setPartOfValues3(const typename Traits<T>::ArrayType *a, const int *bgTuples, const int *endTuples, int bgComp, int endComp, int stepComp, bool strictCompoCompare)
1600   {
1601     if(!a)
1602       throw INTERP_KERNEL::Exception("DataArrayTemplate::setPartOfValues3 : input DataArrayDouble is NULL !");
1603     const char msg[]="DataArrayTemplate::setPartOfValues3";
1604     checkAllocated();
1605     a->checkAllocated();
1606     int newNbOfComp=DataArray::GetNumberOfItemGivenBES(bgComp,endComp,stepComp,msg);
1607     int nbComp=getNumberOfComponents();
1608     int nbOfTuples=getNumberOfTuples();
1609     DataArray::CheckValueInRangeEx(nbComp,bgComp,endComp,"invalid component value");
1610     int newNbOfTuples=(int)std::distance(bgTuples,endTuples);
1611     bool assignTech=true;
1612     if(a->getNbOfElems()==(std::size_t)newNbOfTuples*newNbOfComp)
1613       {
1614         if(strictCompoCompare)
1615           a->checkNbOfTuplesAndComp(newNbOfTuples,newNbOfComp,msg);
1616       }
1617     else
1618       {
1619         a->checkNbOfTuplesAndComp(1,newNbOfComp,msg);
1620         assignTech=false;
1621       }
1622     T *pt(getPointer()+bgComp);
1623     const T *srcPt(a->getConstPointer());
1624     if(assignTech)
1625       {
1626         for(const int *w=bgTuples;w!=endTuples;w++)
1627           for(int j=0;j<newNbOfComp;j++,srcPt++)
1628             {
1629               DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1630               pt[(std::size_t)(*w)*nbComp+j*stepComp]=*srcPt;
1631             }
1632       }
1633     else
1634       {
1635         for(const int *w=bgTuples;w!=endTuples;w++)
1636           {
1637             const T *srcPt2=srcPt;
1638             for(int j=0;j<newNbOfComp;j++,srcPt2++)
1639               {
1640                 DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1641                 pt[(std::size_t)(*w)*nbComp+j*stepComp]=*srcPt2;
1642               }
1643           }
1644       }
1645   }
1646   
1647   /*!
1648    * Assign a given value to values at specified tuples and components of \a this array.
1649    * The tuples to assign to are defined by a C array of indices.
1650    * The components to assign to are defined by three values similar to parameters of
1651    * the Python function \c range(\c start,\c stop,\c step).
1652    *  \param [in] a - the value to assign.
1653    *  \param [in] bgTuples - pointer to an array of tuple indices of \a this array to
1654    *              assign \a a to.
1655    *  \param [in] endTuples - specifies the end of the array \a bgTuples, so that
1656    *              pointer to a tuple index <em>(pi)</em> varies as this: 
1657    *              \a bgTuples <= \a pi < \a endTuples.
1658    *  \param [in] bgComp - index of the first component of \a this array to assign to.
1659    *  \param [in] endComp - index of the component before which the components to assign
1660    *              to are located.
1661    *  \param [in] stepComp - index increment to get index of the next component to assign to.
1662    *  \throw If \a this is not allocated.
1663    *  \throw If any index of tuple given by \a bgTuples is out of a valid range for 
1664    *         \a this array.
1665    *  \throw If parameters specifying components to assign to, do not give a
1666    *            non-empty range of increasing indices or indices are out of a valid range
1667    *            for \c this array.
1668    *
1669    *  \if ENABLE_EXAMPLES
1670    *  \ref py_mcdataarraydouble_setpartofvaluessimple3 "Here is a Python example".
1671    *  \endif
1672    */
1673   template<class T>
1674   void DataArrayTemplate<T>::setPartOfValuesSimple3(T a, const int *bgTuples, const int *endTuples, int bgComp, int endComp, int stepComp)
1675   {
1676     const char msg[]="DataArrayTemplate::setPartOfValuesSimple3";
1677     checkAllocated();
1678     int newNbOfComp(DataArray::GetNumberOfItemGivenBES(bgComp,endComp,stepComp,msg));
1679     int nbComp(getNumberOfComponents()),nbOfTuples(getNumberOfTuples());
1680     DataArray::CheckValueInRangeEx(nbComp,bgComp,endComp,"invalid component value");
1681     T *pt(getPointer()+bgComp);
1682     for(const int *w=bgTuples;w!=endTuples;w++)
1683       for(int j=0;j<newNbOfComp;j++)
1684         {
1685           DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1686           pt[(std::size_t)(*w)*nbComp+j*stepComp]=a;
1687         }
1688   }
1689
1690   /*!
1691    * Copy all values from another DataArrayDouble into specified tuples and components
1692    * of \a this array. Textual data is not copied.
1693    * The tree parameters defining set of indices of tuples and components are similar to
1694    * the tree parameters of the Python function \c range(\c start,\c stop,\c step).
1695    *  \param [in] a - the array to copy values from.
1696    *  \param [in] bgTuples - index of the first tuple of \a this array to assign values to.
1697    *  \param [in] endTuples - index of the tuple before which the tuples to assign to
1698    *              are located.
1699    *  \param [in] stepTuples - index increment to get index of the next tuple to assign to.
1700    *  \param [in] bgComp - pointer to an array of component indices of \a this array to
1701    *              assign \a a to.
1702    *  \param [in] endComp - specifies the end of the array \a bgTuples, so that
1703    *              pointer to a component index (\a pi) varies as this: 
1704    *              \a bgComp <= \a pi < \a endComp.
1705    *  \param [in] strictCompoCompare - if \a true (by default), then \a a->getNumberOfComponents() 
1706    *              must be equal to the number of columns to assign to, else an
1707    *              exception is thrown; if \a false, then it is only required that \a
1708    *              a->getNbOfElems() equals to number of values to assign to (this condition
1709    *              must be respected even if \a strictCompoCompare is \a true). The number of 
1710    *              values to assign to is given by following Python expression:
1711    *              \a nbTargetValues = 
1712    *              \c len(\c range(\a bgTuples,\a endTuples,\a stepTuples)) *
1713    *              \c len(\c range(\a bgComp,\a endComp,\a stepComp)).
1714    *  \throw If \a a is NULL.
1715    *  \throw If \a a is not allocated.
1716    *  \throw If \a this is not allocated.
1717    *  \throw If parameters specifying tuples and components to assign to do not give a
1718    *            non-empty range of increasing indices.
1719    *  \throw If \a a->getNbOfElems() != \a nbTargetValues.
1720    *  \throw If \a strictCompoCompare == \a true && \a a->getNumberOfComponents() !=
1721    *            \c len(\c range(\a bgComp,\a endComp,\a stepComp)).
1722    *
1723    */
1724   template<class T>
1725   void DataArrayTemplate<T>::setPartOfValues4(const typename Traits<T>::ArrayType *a, int bgTuples, int endTuples, int stepTuples, const int *bgComp, const int *endComp, bool strictCompoCompare)
1726   {if(!a)
1727       throw INTERP_KERNEL::Exception("DataArrayTemplate::setPartOfValues4 : input DataArrayTemplate is NULL !");
1728     const char msg[]="DataArrayTemplate::setPartOfValues4";
1729     checkAllocated();
1730     a->checkAllocated();
1731     int newNbOfTuples(DataArray::GetNumberOfItemGivenBES(bgTuples,endTuples,stepTuples,msg));
1732     int newNbOfComp((int)std::distance(bgComp,endComp));
1733     int nbComp(getNumberOfComponents());
1734     for(const int *z=bgComp;z!=endComp;z++)
1735       DataArray::CheckValueInRange(nbComp,*z,"invalid component id");
1736     int nbOfTuples(getNumberOfTuples());
1737     DataArray::CheckValueInRangeEx(nbOfTuples,bgTuples,endTuples,"invalid tuple value");
1738     bool assignTech(true);
1739     if(a->getNbOfElems()==(std::size_t)newNbOfTuples*newNbOfComp)
1740       {
1741         if(strictCompoCompare)
1742           a->checkNbOfTuplesAndComp(newNbOfTuples,newNbOfComp,msg);
1743       }
1744     else
1745       {
1746         a->checkNbOfTuplesAndComp(1,newNbOfComp,msg);
1747         assignTech=false;
1748       }
1749     const T *srcPt(a->getConstPointer());
1750     T *pt(getPointer()+bgTuples*nbComp);
1751     if(assignTech)
1752       {
1753         for(int i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
1754           for(const int *z=bgComp;z!=endComp;z++,srcPt++)
1755             pt[*z]=*srcPt;
1756       }
1757     else
1758       {
1759       for(int i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
1760         {
1761           const T *srcPt2(srcPt);
1762           for(const int *z=bgComp;z!=endComp;z++,srcPt2++)
1763             pt[*z]=*srcPt2;
1764         }
1765       }
1766   }
1767
1768   template<class T>
1769   void DataArrayTemplate<T>::setPartOfValuesSimple4(T a, int bgTuples, int endTuples, int stepTuples, const int *bgComp, const int *endComp)
1770   {
1771     const char msg[]="DataArrayTemplate::setPartOfValuesSimple4";
1772     checkAllocated();
1773     int newNbOfTuples(DataArray::GetNumberOfItemGivenBES(bgTuples,endTuples,stepTuples,msg));
1774     int nbComp(getNumberOfComponents());
1775     for(const int *z=bgComp;z!=endComp;z++)
1776       DataArray::CheckValueInRange(nbComp,*z,"invalid component id");
1777     int nbOfTuples(getNumberOfTuples());
1778     DataArray::CheckValueInRangeEx(nbOfTuples,bgTuples,endTuples,"invalid tuple value");
1779     T *pt=getPointer()+bgTuples*nbComp;
1780     for(int i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
1781       for(const int *z=bgComp;z!=endComp;z++)
1782         pt[*z]=a;
1783   }
1784   
1785   /*!
1786    * Copy some tuples from another DataArrayDouble into specified tuples
1787    * of \a this array. Textual data is not copied. Both arrays must have equal number of
1788    * components.
1789    * Both the tuples to assign and the tuples to assign to are defined by a DataArrayInt.
1790    * All components of selected tuples are copied.
1791    *  \param [in] a - the array to copy values from.
1792    *  \param [in] tuplesSelec - the array specifying both source tuples of \a a and
1793    *              target tuples of \a this. \a tuplesSelec has two components, and the
1794    *              first component specifies index of the source tuple and the second
1795    *              one specifies index of the target tuple.
1796    *  \throw If \a this is not allocated.
1797    *  \throw If \a a is NULL.
1798    *  \throw If \a a is not allocated.
1799    *  \throw If \a tuplesSelec is NULL.
1800    *  \throw If \a tuplesSelec is not allocated.
1801    *  \throw If <em>this->getNumberOfComponents() != a->getNumberOfComponents()</em>.
1802    *  \throw If \a tuplesSelec->getNumberOfComponents() != 2.
1803    *  \throw If any tuple index given by \a tuplesSelec is out of a valid range for 
1804    *         the corresponding (\a this or \a a) array.
1805    */
1806   template<class T>
1807   void DataArrayTemplate<T>::setPartOfValuesAdv(const typename Traits<T>::ArrayType *a, const DataArrayInt *tuplesSelec)
1808   {
1809     if(!a || !tuplesSelec)
1810       throw INTERP_KERNEL::Exception("DataArrayTemplate::setPartOfValuesAdv : input DataArrayTemplate is NULL !");
1811     checkAllocated();
1812     a->checkAllocated();
1813     tuplesSelec->checkAllocated();
1814     int nbOfComp=getNumberOfComponents();
1815     if(nbOfComp!=a->getNumberOfComponents())
1816       throw INTERP_KERNEL::Exception("DataArrayTemplate::setPartOfValuesAdv : This and a do not have the same number of components !");
1817     if(tuplesSelec->getNumberOfComponents()!=2)
1818       throw INTERP_KERNEL::Exception("DataArrayTemplate::setPartOfValuesAdv : Expecting to have a tuple selector DataArrayInt instance with exactly 2 components !");
1819     int thisNt(getNumberOfTuples());
1820     int aNt(a->getNumberOfTuples());
1821     T *valsToSet(getPointer());
1822     const T *valsSrc(a->getConstPointer());
1823     for(const int *tuple=tuplesSelec->begin();tuple!=tuplesSelec->end();tuple+=2)
1824     {
1825       if(tuple[1]>=0 && tuple[1]<aNt)
1826         {
1827           if(tuple[0]>=0 && tuple[0]<thisNt)
1828             std::copy(valsSrc+nbOfComp*tuple[1],valsSrc+nbOfComp*(tuple[1]+1),valsToSet+nbOfComp*tuple[0]);
1829           else
1830             {
1831               std::ostringstream oss; oss << "DataArrayTemplate::setPartOfValuesAdv : Tuple #" << std::distance(tuplesSelec->begin(),tuple)/2;
1832               oss << " of 'tuplesSelec' request of tuple id #" << tuple[0] << " in 'this' ! It should be in [0," << thisNt << ") !";
1833               throw INTERP_KERNEL::Exception(oss.str().c_str());
1834             }
1835         }
1836       else
1837         {
1838           std::ostringstream oss; oss << "DataArrayTemplate::setPartOfValuesAdv : Tuple #" << std::distance(tuplesSelec->begin(),tuple)/2;
1839           oss << " of 'tuplesSelec' request of tuple id #" << tuple[1] << " in 'a' ! It should be in [0," << aNt << ") !";
1840           throw INTERP_KERNEL::Exception(oss.str().c_str());
1841         }
1842     }
1843   }
1844   
1845   /*!
1846    * Copy some tuples from another DataArrayDouble (\a aBase) into contiguous tuples
1847    * of \a this array. Textual data is not copied. Both arrays must have equal number of
1848    * components.
1849    * The tuples to assign to are defined by index of the first tuple, and
1850    * their number is defined by \a tuplesSelec->getNumberOfTuples().
1851    * The tuples to copy are defined by values of a DataArrayInt.
1852    * All components of selected tuples are copied.
1853    *  \param [in] tupleIdStart - index of the first tuple of \a this array to assign
1854    *              values to.
1855    *  \param [in] aBase - the array to copy values from.
1856    *  \param [in] tuplesSelec - the array specifying tuples of \a a to copy.
1857    *  \throw If \a this is not allocated.
1858    *  \throw If \a aBase is NULL.
1859    *  \throw If \a aBase is not allocated.
1860    *  \throw If \a tuplesSelec is NULL.
1861    *  \throw If \a tuplesSelec is not allocated.
1862    *  \throw If <em>this->getNumberOfComponents() != aBase->getNumberOfComponents()</em>.
1863    *  \throw If \a tuplesSelec->getNumberOfComponents() != 1.
1864    *  \throw If <em>tupleIdStart + tuplesSelec->getNumberOfTuples() > this->getNumberOfTuples().</em>
1865    *  \throw If any tuple index given by \a tuplesSelec is out of a valid range for 
1866    *         \a aBase array.
1867  */
1868   template<class T>
1869   void DataArrayTemplate<T>::setContigPartOfSelectedValues(int tupleIdStart, const DataArray *aBase, const DataArrayInt *tuplesSelec)
1870   {
1871     if(!aBase || !tuplesSelec)
1872       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValues : input DataArray is NULL !");
1873     const typename Traits<T>::ArrayType *a(dynamic_cast<const typename Traits<T>::ArrayType *>(aBase));
1874     if(!a)
1875       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValues : input DataArray aBase is not a DataArrayDouble !");
1876     checkAllocated();
1877     a->checkAllocated();
1878     tuplesSelec->checkAllocated();
1879     int nbOfComp(getNumberOfComponents());
1880     if(nbOfComp!=a->getNumberOfComponents())
1881       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValues : This and a do not have the same number of components !");
1882     if(tuplesSelec->getNumberOfComponents()!=1)
1883       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValues : Expecting to have a tuple selector DataArrayInt instance with exactly 1 component !");
1884     int thisNt(getNumberOfTuples());
1885     int aNt(a->getNumberOfTuples());
1886     int nbOfTupleToWrite(tuplesSelec->getNumberOfTuples());
1887     T *valsToSet(getPointer()+tupleIdStart*nbOfComp);
1888     if(tupleIdStart+nbOfTupleToWrite>thisNt)
1889       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValues : invalid number range of values to write !");
1890     const T *valsSrc=a->getConstPointer();
1891     for(const int *tuple=tuplesSelec->begin();tuple!=tuplesSelec->end();tuple++,valsToSet+=nbOfComp)
1892       {
1893         if(*tuple>=0 && *tuple<aNt)
1894           {
1895             std::copy(valsSrc+nbOfComp*(*tuple),valsSrc+nbOfComp*(*tuple+1),valsToSet);
1896           }
1897         else
1898           {
1899             std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::setContigPartOfSelectedValues : Tuple #" << std::distance(tuplesSelec->begin(),tuple);
1900             oss << " of 'tuplesSelec' request of tuple id #" << *tuple << " in 'a' ! It should be in [0," << aNt << ") !";
1901             throw INTERP_KERNEL::Exception(oss.str().c_str());
1902           }
1903       }
1904   }
1905   
1906   /*!
1907    * Copy some tuples from another DataArrayDouble (\a aBase) into contiguous tuples
1908    * of \a this array. Textual data is not copied. Both arrays must have equal number of
1909    * components.
1910    * The tuples to copy are defined by three values similar to parameters of
1911    * the Python function \c range(\c start,\c stop,\c step).
1912    * The tuples to assign to are defined by index of the first tuple, and
1913    * their number is defined by number of tuples to copy.
1914    * All components of selected tuples are copied.
1915    *  \param [in] tupleIdStart - index of the first tuple of \a this array to assign
1916    *              values to.
1917    *  \param [in] aBase - the array to copy values from.
1918    *  \param [in] bg - index of the first tuple to copy of the array \a aBase.
1919    *  \param [in] end2 - index of the tuple of \a aBase before which the tuples to copy
1920    *              are located.
1921    *  \param [in] step - index increment to get index of the next tuple to copy.
1922    *  \throw If \a this is not allocated.
1923    *  \throw If \a aBase is NULL.
1924    *  \throw If \a aBase is not allocated.
1925    *  \throw If <em>this->getNumberOfComponents() != aBase->getNumberOfComponents()</em>.
1926    *  \throw If <em>tupleIdStart + len(range(bg,end2,step)) > this->getNumberOfTuples().</em>
1927    *  \throw If parameters specifying tuples to copy, do not give a
1928    *            non-empty range of increasing indices or indices are out of a valid range
1929    *            for the array \a aBase.
1930    */
1931   template<class T>
1932   void DataArrayTemplate<T>::setContigPartOfSelectedValuesSlice(int tupleIdStart, const DataArray *aBase, int bg, int end2, int step)
1933   {
1934     if(!aBase)
1935       {
1936         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::setContigPartOfSelectedValuesSlice : input DataArray is NULL !";
1937         throw INTERP_KERNEL::Exception(oss.str().c_str());
1938       }
1939     const typename Traits<T>::ArrayType *a(dynamic_cast<const typename Traits<T>::ArrayType *>(aBase));
1940     if(!a)
1941       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValuesSlice : input DataArray aBase is not a DataArrayDouble !");
1942     checkAllocated();
1943     a->checkAllocated();
1944     int nbOfComp(getNumberOfComponents());
1945     const char msg[]="DataArrayDouble::setContigPartOfSelectedValuesSlice";
1946     int nbOfTupleToWrite(DataArray::GetNumberOfItemGivenBES(bg,end2,step,msg));
1947     if(nbOfComp!=a->getNumberOfComponents())
1948       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValuesSlice : This and a do not have the same number of components !");
1949     int thisNt(getNumberOfTuples()),aNt(a->getNumberOfTuples());
1950     T *valsToSet(getPointer()+tupleIdStart*nbOfComp);
1951     if(tupleIdStart+nbOfTupleToWrite>thisNt)
1952       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValuesSlice : invalid number range of values to write !");
1953     if(end2>aNt)
1954       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValuesSlice : invalid range of values to read !");
1955     const T *valsSrc(a->getConstPointer()+bg*nbOfComp);
1956     for(int i=0;i<nbOfTupleToWrite;i++,valsToSet+=nbOfComp,valsSrc+=step*nbOfComp)
1957       {
1958         std::copy(valsSrc,valsSrc+nbOfComp,valsToSet);
1959       }
1960   }
1961
1962   /*!
1963    * Returns a shorten copy of \a this array. The new DataArrayDouble contains ranges
1964    * of tuples specified by \a ranges parameter.
1965    * For more info on renumbering see \ref numbering.
1966    *  \param [in] ranges - std::vector of std::pair's each of which defines a range
1967    *              of tuples in [\c begin,\c end) format.
1968    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1969    *          is to delete using decrRef() as it is no more needed.
1970    *  \throw If \a end < \a begin.
1971    *  \throw If \a end > \a this->getNumberOfTuples().
1972    *  \throw If \a this is not allocated.
1973    */
1974   template<class T>
1975   typename Traits<T>::ArrayType *DataArrayTemplate<T>::mySelectByTupleRanges(const std::vector<std::pair<int,int> >& ranges) const
1976   {
1977     checkAllocated();
1978     int nbOfComp(getNumberOfComponents()),nbOfTuplesThis(getNumberOfTuples());
1979     if(ranges.empty())
1980       {
1981         MCAuto<DataArray> ret0(buildNewEmptyInstance());
1982         MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1983         ret->alloc(0,nbOfComp);
1984         ret->copyStringInfoFrom(*this);
1985         return ret.retn();
1986       }
1987     int ref(ranges.front().first),nbOfTuples(0);
1988     bool isIncreasing(true);
1989     for(std::vector<std::pair<int,int> >::const_iterator it=ranges.begin();it!=ranges.end();it++)
1990       {
1991         if((*it).first<=(*it).second)
1992           {
1993             if((*it).first>=0 && (*it).second<=nbOfTuplesThis)
1994               {
1995                 nbOfTuples+=(*it).second-(*it).first;
1996                 if(isIncreasing)
1997                   isIncreasing=ref<=(*it).first;
1998                 ref=(*it).second;
1999               }
2000             else
2001               {
2002                 std::ostringstream oss; oss << "DataArrayTemplate::selectByTupleRanges : on range #" << std::distance(ranges.begin(),it);
2003                 oss << " (" << (*it).first << "," << (*it).second << ") is greater than number of tuples of this :" << nbOfTuples << " !";
2004                 throw INTERP_KERNEL::Exception(oss.str().c_str());
2005               }
2006           }
2007         else
2008           {
2009             std::ostringstream oss; oss << "DataArrayTemplate::selectByTupleRanges : on range #" << std::distance(ranges.begin(),it);
2010             oss << " (" << (*it).first << "," << (*it).second << ") end is before begin !";
2011             throw INTERP_KERNEL::Exception(oss.str().c_str());
2012           }
2013       }
2014     if(isIncreasing && nbOfTuplesThis==nbOfTuples)
2015       return static_cast<typename Traits<T>::ArrayType *>(deepCopy());
2016     MCAuto<DataArray> ret0(buildNewEmptyInstance());
2017     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
2018     ret->alloc(nbOfTuples,nbOfComp);
2019     ret->copyStringInfoFrom(*this);
2020     const T *src(getConstPointer());
2021     T *work(ret->getPointer());
2022     for(std::vector<std::pair<int,int> >::const_iterator it=ranges.begin();it!=ranges.end();it++)
2023       work=std::copy(src+(*it).first*nbOfComp,src+(*it).second*nbOfComp,work);
2024     return ret.retn();
2025   }
2026
2027   /*!
2028    * Returns the first value of \a this. 
2029    *  \return double - the last value of \a this array.
2030    *  \throw If \a this is not allocated.
2031    *  \throw If \a this->getNumberOfComponents() != 1.
2032    *  \throw If \a this->getNumberOfTuples() < 1.
2033    */
2034   template<class T>
2035   T DataArrayTemplate<T>::front() const
2036   {
2037     checkAllocated();
2038     if(getNumberOfComponents()!=1)
2039       throw INTERP_KERNEL::Exception("DataArrayTemplate::front : number of components not equal to one !");
2040     int nbOfTuples(getNumberOfTuples());
2041     if(nbOfTuples<1)
2042       throw INTERP_KERNEL::Exception("DataArrayTemplate::front : number of tuples must be >= 1 !");
2043     return *(getConstPointer());
2044   }
2045   
2046   /*!
2047    * Returns the last value of \a this. 
2048    *  \return double - the last value of \a this array.
2049    *  \throw If \a this is not allocated.
2050    *  \throw If \a this->getNumberOfComponents() != 1.
2051    *  \throw If \a this->getNumberOfTuples() < 1.
2052    */
2053   template<class T>
2054   T DataArrayTemplate<T>::back() const
2055   {
2056     checkAllocated();
2057     if(getNumberOfComponents()!=1)
2058       throw INTERP_KERNEL::Exception("DataArrayTemplate::back : number of components not equal to one !");
2059     int nbOfTuples(getNumberOfTuples());
2060     if(nbOfTuples<1)
2061       throw INTERP_KERNEL::Exception("DataArrayTemplate::back : number of tuples must be >= 1 !");
2062     return *(getConstPointer()+nbOfTuples-1);
2063   }
2064   
2065   /*!
2066    * Returns the maximal value and its location within \a this one-dimensional array.
2067    *  \param [out] tupleId - index of the tuple holding the maximal value.
2068    *  \return double - the maximal value among all values of \a this array.
2069    *  \throw If \a this->getNumberOfComponents() != 1
2070    *  \throw If \a this->getNumberOfTuples() < 1
2071    */
2072   template<class T>
2073   T DataArrayTemplate<T>::getMaxValue(int& tupleId) const
2074   {
2075     checkAllocated();
2076     if(getNumberOfComponents()!=1)
2077       throw INTERP_KERNEL::Exception("DataArrayDouble::getMaxValue : must be applied on DataArrayDouble with only one component, you can call 'rearrange' method before or call 'getMaxValueInArray' method !");
2078     int nbOfTuples(getNumberOfTuples());
2079     if(nbOfTuples<=0)
2080       throw INTERP_KERNEL::Exception("DataArrayDouble::getMaxValue : array exists but number of tuples must be > 0 !");
2081     const T *vals(getConstPointer());
2082     const T *loc(std::max_element(vals,vals+nbOfTuples));
2083     tupleId=(int)std::distance(vals,loc);
2084     return *loc;
2085   }
2086   
2087   /*!
2088    * Returns the maximal value within \a this array that is allowed to have more than
2089    *  one component.
2090    *  \return double - the maximal value among all values of \a this array.
2091    *  \throw If \a this is not allocated.
2092    */
2093   template<class T>
2094   T DataArrayTemplate<T>::getMaxValueInArray() const
2095   {
2096     checkAllocated();
2097     const T *loc(std::max_element(begin(),end()));
2098     return *loc;
2099   }
2100   
2101   /*!
2102    * Returns the minimal value and its location within \a this one-dimensional array.
2103    *  \param [out] tupleId - index of the tuple holding the minimal value.
2104    *  \return double - the minimal value among all values of \a this array.
2105    *  \throw If \a this->getNumberOfComponents() != 1
2106    *  \throw If \a this->getNumberOfTuples() < 1
2107    */
2108   template<class T>
2109   T DataArrayTemplate<T>::getMinValue(int& tupleId) const
2110   {
2111     checkAllocated();
2112     if(getNumberOfComponents()!=1)
2113       throw INTERP_KERNEL::Exception("DataArrayDouble::getMinValue : must be applied on DataArrayDouble with only one component, you can call 'rearrange' method before call 'getMinValueInArray' method !");
2114     int nbOfTuples(getNumberOfTuples());
2115     if(nbOfTuples<=0)
2116       throw INTERP_KERNEL::Exception("DataArrayDouble::getMinValue : array exists but number of tuples must be > 0 !");
2117     const T *vals(getConstPointer());
2118     const T *loc(std::min_element(vals,vals+nbOfTuples));
2119     tupleId=(int)std::distance(vals,loc);
2120     return *loc;
2121   }
2122   
2123   /*!
2124    * Returns the minimal value within \a this array that is allowed to have more than
2125    *  one component.
2126    *  \return double - the minimal value among all values of \a this array.
2127    *  \throw If \a this is not allocated.
2128    */
2129   template<class T>
2130   T DataArrayTemplate<T>::getMinValueInArray() const
2131   {
2132     checkAllocated();
2133     const T *loc=std::min_element(begin(),end());
2134     return *loc;
2135   }
2136   
2137 }
2138
2139 #endif