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