Salome HOME
number of tuples and components are now std::size_t no more int.
[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(std::size_t nbOfTuple, std::size_t nbOfCompo)
515   {
516     _info_on_compo.resize(nbOfCompo);
517     _mem.alloc(nbOfCompo*nbOfTuple);
518     declareAsNew();
519   }
520
521   /*!
522    * Sets a C array to be used as raw data of \a this. The previously set info
523    *  of components is retained and re-sized. 
524    * For more info see \ref MEDCouplingArraySteps1.
525    *  \param [in] array - the C array to be used as raw data of \a this.
526    *  \param [in] ownership - if \a true, \a array will be deallocated at destruction of \a this.
527    *  \param [in] type - specifies how to deallocate \a array. If \a type == MEDCoupling::CPP_DEALLOC,
528    *                     \c delete [] \c array; will be called. If \a type == MEDCoupling::C_DEALLOC,
529    *                     \c free(\c array ) will be called.
530    *  \param [in] nbOfTuple - new number of tuples in \a this.
531    *  \param [in] nbOfCompo - new number of components in \a this.
532    */
533   template<class T>
534   void DataArrayTemplate<T>::useArray(const T *array, bool ownership, DeallocType type, int nbOfTuple, int nbOfCompo)
535   {
536     _info_on_compo.resize(nbOfCompo);
537     _mem.useArray(array,ownership,type,(std::size_t)nbOfTuple*nbOfCompo);
538     declareAsNew();
539   }
540   
541   template<class T>
542   void DataArrayTemplate<T>::useExternalArrayWithRWAccess(const T *array, int nbOfTuple, int nbOfCompo)
543   {
544     _info_on_compo.resize(nbOfCompo);
545     _mem.useExternalArrayWithRWAccess(array,(std::size_t)nbOfTuple*nbOfCompo);
546     declareAsNew();
547   }
548
549   /*!
550    * Returns a value located at specified tuple and component.
551    * This method is equivalent to DataArrayTemplate<T>::getIJ() except that validity of
552    * parameters is checked. So this method is safe but expensive if used to go through
553    * all values of \a this.
554    *  \param [in] tupleId - index of tuple of interest.
555    *  \param [in] compoId - index of component of interest.
556    *  \return double - value located by \a tupleId and \a compoId.
557    *  \throw If \a this is not allocated.
558    *  \throw If condition <em>( 0 <= tupleId < this->getNumberOfTuples() )</em> is violated.
559    *  \throw If condition <em>( 0 <= compoId < this->getNumberOfComponents() )</em> is violated.
560    */
561   template<class T>
562   T DataArrayTemplate<T>::getIJSafe(int tupleId, int compoId) const
563   {
564     checkAllocated();
565     if(tupleId<0 || tupleId>=getNumberOfTuples())
566       {
567         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::getIJSafe : request for tupleId " << tupleId << " should be in [0," << getNumberOfTuples() << ") !";
568         throw INTERP_KERNEL::Exception(oss.str().c_str());
569       }
570     if(compoId<0 || compoId>=getNumberOfComponents())
571       {
572         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::getIJSafe : request for compoId " << compoId << " should be in [0," << getNumberOfComponents() << ") !";
573         throw INTERP_KERNEL::Exception(oss.str().c_str());
574       }
575     return _mem[tupleId*_info_on_compo.size()+compoId];
576   }
577
578   /*!
579    * 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.
580    *
581    * \sa DataArray::getHeapMemorySizeWithoutChildren, DataArrayTemplate<T>::reserve
582    */
583   template<class T>
584   void DataArrayTemplate<T>::pack() const
585   {
586     _mem.pack();
587   }
588
589   /*!
590    * Checks if raw data is allocated. Read more on the raw data
591    * in \ref MEDCouplingArrayBasicsTuplesAndCompo "DataArrays infos" for more information.
592    *  \return bool - \a true if the raw data is allocated, \a false else.
593    */
594   template<class T>
595   bool DataArrayTemplate<T>::isAllocated() const
596   {
597     return getConstPointer()!=0;
598   }
599   
600   /*!
601    * Checks if raw data is allocated and throws an exception if it is not the case.
602    *  \throw If the raw data is not allocated.
603    */
604   template<class T>
605   void DataArrayTemplate<T>::checkAllocated() const
606   {
607     if(!isAllocated())
608       {
609         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::checkAllocated : Array is defined but not allocated ! Call alloc or setValues method first !";
610         throw INTERP_KERNEL::Exception(oss.str().c_str());
611       }
612   }
613   
614   /*!
615    * This method desallocated \a this without modification of informations relative to the components.
616    * After call of this method, DataArrayDouble::isAllocated will return false.
617    * If \a this is already not allocated, \a this is let unchanged.
618    */
619   template<class T>
620   void DataArrayTemplate<T>::desallocate()
621   {
622     _mem.destroy();
623   }
624
625   /*!
626    * This method reserve nbOfElems elements in memory ( nbOfElems*8 bytes ) \b without impacting the number of tuples in \a this.
627    * 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.
628    * If \a this has not already been allocated, number of components is set to one.
629    * This method allows to reduce number of reallocations on invokation of DataArrayDouble::pushBackSilent and DataArrayDouble::pushBackValsSilent on \a this.
630    * 
631    * \sa DataArrayDouble::pack, DataArrayDouble::pushBackSilent, DataArrayDouble::pushBackValsSilent
632    */
633   template<class T>
634   void DataArrayTemplate<T>::reserve(std::size_t nbOfElems)
635   {
636     int nbCompo(getNumberOfComponents());
637     if(nbCompo==1)
638       {
639         _mem.reserve(nbOfElems);
640       }
641     else if(nbCompo==0)
642       {
643         _mem.reserve(nbOfElems);
644         _info_on_compo.resize(1);
645       }
646     else
647       {
648         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::reserve : not available for DataArrayDouble with number of components different than 1 !";
649         throw INTERP_KERNEL::Exception(oss.str().c_str());
650       }
651   }
652   
653   /*!
654    * 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
655    * of counter. So the caller is expected to call TimeLabel::declareAsNew on \a this at the end of the push session.
656    *
657    * \param [in] val the value to be added in \a this
658    * \throw If \a this has already been allocated with number of components different from one.
659    * \sa DataArrayDouble::pushBackValsSilent
660    */
661   template<class T>
662   void DataArrayTemplate<T>::pushBackSilent(T val)
663   {
664     int nbCompo(getNumberOfComponents());
665     if(nbCompo==1)
666       _mem.pushBack(val);
667     else if(nbCompo==0)
668       {
669         _info_on_compo.resize(1);
670         _mem.pushBack(val);
671       }
672     else
673       {
674         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::pushBackSilent : not available for DataArrayDouble with number of components different than 1 !";
675         throw INTERP_KERNEL::Exception(oss.str().c_str());
676       }
677   }
678   
679   /*!
680    * 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
681    * of counter. So the caller is expected to call TimeLabel::declareAsNew on \a this at the end of the push session.
682    *
683    *  \param [in] valsBg - an array of values to push at the end of \c this.
684    *  \param [in] valsEnd - specifies the end of the array \a valsBg, so that
685    *              the last value of \a valsBg is \a valsEnd[ -1 ].
686    * \throw If \a this has already been allocated with number of components different from one.
687    * \sa DataArrayDouble::pushBackSilent
688    */
689   template<class T>
690   void DataArrayTemplate<T>::pushBackValsSilent(const T *valsBg, const T *valsEnd)
691   {
692     int nbCompo(getNumberOfComponents());
693     if(nbCompo==1)
694       _mem.insertAtTheEnd(valsBg,valsEnd);
695     else if(nbCompo==0)
696       {
697         _info_on_compo.resize(1);
698         _mem.insertAtTheEnd(valsBg,valsEnd);
699       }
700     else
701       {
702         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::pushBackValsSilent : not available for DataArrayDouble with number of components different than 1 !";
703         throw INTERP_KERNEL::Exception(oss.str().c_str());
704       }
705   }
706   
707   /*!
708    * This method returns silently ( without updating time label in \a this ) the last value, if any and suppress it.
709    * \throw If \a this is already empty.
710    * \throw If \a this has number of components different from one.
711    */
712   template<class T>
713   T DataArrayTemplate<T>::popBackSilent()
714   {
715     if(getNumberOfComponents()==1)
716       return _mem.popBack();
717     else
718       {
719         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::popBackSilent : not available for DataArrayDouble with number of components different than 1 !";
720         throw INTERP_KERNEL::Exception(oss.str().c_str());
721       }
722   }
723   
724   /*!
725    * Allocates the raw data in memory. If exactly same memory as needed already
726    * allocated, it is not re-allocated.
727    *  \param [in] nbOfTuple - number of tuples of data to allocate.
728    *  \param [in] nbOfCompo - number of components of data to allocate.
729    *  \throw If \a nbOfTuple < 0 or \a nbOfCompo < 0.
730    */
731   template<class T>
732   void DataArrayTemplate<T>::allocIfNecessary(int nbOfTuple, int nbOfCompo)
733   {
734     if(isAllocated())
735       {
736         if(nbOfTuple!=getNumberOfTuples() || nbOfCompo!=getNumberOfComponents())
737           alloc(nbOfTuple,nbOfCompo);
738       }
739     else
740       alloc(nbOfTuple,nbOfCompo);
741   }
742
743   /*!
744    * Checks the number of tuples.
745    *  \return bool - \a true if getNumberOfTuples() == 0, \a false else.
746    *  \throw If \a this is not allocated.
747    */
748   template<class T>
749   bool DataArrayTemplate<T>::empty() const
750   {
751     checkAllocated();
752     return getNumberOfTuples()==0;
753   }
754
755   /*!
756    * Copies all the data from another DataArrayDouble. For more info see
757    * \ref MEDCouplingArrayBasicsCopyDeepAssign.
758    *  \param [in] other - another instance of DataArrayDouble to copy data from.
759    *  \throw If the \a other is not allocated.
760    */
761   template<class T>
762   void DataArrayTemplate<T>::deepCopyFrom(const DataArrayTemplate<T>& other)
763   {
764     other.checkAllocated();
765     int nbOfTuples(other.getNumberOfTuples()),nbOfComp(other.getNumberOfComponents());
766     allocIfNecessary(nbOfTuples,nbOfComp);
767     std::size_t nbOfElems((std::size_t)nbOfTuples*nbOfComp);
768     T *pt(getPointer());
769     const T *ptI(other.begin());
770     for(std::size_t i=0;i<nbOfElems;i++)
771       pt[i]=ptI[i];
772     copyStringInfoFrom(other);
773   }
774
775   /*!
776    * Reverse the array values.
777    *  \throw If \a this->getNumberOfComponents() < 1.
778    *  \throw If \a this is not allocated.
779    */
780   template<class T>
781   void DataArrayTemplate<T>::reverse()
782   {
783     checkAllocated();
784     _mem.reverse(getNumberOfComponents());
785     declareAsNew();
786   }
787
788   /*!
789    * Assign \a val to all values in \a this array. To know more on filling arrays see
790    * \ref MEDCouplingArrayFill.
791    *  \param [in] val - the value to fill with.
792    *  \throw If \a this is not allocated.
793    */
794   template<class T>
795   void DataArrayTemplate<T>::fillWithValue(T val)
796   {
797     checkAllocated();
798     _mem.fillWithValue(val);
799     declareAsNew();
800   }
801
802   /*!
803    * Changes number of tuples in the array. If the new number of tuples is smaller
804    * than the current number the array is truncated, otherwise the array is extended.
805    *  \param [in] nbOfTuples - new number of tuples. 
806    *  \throw If \a this is not allocated.
807    *  \throw If \a nbOfTuples is negative.
808    */
809   template<class T>
810   void DataArrayTemplate<T>::reAlloc(std::size_t nbOfTuples)
811   {
812     checkAllocated();
813     _mem.reAlloc(getNumberOfComponents()*nbOfTuples);
814     declareAsNew();
815   }
816
817   /*!
818    * Permutes values of \a this array as required by \a old2New array. The values are
819    * permuted so that \c new[ \a old2New[ i ]] = \c old[ i ]. Number of tuples remains
820    * the same as in \c this one.
821    * If a permutation reduction is needed, subArray() or selectByTupleId() should be used.
822    * For more info on renumbering see \ref numbering.
823    *  \param [in] old2New - C array of length equal to \a this->getNumberOfTuples()
824    *     giving a new position for i-th old value.
825    */
826   template<class T>
827   void DataArrayTemplate<T>::renumberInPlace(const int *old2New)
828   {
829     checkAllocated();
830     int nbTuples(getNumberOfTuples()),nbOfCompo(getNumberOfComponents());
831     T *tmp(new T[nbTuples*nbOfCompo]);
832     const T *iptr(begin());
833     for(int i=0;i<nbTuples;i++)
834       {
835         int v=old2New[i];
836         if(v>=0 && v<nbTuples)
837           std::copy(iptr+nbOfCompo*i,iptr+nbOfCompo*(i+1),tmp+nbOfCompo*v);
838         else
839           {
840             std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::renumberInPlace : At place #" << i << " value is " << v << " ! Should be in [0," << nbTuples << ") !";
841             throw INTERP_KERNEL::Exception(oss.str().c_str());
842           }
843       }
844     std::copy(tmp,tmp+nbTuples*nbOfCompo,getPointer());
845     delete [] tmp;
846     declareAsNew();
847   }
848
849
850   /*!
851    * Permutes values of \a this array as required by \a new2Old array. The values are
852    * permuted so that \c new[ i ] = \c old[ \a new2Old[ i ]]. Number of tuples remains
853    * the same as in \c this one.
854    * For more info on renumbering see \ref numbering.
855    *  \param [in] new2Old - C array of length equal to \a this->getNumberOfTuples()
856    *     giving a previous position of i-th new value.
857    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
858    *          is to delete using decrRef() as it is no more needed.
859    */
860   template<class T>
861   void DataArrayTemplate<T>::renumberInPlaceR(const int *new2Old)
862   {
863     checkAllocated();
864     int nbTuples(getNumberOfTuples()),nbOfCompo(getNumberOfComponents());
865     T *tmp(new T[nbTuples*nbOfCompo]);
866     const T *iptr(begin());
867     for(int i=0;i<nbTuples;i++)
868       {
869         int v=new2Old[i];
870         if(v>=0 && v<nbTuples)
871           std::copy(iptr+nbOfCompo*v,iptr+nbOfCompo*(v+1),tmp+nbOfCompo*i);
872         else
873           {
874             std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::renumberInPlaceR : At place #" << i << " value is " << v << " ! Should be in [0," << nbTuples << ") !";
875             throw INTERP_KERNEL::Exception(oss.str().c_str());
876           }
877       }
878     std::copy(tmp,tmp+nbTuples*nbOfCompo,getPointer());
879     delete [] tmp;
880     declareAsNew();
881   }
882
883   /*!
884    * Sorts values of the array.
885    *  \param [in] asc - \a true means ascending order, \a false, descending.
886    *  \throw If \a this is not allocated.
887    *  \throw If \a this->getNumberOfComponents() != 1.
888    */
889   template<class T>
890   void DataArrayTemplate<T>::sort(bool asc)
891   {
892     checkAllocated();
893     if(getNumberOfComponents()!=1)
894       {
895         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::sort : only supported with 'this' array with ONE component !";
896         throw INTERP_KERNEL::Exception(oss.str().c_str());
897       }
898     _mem.sort(asc);
899     declareAsNew();
900   }
901
902   /*!
903    * Returns a copy of \a this array with values permuted as required by \a old2New array.
904    * The values are permuted so that  \c new[ \a old2New[ i ]] = \c old[ i ].
905    * Number of tuples in the result array remains the same as in \c this one.
906    * If a permutation reduction is needed, renumberAndReduce() should be used.
907    * For more info on renumbering see \ref numbering.
908    *  \param [in] old2New - C array of length equal to \a this->getNumberOfTuples()
909    *          giving a new position for i-th old value.
910    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
911    *          is to delete using decrRef() as it is no more needed.
912    *  \throw If \a this is not allocated.
913    */
914   template<class T>
915   typename Traits<T>::ArrayType *DataArrayTemplate<T>::renumber(const int *old2New) const
916   {
917     checkAllocated();
918     int nbTuples(getNumberOfTuples()),nbOfCompo(getNumberOfComponents());
919     MCAuto<DataArray> ret0(buildNewEmptyInstance());
920     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
921     ret->alloc(nbTuples,nbOfCompo);
922     ret->copyStringInfoFrom(*this);
923     const T *iptr(begin());
924     T *optr(ret->getPointer());
925     for(int i=0;i<nbTuples;i++)
926       std::copy(iptr+nbOfCompo*i,iptr+nbOfCompo*(i+1),optr+nbOfCompo*old2New[i]);
927     ret->copyStringInfoFrom(*this);
928     return ret.retn();
929   }
930
931   /*!
932    * Returns a copy of \a this array with values permuted as required by \a new2Old array.
933    * The values are permuted so that  \c new[ i ] = \c old[ \a new2Old[ i ]]. Number of
934    * tuples in the result array remains the same as in \c this one.
935    * If a permutation reduction is needed, subArray() or selectByTupleId() should be used.
936    * For more info on renumbering see \ref numbering.
937    *  \param [in] new2Old - C array of length equal to \a this->getNumberOfTuples()
938    *     giving a previous position of i-th new value.
939    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
940    *          is to delete using decrRef() as it is no more needed.
941    */
942   template<class T>
943   typename Traits<T>::ArrayType *DataArrayTemplate<T>::renumberR(const int *new2Old) const
944   {
945     checkAllocated();
946     int nbTuples(getNumberOfTuples()),nbOfCompo(getNumberOfComponents());
947     MCAuto<DataArray> ret0(buildNewEmptyInstance());
948     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
949     ret->alloc(nbTuples,nbOfCompo);
950     ret->copyStringInfoFrom(*this);
951     const T *iptr(getConstPointer());
952     T *optr(ret->getPointer());
953     for(int i=0;i<nbTuples;i++)
954       std::copy(iptr+nbOfCompo*new2Old[i],iptr+nbOfCompo*(new2Old[i]+1),optr+i*nbOfCompo);
955     ret->copyStringInfoFrom(*this);
956     return ret.retn();
957   }
958
959   /*!
960    * Returns a shorten and permuted copy of \a this array. The new DataArrayDouble is
961    * of size \a newNbOfTuple and it's values are permuted as required by \a old2New array.
962    * The values are permuted so that  \c new[ \a old2New[ i ]] = \c old[ i ] for all
963    * \a old2New[ i ] >= 0. In other words every i-th tuple in \a this array, for which 
964    * \a old2New[ i ] is negative, is missing from the result array.
965    * For more info on renumbering see \ref numbering.
966    *  \param [in] old2New - C array of length equal to \a this->getNumberOfTuples()
967    *     giving a new position for i-th old tuple and giving negative position for
968    *     for i-th old tuple that should be omitted.
969    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
970    *          is to delete using decrRef() as it is no more needed.
971    */
972   template<class T>
973   typename Traits<T>::ArrayType *DataArrayTemplate<T>::renumberAndReduce(const int *old2New, int newNbOfTuple) const
974   {
975     checkAllocated();
976     int nbTuples(getNumberOfTuples()),nbOfCompo(getNumberOfComponents());
977     MCAuto<DataArray> ret0(buildNewEmptyInstance());
978     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
979     ret->alloc(newNbOfTuple,nbOfCompo);
980     const T *iptr=getConstPointer();
981     T *optr=ret->getPointer();
982     for(int i=0;i<nbTuples;i++)
983       {
984         int w=old2New[i];
985         if(w>=0)
986           std::copy(iptr+i*nbOfCompo,iptr+(i+1)*nbOfCompo,optr+w*nbOfCompo);
987       }
988     ret->copyStringInfoFrom(*this);
989     return ret.retn();
990   }
991
992   /*!
993    * Returns a shorten and permuted copy of \a this array. The new DataArrayDouble is
994    * of size \a new2OldEnd - \a new2OldBg and it's values are permuted as required by
995    * \a new2OldBg array.
996    * The values are permuted so that  \c new[ i ] = \c old[ \a new2OldBg[ i ]].
997    * This method is equivalent to renumberAndReduce() except that convention in input is
998    * \c new2old and \b not \c old2new.
999    * For more info on renumbering see \ref numbering.
1000    *  \param [in] new2OldBg - pointer to the beginning of a permutation array that gives a
1001    *              tuple index in \a this array to fill the i-th tuple in the new array.
1002    *  \param [in] new2OldEnd - specifies the end of the permutation array that starts at
1003    *              \a new2OldBg, so that pointer to a tuple index (\a pi) varies as this:
1004    *              \a new2OldBg <= \a pi < \a new2OldEnd.
1005    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1006    *          is to delete using decrRef() as it is no more needed.
1007    */
1008   template<class T>
1009   typename Traits<T>::ArrayType *DataArrayTemplate<T>::mySelectByTupleId(const int *new2OldBg, const int *new2OldEnd) const
1010   {
1011     checkAllocated();
1012     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1013     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1014     int nbComp(getNumberOfComponents());
1015     ret->alloc((int)std::distance(new2OldBg,new2OldEnd),nbComp);
1016     ret->copyStringInfoFrom(*this);
1017     T *pt(ret->getPointer());
1018     const T *srcPt(getConstPointer());
1019     int i(0);
1020     for(const int *w=new2OldBg;w!=new2OldEnd;w++,i++)
1021       std::copy(srcPt+(*w)*nbComp,srcPt+((*w)+1)*nbComp,pt+i*nbComp);
1022     ret->copyStringInfoFrom(*this);
1023     return ret.retn();
1024   }
1025
1026   template<class T>
1027   typename Traits<T>::ArrayType *DataArrayTemplate<T>::mySelectByTupleId(const DataArrayInt& di) const
1028   {
1029     return DataArrayTemplate<T>::mySelectByTupleId(di.begin(),di.end());
1030   }
1031   
1032   /*!
1033    * Returns a shorten and permuted copy of \a this array. The new DataArrayDouble is
1034    * of size \a new2OldEnd - \a new2OldBg and it's values are permuted as required by
1035    * \a new2OldBg array.
1036    * The values are permuted so that  \c new[ i ] = \c old[ \a new2OldBg[ i ]].
1037    * This method is equivalent to renumberAndReduce() except that convention in input is
1038    * \c new2old and \b not \c old2new.
1039    * This method is equivalent to selectByTupleId() except that it prevents coping data
1040    * from behind the end of \a this array.
1041    * For more info on renumbering see \ref numbering.
1042    *  \param [in] new2OldBg - pointer to the beginning of a permutation array that gives a
1043    *              tuple index in \a this array to fill the i-th tuple in the new array.
1044    *  \param [in] new2OldEnd - specifies the end of the permutation array that starts at
1045    *              \a new2OldBg, so that pointer to a tuple index (\a pi) varies as this:
1046    *              \a new2OldBg <= \a pi < \a new2OldEnd.
1047    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1048    *          is to delete using decrRef() as it is no more needed.
1049    *  \throw If \a new2OldEnd - \a new2OldBg > \a this->getNumberOfTuples().
1050    */
1051   template<class T>
1052   typename Traits<T>::ArrayType *DataArrayTemplate<T>::mySelectByTupleIdSafe(const int *new2OldBg, const int *new2OldEnd) const
1053   {
1054     checkAllocated();
1055     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1056     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1057     int nbComp(getNumberOfComponents()),oldNbOfTuples(getNumberOfTuples());
1058     ret->alloc((int)std::distance(new2OldBg,new2OldEnd),nbComp);
1059     ret->copyStringInfoFrom(*this);
1060     T *pt(ret->getPointer());
1061     const T *srcPt(getConstPointer());
1062     int i(0);
1063     for(const int *w=new2OldBg;w!=new2OldEnd;w++,i++)
1064       if(*w>=0 && *w<oldNbOfTuples)
1065         std::copy(srcPt+(*w)*nbComp,srcPt+((*w)+1)*nbComp,pt+i*nbComp);
1066       else
1067         {
1068           std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::selectByTupleIdSafe : some ids has been detected to be out of [0,this->getNumberOfTuples) !";
1069           throw INTERP_KERNEL::Exception(oss.str().c_str());
1070         }
1071     ret->copyStringInfoFrom(*this);
1072     return ret.retn();
1073   }
1074
1075   /*!
1076    * Changes the number of components within \a this array so that its raw data **does
1077    * not** change, instead splitting this data into tuples changes.
1078    *  \warning This method erases all (name and unit) component info set before!
1079    *  \param [in] newNbOfComp - number of components for \a this array to have.
1080    *  \throw If \a this is not allocated
1081    *  \throw If getNbOfElems() % \a newNbOfCompo != 0.
1082    *  \throw If \a newNbOfCompo is lower than 1.
1083    *  \throw If the rearrange method would lead to a number of tuples higher than 2147483647 (maximal capacity of int32 !).
1084    *  \warning This method erases all (name and unit) component info set before!
1085    */
1086   template<class T>
1087   void DataArrayTemplate<T>::rearrange(int newNbOfCompo)
1088   {
1089     checkAllocated();
1090     if(newNbOfCompo<1)
1091       {
1092         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::rearrange : input newNbOfCompo must be > 0 !";
1093         throw INTERP_KERNEL::Exception(oss.str().c_str());
1094       }
1095     std::size_t nbOfElems=getNbOfElems();
1096     if(nbOfElems%newNbOfCompo!=0)
1097       {
1098         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::rearrange : nbOfElems%newNbOfCompo!=0 !";
1099         throw INTERP_KERNEL::Exception(oss.str().c_str());
1100       }
1101     if(nbOfElems/newNbOfCompo>(std::size_t)std::numeric_limits<int>::max())
1102       {
1103         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::rearrange : the rearrangement leads to too high number of tuples (> 2147483647) !";
1104         throw INTERP_KERNEL::Exception(oss.str().c_str());
1105       }
1106     _info_on_compo.clear();
1107     _info_on_compo.resize(newNbOfCompo);
1108     declareAsNew();
1109   }
1110
1111   /*!
1112    * Changes the number of components within \a this array to be equal to its number
1113    * of tuples, and inversely its number of tuples to become equal to its number of 
1114    * components. So that its raw data **does not** change, instead splitting this
1115    * data into tuples changes.
1116    *  \warning This method erases all (name and unit) component info set before!
1117    *  \warning Do not confuse this method with fromNoInterlace() and toNoInterlace()!
1118    *  \throw If \a this is not allocated.
1119    *  \sa rearrange()
1120    */
1121   template<class T>
1122   void DataArrayTemplate<T>::transpose()
1123   {
1124     checkAllocated();
1125     int nbOfTuples(getNumberOfTuples());
1126     rearrange(nbOfTuples);
1127   }
1128
1129   /*!
1130    * Returns a shorten or extended copy of \a this array. If \a newNbOfComp is less
1131    * than \a this->getNumberOfComponents() then the result array is shorten as each tuple
1132    * is truncated to have \a newNbOfComp components, keeping first components. If \a
1133    * newNbOfComp is more than \a this->getNumberOfComponents() then the result array is
1134    * expanded as each tuple is populated with \a dftValue to have \a newNbOfComp
1135    * components.  
1136    *  \param [in] newNbOfComp - number of components for the new array to have.
1137    *  \param [in] dftValue - value assigned to new values added to the new array.
1138    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1139    *          is to delete using decrRef() as it is no more needed.
1140    *  \throw If \a this is not allocated.
1141    */
1142   template<class T>
1143   typename Traits<T>::ArrayType *DataArrayTemplate<T>::changeNbOfComponents(int newNbOfComp, T dftValue) const
1144   {
1145     checkAllocated();
1146     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1147     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1148     ret->alloc(getNumberOfTuples(),newNbOfComp);
1149     const T *oldc(getConstPointer());
1150     T *nc(ret->getPointer());
1151     int nbOfTuples(getNumberOfTuples()),oldNbOfComp(getNumberOfComponents());
1152     int dim(std::min(oldNbOfComp,newNbOfComp));
1153     for(int i=0;i<nbOfTuples;i++)
1154       {
1155         int j=0;
1156         for(;j<dim;j++)
1157           nc[newNbOfComp*i+j]=oldc[i*oldNbOfComp+j];
1158         for(;j<newNbOfComp;j++)
1159           nc[newNbOfComp*i+j]=dftValue;
1160       }
1161     ret->setName(getName());
1162     for(int i=0;i<dim;i++)
1163       ret->setInfoOnComponent(i,getInfoOnComponent(i));
1164     ret->setName(getName());
1165     return ret.retn();
1166   }
1167
1168   /*!
1169    * Returns a copy of \a this array composed of selected components.
1170    * The new DataArrayDouble has the same number of tuples but includes components
1171    * specified by \a compoIds parameter. So that getNbOfElems() of the result array
1172    * can be either less, same or more than \a this->getNbOfElems().
1173    *  \param [in] compoIds - sequence of zero based indices of components to include
1174    *              into the new array.
1175    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1176    *          is to delete using decrRef() as it is no more needed.
1177    *  \throw If \a this is not allocated.
1178    *  \throw If a component index (\a i) is not valid: 
1179    *         \a i < 0 || \a i >= \a this->getNumberOfComponents().
1180    *
1181    *  \if ENABLE_EXAMPLES
1182    *  \ref py_mcdataarraydouble_KeepSelectedComponents "Here is a Python example".
1183    *  \endif
1184    */
1185   template<class T>
1186   typename Traits<T>::ArrayType *DataArrayTemplate<T>::myKeepSelectedComponents(const std::vector<int>& compoIds) const
1187   {
1188     checkAllocated();
1189     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1190     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1191     std::size_t newNbOfCompo(compoIds.size());
1192     int oldNbOfCompo(getNumberOfComponents());
1193     for(std::vector<int>::const_iterator it=compoIds.begin();it!=compoIds.end();it++)
1194       if((*it)<0 || (*it)>=oldNbOfCompo)
1195         {
1196           std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::keepSelectedComponents : invalid requested component : " << *it << " whereas it should be in [0," << oldNbOfCompo << ") !";
1197           throw INTERP_KERNEL::Exception(oss.str().c_str());
1198         }
1199     int nbOfTuples(getNumberOfTuples());
1200     ret->alloc(nbOfTuples,(int)newNbOfCompo);
1201     ret->copyPartOfStringInfoFrom(*this,compoIds);
1202     const T *oldc(getConstPointer());
1203     T *nc(ret->getPointer());
1204     for(int i=0;i<nbOfTuples;i++)
1205       for(std::size_t j=0;j<newNbOfCompo;j++,nc++)
1206         *nc=oldc[i*oldNbOfCompo+compoIds[j]];
1207     return ret.retn();
1208   }
1209
1210   /*!
1211    * Returns a shorten copy of \a this array. The new DataArrayDouble contains all
1212    * tuples starting from the \a tupleIdBg-th tuple and including all tuples located before
1213    * the \a tupleIdEnd-th one. This methods has a similar behavior as std::string::substr().
1214    * This method is a specialization of selectByTupleIdSafeSlice().
1215    *  \param [in] tupleIdBg - index of the first tuple to copy from \a this array.
1216    *  \param [in] tupleIdEnd - index of the tuple before which the tuples to copy are located.
1217    *          If \a tupleIdEnd == -1, all the tuples till the end of \a this array are copied.
1218    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1219    *          is to delete using decrRef() as it is no more needed.
1220    *  \throw If \a tupleIdBg < 0.
1221    *  \throw If \a tupleIdBg > \a this->getNumberOfTuples().
1222    *  \throw If \a tupleIdEnd != -1 && \a tupleIdEnd < \a this->getNumberOfTuples().
1223    *  \sa DataArrayDouble::selectByTupleIdSafeSlice
1224    */
1225   template<class T>
1226   typename Traits<T>::ArrayType *DataArrayTemplate<T>::subArray(int tupleIdBg, int tupleIdEnd) const
1227   {
1228     checkAllocated();
1229     int nbt(getNumberOfTuples());
1230     if(tupleIdBg<0)
1231       {
1232         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::subArray : The tupleIdBg parameter must be greater than 0 !";
1233         throw INTERP_KERNEL::Exception(oss.str().c_str());
1234       }
1235     if(tupleIdBg>nbt)
1236       {
1237         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << ":subArray : The tupleIdBg parameter is greater than number of tuples !";
1238         throw INTERP_KERNEL::Exception(oss.str().c_str());
1239       }
1240     int trueEnd=tupleIdEnd;
1241     if(tupleIdEnd!=-1)
1242       {
1243         if(tupleIdEnd>nbt)
1244           {
1245             std::ostringstream oss; oss << Traits<T>::ArrayTypeName << ":subArray : The tupleIdBg parameter is greater than number of tuples !";
1246             throw INTERP_KERNEL::Exception(oss.str().c_str());
1247           }
1248       }
1249     else
1250       trueEnd=nbt;
1251     int nbComp(getNumberOfComponents());
1252     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1253     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1254     ret->alloc(trueEnd-tupleIdBg,nbComp);
1255     ret->copyStringInfoFrom(*this);
1256     std::copy(getConstPointer()+tupleIdBg*nbComp,getConstPointer()+trueEnd*nbComp,ret->getPointer());
1257     return ret.retn();
1258   }
1259
1260   /*!
1261    * Returns a shorten copy of \a this array. The new DataArrayDouble contains every
1262    * (\a bg + \c i * \a step)-th tuple of \a this array located before the \a end2-th
1263    * tuple. Indices of the selected tuples are the same as ones returned by the Python
1264    * command \c range( \a bg, \a end2, \a step ).
1265    * This method is equivalent to selectByTupleIdSafe() except that the input array is
1266    * not constructed explicitly.
1267    * For more info on renumbering see \ref numbering.
1268    *  \param [in] bg - index of the first tuple to copy from \a this array.
1269    *  \param [in] end2 - index of the tuple before which the tuples to copy are located.
1270    *  \param [in] step - index increment to get index of the next tuple to copy.
1271    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1272    *          is to delete using decrRef() as it is no more needed.
1273    *  \sa DataArrayDouble::subArray.
1274    */
1275   template<class T>
1276   typename Traits<T>::ArrayType *DataArrayTemplate<T>::mySelectByTupleIdSafeSlice(int bg, int end2, int step) const
1277   {
1278     checkAllocated();
1279     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1280     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1281     int nbComp(getNumberOfComponents());
1282     std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::selectByTupleIdSafeSlice : ";
1283     int newNbOfTuples(GetNumberOfItemGivenBESRelative(bg,end2,step,oss.str()));
1284     ret->alloc(newNbOfTuples,nbComp);
1285     T *pt(ret->getPointer());
1286     const T *srcPt(getConstPointer()+bg*nbComp);
1287     for(int i=0;i<newNbOfTuples;i++,srcPt+=step*nbComp)
1288       std::copy(srcPt,srcPt+nbComp,pt+i*nbComp);
1289     ret->copyStringInfoFrom(*this);
1290     return ret.retn();
1291   }
1292   
1293   /*!
1294    * Copy all values from another DataArrayDouble into specified tuples and components
1295    * of \a this array. Textual data is not copied.
1296    * The tree parameters defining set of indices of tuples and components are similar to
1297    * the tree parameters of the Python function \c range(\c start,\c stop,\c step).
1298    *  \param [in] a - the array to copy values from.
1299    *  \param [in] bgTuples - index of the first tuple of \a this array to assign values to.
1300    *  \param [in] endTuples - index of the tuple before which the tuples to assign to
1301    *              are located.
1302    *  \param [in] stepTuples - index increment to get index of the next tuple to assign to.
1303    *  \param [in] bgComp - index of the first component of \a this array to assign values to.
1304    *  \param [in] endComp - index of the component before which the components to assign
1305    *              to are located.
1306    *  \param [in] stepComp - index increment to get index of the next component to assign to.
1307    *  \param [in] strictCompoCompare - if \a true (by default), then \a a->getNumberOfComponents() 
1308    *              must be equal to the number of columns to assign to, else an
1309    *              exception is thrown; if \a false, then it is only required that \a
1310    *              a->getNbOfElems() equals to number of values to assign to (this condition
1311    *              must be respected even if \a strictCompoCompare is \a true). The number of 
1312    *              values to assign to is given by following Python expression:
1313    *              \a nbTargetValues = 
1314    *              \c len(\c range(\a bgTuples,\a endTuples,\a stepTuples)) *
1315    *              \c len(\c range(\a bgComp,\a endComp,\a stepComp)).
1316    *  \throw If \a a is NULL.
1317    *  \throw If \a a is not allocated.
1318    *  \throw If \a this is not allocated.
1319    *  \throw If parameters specifying tuples and components to assign to do not give a
1320    *            non-empty range of increasing indices.
1321    *  \throw If \a a->getNbOfElems() != \a nbTargetValues.
1322    *  \throw If \a strictCompoCompare == \a true && \a a->getNumberOfComponents() !=
1323    *            \c len(\c range(\a bgComp,\a endComp,\a stepComp)).
1324    *
1325    *  \if ENABLE_EXAMPLES
1326    *  \ref py_mcdataarraydouble_setpartofvalues1 "Here is a Python example".
1327    *  \endif
1328    */
1329   template<class T>
1330   void DataArrayTemplate<T>::setPartOfValues1(const typename Traits<T>::ArrayType *a, int bgTuples, int endTuples, int stepTuples, int bgComp, int endComp, int stepComp, bool strictCompoCompare)
1331   {
1332     if(!a)
1333       {
1334         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::setPartOfValues1 : input DataArrayDouble is NULL !";
1335         throw INTERP_KERNEL::Exception(oss.str().c_str());
1336       }
1337     const char msg[]="DataArrayTemplate::setPartOfValues1";
1338     checkAllocated();
1339     a->checkAllocated();
1340     int newNbOfTuples(DataArray::GetNumberOfItemGivenBES(bgTuples,endTuples,stepTuples,msg));
1341     int newNbOfComp(DataArray::GetNumberOfItemGivenBES(bgComp,endComp,stepComp,msg));
1342     int nbComp(getNumberOfComponents()),nbOfTuples(getNumberOfTuples());
1343     DataArray::CheckValueInRangeEx(nbOfTuples,bgTuples,endTuples,"invalid tuple value");
1344     DataArray::CheckValueInRangeEx(nbComp,bgComp,endComp,"invalid component value");
1345     bool assignTech(true);
1346     if(a->getNbOfElems()==(std::size_t)newNbOfTuples*newNbOfComp)
1347       {
1348         if(strictCompoCompare)
1349           a->checkNbOfTuplesAndComp(newNbOfTuples,newNbOfComp,msg);
1350       }
1351     else
1352       {
1353         a->checkNbOfTuplesAndComp(1,newNbOfComp,msg);
1354         assignTech=false;
1355       }
1356     const T *srcPt(a->getConstPointer());
1357     T *pt(getPointer()+bgTuples*nbComp+bgComp);
1358     if(assignTech)
1359       {
1360         for(int i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
1361           for(int j=0;j<newNbOfComp;j++,srcPt++)
1362             pt[j*stepComp]=*srcPt;
1363       }
1364     else
1365       {
1366         for(int i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
1367           {
1368             const T*srcPt2=srcPt;
1369             for(int j=0;j<newNbOfComp;j++,srcPt2++)
1370               pt[j*stepComp]=*srcPt2;
1371           }
1372       }
1373   }
1374   
1375   /*!
1376  * Assign a given value to values at specified tuples and components of \a this array.
1377  * The tree parameters defining set of indices of tuples and components are similar to
1378  * the tree parameters of the Python function \c range(\c start,\c stop,\c step)..
1379  *  \param [in] a - the value to assign.
1380  *  \param [in] bgTuples - index of the first tuple of \a this array to assign to.
1381  *  \param [in] endTuples - index of the tuple before which the tuples to assign to
1382  *              are located.
1383  *  \param [in] stepTuples - index increment to get index of the next tuple to assign to.
1384  *  \param [in] bgComp - index of the first component of \a this array to assign to.
1385  *  \param [in] endComp - index of the component before which the components to assign
1386  *              to are located.
1387  *  \param [in] stepComp - index increment to get index of the next component to assign to.
1388  *  \throw If \a this is not allocated.
1389  *  \throw If parameters specifying tuples and components to assign to, do not give a
1390  *            non-empty range of increasing indices or indices are out of a valid range
1391  *            for \c this array.
1392  *
1393  *  \if ENABLE_EXAMPLES
1394  *  \ref py_mcdataarraydouble_setpartofvaluessimple1 "Here is a Python example".
1395  *  \endif
1396  */
1397   template<class T>
1398   void DataArrayTemplate<T>::setPartOfValuesSimple1(T a, int bgTuples, int endTuples, int stepTuples, int bgComp, int endComp, int stepComp)
1399   {
1400     const char msg[]="DataArrayTemplate::setPartOfValuesSimple1";
1401     checkAllocated();
1402     int newNbOfTuples(DataArray::GetNumberOfItemGivenBES(bgTuples,endTuples,stepTuples,msg));
1403     int newNbOfComp(DataArray::GetNumberOfItemGivenBES(bgComp,endComp,stepComp,msg));
1404     int nbComp(getNumberOfComponents()),nbOfTuples(getNumberOfTuples());
1405     DataArray::CheckValueInRangeEx(nbOfTuples,bgTuples,endTuples,"invalid tuple value");
1406     DataArray::CheckValueInRangeEx(nbComp,bgComp,endComp,"invalid component value");
1407     T *pt=getPointer()+bgTuples*nbComp+bgComp;
1408     for(int i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
1409       for(int j=0;j<newNbOfComp;j++)
1410         pt[j*stepComp]=a;
1411   }
1412   
1413   /*!
1414    * Copy all values from another DataArrayDouble (\a a) into specified tuples and 
1415    * components of \a this array. Textual data is not copied.
1416    * The tuples and components to assign to are defined by C arrays of indices.
1417    * There are two *modes of usage*:
1418    * - If \a a->getNbOfElems() equals to number of values to assign to, then every value
1419    *   of \a a is assigned to its own location within \a this array. 
1420    * - If \a a includes one tuple, then all values of \a a are assigned to the specified
1421    *   components of every specified tuple of \a this array. In this mode it is required
1422    *   that \a a->getNumberOfComponents() equals to the number of specified components.
1423    *
1424    *  \param [in] a - the array to copy values from.
1425    *  \param [in] bgTuples - pointer to an array of tuple indices of \a this array to
1426    *              assign values of \a a to.
1427    *  \param [in] endTuples - specifies the end of the array \a bgTuples, so that
1428    *              pointer to a tuple index <em>(pi)</em> varies as this: 
1429    *              \a bgTuples <= \a pi < \a endTuples.
1430    *  \param [in] bgComp - pointer to an array of component indices of \a this array to
1431    *              assign values of \a a to.
1432    *  \param [in] endComp - specifies the end of the array \a bgTuples, so that
1433    *              pointer to a component index <em>(pi)</em> varies as this: 
1434    *              \a bgComp <= \a pi < \a endComp.
1435    *  \param [in] strictCompoCompare - this parameter is checked only if the
1436    *               *mode of usage* is the first; if it is \a true (default), 
1437    *               then \a a->getNumberOfComponents() must be equal 
1438    *               to the number of specified columns, else this is not required.
1439    *  \throw If \a a is NULL.
1440    *  \throw If \a a is not allocated.
1441    *  \throw If \a this is not allocated.
1442    *  \throw If any index of tuple/component given by <em>bgTuples / bgComp</em> is
1443    *         out of a valid range for \a this array.
1444    *  \throw In the first *mode of usage*, if <em>strictCompoCompare == true </em> and
1445    *         if <em> a->getNumberOfComponents() != (endComp - bgComp) </em>.
1446    *  \throw In the second *mode of usage*, if \a a->getNumberOfTuples() != 1 or
1447    *         <em> a->getNumberOfComponents() != (endComp - bgComp)</em>.
1448    *
1449    *  \if ENABLE_EXAMPLES
1450    *  \ref py_mcdataarraydouble_setpartofvalues2 "Here is a Python example".
1451    *  \endif
1452    */
1453   template<class T>
1454   void DataArrayTemplate<T>::setPartOfValues2(const typename Traits<T>::ArrayType *a, const int *bgTuples, const int *endTuples, const int *bgComp, const int *endComp, bool strictCompoCompare)
1455   {
1456     if(!a)
1457       throw INTERP_KERNEL::Exception("DataArrayDouble::setPartOfValues2 : input DataArrayDouble is NULL !");
1458     const char msg[]="DataArrayTemplate::setPartOfValues2";
1459     checkAllocated();
1460     a->checkAllocated();
1461     int nbComp(getNumberOfComponents()),nbOfTuples(getNumberOfTuples());
1462     for(const int *z=bgComp;z!=endComp;z++)
1463       DataArray::CheckValueInRange(nbComp,*z,"invalid component id");
1464     int newNbOfTuples((int)std::distance(bgTuples,endTuples));
1465     int newNbOfComp((int)std::distance(bgComp,endComp));
1466     bool assignTech(true);
1467     if(a->getNbOfElems()==(std::size_t)newNbOfTuples*newNbOfComp)
1468       {
1469         if(strictCompoCompare)
1470           a->checkNbOfTuplesAndComp(newNbOfTuples,newNbOfComp,msg);
1471       }
1472     else
1473       {
1474         a->checkNbOfTuplesAndComp(1,newNbOfComp,msg);
1475         assignTech=false;
1476       }
1477     T *pt(getPointer());
1478     const T *srcPt(a->getConstPointer());
1479     if(assignTech)
1480       {    
1481         for(const int *w=bgTuples;w!=endTuples;w++)
1482           {
1483             DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1484             for(const int *z=bgComp;z!=endComp;z++,srcPt++)
1485               {    
1486                 pt[(std::size_t)(*w)*nbComp+(*z)]=*srcPt;
1487               }
1488           }
1489       }
1490     else
1491       {
1492         for(const int *w=bgTuples;w!=endTuples;w++)
1493           {
1494             const T *srcPt2=srcPt;
1495             DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1496             for(const int *z=bgComp;z!=endComp;z++,srcPt2++)
1497               {    
1498                 pt[(std::size_t)(*w)*nbComp+(*z)]=*srcPt2;
1499               }
1500           }
1501       }
1502   }
1503   
1504   /*!
1505    * Assign a given value to values at specified tuples and components of \a this array.
1506    * The tuples and components to assign to are defined by C arrays of indices.
1507    *  \param [in] a - the value to assign.
1508    *  \param [in] bgTuples - pointer to an array of tuple indices of \a this array to
1509    *              assign \a a to.
1510    *  \param [in] endTuples - specifies the end of the array \a bgTuples, so that
1511    *              pointer to a tuple index (\a pi) varies as this: 
1512    *              \a bgTuples <= \a pi < \a endTuples.
1513    *  \param [in] bgComp - pointer to an array of component indices of \a this array to
1514    *              assign \a a to.
1515    *  \param [in] endComp - specifies the end of the array \a bgTuples, so that
1516    *              pointer to a component index (\a pi) varies as this: 
1517    *              \a bgComp <= \a pi < \a endComp.
1518    *  \throw If \a this is not allocated.
1519    *  \throw If any index of tuple/component given by <em>bgTuples / bgComp</em> is
1520    *         out of a valid range for \a this array.
1521    *
1522    *  \if ENABLE_EXAMPLES
1523    *  \ref py_mcdataarraydouble_setpartofvaluessimple2 "Here is a Python example".
1524    *  \endif
1525    */
1526   template<class T>
1527   void DataArrayTemplate<T>::setPartOfValuesSimple2(T a, const int *bgTuples, const int *endTuples, const int *bgComp, const int *endComp)
1528   {
1529     checkAllocated();
1530     int nbComp(getNumberOfComponents()),nbOfTuples(getNumberOfTuples());
1531     for(const int *z=bgComp;z!=endComp;z++)
1532       DataArray::CheckValueInRange(nbComp,*z,"invalid component id");
1533     T *pt(getPointer());
1534     for(const int *w=bgTuples;w!=endTuples;w++)
1535       for(const int *z=bgComp;z!=endComp;z++)
1536         {
1537           DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1538           pt[(std::size_t)(*w)*nbComp+(*z)]=a;
1539         }
1540   }
1541   
1542   /*!
1543    * Copy all values from another DataArrayDouble (\a a) into specified tuples and 
1544    * components of \a this array. Textual data is not copied.
1545    * The tuples to assign to are defined by a C array of indices.
1546    * The components to assign to are defined by three values similar to parameters of
1547    * the Python function \c range(\c start,\c stop,\c step).
1548    * There are two *modes of usage*:
1549    * - If \a a->getNbOfElems() equals to number of values to assign to, then every value
1550    *   of \a a is assigned to its own location within \a this array. 
1551    * - If \a a includes one tuple, then all values of \a a are assigned to the specified
1552    *   components of every specified tuple of \a this array. In this mode it is required
1553    *   that \a a->getNumberOfComponents() equals to the number of specified components.
1554    *
1555    *  \param [in] a - the array to copy values from.
1556    *  \param [in] bgTuples - pointer to an array of tuple indices of \a this array to
1557    *              assign values of \a a to.
1558    *  \param [in] endTuples - specifies the end of the array \a bgTuples, so that
1559    *              pointer to a tuple index <em>(pi)</em> varies as this: 
1560    *              \a bgTuples <= \a pi < \a endTuples.
1561    *  \param [in] bgComp - index of the first component of \a this array to assign to.
1562    *  \param [in] endComp - index of the component before which the components to assign
1563    *              to are located.
1564    *  \param [in] stepComp - index increment to get index of the next component to assign to.
1565    *  \param [in] strictCompoCompare - this parameter is checked only in the first
1566    *               *mode of usage*; if \a strictCompoCompare is \a true (default), 
1567    *               then \a a->getNumberOfComponents() must be equal 
1568    *               to the number of specified columns, else this is not required.
1569    *  \throw If \a a is NULL.
1570    *  \throw If \a a is not allocated.
1571    *  \throw If \a this is not allocated.
1572    *  \throw If any index of tuple given by \a bgTuples is out of a valid range for 
1573    *         \a this array.
1574    *  \throw In the first *mode of usage*, if <em>strictCompoCompare == true </em> and
1575    *         if <em> a->getNumberOfComponents()</em> is unequal to the number of components
1576    *         defined by <em>(bgComp,endComp,stepComp)</em>.
1577    *  \throw In the second *mode of usage*, if \a a->getNumberOfTuples() != 1 or
1578    *         <em> a->getNumberOfComponents()</em> is unequal to the number of components
1579    *         defined by <em>(bgComp,endComp,stepComp)</em>.
1580    *  \throw If parameters specifying components to assign to, do not give a
1581    *            non-empty range of increasing indices or indices are out of a valid range
1582    *            for \c this array.
1583    *
1584    *  \if ENABLE_EXAMPLES
1585    *  \ref py_mcdataarraydouble_setpartofvalues3 "Here is a Python example".
1586    *  \endif
1587    */
1588   template<class T>
1589   void DataArrayTemplate<T>::setPartOfValues3(const typename Traits<T>::ArrayType *a, const int *bgTuples, const int *endTuples, int bgComp, int endComp, int stepComp, bool strictCompoCompare)
1590   {
1591     if(!a)
1592       throw INTERP_KERNEL::Exception("DataArrayTemplate::setPartOfValues3 : input DataArrayDouble is NULL !");
1593     const char msg[]="DataArrayTemplate::setPartOfValues3";
1594     checkAllocated();
1595     a->checkAllocated();
1596     int newNbOfComp=DataArray::GetNumberOfItemGivenBES(bgComp,endComp,stepComp,msg);
1597     int nbComp=getNumberOfComponents();
1598     int nbOfTuples=getNumberOfTuples();
1599     DataArray::CheckValueInRangeEx(nbComp,bgComp,endComp,"invalid component value");
1600     int newNbOfTuples=(int)std::distance(bgTuples,endTuples);
1601     bool assignTech=true;
1602     if(a->getNbOfElems()==(std::size_t)newNbOfTuples*newNbOfComp)
1603       {
1604         if(strictCompoCompare)
1605           a->checkNbOfTuplesAndComp(newNbOfTuples,newNbOfComp,msg);
1606       }
1607     else
1608       {
1609         a->checkNbOfTuplesAndComp(1,newNbOfComp,msg);
1610         assignTech=false;
1611       }
1612     T *pt(getPointer()+bgComp);
1613     const T *srcPt(a->getConstPointer());
1614     if(assignTech)
1615       {
1616         for(const int *w=bgTuples;w!=endTuples;w++)
1617           for(int j=0;j<newNbOfComp;j++,srcPt++)
1618             {
1619               DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1620               pt[(std::size_t)(*w)*nbComp+j*stepComp]=*srcPt;
1621             }
1622       }
1623     else
1624       {
1625         for(const int *w=bgTuples;w!=endTuples;w++)
1626           {
1627             const T *srcPt2=srcPt;
1628             for(int j=0;j<newNbOfComp;j++,srcPt2++)
1629               {
1630                 DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1631                 pt[(std::size_t)(*w)*nbComp+j*stepComp]=*srcPt2;
1632               }
1633           }
1634       }
1635   }
1636   
1637   /*!
1638    * Assign a given value to values at specified tuples and components of \a this array.
1639    * The tuples to assign to are defined by a C array of indices.
1640    * The components to assign to are defined by three values similar to parameters of
1641    * the Python function \c range(\c start,\c stop,\c step).
1642    *  \param [in] a - the value to assign.
1643    *  \param [in] bgTuples - pointer to an array of tuple indices of \a this array to
1644    *              assign \a a to.
1645    *  \param [in] endTuples - specifies the end of the array \a bgTuples, so that
1646    *              pointer to a tuple index <em>(pi)</em> varies as this: 
1647    *              \a bgTuples <= \a pi < \a endTuples.
1648    *  \param [in] bgComp - index of the first component of \a this array to assign to.
1649    *  \param [in] endComp - index of the component before which the components to assign
1650    *              to are located.
1651    *  \param [in] stepComp - index increment to get index of the next component to assign to.
1652    *  \throw If \a this is not allocated.
1653    *  \throw If any index of tuple given by \a bgTuples is out of a valid range for 
1654    *         \a this array.
1655    *  \throw If parameters specifying components to assign to, do not give a
1656    *            non-empty range of increasing indices or indices are out of a valid range
1657    *            for \c this array.
1658    *
1659    *  \if ENABLE_EXAMPLES
1660    *  \ref py_mcdataarraydouble_setpartofvaluessimple3 "Here is a Python example".
1661    *  \endif
1662    */
1663   template<class T>
1664   void DataArrayTemplate<T>::setPartOfValuesSimple3(T a, const int *bgTuples, const int *endTuples, int bgComp, int endComp, int stepComp)
1665   {
1666     const char msg[]="DataArrayTemplate::setPartOfValuesSimple3";
1667     checkAllocated();
1668     int newNbOfComp(DataArray::GetNumberOfItemGivenBES(bgComp,endComp,stepComp,msg));
1669     int nbComp(getNumberOfComponents()),nbOfTuples(getNumberOfTuples());
1670     DataArray::CheckValueInRangeEx(nbComp,bgComp,endComp,"invalid component value");
1671     T *pt(getPointer()+bgComp);
1672     for(const int *w=bgTuples;w!=endTuples;w++)
1673       for(int j=0;j<newNbOfComp;j++)
1674         {
1675           DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1676           pt[(std::size_t)(*w)*nbComp+j*stepComp]=a;
1677         }
1678   }
1679
1680   /*!
1681    * Copy all values from another DataArrayDouble into specified tuples and components
1682    * of \a this array. Textual data is not copied.
1683    * The tree parameters defining set of indices of tuples and components are similar to
1684    * the tree parameters of the Python function \c range(\c start,\c stop,\c step).
1685    *  \param [in] a - the array to copy values from.
1686    *  \param [in] bgTuples - index of the first tuple of \a this array to assign values to.
1687    *  \param [in] endTuples - index of the tuple before which the tuples to assign to
1688    *              are located.
1689    *  \param [in] stepTuples - index increment to get index of the next tuple to assign to.
1690    *  \param [in] bgComp - pointer to an array of component indices of \a this array to
1691    *              assign \a a to.
1692    *  \param [in] endComp - specifies the end of the array \a bgTuples, so that
1693    *              pointer to a component index (\a pi) varies as this: 
1694    *              \a bgComp <= \a pi < \a endComp.
1695    *  \param [in] strictCompoCompare - if \a true (by default), then \a a->getNumberOfComponents() 
1696    *              must be equal to the number of columns to assign to, else an
1697    *              exception is thrown; if \a false, then it is only required that \a
1698    *              a->getNbOfElems() equals to number of values to assign to (this condition
1699    *              must be respected even if \a strictCompoCompare is \a true). The number of 
1700    *              values to assign to is given by following Python expression:
1701    *              \a nbTargetValues = 
1702    *              \c len(\c range(\a bgTuples,\a endTuples,\a stepTuples)) *
1703    *              \c len(\c range(\a bgComp,\a endComp,\a stepComp)).
1704    *  \throw If \a a is NULL.
1705    *  \throw If \a a is not allocated.
1706    *  \throw If \a this is not allocated.
1707    *  \throw If parameters specifying tuples and components to assign to do not give a
1708    *            non-empty range of increasing indices.
1709    *  \throw If \a a->getNbOfElems() != \a nbTargetValues.
1710    *  \throw If \a strictCompoCompare == \a true && \a a->getNumberOfComponents() !=
1711    *            \c len(\c range(\a bgComp,\a endComp,\a stepComp)).
1712    *
1713    */
1714   template<class T>
1715   void DataArrayTemplate<T>::setPartOfValues4(const typename Traits<T>::ArrayType *a, int bgTuples, int endTuples, int stepTuples, const int *bgComp, const int *endComp, bool strictCompoCompare)
1716   {if(!a)
1717       throw INTERP_KERNEL::Exception("DataArrayTemplate::setPartOfValues4 : input DataArrayTemplate is NULL !");
1718     const char msg[]="DataArrayTemplate::setPartOfValues4";
1719     checkAllocated();
1720     a->checkAllocated();
1721     int newNbOfTuples(DataArray::GetNumberOfItemGivenBES(bgTuples,endTuples,stepTuples,msg));
1722     int newNbOfComp((int)std::distance(bgComp,endComp));
1723     int nbComp(getNumberOfComponents());
1724     for(const int *z=bgComp;z!=endComp;z++)
1725       DataArray::CheckValueInRange(nbComp,*z,"invalid component id");
1726     int nbOfTuples(getNumberOfTuples());
1727     DataArray::CheckValueInRangeEx(nbOfTuples,bgTuples,endTuples,"invalid tuple value");
1728     bool assignTech(true);
1729     if(a->getNbOfElems()==(std::size_t)newNbOfTuples*newNbOfComp)
1730       {
1731         if(strictCompoCompare)
1732           a->checkNbOfTuplesAndComp(newNbOfTuples,newNbOfComp,msg);
1733       }
1734     else
1735       {
1736         a->checkNbOfTuplesAndComp(1,newNbOfComp,msg);
1737         assignTech=false;
1738       }
1739     const T *srcPt(a->getConstPointer());
1740     T *pt(getPointer()+bgTuples*nbComp);
1741     if(assignTech)
1742       {
1743         for(int i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
1744           for(const int *z=bgComp;z!=endComp;z++,srcPt++)
1745             pt[*z]=*srcPt;
1746       }
1747     else
1748       {
1749       for(int i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
1750         {
1751           const T *srcPt2(srcPt);
1752           for(const int *z=bgComp;z!=endComp;z++,srcPt2++)
1753             pt[*z]=*srcPt2;
1754         }
1755       }
1756   }
1757
1758   template<class T>
1759   void DataArrayTemplate<T>::setPartOfValuesSimple4(T a, int bgTuples, int endTuples, int stepTuples, const int *bgComp, const int *endComp)
1760   {
1761     const char msg[]="DataArrayTemplate::setPartOfValuesSimple4";
1762     checkAllocated();
1763     int newNbOfTuples(DataArray::GetNumberOfItemGivenBES(bgTuples,endTuples,stepTuples,msg));
1764     int nbComp(getNumberOfComponents());
1765     for(const int *z=bgComp;z!=endComp;z++)
1766       DataArray::CheckValueInRange(nbComp,*z,"invalid component id");
1767     int nbOfTuples(getNumberOfTuples());
1768     DataArray::CheckValueInRangeEx(nbOfTuples,bgTuples,endTuples,"invalid tuple value");
1769     T *pt=getPointer()+bgTuples*nbComp;
1770     for(int i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
1771       for(const int *z=bgComp;z!=endComp;z++)
1772         pt[*z]=a;
1773   }
1774   
1775   /*!
1776    * Copy some tuples from another DataArrayDouble into specified tuples
1777    * of \a this array. Textual data is not copied. Both arrays must have equal number of
1778    * components.
1779    * Both the tuples to assign and the tuples to assign to are defined by a DataArrayInt.
1780    * All components of selected tuples are copied.
1781    *  \param [in] a - the array to copy values from.
1782    *  \param [in] tuplesSelec - the array specifying both source tuples of \a a and
1783    *              target tuples of \a this. \a tuplesSelec has two components, and the
1784    *              first component specifies index of the source tuple and the second
1785    *              one specifies index of the target tuple.
1786    *  \throw If \a this is not allocated.
1787    *  \throw If \a a is NULL.
1788    *  \throw If \a a is not allocated.
1789    *  \throw If \a tuplesSelec is NULL.
1790    *  \throw If \a tuplesSelec is not allocated.
1791    *  \throw If <em>this->getNumberOfComponents() != a->getNumberOfComponents()</em>.
1792    *  \throw If \a tuplesSelec->getNumberOfComponents() != 2.
1793    *  \throw If any tuple index given by \a tuplesSelec is out of a valid range for 
1794    *         the corresponding (\a this or \a a) array.
1795    */
1796   template<class T>
1797   void DataArrayTemplate<T>::setPartOfValuesAdv(const typename Traits<T>::ArrayType *a, const DataArrayInt *tuplesSelec)
1798   {
1799     if(!a || !tuplesSelec)
1800       throw INTERP_KERNEL::Exception("DataArrayTemplate::setPartOfValuesAdv : input DataArrayTemplate is NULL !");
1801     checkAllocated();
1802     a->checkAllocated();
1803     tuplesSelec->checkAllocated();
1804     int nbOfComp=getNumberOfComponents();
1805     if(nbOfComp!=a->getNumberOfComponents())
1806       throw INTERP_KERNEL::Exception("DataArrayTemplate::setPartOfValuesAdv : This and a do not have the same number of components !");
1807     if(tuplesSelec->getNumberOfComponents()!=2)
1808       throw INTERP_KERNEL::Exception("DataArrayTemplate::setPartOfValuesAdv : Expecting to have a tuple selector DataArrayInt instance with exactly 2 components !");
1809     int thisNt(getNumberOfTuples());
1810     int aNt(a->getNumberOfTuples());
1811     T *valsToSet(getPointer());
1812     const T *valsSrc(a->getConstPointer());
1813     for(const int *tuple=tuplesSelec->begin();tuple!=tuplesSelec->end();tuple+=2)
1814     {
1815       if(tuple[1]>=0 && tuple[1]<aNt)
1816         {
1817           if(tuple[0]>=0 && tuple[0]<thisNt)
1818             std::copy(valsSrc+nbOfComp*tuple[1],valsSrc+nbOfComp*(tuple[1]+1),valsToSet+nbOfComp*tuple[0]);
1819           else
1820             {
1821               std::ostringstream oss; oss << "DataArrayTemplate::setPartOfValuesAdv : Tuple #" << std::distance(tuplesSelec->begin(),tuple)/2;
1822               oss << " of 'tuplesSelec' request of tuple id #" << tuple[0] << " in 'this' ! It should be in [0," << thisNt << ") !";
1823               throw INTERP_KERNEL::Exception(oss.str().c_str());
1824             }
1825         }
1826       else
1827         {
1828           std::ostringstream oss; oss << "DataArrayTemplate::setPartOfValuesAdv : Tuple #" << std::distance(tuplesSelec->begin(),tuple)/2;
1829           oss << " of 'tuplesSelec' request of tuple id #" << tuple[1] << " in 'a' ! It should be in [0," << aNt << ") !";
1830           throw INTERP_KERNEL::Exception(oss.str().c_str());
1831         }
1832     }
1833   }
1834   
1835   /*!
1836    * Copy some tuples from another DataArrayDouble (\a aBase) into contiguous tuples
1837    * of \a this array. Textual data is not copied. Both arrays must have equal number of
1838    * components.
1839    * The tuples to assign to are defined by index of the first tuple, and
1840    * their number is defined by \a tuplesSelec->getNumberOfTuples().
1841    * The tuples to copy are defined by values of a DataArrayInt.
1842    * All components of selected tuples are copied.
1843    *  \param [in] tupleIdStart - index of the first tuple of \a this array to assign
1844    *              values to.
1845    *  \param [in] aBase - the array to copy values from.
1846    *  \param [in] tuplesSelec - the array specifying tuples of \a a to copy.
1847    *  \throw If \a this is not allocated.
1848    *  \throw If \a aBase is NULL.
1849    *  \throw If \a aBase is not allocated.
1850    *  \throw If \a tuplesSelec is NULL.
1851    *  \throw If \a tuplesSelec is not allocated.
1852    *  \throw If <em>this->getNumberOfComponents() != aBase->getNumberOfComponents()</em>.
1853    *  \throw If \a tuplesSelec->getNumberOfComponents() != 1.
1854    *  \throw If <em>tupleIdStart + tuplesSelec->getNumberOfTuples() > this->getNumberOfTuples().</em>
1855    *  \throw If any tuple index given by \a tuplesSelec is out of a valid range for 
1856    *         \a aBase array.
1857  */
1858   template<class T>
1859   void DataArrayTemplate<T>::setContigPartOfSelectedValues(int tupleIdStart, const DataArray *aBase, const DataArrayInt *tuplesSelec)
1860   {
1861     if(!aBase || !tuplesSelec)
1862       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValues : input DataArray is NULL !");
1863     const typename Traits<T>::ArrayType *a(dynamic_cast<const typename Traits<T>::ArrayType *>(aBase));
1864     if(!a)
1865       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValues : input DataArray aBase is not a DataArrayDouble !");
1866     checkAllocated();
1867     a->checkAllocated();
1868     tuplesSelec->checkAllocated();
1869     int nbOfComp(getNumberOfComponents());
1870     if(nbOfComp!=a->getNumberOfComponents())
1871       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValues : This and a do not have the same number of components !");
1872     if(tuplesSelec->getNumberOfComponents()!=1)
1873       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValues : Expecting to have a tuple selector DataArrayInt instance with exactly 1 component !");
1874     int thisNt(getNumberOfTuples());
1875     int aNt(a->getNumberOfTuples());
1876     int nbOfTupleToWrite(tuplesSelec->getNumberOfTuples());
1877     T *valsToSet(getPointer()+tupleIdStart*nbOfComp);
1878     if(tupleIdStart+nbOfTupleToWrite>thisNt)
1879       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValues : invalid number range of values to write !");
1880     const T *valsSrc=a->getConstPointer();
1881     for(const int *tuple=tuplesSelec->begin();tuple!=tuplesSelec->end();tuple++,valsToSet+=nbOfComp)
1882       {
1883         if(*tuple>=0 && *tuple<aNt)
1884           {
1885             std::copy(valsSrc+nbOfComp*(*tuple),valsSrc+nbOfComp*(*tuple+1),valsToSet);
1886           }
1887         else
1888           {
1889             std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::setContigPartOfSelectedValues : Tuple #" << std::distance(tuplesSelec->begin(),tuple);
1890             oss << " of 'tuplesSelec' request of tuple id #" << *tuple << " in 'a' ! It should be in [0," << aNt << ") !";
1891             throw INTERP_KERNEL::Exception(oss.str().c_str());
1892           }
1893       }
1894   }
1895   
1896   /*!
1897    * Copy some tuples from another DataArrayDouble (\a aBase) into contiguous tuples
1898    * of \a this array. Textual data is not copied. Both arrays must have equal number of
1899    * components.
1900    * The tuples to copy are defined by three values similar to parameters of
1901    * the Python function \c range(\c start,\c stop,\c step).
1902    * The tuples to assign to are defined by index of the first tuple, and
1903    * their number is defined by number of tuples to copy.
1904    * All components of selected tuples are copied.
1905    *  \param [in] tupleIdStart - index of the first tuple of \a this array to assign
1906    *              values to.
1907    *  \param [in] aBase - the array to copy values from.
1908    *  \param [in] bg - index of the first tuple to copy of the array \a aBase.
1909    *  \param [in] end2 - index of the tuple of \a aBase before which the tuples to copy
1910    *              are located.
1911    *  \param [in] step - index increment to get index of the next tuple to copy.
1912    *  \throw If \a this is not allocated.
1913    *  \throw If \a aBase is NULL.
1914    *  \throw If \a aBase is not allocated.
1915    *  \throw If <em>this->getNumberOfComponents() != aBase->getNumberOfComponents()</em>.
1916    *  \throw If <em>tupleIdStart + len(range(bg,end2,step)) > this->getNumberOfTuples().</em>
1917    *  \throw If parameters specifying tuples to copy, do not give a
1918    *            non-empty range of increasing indices or indices are out of a valid range
1919    *            for the array \a aBase.
1920    */
1921   template<class T>
1922   void DataArrayTemplate<T>::setContigPartOfSelectedValuesSlice(int tupleIdStart, const DataArray *aBase, int bg, int end2, int step)
1923   {
1924     if(!aBase)
1925       {
1926         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::setContigPartOfSelectedValuesSlice : input DataArray is NULL !";
1927         throw INTERP_KERNEL::Exception(oss.str().c_str());
1928       }
1929     const typename Traits<T>::ArrayType *a(dynamic_cast<const typename Traits<T>::ArrayType *>(aBase));
1930     if(!a)
1931       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValuesSlice : input DataArray aBase is not a DataArrayDouble !");
1932     checkAllocated();
1933     a->checkAllocated();
1934     int nbOfComp(getNumberOfComponents());
1935     const char msg[]="DataArrayDouble::setContigPartOfSelectedValuesSlice";
1936     int nbOfTupleToWrite(DataArray::GetNumberOfItemGivenBES(bg,end2,step,msg));
1937     if(nbOfComp!=a->getNumberOfComponents())
1938       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValuesSlice : This and a do not have the same number of components !");
1939     int thisNt(getNumberOfTuples()),aNt(a->getNumberOfTuples());
1940     T *valsToSet(getPointer()+tupleIdStart*nbOfComp);
1941     if(tupleIdStart+nbOfTupleToWrite>thisNt)
1942       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValuesSlice : invalid number range of values to write !");
1943     if(end2>aNt)
1944       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValuesSlice : invalid range of values to read !");
1945     const T *valsSrc(a->getConstPointer()+bg*nbOfComp);
1946     for(int i=0;i<nbOfTupleToWrite;i++,valsToSet+=nbOfComp,valsSrc+=step*nbOfComp)
1947       {
1948         std::copy(valsSrc,valsSrc+nbOfComp,valsToSet);
1949       }
1950   }
1951
1952   /*!
1953    * Returns a shorten copy of \a this array. The new DataArrayDouble contains ranges
1954    * of tuples specified by \a ranges parameter.
1955    * For more info on renumbering see \ref numbering.
1956    *  \param [in] ranges - std::vector of std::pair's each of which defines a range
1957    *              of tuples in [\c begin,\c end) format.
1958    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1959    *          is to delete using decrRef() as it is no more needed.
1960    *  \throw If \a end < \a begin.
1961    *  \throw If \a end > \a this->getNumberOfTuples().
1962    *  \throw If \a this is not allocated.
1963    */
1964   template<class T>
1965   typename Traits<T>::ArrayType *DataArrayTemplate<T>::mySelectByTupleRanges(const std::vector<std::pair<int,int> >& ranges) const
1966   {
1967     checkAllocated();
1968     int nbOfComp(getNumberOfComponents()),nbOfTuplesThis(getNumberOfTuples());
1969     if(ranges.empty())
1970       {
1971         MCAuto<DataArray> ret0(buildNewEmptyInstance());
1972         MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1973         ret->alloc(0,nbOfComp);
1974         ret->copyStringInfoFrom(*this);
1975         return ret.retn();
1976       }
1977     int ref(ranges.front().first),nbOfTuples(0);
1978     bool isIncreasing(true);
1979     for(std::vector<std::pair<int,int> >::const_iterator it=ranges.begin();it!=ranges.end();it++)
1980       {
1981         if((*it).first<=(*it).second)
1982           {
1983             if((*it).first>=0 && (*it).second<=nbOfTuplesThis)
1984               {
1985                 nbOfTuples+=(*it).second-(*it).first;
1986                 if(isIncreasing)
1987                   isIncreasing=ref<=(*it).first;
1988                 ref=(*it).second;
1989               }
1990             else
1991               {
1992                 std::ostringstream oss; oss << "DataArrayTemplate::selectByTupleRanges : on range #" << std::distance(ranges.begin(),it);
1993                 oss << " (" << (*it).first << "," << (*it).second << ") is greater than number of tuples of this :" << nbOfTuples << " !";
1994                 throw INTERP_KERNEL::Exception(oss.str().c_str());
1995               }
1996           }
1997         else
1998           {
1999             std::ostringstream oss; oss << "DataArrayTemplate::selectByTupleRanges : on range #" << std::distance(ranges.begin(),it);
2000             oss << " (" << (*it).first << "," << (*it).second << ") end is before begin !";
2001             throw INTERP_KERNEL::Exception(oss.str().c_str());
2002           }
2003       }
2004     if(isIncreasing && nbOfTuplesThis==nbOfTuples)
2005       return static_cast<typename Traits<T>::ArrayType *>(deepCopy());
2006     MCAuto<DataArray> ret0(buildNewEmptyInstance());
2007     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
2008     ret->alloc(nbOfTuples,nbOfComp);
2009     ret->copyStringInfoFrom(*this);
2010     const T *src(getConstPointer());
2011     T *work(ret->getPointer());
2012     for(std::vector<std::pair<int,int> >::const_iterator it=ranges.begin();it!=ranges.end();it++)
2013       work=std::copy(src+(*it).first*nbOfComp,src+(*it).second*nbOfComp,work);
2014     return ret.retn();
2015   }
2016
2017   /*!
2018    * Returns the first value of \a this. 
2019    *  \return double - the last value of \a this array.
2020    *  \throw If \a this is not allocated.
2021    *  \throw If \a this->getNumberOfComponents() != 1.
2022    *  \throw If \a this->getNumberOfTuples() < 1.
2023    */
2024   template<class T>
2025   T DataArrayTemplate<T>::front() const
2026   {
2027     checkAllocated();
2028     if(getNumberOfComponents()!=1)
2029       throw INTERP_KERNEL::Exception("DataArrayTemplate::front : number of components not equal to one !");
2030     int nbOfTuples(getNumberOfTuples());
2031     if(nbOfTuples<1)
2032       throw INTERP_KERNEL::Exception("DataArrayTemplate::front : number of tuples must be >= 1 !");
2033     return *(getConstPointer());
2034   }
2035   
2036   /*!
2037    * Returns the last value of \a this. 
2038    *  \return double - the last value of \a this array.
2039    *  \throw If \a this is not allocated.
2040    *  \throw If \a this->getNumberOfComponents() != 1.
2041    *  \throw If \a this->getNumberOfTuples() < 1.
2042    */
2043   template<class T>
2044   T DataArrayTemplate<T>::back() const
2045   {
2046     checkAllocated();
2047     if(getNumberOfComponents()!=1)
2048       throw INTERP_KERNEL::Exception("DataArrayTemplate::back : number of components not equal to one !");
2049     int nbOfTuples(getNumberOfTuples());
2050     if(nbOfTuples<1)
2051       throw INTERP_KERNEL::Exception("DataArrayTemplate::back : number of tuples must be >= 1 !");
2052     return *(getConstPointer()+nbOfTuples-1);
2053   }
2054   
2055   /*!
2056    * Returns the maximal value and its location within \a this one-dimensional array.
2057    *  \param [out] tupleId - index of the tuple holding the maximal value.
2058    *  \return double - the maximal value among all values of \a this array.
2059    *  \throw If \a this->getNumberOfComponents() != 1
2060    *  \throw If \a this->getNumberOfTuples() < 1
2061    */
2062   template<class T>
2063   T DataArrayTemplate<T>::getMaxValue(int& tupleId) const
2064   {
2065     checkAllocated();
2066     if(getNumberOfComponents()!=1)
2067       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 !");
2068     int nbOfTuples(getNumberOfTuples());
2069     if(nbOfTuples<=0)
2070       throw INTERP_KERNEL::Exception("DataArrayDouble::getMaxValue : array exists but number of tuples must be > 0 !");
2071     const T *vals(getConstPointer());
2072     const T *loc(std::max_element(vals,vals+nbOfTuples));
2073     tupleId=(int)std::distance(vals,loc);
2074     return *loc;
2075   }
2076   
2077   /*!
2078    * Returns the maximal value within \a this array that is allowed to have more than
2079    *  one component.
2080    *  \return double - the maximal value among all values of \a this array.
2081    *  \throw If \a this is not allocated.
2082    */
2083   template<class T>
2084   T DataArrayTemplate<T>::getMaxValueInArray() const
2085   {
2086     checkAllocated();
2087     const T *loc(std::max_element(begin(),end()));
2088     return *loc;
2089   }
2090   
2091   /*!
2092    * Returns the minimal value and its location within \a this one-dimensional array.
2093    *  \param [out] tupleId - index of the tuple holding the minimal value.
2094    *  \return double - the minimal value among all values of \a this array.
2095    *  \throw If \a this->getNumberOfComponents() != 1
2096    *  \throw If \a this->getNumberOfTuples() < 1
2097    */
2098   template<class T>
2099   T DataArrayTemplate<T>::getMinValue(int& tupleId) const
2100   {
2101     checkAllocated();
2102     if(getNumberOfComponents()!=1)
2103       throw INTERP_KERNEL::Exception("DataArrayDouble::getMinValue : must be applied on DataArrayDouble with only one component, you can call 'rearrange' method before call 'getMinValueInArray' method !");
2104     int nbOfTuples(getNumberOfTuples());
2105     if(nbOfTuples<=0)
2106       throw INTERP_KERNEL::Exception("DataArrayDouble::getMinValue : array exists but number of tuples must be > 0 !");
2107     const T *vals(getConstPointer());
2108     const T *loc(std::min_element(vals,vals+nbOfTuples));
2109     tupleId=(int)std::distance(vals,loc);
2110     return *loc;
2111   }
2112   
2113   /*!
2114    * Returns the minimal value within \a this array that is allowed to have more than
2115    *  one component.
2116    *  \return double - the minimal value among all values of \a this array.
2117    *  \throw If \a this is not allocated.
2118    */
2119   template<class T>
2120   T DataArrayTemplate<T>::getMinValueInArray() const
2121   {
2122     checkAllocated();
2123     const T *loc=std::min_element(begin(),end());
2124     return *loc;
2125   }
2126   
2127 }
2128
2129 #endif