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