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