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