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