Salome HOME
4cf654c86457c9ed122a331c07aa791101b4b8ee
[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 (EDF R&D)
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 <numeric>
35 #include <algorithm>
36
37 namespace MEDCoupling
38 {
39   template<class T>
40   void MEDCouplingPointer<T>::setInternal(T *pointer)
41   {
42     _internal=pointer;
43     _external=0;
44   }
45
46   template<class T>
47   void MEDCouplingPointer<T>::setExternal(const T *pointer)
48   {
49     _external=pointer;
50     _internal=0;
51   }
52
53   template<class T>
54   MemArray<T>::MemArray(const MemArray<T>& other):_nb_of_elem(0),_nb_of_elem_alloc(0),_ownership(false),_dealloc(0),_param_for_deallocator(0)
55   {
56     if(!other._pointer.isNull())
57       {
58         _nb_of_elem_alloc=other._nb_of_elem;
59         T *pointer=(T*)malloc(_nb_of_elem_alloc*sizeof(T));
60         std::copy(other._pointer.getConstPointer(),other._pointer.getConstPointer()+other._nb_of_elem,pointer);
61         useArray(pointer,true,C_DEALLOC,other._nb_of_elem);
62       }
63   }
64
65   template<class T>
66   void MemArray<T>::useArray(const T *array, bool ownership, DeallocType type, std::size_t nbOfElem)
67   {
68     destroy();
69     _nb_of_elem=nbOfElem;
70     _nb_of_elem_alloc=nbOfElem;
71     if(ownership)
72       _pointer.setInternal(const_cast<T *>(array));
73     else
74       _pointer.setExternal(array);
75     _ownership=ownership;
76     _dealloc=BuildFromType(type);
77   }
78
79   template<class T>
80   void MemArray<T>::useExternalArrayWithRWAccess(const T *array, std::size_t nbOfElem)
81   {
82     destroy();
83     _nb_of_elem=nbOfElem;
84     _nb_of_elem_alloc=nbOfElem;
85     _pointer.setInternal(const_cast<T *>(array));
86     _ownership=false;
87     _dealloc=CPPDeallocator;
88   }
89
90   template<class T>
91   void MemArray<T>::writeOnPlace(std::size_t id, T element0, const T *others, std::size_t sizeOfOthers)
92   {
93     if(id+sizeOfOthers>=_nb_of_elem_alloc)
94       reserve(2*_nb_of_elem+sizeOfOthers+1);
95     T *pointer=_pointer.getPointer();
96     pointer[id]=element0;
97     std::copy(others,others+sizeOfOthers,pointer+id+1);
98     _nb_of_elem=std::max<std::size_t>(_nb_of_elem,id+sizeOfOthers+1);
99   }
100
101   template<class T>
102   void MemArray<T>::pushBack(T elem)
103   {
104     if(_nb_of_elem>=_nb_of_elem_alloc)
105       reserve(_nb_of_elem_alloc>0?2*_nb_of_elem_alloc:1);
106     T *pt=getPointer();
107     pt[_nb_of_elem++]=elem;
108   }
109
110   template<class T>
111   T MemArray<T>::popBack()
112   {
113     if(_nb_of_elem>0)
114       {
115         const T *pt=getConstPointer();
116         return pt[--_nb_of_elem];
117       }
118     throw INTERP_KERNEL::Exception("MemArray::popBack : nothing to pop in array !");
119   }
120
121   template<class T>
122   void MemArray<T>::pack() const
123   {
124     (const_cast<MemArray<T> * >(this))->reserve(_nb_of_elem);
125   }
126
127   template<class T>
128   bool MemArray<T>::isEqual(const MemArray<T>& other, T prec, std::string& reason) const
129   {
130     std::ostringstream oss; oss.precision(15);
131     if(_nb_of_elem!=other._nb_of_elem)
132       {
133         oss << "Number of elements in coarse data of DataArray mismatch : this=" << _nb_of_elem << " other=" << other._nb_of_elem;
134         reason=oss.str();
135         return false;
136       }
137     const T *pt1=_pointer.getConstPointer();
138     const T *pt2=other._pointer.getConstPointer();
139     if(pt1==0 && pt2==0)
140       return true;
141     if(pt1==0 || pt2==0)
142       {
143         oss << "coarse data pointer is defined for only one DataArray instance !";
144         reason=oss.str();
145         return false;
146       }
147     if(pt1==pt2)
148       return true;
149     for(std::size_t i=0;i<_nb_of_elem;i++)
150       if(pt1[i]-pt2[i]<-prec || (pt1[i]-pt2[i])>prec)
151         {
152           oss << "The content of data differs at pos #" << i << " of coarse data ! this[i]=" << pt1[i] << " other[i]=" << pt2[i];
153           reason=oss.str();
154           return false;
155         }
156     return true;
157   }
158
159   /*!
160    * \param [in] sl is typically the number of components
161    * \return True if a not null pointer is present, False if not.
162    */
163   template<class T>
164   bool MemArray<T>::reprHeader(int sl, std::ostream& stream) const
165   {
166     stream << "Number of tuples : ";
167     if(!_pointer.isNull())
168       {
169         if(sl!=0)
170           stream << _nb_of_elem/sl << std::endl << "Internal memory facts : " << _nb_of_elem << "/" << _nb_of_elem_alloc;
171         else
172           stream << "Empty Data";
173       }
174     else
175       stream << "No data";
176     stream << "\n";
177     stream << "Data content :\n";
178     bool ret=!_pointer.isNull();
179     if(!ret)
180       stream << "No data !\n";
181     return ret;
182   }
183
184   /*!
185    * \param [in] sl is typically the number of components
186    */
187   template<class T>
188   void MemArray<T>::repr(int sl, std::ostream& stream) const
189   {
190     if(reprHeader(sl,stream))
191       {
192         const T *data=getConstPointer();
193         if(_nb_of_elem!=0 && sl!=0)
194           {
195             std::size_t nbOfTuples=_nb_of_elem/std::abs(sl);
196             for(std::size_t i=0;i<nbOfTuples;i++)
197               {
198                 stream << "Tuple #" << i << " : ";
199                 std::copy(data,data+sl,std::ostream_iterator<T>(stream," "));
200                 stream << "\n";
201                 data+=sl;
202               }
203           }
204         else
205           stream << "Empty Data\n";
206       }
207   }
208
209   /*!
210    * \param [in] sl is typically the number of components
211    */
212   template<class T>
213   void MemArray<T>::reprZip(int sl, std::ostream& stream) const
214   {
215     stream << "Number of tuples : ";
216     if(!_pointer.isNull())
217       {
218         if(sl!=0)
219           stream << _nb_of_elem/sl;
220         else
221           stream << "Empty Data";
222       }
223     else
224       stream << "No data";
225     stream << "\n";
226     stream << "Data content : ";
227     const T *data=getConstPointer();
228     if(!_pointer.isNull())
229       {
230         if(_nb_of_elem!=0 && sl!=0)
231           {
232             std::size_t nbOfTuples=_nb_of_elem/std::abs(sl);
233             for(std::size_t i=0;i<nbOfTuples;i++)
234               {
235                 stream << "|";
236                 std::copy(data,data+sl,std::ostream_iterator<T>(stream," "));
237                 stream << "| ";
238                 data+=sl;
239               }
240             stream << "\n";
241           }
242         else
243           stream << "Empty Data\n";
244       }
245     else
246       stream << "No data !\n";
247   }
248
249   /*!
250    * \param [in] sl is typically the number of components
251    */
252   template<class T>
253   void MemArray<T>::reprNotTooLong(int sl, std::ostream& stream) const
254   {
255     if(reprHeader(sl,stream))
256       {
257         const T *data=getConstPointer();
258         if(_nb_of_elem!=0 && sl!=0)
259           {
260             std::size_t nbOfTuples=_nb_of_elem/std::abs(sl);
261             if(nbOfTuples<=1000)
262               {
263                 for(std::size_t i=0;i<nbOfTuples;i++)
264                   {
265                     stream << "Tuple #" << i << " : ";
266                     std::copy(data,data+sl,std::ostream_iterator<T>(stream," "));
267                     stream << "\n";
268                     data+=sl;
269                   }
270               }
271             else
272               {// too much tuples -> print the 3 first tuples and 3 last.
273                 stream << "Tuple #0 : ";
274                 std::copy(data,data+sl,std::ostream_iterator<T>(stream," ")); stream << "\n";
275                 stream << "Tuple #1 : ";
276                 std::copy(data+sl,data+2*sl,std::ostream_iterator<T>(stream," ")); stream << "\n";
277                 stream << "Tuple #2 : ";
278                 std::copy(data+2*sl,data+3*sl,std::ostream_iterator<T>(stream," ")); stream << "\n";
279                 stream << "...\n";
280                 stream << "Tuple #" << nbOfTuples-3 << " : ";
281                 std::copy(data+(nbOfTuples-3)*sl,data+(nbOfTuples-2)*sl,std::ostream_iterator<T>(stream," ")); stream << "\n";
282                 stream << "Tuple #" << nbOfTuples-2 << " : ";
283                 std::copy(data+(nbOfTuples-2)*sl,data+(nbOfTuples-1)*sl,std::ostream_iterator<T>(stream," ")); stream << "\n";
284                 stream << "Tuple #" << nbOfTuples-1 << " : ";
285                 std::copy(data+(nbOfTuples-1)*sl,data+nbOfTuples*sl,std::ostream_iterator<T>(stream," ")); stream << "\n";
286               }
287           }
288         else
289           stream << "Empty Data\n";
290       }
291   }
292
293   template<class T>
294   void MemArray<T>::fillWithValue(const T& val)
295   {
296     T *pt=_pointer.getPointer();
297     std::fill(pt,pt+_nb_of_elem,val);
298   }
299
300   template<class T>
301   T *MemArray<T>::fromNoInterlace(int nbOfComp) const
302   {
303     if(nbOfComp<1)
304       throw INTERP_KERNEL::Exception("MemArray<T>::fromNoInterlace : number of components must be > 0 !");
305     const T *pt=_pointer.getConstPointer();
306     std::size_t nbOfTuples=_nb_of_elem/nbOfComp;
307     T *ret=(T*)malloc(_nb_of_elem*sizeof(T));
308     T *w=ret;
309     for(std::size_t i=0;i<nbOfTuples;i++)
310       for(int j=0;j<nbOfComp;j++,w++)
311         *w=pt[j*nbOfTuples+i];
312     return ret;
313   }
314
315   template<class T>
316   T *MemArray<T>::toNoInterlace(int nbOfComp) const
317   {
318     if(nbOfComp<1)
319       throw INTERP_KERNEL::Exception("MemArray<T>::toNoInterlace : number of components must be > 0 !");
320     const T *pt=_pointer.getConstPointer();
321     std::size_t nbOfTuples=_nb_of_elem/nbOfComp;
322     T *ret=(T*)malloc(_nb_of_elem*sizeof(T));
323     T *w=ret;
324     for(int i=0;i<nbOfComp;i++)
325       for(std::size_t j=0;j<nbOfTuples;j++,w++)
326         *w=pt[j*nbOfComp+i];
327     return ret;
328   }
329
330   template<class T>
331   void MemArray<T>::sort(bool asc)
332   {
333     T *pt=_pointer.getPointer();
334     if(asc)
335       std::sort(pt,pt+_nb_of_elem);
336     else
337       {
338         typename std::reverse_iterator<T *> it1(pt+_nb_of_elem);
339         typename std::reverse_iterator<T *> it2(pt);
340         std::sort(it1,it2);
341       }
342   }
343
344   template<class T>
345   void MemArray<T>::reverse(int nbOfComp)
346   {
347     if(nbOfComp<1)
348       throw INTERP_KERNEL::Exception("MemArray<T>::reverse : only supported with 'this' array with ONE or more than ONE component !");
349     T *pt=_pointer.getPointer();
350     if(nbOfComp==1)
351       {
352         std::reverse(pt,pt+_nb_of_elem);
353         return ;
354       }
355     else
356       {
357         T *pt2=pt+_nb_of_elem-nbOfComp;
358         std::size_t nbOfTuples=_nb_of_elem/nbOfComp;
359         for(std::size_t i=0;i<nbOfTuples/2;i++,pt+=nbOfComp,pt2-=nbOfComp)
360           {
361             for(int j=0;j<nbOfComp;j++)
362               std::swap(pt[j],pt2[j]);
363           }
364       }
365   }
366
367   template<class T>
368   void MemArray<T>::alloc(std::size_t nbOfElements)
369   {
370     destroy();
371     _nb_of_elem=nbOfElements;
372     _nb_of_elem_alloc=nbOfElements;
373     _pointer.setInternal((T*)malloc(_nb_of_elem_alloc*sizeof(T)));
374     _ownership=true;
375     _dealloc=CDeallocator;
376   }
377
378   /*!
379    * This method performs systematically an allocation of \a newNbOfElements elements in \a this.
380    * \a _nb_of_elem and \a _nb_of_elem_alloc will \b NOT be systematically equal (contrary to MemArray<T>::reAlloc method.
381    * 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 
382    * \a newNbOfElements. This method is typically used to perform a pushBack to avoid systematic allocations-copy-deallocation.
383    * So after the call of this method the accessible content is perfectly set.
384    * 
385    * So this method should not be confused with MemArray<T>::reserve that is close to MemArray<T>::reAlloc but not same.
386    */
387   template<class T>
388   void MemArray<T>::reserve(std::size_t newNbOfElements)
389   {
390     if(_nb_of_elem_alloc==newNbOfElements)
391       return ;
392     T *pointer=(T*)malloc(newNbOfElements*sizeof(T));
393     std::copy(_pointer.getConstPointer(),_pointer.getConstPointer()+std::min<std::size_t>(_nb_of_elem,newNbOfElements),pointer);
394     if(_ownership)
395       DestroyPointer(const_cast<T *>(_pointer.getConstPointer()),_dealloc,_param_for_deallocator);//Do not use getPointer because in case of _external
396     _pointer.setInternal(pointer);
397     _nb_of_elem=std::min<std::size_t>(_nb_of_elem,newNbOfElements);
398     _nb_of_elem_alloc=newNbOfElements;
399     _ownership=true;
400     _dealloc=CDeallocator;
401     _param_for_deallocator=0;
402   }
403
404   /*!
405    * This method performs systematically an allocation of \a newNbOfElements elements in \a this.
406    * \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 .
407    * The remaining part of the new allocated chunk are available but not set previously !
408    * 
409    * So this method should not be confused with MemArray<T>::reserve that is close to MemArray<T>::reAlloc but not same.
410    */
411   template<class T>
412   void MemArray<T>::reAlloc(std::size_t newNbOfElements)
413   {
414     if(_nb_of_elem==newNbOfElements)
415       return ;
416     T *pointer=(T*)malloc(newNbOfElements*sizeof(T));
417     std::copy(_pointer.getConstPointer(),_pointer.getConstPointer()+std::min<std::size_t>(_nb_of_elem,newNbOfElements),pointer);
418     if(_ownership)
419       DestroyPointer(const_cast<T *>(_pointer.getConstPointer()),_dealloc,_param_for_deallocator);//Do not use getPointer because in case of _external
420     _pointer.setInternal(pointer);
421     _nb_of_elem=newNbOfElements;
422     _nb_of_elem_alloc=newNbOfElements;
423     _ownership=true;
424     _dealloc=CDeallocator;
425     _param_for_deallocator=0;
426   }
427
428   template<class T>
429   void MemArray<T>::CPPDeallocator(void *pt, void *param)
430   {
431     delete [] reinterpret_cast<T*>(pt);
432   }
433
434   template<class T>
435   void MemArray<T>::CDeallocator(void *pt, void *param)
436   {
437     free(pt);
438   }
439
440   template<class T>
441   typename MemArray<T>::Deallocator MemArray<T>::BuildFromType(DeallocType type)
442   {
443     switch(type)
444     {
445       case CPP_DEALLOC:
446         return CPPDeallocator;
447       case C_DEALLOC:
448         return CDeallocator;
449       default:
450         throw INTERP_KERNEL::Exception("Invalid deallocation requested ! Unrecognized enum DeallocType !");
451     }
452   }
453
454   template<class T>
455   void MemArray<T>::DestroyPointer(T *pt, typename MemArray<T>::Deallocator dealloc, void *param)
456   {
457     if(dealloc)
458       dealloc(pt,param);
459   }
460
461   template<class T>
462   void MemArray<T>::destroy()
463   {
464     if(_ownership)
465       DestroyPointer(const_cast<T *>(_pointer.getConstPointer()),_dealloc,_param_for_deallocator);//Do not use getPointer because in case of _external
466     _pointer.null();
467     _ownership=false;
468     _dealloc=NULL;
469     _param_for_deallocator=NULL;
470     _nb_of_elem=0;
471     _nb_of_elem_alloc=0;
472   }
473
474   template<class T>
475   MemArray<T> &MemArray<T>::operator=(const MemArray<T>& other)
476   {
477     alloc(other._nb_of_elem);
478     std::copy(other._pointer.getConstPointer(),other._pointer.getConstPointer()+_nb_of_elem,_pointer.getPointer());
479     return *this;
480   }
481
482   //////////////////////////////////
483
484   template<class T>
485   DataArrayIterator<T>::DataArrayIterator(typename Traits<T>::ArrayType *da):_da(da),_tuple_id(0),_nb_comp(0),_nb_tuple(0)
486   {
487     if(_da)
488       {
489         _da->incrRef();
490         if(_da->isAllocated())
491           {
492             _nb_comp=da->getNumberOfComponents();
493             _nb_tuple=da->getNumberOfTuples();
494             _pt=da->getPointer();
495           }
496       }
497   }
498   
499   template<class T>
500   DataArrayIterator<T>::~DataArrayIterator()
501   {
502     if(_da)
503       _da->decrRef();
504   }
505
506   template<class T>
507   typename Traits<T>::ArrayTuple *DataArrayIterator<T>::nextt()
508   {
509     if(_tuple_id<_nb_tuple)
510       {
511         _tuple_id++;
512         typename Traits<T>::ArrayTuple *ret=new typename Traits<T>::ArrayTuple(_pt,_nb_comp);
513         _pt+=_nb_comp;
514         return ret;
515       }
516     else
517       return 0;
518   }
519
520   //////////////////////////////////
521
522   template<class T>
523   DataArrayTuple<T>::DataArrayTuple(T *pt, int nbOfComp):_pt(pt),_nb_of_compo(nbOfComp)
524   {
525   }
526   
527   template<class T>
528   T DataArrayTuple<T>::zeValue() const
529   {
530     if(_nb_of_compo==1)
531       return *_pt;
532     throw INTERP_KERNEL::Exception("DataArrayTuple<T>::zeValue : DataArrayTuple instance has not exactly 1 component -> Not possible to convert it into a single value !");
533   }
534   
535   template<class T>
536   typename Traits<T>::ArrayType *DataArrayTuple<T>::buildDA(int nbOfTuples, int nbOfCompo) const
537   {
538     if((_nb_of_compo==nbOfCompo && nbOfTuples==1) || (_nb_of_compo==nbOfTuples && nbOfCompo==1))
539     {
540       typename Traits<T>::ArrayType *ret=Traits<T>::ArrayType::New();
541       ret->useExternalArrayWithRWAccess(_pt,nbOfTuples,nbOfCompo);
542       return ret;
543     }
544   else
545     {
546       std::ostringstream oss; oss << "DataArrayTuple<T>::buildDA : unable to build a requested DataArrayDouble instance with nbofTuple=" << nbOfTuples << " and nbOfCompo=" << nbOfCompo;
547       oss << ".\nBecause the number of elements in this is " << _nb_of_compo << " !";
548       throw INTERP_KERNEL::Exception(oss.str().c_str());
549     }
550   }
551   
552   //////////////////////////////////
553
554   template<class T>
555   MCAuto< typename Traits<T>::ArrayTypeCh > DataArrayTemplate<T>::NewFromStdVector(const typename std::vector<T>& v)
556   {
557     std::size_t sz(v.size());
558     MCAuto< typename Traits<T>::ArrayTypeCh > ret(Traits<T>::ArrayTypeCh::New());
559     ret->alloc(sz,1);
560     T *pt(ret->getPointer());
561     std::copy(v.begin(),v.end(),pt);
562     return ret;
563   }
564   
565   template<class T>
566   std::vector< MCAuto< typename Traits<T>::ArrayTypeCh > > DataArrayTemplate<T>::explodeComponents() const
567   {
568     checkAllocated();
569     std::size_t sz(getNumberOfComponents());
570     int nbTuples(getNumberOfTuples());
571     std::string name(getName());
572     std::vector<std::string> compNames(getInfoOnComponents());
573     std::vector< MCAuto< typename Traits<T>::ArrayTypeCh > > ret(sz);
574     const T *thisPt(begin());
575     for(std::size_t i=0;i<sz;i++)
576       {
577         MCAuto< typename Traits<T>::ArrayTypeCh > part(Traits<T>::ArrayTypeCh::New());
578         part->alloc(nbTuples,1);
579         part->setName(name);
580         part->setInfoOnComponent(0,compNames[i]);
581         T *otherPt(part->getPointer());
582         for(int j=0;j<nbTuples;j++)
583           otherPt[j]=thisPt[sz*j+i];
584         ret[i]=part;
585       }
586     return ret;
587   }
588   
589   template<class T>
590   std::size_t DataArrayTemplate<T>::getHeapMemorySizeWithoutChildren() const
591   {
592     std::size_t sz(_mem.getNbOfElemAllocated());
593     sz*=sizeof(T);
594     return DataArray::getHeapMemorySizeWithoutChildren()+sz;
595   }
596   
597   /*!
598    * Allocates the raw data in memory. If the memory was already allocated, then it is
599    * freed and re-allocated. See an example of this method use
600    * \ref MEDCouplingArraySteps1WC "here".
601    *  \param [in] nbOfTuple - number of tuples of data to allocate.
602    *  \param [in] nbOfCompo - number of components of data to allocate.
603    *  \throw If \a nbOfTuple < 0 or \a nbOfCompo < 0.
604    */
605   template<class T>
606   void DataArrayTemplate<T>::alloc(std::size_t nbOfTuple, std::size_t nbOfCompo)
607   {
608     _info_on_compo.resize(nbOfCompo);
609     _mem.alloc(nbOfCompo*nbOfTuple);
610     declareAsNew();
611   }
612
613   /*!
614    * Sets a C array to be used as raw data of \a this. The previously set info
615    *  of components is retained and re-sized. 
616    * For more info see \ref MEDCouplingArraySteps1.
617    *  \param [in] array - the C array to be used as raw data of \a this.
618    *  \param [in] ownership - if \a true, \a array will be deallocated at destruction of \a this.
619    *  \param [in] type - specifies how to deallocate \a array. If \a type == MEDCoupling::CPP_DEALLOC,
620    *                     \c delete [] \c array; will be called. If \a type == MEDCoupling::C_DEALLOC,
621    *                     \c free(\c array ) will be called.
622    *  \param [in] nbOfTuple - new number of tuples in \a this.
623    *  \param [in] nbOfCompo - new number of components in \a this.
624    */
625   template<class T>
626   void DataArrayTemplate<T>::useArray(const T *array, bool ownership, DeallocType type, int nbOfTuple, int nbOfCompo)
627   {
628     _info_on_compo.resize(nbOfCompo);
629     _mem.useArray(array,ownership,type,(std::size_t)nbOfTuple*nbOfCompo);
630     declareAsNew();
631   }
632   
633   template<class T>
634   void DataArrayTemplate<T>::useExternalArrayWithRWAccess(const T *array, int nbOfTuple, int nbOfCompo)
635   {
636     _info_on_compo.resize(nbOfCompo);
637     _mem.useExternalArrayWithRWAccess(array,(std::size_t)nbOfTuple*nbOfCompo);
638     declareAsNew();
639   }
640
641   /*!
642    * Returns a value located at specified tuple and component.
643    * This method is equivalent to DataArrayTemplate<T>::getIJ() except that validity of
644    * parameters is checked. So this method is safe but expensive if used to go through
645    * all values of \a this.
646    *  \param [in] tupleId - index of tuple of interest.
647    *  \param [in] compoId - index of component of interest.
648    *  \return double - value located by \a tupleId and \a compoId.
649    *  \throw If \a this is not allocated.
650    *  \throw If condition <em>( 0 <= tupleId < this->getNumberOfTuples() )</em> is violated.
651    *  \throw If condition <em>( 0 <= compoId < this->getNumberOfComponents() )</em> is violated.
652    */
653   template<class T>
654   T DataArrayTemplate<T>::getIJSafe(int tupleId, int compoId) const
655   {
656     checkAllocated();
657     if(tupleId<0 || tupleId>=getNumberOfTuples())
658       {
659         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::getIJSafe : request for tupleId " << tupleId << " should be in [0," << getNumberOfTuples() << ") !";
660         throw INTERP_KERNEL::Exception(oss.str().c_str());
661       }
662     if(compoId<0 || compoId>=(int)getNumberOfComponents())
663       {
664         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::getIJSafe : request for compoId " << compoId << " should be in [0," << getNumberOfComponents() << ") !";
665         throw INTERP_KERNEL::Exception(oss.str().c_str());
666       }
667     return _mem[tupleId*_info_on_compo.size()+compoId];
668   }
669
670   /*!
671    * 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.
672    *
673    * \sa DataArray::getHeapMemorySizeWithoutChildren, DataArrayTemplate<T>::reserve
674    */
675   template<class T>
676   void DataArrayTemplate<T>::pack() const
677   {
678     _mem.pack();
679   }
680
681   /*!
682    * Checks if raw data is allocated. Read more on the raw data
683    * in \ref MEDCouplingArrayBasicsTuplesAndCompo "DataArrays infos" for more information.
684    *  \return bool - \a true if the raw data is allocated, \a false else.
685    */
686   template<class T>
687   bool DataArrayTemplate<T>::isAllocated() const
688   {
689     return getConstPointer()!=0;
690   }
691   
692   /*!
693    * Checks if raw data is allocated and throws an exception if it is not the case.
694    *  \throw If the raw data is not allocated.
695    */
696   template<class T>
697   void DataArrayTemplate<T>::checkAllocated() const
698   {
699     if(!isAllocated())
700       {
701         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::checkAllocated : Array is defined but not allocated ! Call alloc or setValues method first !";
702         throw INTERP_KERNEL::Exception(oss.str().c_str());
703       }
704   }
705   
706   /*!
707    * This method deallocated \a this without modification of information relative to the components.
708    * After call of this method, DataArrayDouble::isAllocated will return false.
709    * If \a this is already not allocated, \a this is let unchanged.
710    */
711   template<class T>
712   void DataArrayTemplate<T>::desallocate()
713   {
714     _mem.destroy();
715   }
716
717   /*!
718    * This method reserve nbOfElems elements in memory ( nbOfElems*8 bytes ) \b without impacting the number of tuples in \a this.
719    * 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.
720    * If \a this has not already been allocated, number of components is set to one.
721    * This method allows to reduce number of reallocations on invokation of DataArrayDouble::pushBackSilent and DataArrayDouble::pushBackValsSilent on \a this.
722    * 
723    * \sa DataArrayDouble::pack, DataArrayDouble::pushBackSilent, DataArrayDouble::pushBackValsSilent
724    */
725   template<class T>
726   void DataArrayTemplate<T>::reserve(std::size_t nbOfElems)
727   {
728     int nbCompo(getNumberOfComponents());
729     if(nbCompo==1)
730       {
731         _mem.reserve(nbOfElems);
732       }
733     else if(nbCompo==0)
734       {
735         _mem.reserve(nbOfElems);
736         _info_on_compo.resize(1);
737       }
738     else
739       {
740         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::reserve : 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 the single value \a val. 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] val the value to be added in \a this
750    * \throw If \a this has already been allocated with number of components different from one.
751    * \sa DataArrayDouble::pushBackValsSilent
752    */
753   template<class T>
754   void DataArrayTemplate<T>::pushBackSilent(T val)
755   {
756     int nbCompo(getNumberOfComponents());
757     if(nbCompo==1)
758       _mem.pushBack(val);
759     else if(nbCompo==0)
760       {
761         _info_on_compo.resize(1);
762         _mem.pushBack(val);
763       }
764     else
765       {
766         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::pushBackSilent : not available for DataArrayDouble with number of components different than 1 !";
767         throw INTERP_KERNEL::Exception(oss.str().c_str());
768       }
769   }
770   
771   /*!
772    * 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
773    * of counter. So the caller is expected to call TimeLabel::declareAsNew on \a this at the end of the push session.
774    *
775    *  \param [in] valsBg - an array of values to push at the end of \c this.
776    *  \param [in] valsEnd - specifies the end of the array \a valsBg, so that
777    *              the last value of \a valsBg is \a valsEnd[ -1 ].
778    * \throw If \a this has already been allocated with number of components different from one.
779    * \sa DataArrayDouble::pushBackSilent
780    */
781   template<class T>
782   void DataArrayTemplate<T>::pushBackValsSilent(const T *valsBg, const T *valsEnd)
783   {
784     int nbCompo(getNumberOfComponents());
785     if(nbCompo==1)
786       _mem.insertAtTheEnd(valsBg,valsEnd);
787     else if(nbCompo==0)
788       {
789         _info_on_compo.resize(1);
790         _mem.insertAtTheEnd(valsBg,valsEnd);
791       }
792     else
793       {
794         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::pushBackValsSilent : not available for DataArrayDouble with number of components different than 1 !";
795         throw INTERP_KERNEL::Exception(oss.str().c_str());
796       }
797   }
798   
799   /*!
800    * This method returns silently ( without updating time label in \a this ) the last value, if any and suppress it.
801    * \throw If \a this is already empty.
802    * \throw If \a this has number of components different from one.
803    */
804   template<class T>
805   T DataArrayTemplate<T>::popBackSilent()
806   {
807     if(getNumberOfComponents()==1)
808       return _mem.popBack();
809     else
810       {
811         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::popBackSilent : not available for DataArrayDouble with number of components different than 1 !";
812         throw INTERP_KERNEL::Exception(oss.str().c_str());
813       }
814   }
815   
816   /*!
817    * Allocates the raw data in memory. If exactly same memory as needed already
818    * allocated, it is not re-allocated.
819    *  \param [in] nbOfTuple - number of tuples of data to allocate.
820    *  \param [in] nbOfCompo - number of components of data to allocate.
821    *  \throw If \a nbOfTuple < 0 or \a nbOfCompo < 0.
822    */
823   template<class T>
824   void DataArrayTemplate<T>::allocIfNecessary(int nbOfTuple, int nbOfCompo)
825   {
826     if(isAllocated())
827       {
828         if(nbOfTuple!=getNumberOfTuples() || nbOfCompo!=(int)getNumberOfComponents())
829           alloc(nbOfTuple,nbOfCompo);
830       }
831     else
832       alloc(nbOfTuple,nbOfCompo);
833   }
834
835   /*!
836    * Checks the number of tuples.
837    *  \return bool - \a true if getNumberOfTuples() == 0, \a false else.
838    *  \throw If \a this is not allocated.
839    */
840   template<class T>
841   bool DataArrayTemplate<T>::empty() const
842   {
843     checkAllocated();
844     return getNumberOfTuples()==0;
845   }
846
847   /*!
848    * Copies all the data from another DataArrayDouble. For more info see
849    * \ref MEDCouplingArrayBasicsCopyDeepAssign.
850    *  \param [in] other - another instance of DataArrayDouble to copy data from.
851    *  \throw If the \a other is not allocated.
852    */
853   template<class T>
854   void DataArrayTemplate<T>::deepCopyFrom(const DataArrayTemplate<T>& other)
855   {
856     other.checkAllocated();
857     int nbOfTuples(other.getNumberOfTuples()),nbOfComp(other.getNumberOfComponents());
858     allocIfNecessary(nbOfTuples,nbOfComp);
859     std::size_t nbOfElems((std::size_t)nbOfTuples*nbOfComp);
860     T *pt(getPointer());
861     const T *ptI(other.begin());
862     for(std::size_t i=0;i<nbOfElems;i++)
863       pt[i]=ptI[i];
864     copyStringInfoFrom(other);
865   }
866
867   /*!
868    * Reverse the array values.
869    *  \throw If \a this->getNumberOfComponents() < 1.
870    *  \throw If \a this is not allocated.
871    */
872   template<class T>
873   void DataArrayTemplate<T>::reverse()
874   {
875     checkAllocated();
876     _mem.reverse(getNumberOfComponents());
877     declareAsNew();
878   }
879
880   /*!
881    * Assign \a val to all values in \a this array. To know more on filling arrays see
882    * \ref MEDCouplingArrayFill.
883    *  \param [in] val - the value to fill with.
884    *  \throw If \a this is not allocated.
885    */
886   template<class T>
887   void DataArrayTemplate<T>::fillWithValue(T val)
888   {
889     checkAllocated();
890     _mem.fillWithValue(val);
891     declareAsNew();
892   }
893
894   /*!
895    * Changes number of tuples in the array. If the new number of tuples is smaller
896    * than the current number the array is truncated, otherwise the array is extended.
897    *  \param [in] nbOfTuples - new number of tuples. 
898    *  \throw If \a this is not allocated.
899    *  \throw If \a nbOfTuples is negative.
900    */
901   template<class T>
902   void DataArrayTemplate<T>::reAlloc(std::size_t nbOfTuples)
903   {
904     checkAllocated();
905     _mem.reAlloc(getNumberOfComponents()*nbOfTuples);
906     declareAsNew();
907   }
908
909   /*!
910    * Permutes values of \a this array as required by \a old2New array. The values are
911    * permuted so that \c new[ \a old2New[ i ]] = \c old[ i ]. Number of tuples remains
912    * the same as in \c this one.
913    * If a permutation reduction is needed, subArray() or selectByTupleId() should be used.
914    * For more info on renumbering see \ref numbering.
915    *  \param [in] old2New - C array of length equal to \a this->getNumberOfTuples()
916    *     giving a new position for i-th old value.
917    */
918   template<class T>
919   void DataArrayTemplate<T>::renumberInPlace(const int *old2New)
920   {
921     checkAllocated();
922     int nbTuples(getNumberOfTuples()),nbOfCompo(getNumberOfComponents());
923     T *tmp(new T[nbTuples*nbOfCompo]);
924     const T *iptr(begin());
925     for(int i=0;i<nbTuples;i++)
926       {
927         int v=old2New[i];
928         if(v>=0 && v<nbTuples)
929           std::copy(iptr+nbOfCompo*i,iptr+nbOfCompo*(i+1),tmp+nbOfCompo*v);
930         else
931           {
932             std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::renumberInPlace : At place #" << i << " value is " << v << " ! Should be in [0," << nbTuples << ") !";
933             throw INTERP_KERNEL::Exception(oss.str().c_str());
934           }
935       }
936     std::copy(tmp,tmp+nbTuples*nbOfCompo,getPointer());
937     delete [] tmp;
938     declareAsNew();
939   }
940
941
942   /*!
943    * Permutes values of \a this array as required by \a new2Old array. The values are
944    * permuted so that \c new[ i ] = \c old[ \a new2Old[ i ]]. Number of tuples remains
945    * the same as in \c this one.
946    * For more info on renumbering see \ref numbering.
947    *  \param [in] new2Old - C array of length equal to \a this->getNumberOfTuples()
948    *     giving a previous position of i-th new value.
949    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
950    *          is to delete using decrRef() as it is no more needed.
951    */
952   template<class T>
953   void DataArrayTemplate<T>::renumberInPlaceR(const int *new2Old)
954   {
955     checkAllocated();
956     int nbTuples(getNumberOfTuples()),nbOfCompo(getNumberOfComponents());
957     T *tmp(new T[nbTuples*nbOfCompo]);
958     const T *iptr(begin());
959     for(int i=0;i<nbTuples;i++)
960       {
961         int v=new2Old[i];
962         if(v>=0 && v<nbTuples)
963           std::copy(iptr+nbOfCompo*v,iptr+nbOfCompo*(v+1),tmp+nbOfCompo*i);
964         else
965           {
966             std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::renumberInPlaceR : At place #" << i << " value is " << v << " ! Should be in [0," << nbTuples << ") !";
967             throw INTERP_KERNEL::Exception(oss.str().c_str());
968           }
969       }
970     std::copy(tmp,tmp+nbTuples*nbOfCompo,getPointer());
971     delete [] tmp;
972     declareAsNew();
973   }
974
975   /*!
976    * Sorts values of the array.
977    *  \param [in] asc - \a true means ascending order, \a false, descending.
978    *  \throw If \a this is not allocated.
979    *  \throw If \a this->getNumberOfComponents() != 1.
980    */
981   template<class T>
982   void DataArrayTemplate<T>::sort(bool asc)
983   {
984     checkAllocated();
985     if(getNumberOfComponents()!=1)
986       {
987         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::sort : only supported with 'this' array with ONE component !";
988         throw INTERP_KERNEL::Exception(oss.str().c_str());
989       }
990     _mem.sort(asc);
991     declareAsNew();
992   }
993
994   /*!
995    * Returns a copy of \a this array with values permuted as required by \a old2New array.
996    * The values are permuted so that  \c new[ \a old2New[ i ]] = \c old[ i ].
997    * Number of tuples in the result array remains the same as in \c this one.
998    * If a permutation reduction is needed, renumberAndReduce() should be used.
999    * For more info on renumbering see \ref numbering.
1000    *  \param [in] old2New - C array of length equal to \a this->getNumberOfTuples()
1001    *          giving a new position for i-th old value.
1002    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1003    *          is to delete using decrRef() as it is no more needed.
1004    *  \throw If \a this is not allocated.
1005    */
1006   template<class T>
1007   typename Traits<T>::ArrayType *DataArrayTemplate<T>::renumber(const int *old2New) const
1008   {
1009     checkAllocated();
1010     int nbTuples(getNumberOfTuples()),nbOfCompo(getNumberOfComponents());
1011     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1012     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1013     ret->alloc(nbTuples,nbOfCompo);
1014     ret->copyStringInfoFrom(*this);
1015     const T *iptr(begin());
1016     T *optr(ret->getPointer());
1017     for(int i=0;i<nbTuples;i++)
1018       std::copy(iptr+nbOfCompo*i,iptr+nbOfCompo*(i+1),optr+nbOfCompo*old2New[i]);
1019     ret->copyStringInfoFrom(*this);
1020     return ret.retn();
1021   }
1022
1023   /*!
1024    * Returns a copy of \a this array with values permuted as required by \a new2Old array.
1025    * The values are permuted so that  \c new[ i ] = \c old[ \a new2Old[ i ]]. Number of
1026    * tuples in the result array remains the same as in \c this one.
1027    * If a permutation reduction is needed, subArray() or selectByTupleId() should be used.
1028    * For more info on renumbering see \ref numbering.
1029    *  \param [in] new2Old - C array of length equal to \a this->getNumberOfTuples()
1030    *     giving a previous position of i-th new value.
1031    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1032    *          is to delete using decrRef() as it is no more needed.
1033    */
1034   template<class T>
1035   typename Traits<T>::ArrayType *DataArrayTemplate<T>::renumberR(const int *new2Old) const
1036   {
1037     checkAllocated();
1038     int nbTuples(getNumberOfTuples()),nbOfCompo(getNumberOfComponents());
1039     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1040     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1041     ret->alloc(nbTuples,nbOfCompo);
1042     ret->copyStringInfoFrom(*this);
1043     const T *iptr(getConstPointer());
1044     T *optr(ret->getPointer());
1045     for(int i=0;i<nbTuples;i++)
1046       std::copy(iptr+nbOfCompo*new2Old[i],iptr+nbOfCompo*(new2Old[i]+1),optr+i*nbOfCompo);
1047     ret->copyStringInfoFrom(*this);
1048     return ret.retn();
1049   }
1050
1051   /*!
1052    * Returns a shorten and permuted copy of \a this array. The new DataArrayDouble is
1053    * of size \a newNbOfTuple and it's values are permuted as required by \a old2New array.
1054    * The values are permuted so that  \c new[ \a old2New[ i ]] = \c old[ i ] for all
1055    * \a old2New[ i ] >= 0. In other words every i-th tuple in \a this array, for which 
1056    * \a old2New[ i ] is negative, is missing from the result array.
1057    * For more info on renumbering see \ref numbering.
1058    *  \param [in] old2New - C array of length equal to \a this->getNumberOfTuples()
1059    *     giving a new position for i-th old tuple and giving negative position for
1060    *     for i-th old tuple that should be omitted.
1061    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1062    *          is to delete using decrRef() as it is no more needed.
1063    */
1064   template<class T>
1065   typename Traits<T>::ArrayType *DataArrayTemplate<T>::renumberAndReduce(const int *old2New, int newNbOfTuple) const
1066   {
1067     checkAllocated();
1068     int nbTuples(getNumberOfTuples()),nbOfCompo(getNumberOfComponents());
1069     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1070     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1071     ret->alloc(newNbOfTuple,nbOfCompo);
1072     const T *iptr=getConstPointer();
1073     T *optr=ret->getPointer();
1074     for(int i=0;i<nbTuples;i++)
1075       {
1076         int w=old2New[i];
1077         if(w>=0)
1078           std::copy(iptr+i*nbOfCompo,iptr+(i+1)*nbOfCompo,optr+w*nbOfCompo);
1079       }
1080     ret->copyStringInfoFrom(*this);
1081     return ret.retn();
1082   }
1083
1084   /*!
1085    * Returns a shorten and permuted copy of \a this array. The new DataArrayDouble is
1086    * of size \a new2OldEnd - \a new2OldBg and it's values are permuted as required by
1087    * \a new2OldBg array.
1088    * The values are permuted so that  \c new[ i ] = \c old[ \a new2OldBg[ i ]].
1089    * This method is equivalent to renumberAndReduce() except that convention in input is
1090    * \c new2old and \b not \c old2new.
1091    * For more info on renumbering see \ref numbering.
1092    *  \param [in] new2OldBg - pointer to the beginning of a permutation array that gives a
1093    *              tuple index in \a this array to fill the i-th tuple in the new array.
1094    *  \param [in] new2OldEnd - specifies the end of the permutation array that starts at
1095    *              \a new2OldBg, so that pointer to a tuple index (\a pi) varies as this:
1096    *              \a new2OldBg <= \a pi < \a new2OldEnd.
1097    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1098    *          is to delete using decrRef() as it is no more needed.
1099    */
1100   template<class T>
1101   typename Traits<T>::ArrayType *DataArrayTemplate<T>::mySelectByTupleId(const int *new2OldBg, const int *new2OldEnd) const
1102   {
1103     checkAllocated();
1104     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1105     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1106     int nbComp(getNumberOfComponents());
1107     ret->alloc((int)std::distance(new2OldBg,new2OldEnd),nbComp);
1108     ret->copyStringInfoFrom(*this);
1109     T *pt(ret->getPointer());
1110     const T *srcPt(getConstPointer());
1111     int i(0);
1112     for(const int *w=new2OldBg;w!=new2OldEnd;w++,i++)
1113       std::copy(srcPt+(*w)*nbComp,srcPt+((*w)+1)*nbComp,pt+i*nbComp);
1114     ret->copyStringInfoFrom(*this);
1115     return ret.retn();
1116   }
1117
1118   template<class T>
1119   typename Traits<T>::ArrayType *DataArrayTemplate<T>::mySelectByTupleId(const DataArrayInt& di) const
1120   {
1121     return DataArrayTemplate<T>::mySelectByTupleId(di.begin(),di.end());
1122   }
1123
1124   template<class T>
1125   MCAuto<typename Traits<T>::ArrayTypeCh> DataArrayTemplate<T>::selectPartDef(const PartDefinition *pd) const
1126   {
1127     if(!pd)
1128       throw INTERP_KERNEL::Exception("DataArrayTemplate<T>::selectPartDef : null input pointer !");
1129     MCAuto<typename Traits<T>::ArrayTypeCh> ret(Traits<T>::ArrayTypeCh::New());
1130     const SlicePartDefinition *spd(dynamic_cast<const SlicePartDefinition *>(pd));
1131     if(spd)
1132       {
1133         int a,b,c;
1134         spd->getSlice(a,b,c);
1135         if(a==0 && b==(int)getNumberOfTuples() && c==1)
1136           {
1137             DataArrayTemplate<T> *directRet(const_cast<DataArrayTemplate<T> *>(this));
1138             directRet->incrRef();
1139             MCAuto<DataArrayTemplate<T> > ret2(directRet);
1140             return DynamicCastSafe<DataArrayTemplate<T>,typename Traits<T>::ArrayTypeCh>(ret2);
1141           }
1142         else
1143           {
1144             MCAuto<DataArray> ret2(selectByTupleIdSafeSlice(a,b,c));
1145             return DynamicCastSafe<DataArray,typename Traits<T>::ArrayTypeCh>(ret2);
1146           }
1147       }
1148     const DataArrayPartDefinition *dpd(dynamic_cast<const DataArrayPartDefinition *>(pd));
1149     if(dpd)
1150       {
1151         MCAuto<DataArrayInt> arr(dpd->toDAI());
1152         MCAuto<DataArray> ret2(selectByTupleIdSafe(arr->begin(),arr->end()));
1153         return DynamicCastSafe<DataArray,typename Traits<T>::ArrayTypeCh>(ret2);
1154         
1155       }
1156     throw INTERP_KERNEL::Exception("DataArrayTemplate<T>::selectPartDef : unrecognized part def !");
1157   }
1158   
1159   /*!
1160    * Returns a shorten and permuted copy of \a this array. The new DataArrayDouble is
1161    * of size \a new2OldEnd - \a new2OldBg and it's values are permuted as required by
1162    * \a new2OldBg array.
1163    * The values are permuted so that  \c new[ i ] = \c old[ \a new2OldBg[ i ]].
1164    * This method is equivalent to renumberAndReduce() except that convention in input is
1165    * \c new2old and \b not \c old2new.
1166    * This method is equivalent to selectByTupleId() except that it prevents coping data
1167    * from behind the end of \a this array.
1168    * For more info on renumbering see \ref numbering.
1169    *  \param [in] new2OldBg - pointer to the beginning of a permutation array that gives a
1170    *              tuple index in \a this array to fill the i-th tuple in the new array.
1171    *  \param [in] new2OldEnd - specifies the end of the permutation array that starts at
1172    *              \a new2OldBg, so that pointer to a tuple index (\a pi) varies as this:
1173    *              \a new2OldBg <= \a pi < \a new2OldEnd.
1174    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1175    *          is to delete using decrRef() as it is no more needed.
1176    *  \throw If \a new2OldEnd - \a new2OldBg > \a this->getNumberOfTuples().
1177    */
1178   template<class T>
1179   typename Traits<T>::ArrayType *DataArrayTemplate<T>::mySelectByTupleIdSafe(const int *new2OldBg, const int *new2OldEnd) const
1180   {
1181     checkAllocated();
1182     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1183     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1184     int nbComp(getNumberOfComponents()),oldNbOfTuples(getNumberOfTuples());
1185     ret->alloc((int)std::distance(new2OldBg,new2OldEnd),nbComp);
1186     ret->copyStringInfoFrom(*this);
1187     T *pt(ret->getPointer());
1188     const T *srcPt(getConstPointer());
1189     int i(0);
1190     for(const int *w=new2OldBg;w!=new2OldEnd;w++,i++)
1191       if(*w>=0 && *w<oldNbOfTuples)
1192         std::copy(srcPt+(*w)*nbComp,srcPt+((*w)+1)*nbComp,pt+i*nbComp);
1193       else
1194         {
1195           std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::selectByTupleIdSafe : some ids has been detected to be out of [0,this->getNumberOfTuples) !";
1196           throw INTERP_KERNEL::Exception(oss.str().c_str());
1197         }
1198     ret->copyStringInfoFrom(*this);
1199     return ret.retn();
1200   }
1201
1202   /*!
1203    * Changes the number of components within \a this array so that its raw data **does
1204    * not** change, instead splitting this data into tuples changes.
1205    *  \warning This method erases all (name and unit) component info set before!
1206    *  \param [in] newNbOfComp - number of components for \a this array to have.
1207    *  \throw If \a this is not allocated
1208    *  \throw If getNbOfElems() % \a newNbOfCompo != 0.
1209    *  \throw If \a newNbOfCompo is lower than 1.
1210    *  \throw If the rearrange method would lead to a number of tuples higher than 2147483647 (maximal capacity of int32 !).
1211    *  \warning This method erases all (name and unit) component info set before!
1212    */
1213   template<class T>
1214   void DataArrayTemplate<T>::rearrange(int newNbOfCompo)
1215   {
1216     checkAllocated();
1217     if(newNbOfCompo<1)
1218       {
1219         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::rearrange : input newNbOfCompo must be > 0 !";
1220         throw INTERP_KERNEL::Exception(oss.str().c_str());
1221       }
1222     std::size_t nbOfElems=getNbOfElems();
1223     if(nbOfElems%newNbOfCompo!=0)
1224       {
1225         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::rearrange : nbOfElems%newNbOfCompo!=0 !";
1226         throw INTERP_KERNEL::Exception(oss.str().c_str());
1227       }
1228     if(nbOfElems/newNbOfCompo>(std::size_t)std::numeric_limits<int>::max())
1229       {
1230         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::rearrange : the rearrangement leads to too high number of tuples (> 2147483647) !";
1231         throw INTERP_KERNEL::Exception(oss.str().c_str());
1232       }
1233     _info_on_compo.clear();
1234     _info_on_compo.resize(newNbOfCompo);
1235     declareAsNew();
1236   }
1237
1238   /*!
1239    * Changes the number of components within \a this array to be equal to its number
1240    * of tuples, and inversely its number of tuples to become equal to its number of 
1241    * components. So that its raw data **does not** change, instead splitting this
1242    * data into tuples changes.
1243    *  \warning This method erases all (name and unit) component info set before!
1244    *  \warning Do not confuse this method with fromNoInterlace() and toNoInterlace()!
1245    *  \throw If \a this is not allocated.
1246    *  \sa rearrange()
1247    */
1248   template<class T>
1249   void DataArrayTemplate<T>::transpose()
1250   {
1251     checkAllocated();
1252     int nbOfTuples(getNumberOfTuples());
1253     rearrange(nbOfTuples);
1254   }
1255
1256   /*!
1257    * Returns a shorten or extended copy of \a this array. If \a newNbOfComp is less
1258    * than \a this->getNumberOfComponents() then the result array is shorten as each tuple
1259    * is truncated to have \a newNbOfComp components, keeping first components. If \a
1260    * newNbOfComp is more than \a this->getNumberOfComponents() then the result array is
1261    * expanded as each tuple is populated with \a dftValue to have \a newNbOfComp
1262    * components.  
1263    *  \param [in] newNbOfComp - number of components for the new array to have.
1264    *  \param [in] dftValue - value assigned to new values added to the new array.
1265    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1266    *          is to delete using decrRef() as it is no more needed.
1267    *  \throw If \a this is not allocated.
1268    */
1269   template<class T>
1270   typename Traits<T>::ArrayType *DataArrayTemplate<T>::changeNbOfComponents(int newNbOfComp, T dftValue) const
1271   {
1272     checkAllocated();
1273     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1274     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1275     ret->alloc(getNumberOfTuples(),newNbOfComp);
1276     const T *oldc(getConstPointer());
1277     T *nc(ret->getPointer());
1278     int nbOfTuples(getNumberOfTuples()),oldNbOfComp(getNumberOfComponents());
1279     int dim(std::min(oldNbOfComp,newNbOfComp));
1280     for(int i=0;i<nbOfTuples;i++)
1281       {
1282         int j=0;
1283         for(;j<dim;j++)
1284           nc[newNbOfComp*i+j]=oldc[i*oldNbOfComp+j];
1285         for(;j<newNbOfComp;j++)
1286           nc[newNbOfComp*i+j]=dftValue;
1287       }
1288     ret->setName(getName());
1289     for(int i=0;i<dim;i++)
1290       ret->setInfoOnComponent(i,getInfoOnComponent(i));
1291     ret->setName(getName());
1292     return ret.retn();
1293   }
1294
1295   /*!
1296    * Returns a copy of \a this array composed of selected components.
1297    * The new DataArrayDouble has the same number of tuples but includes components
1298    * specified by \a compoIds parameter. So that getNbOfElems() of the result array
1299    * can be either less, same or more than \a this->getNbOfElems().
1300    *  \param [in] compoIds - sequence of zero based indices of components to include
1301    *              into the new array.
1302    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1303    *          is to delete using decrRef() as it is no more needed.
1304    *  \throw If \a this is not allocated.
1305    *  \throw If a component index (\a i) is not valid: 
1306    *         \a i < 0 || \a i >= \a this->getNumberOfComponents().
1307    *
1308    *  \if ENABLE_EXAMPLES
1309    *  \ref py_mcdataarraydouble_KeepSelectedComponents "Here is a Python example".
1310    *  \endif
1311    */
1312   template<class T>
1313   typename Traits<T>::ArrayType *DataArrayTemplate<T>::myKeepSelectedComponents(const std::vector<int>& compoIds) const
1314   {
1315     checkAllocated();
1316     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1317     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1318     std::size_t newNbOfCompo(compoIds.size());
1319     int oldNbOfCompo(getNumberOfComponents());
1320     for(std::vector<int>::const_iterator it=compoIds.begin();it!=compoIds.end();it++)
1321       if((*it)<0 || (*it)>=oldNbOfCompo)
1322         {
1323           std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::keepSelectedComponents : invalid requested component : " << *it << " whereas it should be in [0," << oldNbOfCompo << ") !";
1324           throw INTERP_KERNEL::Exception(oss.str().c_str());
1325         }
1326     int nbOfTuples(getNumberOfTuples());
1327     ret->alloc(nbOfTuples,(int)newNbOfCompo);
1328     ret->copyPartOfStringInfoFrom(*this,compoIds);
1329     const T *oldc(getConstPointer());
1330     T *nc(ret->getPointer());
1331     for(int i=0;i<nbOfTuples;i++)
1332       for(std::size_t j=0;j<newNbOfCompo;j++,nc++)
1333         *nc=oldc[i*oldNbOfCompo+compoIds[j]];
1334     return ret.retn();
1335   }
1336
1337   /*!
1338    * Returns a shorten copy of \a this array. The new DataArrayDouble contains all
1339    * tuples starting from the \a tupleIdBg-th tuple and including all tuples located before
1340    * the \a tupleIdEnd-th one. This methods has a similar behavior as std::string::substr().
1341    * This method is a specialization of selectByTupleIdSafeSlice().
1342    *  \param [in] tupleIdBg - index of the first tuple to copy from \a this array.
1343    *  \param [in] tupleIdEnd - index of the tuple before which the tuples to copy are located.
1344    *          If \a tupleIdEnd == -1, all the tuples till the end of \a this array are copied.
1345    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1346    *          is to delete using decrRef() as it is no more needed.
1347    *  \throw If \a tupleIdBg < 0.
1348    *  \throw If \a tupleIdBg > \a this->getNumberOfTuples().
1349    *  \throw If \a tupleIdEnd != -1 && \a tupleIdEnd < \a this->getNumberOfTuples().
1350    *  \sa DataArrayDouble::selectByTupleIdSafeSlice
1351    */
1352   template<class T>
1353   typename Traits<T>::ArrayType *DataArrayTemplate<T>::subArray(int tupleIdBg, int tupleIdEnd) const
1354   {
1355     checkAllocated();
1356     int nbt(getNumberOfTuples());
1357     if(tupleIdBg<0)
1358       {
1359         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::subArray : The tupleIdBg parameter must be greater than 0 !";
1360         throw INTERP_KERNEL::Exception(oss.str().c_str());
1361       }
1362     if(tupleIdBg>nbt)
1363       {
1364         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << ":subArray : The tupleIdBg parameter is greater than number of tuples !";
1365         throw INTERP_KERNEL::Exception(oss.str().c_str());
1366       }
1367     int trueEnd=tupleIdEnd;
1368     if(tupleIdEnd!=-1)
1369       {
1370         if(tupleIdEnd>nbt)
1371           {
1372             std::ostringstream oss; oss << Traits<T>::ArrayTypeName << ":subArray : The tupleIdBg parameter is greater than number of tuples !";
1373             throw INTERP_KERNEL::Exception(oss.str().c_str());
1374           }
1375       }
1376     else
1377       trueEnd=nbt;
1378     int nbComp(getNumberOfComponents());
1379     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1380     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1381     ret->alloc(trueEnd-tupleIdBg,nbComp);
1382     ret->copyStringInfoFrom(*this);
1383     std::copy(getConstPointer()+tupleIdBg*nbComp,getConstPointer()+trueEnd*nbComp,ret->getPointer());
1384     return ret.retn();
1385   }
1386
1387   /*!
1388    * Returns a shorten copy of \a this array. The new DataArrayDouble contains every
1389    * (\a bg + \c i * \a step)-th tuple of \a this array located before the \a end2-th
1390    * tuple. Indices of the selected tuples are the same as ones returned by the Python
1391    * command \c range( \a bg, \a end2, \a step ).
1392    * This method is equivalent to selectByTupleIdSafe() except that the input array is
1393    * not constructed explicitly.
1394    * For more info on renumbering see \ref numbering.
1395    *  \param [in] bg - index of the first tuple to copy from \a this array.
1396    *  \param [in] end2 - index of the tuple before which the tuples to copy are located.
1397    *  \param [in] step - index increment to get index of the next tuple to copy.
1398    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1399    *          is to delete using decrRef() as it is no more needed.
1400    *  \sa DataArrayDouble::subArray.
1401    */
1402   template<class T>
1403   typename Traits<T>::ArrayType *DataArrayTemplate<T>::mySelectByTupleIdSafeSlice(int bg, int end2, int step) const
1404   {
1405     checkAllocated();
1406     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1407     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1408     int nbComp(getNumberOfComponents());
1409     std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::selectByTupleIdSafeSlice : ";
1410     int newNbOfTuples(GetNumberOfItemGivenBESRelative(bg,end2,step,oss.str()));
1411     ret->alloc(newNbOfTuples,nbComp);
1412     T *pt(ret->getPointer());
1413     const T *srcPt(getConstPointer()+bg*nbComp);
1414     for(int i=0;i<newNbOfTuples;i++,srcPt+=step*nbComp)
1415       std::copy(srcPt,srcPt+nbComp,pt+i*nbComp);
1416     ret->copyStringInfoFrom(*this);
1417     return ret.retn();
1418   }
1419   
1420   /*!
1421    * Copy all values from another DataArrayDouble into specified tuples and components
1422    * of \a this array. Textual data is not copied.
1423    * The tree parameters defining set of indices of tuples and components are similar to
1424    * the tree parameters of the Python function \c range(\c start,\c stop,\c step).
1425    *  \param [in] a - the array to copy values from.
1426    *  \param [in] bgTuples - index of the first tuple of \a this array to assign values to.
1427    *  \param [in] endTuples - index of the tuple before which the tuples to assign to
1428    *              are located.
1429    *  \param [in] stepTuples - index increment to get index of the next tuple to assign to.
1430    *  \param [in] bgComp - index of the first component of \a this array to assign values to.
1431    *  \param [in] endComp - index of the component before which the components to assign
1432    *              to are located.
1433    *  \param [in] stepComp - index increment to get index of the next component to assign to.
1434    *  \param [in] strictCompoCompare - if \a true (by default), then \a a->getNumberOfComponents() 
1435    *              must be equal to the number of columns to assign to, else an
1436    *              exception is thrown; if \a false, then it is only required that \a
1437    *              a->getNbOfElems() equals to number of values to assign to (this condition
1438    *              must be respected even if \a strictCompoCompare is \a true). The number of 
1439    *              values to assign to is given by following Python expression:
1440    *              \a nbTargetValues = 
1441    *              \c len(\c range(\a bgTuples,\a endTuples,\a stepTuples)) *
1442    *              \c len(\c range(\a bgComp,\a endComp,\a stepComp)).
1443    *  \throw If \a a is NULL.
1444    *  \throw If \a a is not allocated.
1445    *  \throw If \a this is not allocated.
1446    *  \throw If parameters specifying tuples and components to assign to do not give a
1447    *            non-empty range of increasing indices.
1448    *  \throw If \a a->getNbOfElems() != \a nbTargetValues.
1449    *  \throw If \a strictCompoCompare == \a true && \a a->getNumberOfComponents() !=
1450    *            \c len(\c range(\a bgComp,\a endComp,\a stepComp)).
1451    *
1452    *  \if ENABLE_EXAMPLES
1453    *  \ref py_mcdataarraydouble_setpartofvalues1 "Here is a Python example".
1454    *  \endif
1455    */
1456   template<class T>
1457   void DataArrayTemplate<T>::setPartOfValues1(const typename Traits<T>::ArrayType *a, int bgTuples, int endTuples, int stepTuples, int bgComp, int endComp, int stepComp, bool strictCompoCompare)
1458   {
1459     if(!a)
1460       {
1461         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::setPartOfValues1 : input DataArrayDouble is NULL !";
1462         throw INTERP_KERNEL::Exception(oss.str().c_str());
1463       }
1464     const char msg[]="DataArrayTemplate::setPartOfValues1";
1465     checkAllocated();
1466     a->checkAllocated();
1467     int newNbOfTuples(DataArray::GetNumberOfItemGivenBES(bgTuples,endTuples,stepTuples,msg));
1468     int newNbOfComp(DataArray::GetNumberOfItemGivenBES(bgComp,endComp,stepComp,msg));
1469     int nbComp(getNumberOfComponents()),nbOfTuples(getNumberOfTuples());
1470     DataArray::CheckValueInRangeEx(nbOfTuples,bgTuples,endTuples,"invalid tuple value");
1471     DataArray::CheckValueInRangeEx(nbComp,bgComp,endComp,"invalid component value");
1472     bool assignTech(true);
1473     if(a->getNbOfElems()==(std::size_t)newNbOfTuples*newNbOfComp)
1474       {
1475         if(strictCompoCompare)
1476           a->checkNbOfTuplesAndComp(newNbOfTuples,newNbOfComp,msg);
1477       }
1478     else
1479       {
1480         a->checkNbOfTuplesAndComp(1,newNbOfComp,msg);
1481         assignTech=false;
1482       }
1483     const T *srcPt(a->getConstPointer());
1484     T *pt(getPointer()+bgTuples*nbComp+bgComp);
1485     if(assignTech)
1486       {
1487         for(int i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
1488           for(int j=0;j<newNbOfComp;j++,srcPt++)
1489             pt[j*stepComp]=*srcPt;
1490       }
1491     else
1492       {
1493         for(int i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
1494           {
1495             const T*srcPt2=srcPt;
1496             for(int j=0;j<newNbOfComp;j++,srcPt2++)
1497               pt[j*stepComp]=*srcPt2;
1498           }
1499       }
1500   }
1501   
1502   /*!
1503  * Assign a given value to values at specified tuples and components of \a this array.
1504  * The tree parameters defining set of indices of tuples and components are similar to
1505  * the tree parameters of the Python function \c range(\c start,\c stop,\c step)..
1506  *  \param [in] a - the value to assign.
1507  *  \param [in] bgTuples - index of the first tuple of \a this array to assign to.
1508  *  \param [in] endTuples - index of the tuple before which the tuples to assign to
1509  *              are located.
1510  *  \param [in] stepTuples - index increment to get index of the next tuple to assign to.
1511  *  \param [in] bgComp - index of the first component of \a this array to assign to.
1512  *  \param [in] endComp - index of the component before which the components to assign
1513  *              to are located.
1514  *  \param [in] stepComp - index increment to get index of the next component to assign to.
1515  *  \throw If \a this is not allocated.
1516  *  \throw If parameters specifying tuples and components to assign to, do not give a
1517  *            non-empty range of increasing indices or indices are out of a valid range
1518  *            for \c this array.
1519  *
1520  *  \if ENABLE_EXAMPLES
1521  *  \ref py_mcdataarraydouble_setpartofvaluessimple1 "Here is a Python example".
1522  *  \endif
1523  */
1524   template<class T>
1525   void DataArrayTemplate<T>::setPartOfValuesSimple1(T a, int bgTuples, int endTuples, int stepTuples, int bgComp, int endComp, int stepComp)
1526   {
1527     const char msg[]="DataArrayTemplate::setPartOfValuesSimple1";
1528     checkAllocated();
1529     int newNbOfTuples(DataArray::GetNumberOfItemGivenBES(bgTuples,endTuples,stepTuples,msg));
1530     int newNbOfComp(DataArray::GetNumberOfItemGivenBES(bgComp,endComp,stepComp,msg));
1531     int nbComp(getNumberOfComponents()),nbOfTuples(getNumberOfTuples());
1532     DataArray::CheckValueInRangeEx(nbOfTuples,bgTuples,endTuples,"invalid tuple value");
1533     DataArray::CheckValueInRangeEx(nbComp,bgComp,endComp,"invalid component value");
1534     T *pt=getPointer()+bgTuples*nbComp+bgComp;
1535     for(int i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
1536       for(int j=0;j<newNbOfComp;j++)
1537         pt[j*stepComp]=a;
1538   }
1539   
1540   /*!
1541    * Copy all values from another DataArrayDouble (\a a) into specified tuples and 
1542    * components of \a this array. Textual data is not copied.
1543    * The tuples and components to assign to are defined by C arrays of indices.
1544    * There are two *modes of usage*:
1545    * - If \a a->getNbOfElems() equals to number of values to assign to, then every value
1546    *   of \a a is assigned to its own location within \a this array. 
1547    * - If \a a includes one tuple, then all values of \a a are assigned to the specified
1548    *   components of every specified tuple of \a this array. In this mode it is required
1549    *   that \a a->getNumberOfComponents() equals to the number of specified components.
1550    *
1551    *  \param [in] a - the array to copy values from.
1552    *  \param [in] bgTuples - pointer to an array of tuple indices of \a this array to
1553    *              assign values of \a a to.
1554    *  \param [in] endTuples - specifies the end of the array \a bgTuples, so that
1555    *              pointer to a tuple index <em>(pi)</em> varies as this: 
1556    *              \a bgTuples <= \a pi < \a endTuples.
1557    *  \param [in] bgComp - pointer to an array of component indices of \a this array to
1558    *              assign values of \a a to.
1559    *  \param [in] endComp - specifies the end of the array \a bgTuples, so that
1560    *              pointer to a component index <em>(pi)</em> varies as this: 
1561    *              \a bgComp <= \a pi < \a endComp.
1562    *  \param [in] strictCompoCompare - this parameter is checked only if the
1563    *               *mode of usage* is the first; if it is \a true (default), 
1564    *               then \a a->getNumberOfComponents() must be equal 
1565    *               to the number of specified columns, else this is not required.
1566    *  \throw If \a a is NULL.
1567    *  \throw If \a a is not allocated.
1568    *  \throw If \a this is not allocated.
1569    *  \throw If any index of tuple/component given by <em>bgTuples / bgComp</em> is
1570    *         out of a valid range for \a this array.
1571    *  \throw In the first *mode of usage*, if <em>strictCompoCompare == true </em> and
1572    *         if <em> a->getNumberOfComponents() != (endComp - bgComp) </em>.
1573    *  \throw In the second *mode of usage*, if \a a->getNumberOfTuples() != 1 or
1574    *         <em> a->getNumberOfComponents() != (endComp - bgComp)</em>.
1575    *
1576    *  \if ENABLE_EXAMPLES
1577    *  \ref py_mcdataarraydouble_setpartofvalues2 "Here is a Python example".
1578    *  \endif
1579    */
1580   template<class T>
1581   void DataArrayTemplate<T>::setPartOfValues2(const typename Traits<T>::ArrayType *a, const int *bgTuples, const int *endTuples, const int *bgComp, const int *endComp, bool strictCompoCompare)
1582   {
1583     if(!a)
1584       throw INTERP_KERNEL::Exception("DataArrayDouble::setPartOfValues2 : input DataArrayDouble is NULL !");
1585     const char msg[]="DataArrayTemplate::setPartOfValues2";
1586     checkAllocated();
1587     a->checkAllocated();
1588     int nbComp(getNumberOfComponents()),nbOfTuples(getNumberOfTuples());
1589     for(const int *z=bgComp;z!=endComp;z++)
1590       DataArray::CheckValueInRange(nbComp,*z,"invalid component id");
1591     int newNbOfTuples((int)std::distance(bgTuples,endTuples));
1592     int newNbOfComp((int)std::distance(bgComp,endComp));
1593     bool assignTech(true);
1594     if(a->getNbOfElems()==(std::size_t)newNbOfTuples*newNbOfComp)
1595       {
1596         if(strictCompoCompare)
1597           a->checkNbOfTuplesAndComp(newNbOfTuples,newNbOfComp,msg);
1598       }
1599     else
1600       {
1601         a->checkNbOfTuplesAndComp(1,newNbOfComp,msg);
1602         assignTech=false;
1603       }
1604     T *pt(getPointer());
1605     const T *srcPt(a->getConstPointer());
1606     if(assignTech)
1607       {    
1608         for(const int *w=bgTuples;w!=endTuples;w++)
1609           {
1610             DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1611             for(const int *z=bgComp;z!=endComp;z++,srcPt++)
1612               {    
1613                 pt[(std::size_t)(*w)*nbComp+(*z)]=*srcPt;
1614               }
1615           }
1616       }
1617     else
1618       {
1619         for(const int *w=bgTuples;w!=endTuples;w++)
1620           {
1621             const T *srcPt2=srcPt;
1622             DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1623             for(const int *z=bgComp;z!=endComp;z++,srcPt2++)
1624               {    
1625                 pt[(std::size_t)(*w)*nbComp+(*z)]=*srcPt2;
1626               }
1627           }
1628       }
1629   }
1630   
1631   /*!
1632    * Assign a given value to values at specified tuples and components of \a this array.
1633    * The tuples and components to assign to are defined by C arrays of indices.
1634    *  \param [in] a - the value to assign.
1635    *  \param [in] bgTuples - pointer to an array of tuple indices of \a this array to
1636    *              assign \a a to.
1637    *  \param [in] endTuples - specifies the end of the array \a bgTuples, so that
1638    *              pointer to a tuple index (\a pi) varies as this: 
1639    *              \a bgTuples <= \a pi < \a endTuples.
1640    *  \param [in] bgComp - pointer to an array of component indices of \a this array to
1641    *              assign \a a to.
1642    *  \param [in] endComp - specifies the end of the array \a bgTuples, so that
1643    *              pointer to a component index (\a pi) varies as this: 
1644    *              \a bgComp <= \a pi < \a endComp.
1645    *  \throw If \a this is not allocated.
1646    *  \throw If any index of tuple/component given by <em>bgTuples / bgComp</em> is
1647    *         out of a valid range for \a this array.
1648    *
1649    *  \if ENABLE_EXAMPLES
1650    *  \ref py_mcdataarraydouble_setpartofvaluessimple2 "Here is a Python example".
1651    *  \endif
1652    */
1653   template<class T>
1654   void DataArrayTemplate<T>::setPartOfValuesSimple2(T a, const int *bgTuples, const int *endTuples, const int *bgComp, const int *endComp)
1655   {
1656     checkAllocated();
1657     int nbComp(getNumberOfComponents()),nbOfTuples(getNumberOfTuples());
1658     for(const int *z=bgComp;z!=endComp;z++)
1659       DataArray::CheckValueInRange(nbComp,*z,"invalid component id");
1660     T *pt(getPointer());
1661     for(const int *w=bgTuples;w!=endTuples;w++)
1662       for(const int *z=bgComp;z!=endComp;z++)
1663         {
1664           DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1665           pt[(std::size_t)(*w)*nbComp+(*z)]=a;
1666         }
1667   }
1668   
1669   /*!
1670    * Copy all values from another DataArrayDouble (\a a) into specified tuples and 
1671    * components of \a this array. Textual data is not copied.
1672    * The tuples to assign to are defined by a C array of indices.
1673    * The components to assign to are defined by three values similar to parameters of
1674    * the Python function \c range(\c start,\c stop,\c step).
1675    * There are two *modes of usage*:
1676    * - If \a a->getNbOfElems() equals to number of values to assign to, then every value
1677    *   of \a a is assigned to its own location within \a this array. 
1678    * - If \a a includes one tuple, then all values of \a a are assigned to the specified
1679    *   components of every specified tuple of \a this array. In this mode it is required
1680    *   that \a a->getNumberOfComponents() equals to the number of specified components.
1681    *
1682    *  \param [in] a - the array to copy values from.
1683    *  \param [in] bgTuples - pointer to an array of tuple indices of \a this array to
1684    *              assign values of \a a to.
1685    *  \param [in] endTuples - specifies the end of the array \a bgTuples, so that
1686    *              pointer to a tuple index <em>(pi)</em> varies as this: 
1687    *              \a bgTuples <= \a pi < \a endTuples.
1688    *  \param [in] bgComp - index of the first component of \a this array to assign to.
1689    *  \param [in] endComp - index of the component before which the components to assign
1690    *              to are located.
1691    *  \param [in] stepComp - index increment to get index of the next component to assign to.
1692    *  \param [in] strictCompoCompare - this parameter is checked only in the first
1693    *               *mode of usage*; if \a strictCompoCompare is \a true (default), 
1694    *               then \a a->getNumberOfComponents() must be equal 
1695    *               to the number of specified columns, else this is not required.
1696    *  \throw If \a a is NULL.
1697    *  \throw If \a a is not allocated.
1698    *  \throw If \a this is not allocated.
1699    *  \throw If any index of tuple given by \a bgTuples is out of a valid range for 
1700    *         \a this array.
1701    *  \throw In the first *mode of usage*, if <em>strictCompoCompare == true </em> and
1702    *         if <em> a->getNumberOfComponents()</em> is unequal to the number of components
1703    *         defined by <em>(bgComp,endComp,stepComp)</em>.
1704    *  \throw In the second *mode of usage*, if \a a->getNumberOfTuples() != 1 or
1705    *         <em> a->getNumberOfComponents()</em> is unequal to the number of components
1706    *         defined by <em>(bgComp,endComp,stepComp)</em>.
1707    *  \throw If parameters specifying components to assign to, do not give a
1708    *            non-empty range of increasing indices or indices are out of a valid range
1709    *            for \c this array.
1710    *
1711    *  \if ENABLE_EXAMPLES
1712    *  \ref py_mcdataarraydouble_setpartofvalues3 "Here is a Python example".
1713    *  \endif
1714    */
1715   template<class T>
1716   void DataArrayTemplate<T>::setPartOfValues3(const typename Traits<T>::ArrayType *a, const int *bgTuples, const int *endTuples, int bgComp, int endComp, int stepComp, bool strictCompoCompare)
1717   {
1718     if(!a)
1719       throw INTERP_KERNEL::Exception("DataArrayTemplate::setPartOfValues3 : input DataArrayDouble is NULL !");
1720     const char msg[]="DataArrayTemplate::setPartOfValues3";
1721     checkAllocated();
1722     a->checkAllocated();
1723     int newNbOfComp=DataArray::GetNumberOfItemGivenBES(bgComp,endComp,stepComp,msg);
1724     int nbComp=getNumberOfComponents();
1725     int nbOfTuples=getNumberOfTuples();
1726     DataArray::CheckValueInRangeEx(nbComp,bgComp,endComp,"invalid component value");
1727     int newNbOfTuples=(int)std::distance(bgTuples,endTuples);
1728     bool assignTech=true;
1729     if(a->getNbOfElems()==(std::size_t)newNbOfTuples*newNbOfComp)
1730       {
1731         if(strictCompoCompare)
1732           a->checkNbOfTuplesAndComp(newNbOfTuples,newNbOfComp,msg);
1733       }
1734     else
1735       {
1736         a->checkNbOfTuplesAndComp(1,newNbOfComp,msg);
1737         assignTech=false;
1738       }
1739     T *pt(getPointer()+bgComp);
1740     const T *srcPt(a->getConstPointer());
1741     if(assignTech)
1742       {
1743         for(const int *w=bgTuples;w!=endTuples;w++)
1744           for(int j=0;j<newNbOfComp;j++,srcPt++)
1745             {
1746               DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1747               pt[(std::size_t)(*w)*nbComp+j*stepComp]=*srcPt;
1748             }
1749       }
1750     else
1751       {
1752         for(const int *w=bgTuples;w!=endTuples;w++)
1753           {
1754             const T *srcPt2=srcPt;
1755             for(int j=0;j<newNbOfComp;j++,srcPt2++)
1756               {
1757                 DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1758                 pt[(std::size_t)(*w)*nbComp+j*stepComp]=*srcPt2;
1759               }
1760           }
1761       }
1762   }
1763   
1764   /*!
1765    * Assign a given value to values at specified tuples and components of \a this array.
1766    * The tuples to assign to are defined by a C array of indices.
1767    * The components to assign to are defined by three values similar to parameters of
1768    * the Python function \c range(\c start,\c stop,\c step).
1769    *  \param [in] a - the value to assign.
1770    *  \param [in] bgTuples - pointer to an array of tuple indices of \a this array to
1771    *              assign \a a to.
1772    *  \param [in] endTuples - specifies the end of the array \a bgTuples, so that
1773    *              pointer to a tuple index <em>(pi)</em> varies as this: 
1774    *              \a bgTuples <= \a pi < \a endTuples.
1775    *  \param [in] bgComp - index of the first component of \a this array to assign to.
1776    *  \param [in] endComp - index of the component before which the components to assign
1777    *              to are located.
1778    *  \param [in] stepComp - index increment to get index of the next component to assign to.
1779    *  \throw If \a this is not allocated.
1780    *  \throw If any index of tuple given by \a bgTuples is out of a valid range for 
1781    *         \a this array.
1782    *  \throw If parameters specifying components to assign to, do not give a
1783    *            non-empty range of increasing indices or indices are out of a valid range
1784    *            for \c this array.
1785    *
1786    *  \if ENABLE_EXAMPLES
1787    *  \ref py_mcdataarraydouble_setpartofvaluessimple3 "Here is a Python example".
1788    *  \endif
1789    */
1790   template<class T>
1791   void DataArrayTemplate<T>::setPartOfValuesSimple3(T a, const int *bgTuples, const int *endTuples, int bgComp, int endComp, int stepComp)
1792   {
1793     const char msg[]="DataArrayTemplate::setPartOfValuesSimple3";
1794     checkAllocated();
1795     int newNbOfComp(DataArray::GetNumberOfItemGivenBES(bgComp,endComp,stepComp,msg));
1796     int nbComp(getNumberOfComponents()),nbOfTuples(getNumberOfTuples());
1797     DataArray::CheckValueInRangeEx(nbComp,bgComp,endComp,"invalid component value");
1798     T *pt(getPointer()+bgComp);
1799     for(const int *w=bgTuples;w!=endTuples;w++)
1800       for(int j=0;j<newNbOfComp;j++)
1801         {
1802           DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1803           pt[(std::size_t)(*w)*nbComp+j*stepComp]=a;
1804         }
1805   }
1806
1807   /*!
1808    * Copy all values from another DataArrayDouble into specified tuples and components
1809    * of \a this array. Textual data is not copied.
1810    * The tree parameters defining set of indices of tuples and components are similar to
1811    * the tree parameters of the Python function \c range(\c start,\c stop,\c step).
1812    *  \param [in] a - the array to copy values from.
1813    *  \param [in] bgTuples - index of the first tuple of \a this array to assign values to.
1814    *  \param [in] endTuples - index of the tuple before which the tuples to assign to
1815    *              are located.
1816    *  \param [in] stepTuples - index increment to get index of the next tuple to assign to.
1817    *  \param [in] bgComp - pointer to an array of component indices of \a this array to
1818    *              assign \a a to.
1819    *  \param [in] endComp - specifies the end of the array \a bgTuples, so that
1820    *              pointer to a component index (\a pi) varies as this: 
1821    *              \a bgComp <= \a pi < \a endComp.
1822    *  \param [in] strictCompoCompare - if \a true (by default), then \a a->getNumberOfComponents() 
1823    *              must be equal to the number of columns to assign to, else an
1824    *              exception is thrown; if \a false, then it is only required that \a
1825    *              a->getNbOfElems() equals to number of values to assign to (this condition
1826    *              must be respected even if \a strictCompoCompare is \a true). The number of 
1827    *              values to assign to is given by following Python expression:
1828    *              \a nbTargetValues = 
1829    *              \c len(\c range(\a bgTuples,\a endTuples,\a stepTuples)) *
1830    *              \c len(\c range(\a bgComp,\a endComp,\a stepComp)).
1831    *  \throw If \a a is NULL.
1832    *  \throw If \a a is not allocated.
1833    *  \throw If \a this is not allocated.
1834    *  \throw If parameters specifying tuples and components to assign to do not give a
1835    *            non-empty range of increasing indices.
1836    *  \throw If \a a->getNbOfElems() != \a nbTargetValues.
1837    *  \throw If \a strictCompoCompare == \a true && \a a->getNumberOfComponents() !=
1838    *            \c len(\c range(\a bgComp,\a endComp,\a stepComp)).
1839    *
1840    */
1841   template<class T>
1842   void DataArrayTemplate<T>::setPartOfValues4(const typename Traits<T>::ArrayType *a, int bgTuples, int endTuples, int stepTuples, const int *bgComp, const int *endComp, bool strictCompoCompare)
1843   {if(!a)
1844       throw INTERP_KERNEL::Exception("DataArrayTemplate::setPartOfValues4 : input DataArrayTemplate is NULL !");
1845     const char msg[]="DataArrayTemplate::setPartOfValues4";
1846     checkAllocated();
1847     a->checkAllocated();
1848     int newNbOfTuples(DataArray::GetNumberOfItemGivenBES(bgTuples,endTuples,stepTuples,msg));
1849     int newNbOfComp((int)std::distance(bgComp,endComp));
1850     int nbComp(getNumberOfComponents());
1851     for(const int *z=bgComp;z!=endComp;z++)
1852       DataArray::CheckValueInRange(nbComp,*z,"invalid component id");
1853     int nbOfTuples(getNumberOfTuples());
1854     DataArray::CheckValueInRangeEx(nbOfTuples,bgTuples,endTuples,"invalid tuple value");
1855     bool assignTech(true);
1856     if(a->getNbOfElems()==(std::size_t)newNbOfTuples*newNbOfComp)
1857       {
1858         if(strictCompoCompare)
1859           a->checkNbOfTuplesAndComp(newNbOfTuples,newNbOfComp,msg);
1860       }
1861     else
1862       {
1863         a->checkNbOfTuplesAndComp(1,newNbOfComp,msg);
1864         assignTech=false;
1865       }
1866     const T *srcPt(a->getConstPointer());
1867     T *pt(getPointer()+bgTuples*nbComp);
1868     if(assignTech)
1869       {
1870         for(int i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
1871           for(const int *z=bgComp;z!=endComp;z++,srcPt++)
1872             pt[*z]=*srcPt;
1873       }
1874     else
1875       {
1876       for(int i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
1877         {
1878           const T *srcPt2(srcPt);
1879           for(const int *z=bgComp;z!=endComp;z++,srcPt2++)
1880             pt[*z]=*srcPt2;
1881         }
1882       }
1883   }
1884
1885   template<class T>
1886   void DataArrayTemplate<T>::setPartOfValuesSimple4(T a, int bgTuples, int endTuples, int stepTuples, const int *bgComp, const int *endComp)
1887   {
1888     const char msg[]="DataArrayTemplate::setPartOfValuesSimple4";
1889     checkAllocated();
1890     int newNbOfTuples(DataArray::GetNumberOfItemGivenBES(bgTuples,endTuples,stepTuples,msg));
1891     int nbComp(getNumberOfComponents());
1892     for(const int *z=bgComp;z!=endComp;z++)
1893       DataArray::CheckValueInRange(nbComp,*z,"invalid component id");
1894     int nbOfTuples(getNumberOfTuples());
1895     DataArray::CheckValueInRangeEx(nbOfTuples,bgTuples,endTuples,"invalid tuple value");
1896     T *pt=getPointer()+bgTuples*nbComp;
1897     for(int i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
1898       for(const int *z=bgComp;z!=endComp;z++)
1899         pt[*z]=a;
1900   }
1901   
1902   /*!
1903    * Copy some tuples from another DataArrayDouble into specified tuples
1904    * of \a this array. Textual data is not copied. Both arrays must have equal number of
1905    * components.
1906    * Both the tuples to assign and the tuples to assign to are defined by a DataArrayInt.
1907    * All components of selected tuples are copied.
1908    *  \param [in] a - the array to copy values from.
1909    *  \param [in] tuplesSelec - the array specifying both source tuples of \a a and
1910    *              target tuples of \a this. \a tuplesSelec has two components, and the
1911    *              first component specifies index of the source tuple and the second
1912    *              one specifies index of the target tuple.
1913    *  \throw If \a this is not allocated.
1914    *  \throw If \a a is NULL.
1915    *  \throw If \a a is not allocated.
1916    *  \throw If \a tuplesSelec is NULL.
1917    *  \throw If \a tuplesSelec is not allocated.
1918    *  \throw If <em>this->getNumberOfComponents() != a->getNumberOfComponents()</em>.
1919    *  \throw If \a tuplesSelec->getNumberOfComponents() != 2.
1920    *  \throw If any tuple index given by \a tuplesSelec is out of a valid range for 
1921    *         the corresponding (\a this or \a a) array.
1922    */
1923   template<class T>
1924   void DataArrayTemplate<T>::setPartOfValuesAdv(const typename Traits<T>::ArrayType *a, const DataArrayInt *tuplesSelec)
1925   {
1926     if(!a || !tuplesSelec)
1927       throw INTERP_KERNEL::Exception("DataArrayTemplate::setPartOfValuesAdv : input DataArrayTemplate is NULL !");
1928     checkAllocated();
1929     a->checkAllocated();
1930     tuplesSelec->checkAllocated();
1931     std::size_t nbOfComp(getNumberOfComponents());
1932     if(nbOfComp!=a->getNumberOfComponents())
1933       throw INTERP_KERNEL::Exception("DataArrayTemplate::setPartOfValuesAdv : This and a do not have the same number of components !");
1934     if(tuplesSelec->getNumberOfComponents()!=2)
1935       throw INTERP_KERNEL::Exception("DataArrayTemplate::setPartOfValuesAdv : Expecting to have a tuple selector DataArrayInt instance with exactly 2 components !");
1936     int thisNt(getNumberOfTuples());
1937     int aNt(a->getNumberOfTuples());
1938     T *valsToSet(getPointer());
1939     const T *valsSrc(a->getConstPointer());
1940     for(const int *tuple=tuplesSelec->begin();tuple!=tuplesSelec->end();tuple+=2)
1941     {
1942       if(tuple[1]>=0 && tuple[1]<aNt)
1943         {
1944           if(tuple[0]>=0 && tuple[0]<thisNt)
1945             std::copy(valsSrc+nbOfComp*tuple[1],valsSrc+nbOfComp*(tuple[1]+1),valsToSet+nbOfComp*tuple[0]);
1946           else
1947             {
1948               std::ostringstream oss; oss << "DataArrayTemplate::setPartOfValuesAdv : Tuple #" << std::distance(tuplesSelec->begin(),tuple)/2;
1949               oss << " of 'tuplesSelec' request of tuple id #" << tuple[0] << " in 'this' ! It should be in [0," << thisNt << ") !";
1950               throw INTERP_KERNEL::Exception(oss.str().c_str());
1951             }
1952         }
1953       else
1954         {
1955           std::ostringstream oss; oss << "DataArrayTemplate::setPartOfValuesAdv : Tuple #" << std::distance(tuplesSelec->begin(),tuple)/2;
1956           oss << " of 'tuplesSelec' request of tuple id #" << tuple[1] << " in 'a' ! It should be in [0," << aNt << ") !";
1957           throw INTERP_KERNEL::Exception(oss.str().c_str());
1958         }
1959     }
1960   }
1961   
1962   /*!
1963    * Copy some tuples from another DataArrayDouble (\a aBase) into contiguous tuples
1964    * of \a this array. Textual data is not copied. Both arrays must have equal number of
1965    * components.
1966    * The tuples to assign to are defined by index of the first tuple, and
1967    * their number is defined by \a tuplesSelec->getNumberOfTuples().
1968    * The tuples to copy are defined by values of a DataArrayInt.
1969    * All components of selected tuples are copied.
1970    *  \param [in] tupleIdStart - index of the first tuple of \a this array to assign
1971    *              values to.
1972    *  \param [in] aBase - the array to copy values from.
1973    *  \param [in] tuplesSelec - the array specifying tuples of \a a to copy.
1974    *  \throw If \a this is not allocated.
1975    *  \throw If \a aBase is NULL.
1976    *  \throw If \a aBase is not allocated.
1977    *  \throw If \a tuplesSelec is NULL.
1978    *  \throw If \a tuplesSelec is not allocated.
1979    *  \throw If <em>this->getNumberOfComponents() != aBase->getNumberOfComponents()</em>.
1980    *  \throw If \a tuplesSelec->getNumberOfComponents() != 1.
1981    *  \throw If <em>tupleIdStart + tuplesSelec->getNumberOfTuples() > this->getNumberOfTuples().</em>
1982    *  \throw If any tuple index given by \a tuplesSelec is out of a valid range for 
1983    *         \a aBase array.
1984  */
1985   template<class T>
1986   void DataArrayTemplate<T>::setContigPartOfSelectedValues(int tupleIdStart, const DataArray *aBase, const DataArrayInt *tuplesSelec)
1987   {
1988     if(!aBase || !tuplesSelec)
1989       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValues : input DataArray is NULL !");
1990     const typename Traits<T>::ArrayType *a(dynamic_cast<const typename Traits<T>::ArrayType *>(aBase));
1991     if(!a)
1992       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValues : input DataArray aBase is not a DataArrayDouble !");
1993     checkAllocated();
1994     a->checkAllocated();
1995     tuplesSelec->checkAllocated();
1996     std::size_t nbOfComp(getNumberOfComponents());
1997     if(nbOfComp!=a->getNumberOfComponents())
1998       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValues : This and a do not have the same number of components !");
1999     if(tuplesSelec->getNumberOfComponents()!=1)
2000       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValues : Expecting to have a tuple selector DataArrayInt instance with exactly 1 component !");
2001     int thisNt(getNumberOfTuples());
2002     int aNt(a->getNumberOfTuples());
2003     int nbOfTupleToWrite(tuplesSelec->getNumberOfTuples());
2004     T *valsToSet(getPointer()+tupleIdStart*nbOfComp);
2005     if(tupleIdStart+nbOfTupleToWrite>thisNt)
2006       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValues : invalid number range of values to write !");
2007     const T *valsSrc=a->getConstPointer();
2008     for(const int *tuple=tuplesSelec->begin();tuple!=tuplesSelec->end();tuple++,valsToSet+=nbOfComp)
2009       {
2010         if(*tuple>=0 && *tuple<aNt)
2011           {
2012             std::copy(valsSrc+nbOfComp*(*tuple),valsSrc+nbOfComp*(*tuple+1),valsToSet);
2013           }
2014         else
2015           {
2016             std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::setContigPartOfSelectedValues : Tuple #" << std::distance(tuplesSelec->begin(),tuple);
2017             oss << " of 'tuplesSelec' request of tuple id #" << *tuple << " in 'a' ! It should be in [0," << aNt << ") !";
2018             throw INTERP_KERNEL::Exception(oss.str().c_str());
2019           }
2020       }
2021   }
2022   
2023   /*!
2024    * Copy some tuples from another DataArrayDouble (\a aBase) into contiguous tuples
2025    * of \a this array. Textual data is not copied. Both arrays must have equal number of
2026    * components.
2027    * The tuples to copy are defined by three values similar to parameters of
2028    * the Python function \c range(\c start,\c stop,\c step).
2029    * The tuples to assign to are defined by index of the first tuple, and
2030    * their number is defined by number of tuples to copy.
2031    * All components of selected tuples are copied.
2032    *  \param [in] tupleIdStart - index of the first tuple of \a this array to assign
2033    *              values to.
2034    *  \param [in] aBase - the array to copy values from.
2035    *  \param [in] bg - index of the first tuple to copy of the array \a aBase.
2036    *  \param [in] end2 - index of the tuple of \a aBase before which the tuples to copy
2037    *              are located.
2038    *  \param [in] step - index increment to get index of the next tuple to copy.
2039    *  \throw If \a this is not allocated.
2040    *  \throw If \a aBase is NULL.
2041    *  \throw If \a aBase is not allocated.
2042    *  \throw If <em>this->getNumberOfComponents() != aBase->getNumberOfComponents()</em>.
2043    *  \throw If <em>tupleIdStart + len(range(bg,end2,step)) > this->getNumberOfTuples().</em>
2044    *  \throw If parameters specifying tuples to copy, do not give a
2045    *            non-empty range of increasing indices or indices are out of a valid range
2046    *            for the array \a aBase.
2047    */
2048   template<class T>
2049   void DataArrayTemplate<T>::setContigPartOfSelectedValuesSlice(int tupleIdStart, const DataArray *aBase, int bg, int end2, int step)
2050   {
2051     if(!aBase)
2052       {
2053         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::setContigPartOfSelectedValuesSlice : input DataArray is NULL !";
2054         throw INTERP_KERNEL::Exception(oss.str().c_str());
2055       }
2056     const typename Traits<T>::ArrayType *a(dynamic_cast<const typename Traits<T>::ArrayType *>(aBase));
2057     if(!a)
2058       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValuesSlice : input DataArray aBase is not a DataArrayDouble !");
2059     checkAllocated();
2060     a->checkAllocated();
2061     std::size_t nbOfComp(getNumberOfComponents());
2062     const char msg[]="DataArrayDouble::setContigPartOfSelectedValuesSlice";
2063     int nbOfTupleToWrite(DataArray::GetNumberOfItemGivenBES(bg,end2,step,msg));
2064     if(nbOfComp!=a->getNumberOfComponents())
2065       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValuesSlice : This and a do not have the same number of components !");
2066     int thisNt(getNumberOfTuples()),aNt(a->getNumberOfTuples());
2067     T *valsToSet(getPointer()+tupleIdStart*nbOfComp);
2068     if(tupleIdStart+nbOfTupleToWrite>thisNt)
2069       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValuesSlice : invalid number range of values to write !");
2070     if(end2>aNt)
2071       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValuesSlice : invalid range of values to read !");
2072     const T *valsSrc(a->getConstPointer()+bg*nbOfComp);
2073     for(int i=0;i<nbOfTupleToWrite;i++,valsToSet+=nbOfComp,valsSrc+=step*nbOfComp)
2074       {
2075         std::copy(valsSrc,valsSrc+nbOfComp,valsToSet);
2076       }
2077   }
2078
2079   /*!
2080    * Returns a shorten copy of \a this array. The new DataArrayDouble contains ranges
2081    * of tuples specified by \a ranges parameter.
2082    * For more info on renumbering see \ref numbering.
2083    *  \param [in] ranges - std::vector of std::pair's each of which defines a range
2084    *              of tuples in [\c begin,\c end) format.
2085    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
2086    *          is to delete using decrRef() as it is no more needed.
2087    *  \throw If \a end < \a begin.
2088    *  \throw If \a end > \a this->getNumberOfTuples().
2089    *  \throw If \a this is not allocated.
2090    */
2091   template<class T>
2092   typename Traits<T>::ArrayType *DataArrayTemplate<T>::mySelectByTupleRanges(const std::vector<std::pair<int,int> >& ranges) const
2093   {
2094     checkAllocated();
2095     int nbOfComp(getNumberOfComponents()),nbOfTuplesThis(getNumberOfTuples());
2096     if(ranges.empty())
2097       {
2098         MCAuto<DataArray> ret0(buildNewEmptyInstance());
2099         MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
2100         ret->alloc(0,nbOfComp);
2101         ret->copyStringInfoFrom(*this);
2102         return ret.retn();
2103       }
2104     int ref(ranges.front().first),nbOfTuples(0);
2105     bool isIncreasing(true);
2106     for(std::vector<std::pair<int,int> >::const_iterator it=ranges.begin();it!=ranges.end();it++)
2107       {
2108         if((*it).first<=(*it).second)
2109           {
2110             if((*it).first>=0 && (*it).second<=nbOfTuplesThis)
2111               {
2112                 nbOfTuples+=(*it).second-(*it).first;
2113                 if(isIncreasing)
2114                   isIncreasing=ref<=(*it).first;
2115                 ref=(*it).second;
2116               }
2117             else
2118               {
2119                 std::ostringstream oss; oss << "DataArrayTemplate::selectByTupleRanges : on range #" << std::distance(ranges.begin(),it);
2120                 oss << " (" << (*it).first << "," << (*it).second << ") is greater than number of tuples of this :" << nbOfTuples << " !";
2121                 throw INTERP_KERNEL::Exception(oss.str().c_str());
2122               }
2123           }
2124         else
2125           {
2126             std::ostringstream oss; oss << "DataArrayTemplate::selectByTupleRanges : on range #" << std::distance(ranges.begin(),it);
2127             oss << " (" << (*it).first << "," << (*it).second << ") end is before begin !";
2128             throw INTERP_KERNEL::Exception(oss.str().c_str());
2129           }
2130       }
2131     if(isIncreasing && nbOfTuplesThis==nbOfTuples)
2132       return static_cast<typename Traits<T>::ArrayType *>(deepCopy());
2133     MCAuto<DataArray> ret0(buildNewEmptyInstance());
2134     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
2135     ret->alloc(nbOfTuples,nbOfComp);
2136     ret->copyStringInfoFrom(*this);
2137     const T *src(getConstPointer());
2138     T *work(ret->getPointer());
2139     for(std::vector<std::pair<int,int> >::const_iterator it=ranges.begin();it!=ranges.end();it++)
2140       work=std::copy(src+(*it).first*nbOfComp,src+(*it).second*nbOfComp,work);
2141     return ret.retn();
2142   }
2143
2144   /*!
2145    * Returns the first value of \a this. 
2146    *  \return double - the last value of \a this array.
2147    *  \throw If \a this is not allocated.
2148    *  \throw If \a this->getNumberOfComponents() != 1.
2149    *  \throw If \a this->getNumberOfTuples() < 1.
2150    */
2151   template<class T>
2152   T DataArrayTemplate<T>::front() const
2153   {
2154     checkAllocated();
2155     if(getNumberOfComponents()!=1)
2156       throw INTERP_KERNEL::Exception("DataArrayTemplate::front : number of components not equal to one !");
2157     int nbOfTuples(getNumberOfTuples());
2158     if(nbOfTuples<1)
2159       throw INTERP_KERNEL::Exception("DataArrayTemplate::front : number of tuples must be >= 1 !");
2160     return *(getConstPointer());
2161   }
2162   
2163   /*!
2164    * Returns the last value of \a this. 
2165    *  \return double - the last value of \a this array.
2166    *  \throw If \a this is not allocated.
2167    *  \throw If \a this->getNumberOfComponents() != 1.
2168    *  \throw If \a this->getNumberOfTuples() < 1.
2169    */
2170   template<class T>
2171   T DataArrayTemplate<T>::back() const
2172   {
2173     checkAllocated();
2174     if(getNumberOfComponents()!=1)
2175       throw INTERP_KERNEL::Exception("DataArrayTemplate::back : number of components not equal to one !");
2176     int nbOfTuples(getNumberOfTuples());
2177     if(nbOfTuples<1)
2178       throw INTERP_KERNEL::Exception("DataArrayTemplate::back : number of tuples must be >= 1 !");
2179     return *(getConstPointer()+nbOfTuples-1);
2180   }
2181   
2182   /*!
2183    * Returns the maximal value and its location within \a this one-dimensional array.
2184    *  \param [out] tupleId - index of the tuple holding the maximal value.
2185    *  \return double - the maximal value among all values of \a this array.
2186    *  \throw If \a this->getNumberOfComponents() != 1
2187    *  \throw If \a this->getNumberOfTuples() < 1
2188    *  \sa getMaxAbsValue, getMinValue
2189    */
2190   template<class T>
2191   T DataArrayTemplate<T>::getMaxValue(int& tupleId) const
2192   {
2193     checkAllocated();
2194     if(getNumberOfComponents()!=1)
2195       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 !");
2196     int nbOfTuples(getNumberOfTuples());
2197     if(nbOfTuples<=0)
2198       throw INTERP_KERNEL::Exception("DataArrayDouble::getMaxValue : array exists but number of tuples must be > 0 !");
2199     const T *vals(getConstPointer());
2200     const T *loc(std::max_element(vals,vals+nbOfTuples));
2201     tupleId=(int)std::distance(vals,loc);
2202     return *loc;
2203   }
2204   
2205   /*!
2206    * Returns the maximal value within \a this array that is allowed to have more than
2207    *  one component.
2208    *  \return double - the maximal value among all values of \a this array.
2209    *  \throw If \a this is not allocated.
2210    *  \sa getMaxAbsValueInArray, getMinValueInArray
2211    */
2212   template<class T>
2213   T DataArrayTemplate<T>::getMaxValueInArray() const
2214   {
2215     checkAllocated();
2216     const T *loc(std::max_element(begin(),end()));
2217     return *loc;
2218   }
2219   
2220   /*!
2221    * Returns the maximal absolute value in \a this and the first occurrence location associated to it.
2222    * \return the element in this (positive or negative) having the max abs value in \a this.
2223    *  \throw If \a this is not allocated.
2224    *  \throw If \a this is non one component array.
2225    *  \throw If \a this is empty.
2226    */
2227   template<class T>
2228   T DataArrayTemplate<T>::getMaxAbsValue(std::size_t& tupleId) const
2229   {
2230     checkAllocated();
2231     if(getNumberOfComponents()!=1)
2232       throw INTERP_KERNEL::Exception("DataArrayDouble::getMaxAbsValue : must be applied on DataArrayDouble with only one component, you can call 'rearrange' method before or call 'getMaxValueInArray' method !");
2233     std::size_t nbTuples(this->getNumberOfTuples());
2234     if(nbTuples==0)
2235       throw INTERP_KERNEL::Exception("DataArrayTemplate<T>::getMaxAbsValue : empty array !");
2236     T ret((T)-1);
2237     tupleId=0;
2238     const T *pt(begin());
2239     for(std::size_t i=0;i<nbTuples;i++,pt++)
2240       {
2241         T cand(std::abs(*pt));
2242         if(cand>ret)
2243           {
2244             ret=cand;
2245             tupleId=i;
2246           }
2247       }
2248     return this->getIJ(tupleId,0);
2249   }
2250
2251   /*!
2252    * Returns the maximal absolute value in \a this.
2253    *  \throw If \a this is not allocated.
2254    *  \throw If \a this is non one component array.
2255    *  \throw If \a this is empty.
2256    */
2257   template<class T>
2258   T DataArrayTemplate<T>::getMaxAbsValueInArray() const
2259   {
2260     std::size_t dummy;
2261     return getMaxAbsValue(dummy);
2262   }
2263
2264   /*!
2265    * Returns the minimal value and its location within \a this one-dimensional array.
2266    *  \param [out] tupleId - index of the tuple holding the minimal value.
2267    *  \return double - the minimal value among all values of \a this array.
2268    *  \throw If \a this->getNumberOfComponents() != 1
2269    *  \throw If \a this->getNumberOfTuples() < 1
2270    */
2271   template<class T>
2272   T DataArrayTemplate<T>::getMinValue(int& tupleId) const
2273   {
2274     checkAllocated();
2275     if(getNumberOfComponents()!=1)
2276       throw INTERP_KERNEL::Exception("DataArrayDouble::getMinValue : must be applied on DataArrayDouble with only one component, you can call 'rearrange' method before call 'getMinValueInArray' method !");
2277     int nbOfTuples(getNumberOfTuples());
2278     if(nbOfTuples<=0)
2279       throw INTERP_KERNEL::Exception("DataArrayDouble::getMinValue : array exists but number of tuples must be > 0 !");
2280     const T *vals(getConstPointer());
2281     const T *loc(std::min_element(vals,vals+nbOfTuples));
2282     tupleId=(int)std::distance(vals,loc);
2283     return *loc;
2284   }
2285   
2286   /*!
2287    * Returns the minimal value within \a this array that is allowed to have more than
2288    *  one component.
2289    *  \return double - the minimal value among all values of \a this array.
2290    *  \throw If \a this is not allocated.
2291    */
2292   template<class T>
2293   T DataArrayTemplate<T>::getMinValueInArray() const
2294   {
2295     checkAllocated();
2296     const T *loc=std::min_element(begin(),end());
2297     return *loc;
2298   }
2299   
2300   template<class T>
2301   void DataArrayTemplate<T>::circularPermutation(int nbOfShift)
2302   {
2303     checkAllocated();
2304     int nbOfCompo(getNumberOfComponents()),nbTuples(getNumberOfTuples());
2305     int effNbSh(EffectiveCircPerm(nbOfShift,nbTuples));
2306     if(effNbSh==0)
2307       return ;
2308     T *work(getPointer());
2309     if(effNbSh<nbTuples-effNbSh)
2310       {
2311         typename INTERP_KERNEL::AutoPtr<T> buf(new T[effNbSh*nbOfCompo]);
2312         std::copy(work,work+effNbSh*nbOfCompo,(T *)buf);
2313         std::copy(work+effNbSh*nbOfCompo,work+nbTuples*nbOfCompo,work);// ze big shift
2314         std::copy((T *)buf,(T *)buf+effNbSh*nbOfCompo,work+(nbTuples-effNbSh)*nbOfCompo);
2315       }
2316     else
2317       {
2318         typename INTERP_KERNEL::AutoPtr<T> buf(new T[(nbTuples-effNbSh)*nbOfCompo]);
2319         std::copy(work+effNbSh*nbOfCompo,work+nbTuples*nbOfCompo,(T *)buf);
2320         std::copy(work,work+effNbSh*nbOfCompo,work+(nbTuples-effNbSh)*nbOfCompo);// ze big shift
2321         std::copy((T*)buf,(T *)buf+(nbTuples-effNbSh)*nbOfCompo,work);
2322       }
2323   }
2324   
2325   template<class T>
2326   void DataArrayTemplate<T>::circularPermutationPerTuple(int nbOfShift)
2327   {
2328     checkAllocated();
2329     int nbOfCompo(getNumberOfComponents()),nbTuples(getNumberOfTuples());
2330     int effNbSh(EffectiveCircPerm(nbOfShift,nbOfCompo));
2331     if(effNbSh==0)
2332       return ;
2333     T *work(getPointer());
2334     if(effNbSh<nbOfCompo-effNbSh)
2335       {
2336         typename INTERP_KERNEL::AutoPtr<T> buf(new T[effNbSh]);
2337         for(int i=0;i<nbTuples;i++,work+=nbOfCompo)
2338           {
2339             std::copy(work,work+effNbSh,(T *)buf);
2340             std::copy(work+effNbSh,work+nbOfCompo,work);// ze big shift
2341             std::copy((T *)buf,(T *)buf+effNbSh,work+(nbOfCompo-effNbSh));
2342           }
2343       }
2344     else
2345       {
2346         typename INTERP_KERNEL::AutoPtr<T> buf(new T[nbOfCompo-effNbSh]);
2347         for(int i=0;i<nbTuples;i++,work+=nbOfCompo)
2348           {
2349             std::copy(work+effNbSh,work+nbOfCompo,(T *)buf);
2350             std::copy(work,work+effNbSh,work+(nbOfCompo-effNbSh));// ze big shift
2351             std::copy((T*)buf,(T *)buf+(nbOfCompo-effNbSh),work);
2352           }
2353       }
2354     std::vector<std::string> sts(nbOfCompo);
2355     for(int i=0;i<nbOfCompo;i++)
2356       sts[i]=_info_on_compo[(i+effNbSh)%nbOfCompo];
2357     setInfoOnComponents(sts);
2358   }
2359   
2360   template<class T>
2361   void DataArrayTemplate<T>::reversePerTuple()
2362   {
2363     checkAllocated();
2364     int nbOfCompo(getNumberOfComponents()),nbTuples(getNumberOfTuples());
2365     if(nbOfCompo<=1)
2366       return ;
2367     T *work(getPointer());
2368     for(int i=0;i<nbTuples;i++,work+=nbOfCompo)
2369       std::reverse(work,work+nbOfCompo);
2370     std::reverse(_info_on_compo.begin(),_info_on_compo.end());
2371   }
2372
2373   /*!
2374    * Assign pointer to one array to a pointer to another appay. Reference counter of
2375    * \a arrayToSet is incremented / decremented.
2376    *  \param [in] newArray - the pointer to array to assign to \a arrayToSet.
2377    *  \param [in,out] arrayToSet - the pointer to array to assign to.
2378    */
2379   template<class T>
2380   void DataArrayTemplate<T>::SetArrayIn(typename Traits<T>::ArrayType *newArray, typename Traits<T>::ArrayType* &arrayToSet)
2381   {
2382     if(newArray!=arrayToSet)
2383       {
2384         if(arrayToSet)
2385           arrayToSet->decrRef();
2386         arrayToSet=newArray;
2387         if(arrayToSet)
2388           arrayToSet->incrRef();
2389       }
2390   }
2391
2392     /*!
2393    * Assign zero to all values in \a this array. To know more on filling arrays see
2394    * \ref MEDCouplingArrayFill.
2395    * \throw If \a this is not allocated.
2396    */
2397   template<class T>
2398   void DataArrayTemplate<T>::fillWithZero()
2399   {
2400     fillWithValue((T)0);
2401   }
2402
2403   //////////////////////////////
2404
2405   template<class T>
2406   template<class U>
2407   MCAuto< typename Traits<U>::ArrayType > DataArrayTemplateClassic<T>::convertToOtherTypeOfArr() const
2408   {
2409     this->checkAllocated();
2410     MCAuto<typename Traits<U>::ArrayType> ret(Traits<U>::ArrayType::New());
2411     ret->alloc(this->getNumberOfTuples(),this->getNumberOfComponents());
2412     std::size_t nbOfVals(this->getNbOfElems());
2413     const T *src(this->begin());
2414     U *dest(ret->getPointer());
2415     // to make Visual C++ happy : instead of std::size_t nbOfVals=getNbOfElems(); std::copy(src,src+nbOfVals,dest);
2416     //for(const T *src=this->begin();src!=this->end();src++,dest++)
2417     //  *dest=(int)*src;
2418     std::copy(src,src+nbOfVals,dest);
2419     ret->copyStringInfoFrom(*this);
2420     return ret;
2421   }
2422   
2423   /*!
2424    * Creates a new DataArrayDouble and assigns all (textual and numerical) data of \a this
2425    * array to the new one.
2426    *  \return DataArrayDouble * - the new instance of DataArrayInt.
2427    */
2428   template<class T>
2429   MCAuto<DataArrayDouble> DataArrayTemplateClassic<T>::convertToDblArr() const
2430   {
2431     return convertToOtherTypeOfArr<double>();
2432   }
2433
2434   /*!
2435    * Creates a new DataArrayInt and assigns all (textual and numerical) data of \a this
2436    * array to the new one.
2437    *  \return DataArrayInt * - the new instance of DataArrayInt.
2438    */
2439   template<class T>
2440   MCAuto<DataArrayInt> DataArrayTemplateClassic<T>::convertToIntArr() const
2441   {
2442     return convertToOtherTypeOfArr<int>();
2443   }
2444
2445   /*!
2446    * Creates a new DataArrayFloat and assigns all (textual and numerical) data of \a this
2447    * array to the new one.
2448    *  \return DataArrayFloat * - the new instance of DataArrayInt.
2449    */
2450   template<class T>
2451   MCAuto<DataArrayFloat> DataArrayTemplateClassic<T>::convertToFloatArr() const
2452   {
2453     return convertToOtherTypeOfArr<float>();
2454   }
2455
2456   /*!
2457    * Apply a linear function to a given component of \a this array, so that
2458    * an array element <em>(x)</em> becomes \f$ a * x + b \f$.
2459    *  \param [in] a - the first coefficient of the function.
2460    *  \param [in] b - the second coefficient of the function.
2461    *  \param [in] compoId - the index of component to modify.
2462    *  \throw If \a this is not allocated, or \a compoId is not in [0,\c this->getNumberOfComponents() ).
2463    */
2464   template<class T>
2465   void DataArrayTemplateClassic<T>::applyLin(T a, T b, int compoId)
2466   {
2467     this->checkAllocated();
2468     T *ptr(this->getPointer()+compoId);
2469     int nbOfComp(this->getNumberOfComponents()),nbOfTuple(this->getNumberOfTuples());
2470     if(compoId<0 || compoId>=nbOfComp)
2471       {
2472         std::ostringstream oss; oss << "DataArrayDouble::applyLin : The compoId requested (" << compoId << ") is not valid ! Must be in [0," << nbOfComp << ") !";
2473         throw INTERP_KERNEL::Exception(oss.str().c_str());
2474       }
2475     for(int i=0;i<nbOfTuple;i++,ptr+=nbOfComp)
2476       *ptr=a*(*ptr)+b;
2477     this->declareAsNew();
2478   }
2479
2480   /*!
2481    * Apply a linear function to all elements of \a this array, so that
2482    * an element _x_ becomes \f$ a * x + b \f$.
2483    *  \param [in] a - the first coefficient of the function.
2484    *  \param [in] b - the second coefficient of the function.
2485    *  \throw If \a this is not allocated.
2486    */
2487   template<class T>
2488   void DataArrayTemplateClassic<T>::applyLin(T a, T b)
2489   {
2490     this->checkAllocated();
2491     T *ptr(this->getPointer());
2492     std::size_t nbOfElems(this->getNbOfElems());
2493     for(std::size_t i=0;i<nbOfElems;i++,ptr++)
2494       *ptr=a*(*ptr)+b;
2495     this->declareAsNew();
2496   }
2497   
2498   /*!
2499    * Returns a full copy of \a this array except that sign of all elements is reversed.
2500    *  \return DataArrayDouble * - the new instance of DataArrayDouble containing the
2501    *          same number of tuples and component as \a this array.
2502    *          The caller is to delete this result array using decrRef() as it is no more
2503    *          needed.
2504    *  \throw If \a this is not allocated.
2505    */
2506   template<class T>
2507   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::negate() const
2508   {
2509     this->checkAllocated();
2510     MCAuto<typename Traits<T>::ArrayType> newArr(Traits<T>::ArrayType::New());
2511     int nbOfTuples(this->getNumberOfTuples()),nbOfComp(this->getNumberOfComponents());
2512     newArr->alloc(nbOfTuples,nbOfComp);
2513     const T *cptr(this->begin());
2514     std::transform(cptr,cptr+nbOfTuples*nbOfComp,newArr->getPointer(),std::negate<T>());
2515     newArr->copyStringInfoFrom(*this);
2516     return newArr.retn();
2517   }
2518
2519   template<class T>
2520   template<class FCT>
2521   void DataArrayTemplateClassic<T>::somethingEqual(const typename Traits<T>::ArrayType *other)
2522   {
2523     if(!other)
2524       throw INTERP_KERNEL::Exception("DataArray<T>::SomethingEqual : input DataArray<T> instance is NULL !");
2525     const char *msg="Nb of tuples mismatch for DataArrayDouble::multiplyEqual !";
2526     this->checkAllocated();
2527     other->checkAllocated();
2528     int nbOfTuple(this->getNumberOfTuples()),nbOfTuple2(other->getNumberOfTuples());
2529     int nbOfComp(this->getNumberOfComponents()),nbOfComp2(other->getNumberOfComponents());
2530     if(nbOfTuple==nbOfTuple2)
2531       {
2532         if(nbOfComp==nbOfComp2)
2533           {
2534             std::transform(this->begin(),this->end(),other->begin(),this->getPointer(),FCT());
2535           }
2536         else if(nbOfComp2==1)
2537           {
2538             T *ptr(this->getPointer());
2539             const T *ptrc(other->begin());
2540             for(int i=0;i<nbOfTuple;i++)
2541               std::transform(ptr+i*nbOfComp,ptr+(i+1)*nbOfComp,ptr+i*nbOfComp,std::bind2nd(FCT(),*ptrc++));
2542           }
2543         else
2544           throw INTERP_KERNEL::Exception(msg);
2545       }
2546     else if(nbOfTuple2==1)
2547       {
2548         if(nbOfComp2==nbOfComp)
2549           {
2550             T *ptr(this->getPointer());
2551             const T *ptrc(other->begin());
2552             for(int i=0;i<nbOfTuple;i++)
2553               std::transform(ptr+i*nbOfComp,ptr+(i+1)*nbOfComp,ptrc,ptr+i*nbOfComp,FCT());
2554           }
2555         else
2556           throw INTERP_KERNEL::Exception(msg);
2557       }
2558     else
2559       throw INTERP_KERNEL::Exception(msg);
2560     this->declareAsNew();
2561   }
2562   
2563   /*!
2564    * Adds values of another DataArrayDouble to values of \a this one. There are 3
2565    * valid cases.
2566    * 1.  The arrays have same number of tuples and components. Then each value of
2567    *   \a other array is added to the corresponding value of \a this array, i.e.:
2568    *   _a_ [ i, j ] += _other_ [ i, j ].
2569    * 2.  The arrays have same number of tuples and \a other array has one component. Then
2570    *   _a_ [ i, j ] += _other_ [ i, 0 ].
2571    * 3.  The arrays have same number of components and \a other array has one tuple. Then
2572    *   _a_ [ i, j ] += _a2_ [ 0, j ].
2573    *
2574    *  \param [in] other - an array to add to \a this one.
2575    *  \throw If \a other is NULL.
2576    *  \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples() and
2577    *         \a this->getNumberOfComponents() != \a other->getNumberOfComponents() and
2578    *         \a other has number of both tuples and components not equal to 1.
2579    */
2580   template<class T>
2581   void DataArrayTemplateClassic<T>::addEqual(const typename Traits<T>::ArrayType *other)
2582   {
2583     this->somethingEqual< std::plus<T> >(other);
2584   }
2585
2586   /*!
2587    * Subtract values of another DataArrayDouble from values of \a this one. There are 3
2588    * valid cases.
2589    * 1.  The arrays have same number of tuples and components. Then each value of
2590    *   \a other array is subtracted from the corresponding value of \a this array, i.e.:
2591    *   _a_ [ i, j ] -= _other_ [ i, j ].
2592    * 2.  The arrays have same number of tuples and \a other array has one component. Then
2593    *   _a_ [ i, j ] -= _other_ [ i, 0 ].
2594    * 3.  The arrays have same number of components and \a other array has one tuple. Then
2595    *   _a_ [ i, j ] -= _a2_ [ 0, j ].
2596    *
2597    *  \param [in] other - an array to subtract from \a this one.
2598    *  \throw If \a other is NULL.
2599    *  \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples() and
2600    *         \a this->getNumberOfComponents() != \a other->getNumberOfComponents() and
2601    *         \a other has number of both tuples and components not equal to 1.
2602    */
2603   template<class T>
2604   void DataArrayTemplateClassic<T>::substractEqual(const typename Traits<T>::ArrayType *other)
2605   {
2606     this->somethingEqual< std::minus<T> >(other);
2607   }
2608   
2609   /*!
2610    * Multiply values of another DataArrayDouble to values of \a this one. There are 3
2611    * valid cases.
2612    * 1.  The arrays have same number of tuples and components. Then each value of
2613    *   \a other array is multiplied to the corresponding value of \a this array, i.e.
2614    *   _this_ [ i, j ] *= _other_ [ i, j ].
2615    * 2.  The arrays have same number of tuples and \a other array has one component. Then
2616    *   _this_ [ i, j ] *= _other_ [ i, 0 ].
2617    * 3.  The arrays have same number of components and \a other array has one tuple. Then
2618    *   _this_ [ i, j ] *= _a2_ [ 0, j ].
2619    *
2620    *  \param [in] other - an array to multiply to \a this one.
2621    *  \throw If \a other is NULL.
2622    *  \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples() and
2623    *         \a this->getNumberOfComponents() != \a other->getNumberOfComponents() and
2624    *         \a other has number of both tuples and components not equal to 1.
2625    */
2626   template<class T>
2627   void DataArrayTemplateClassic<T>::multiplyEqual(const typename Traits<T>::ArrayType *other)
2628   {
2629     this->somethingEqual< std::multiplies<T> >(other);
2630   }
2631
2632   /*!
2633    * Divide values of \a this array by values of another DataArrayDouble. There are 3
2634    * valid cases.
2635    * 1.  The arrays have same number of tuples and components. Then each value of
2636    *    \a this array is divided by the corresponding value of \a other one, i.e.:
2637    *   _a_ [ i, j ] /= _other_ [ i, j ].
2638    * 2.  The arrays have same number of tuples and \a other array has one component. Then
2639    *   _a_ [ i, j ] /= _other_ [ i, 0 ].
2640    * 3.  The arrays have same number of components and \a other array has one tuple. Then
2641    *   _a_ [ i, j ] /= _a2_ [ 0, j ].
2642    *
2643    *  \warning No check of division by zero is performed!
2644    *  \param [in] other - an array to divide \a this one by.
2645    *  \throw If \a other is NULL.
2646    *  \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples() and
2647    *         \a this->getNumberOfComponents() != \a other->getNumberOfComponents() and
2648    *         \a other has number of both tuples and components not equal to 1.
2649    */
2650   template<class T>
2651   void DataArrayTemplateClassic<T>::divideEqual(const typename Traits<T>::ArrayType *other)
2652   {
2653     this->somethingEqual< std::divides<T> >(other);
2654   }
2655   
2656   template<class T, class FCT>
2657   typename Traits<T>::ArrayType *DivSub(const typename Traits<T>::ArrayType *a1, const typename Traits<T>::ArrayType *a2)
2658   {
2659     if(!a1 || !a2)
2660       throw INTERP_KERNEL::Exception("DivSub : input DataArrayDouble instance is NULL !");
2661     int nbOfTuple1(a1->getNumberOfTuples()),nbOfTuple2(a2->getNumberOfTuples());
2662     int nbOfComp1(a1->getNumberOfComponents()),nbOfComp2(a2->getNumberOfComponents());
2663     if(nbOfTuple2==nbOfTuple1)
2664       {
2665         if(nbOfComp1==nbOfComp2)
2666           {
2667             MCAuto<typename Traits<T>::ArrayType> ret(Traits<T>::ArrayType::New());
2668             ret->alloc(nbOfTuple2,nbOfComp1);
2669             std::transform(a1->begin(),a1->end(),a2->begin(),ret->getPointer(),FCT());
2670             ret->copyStringInfoFrom(*a1);
2671             return ret.retn();
2672           }
2673         else if(nbOfComp2==1)
2674           {
2675             MCAuto<typename Traits<T>::ArrayType> ret(Traits<T>::ArrayType::New());
2676             ret->alloc(nbOfTuple1,nbOfComp1);
2677             const T *a2Ptr(a2->begin()),*a1Ptr(a1->begin());
2678             T *res(ret->getPointer());
2679             for(int i=0;i<nbOfTuple1;i++)
2680               res=std::transform(a1Ptr+i*nbOfComp1,a1Ptr+(i+1)*nbOfComp1,res,std::bind2nd(FCT(),a2Ptr[i]));
2681             ret->copyStringInfoFrom(*a1);
2682             return ret.retn();
2683           }
2684         else
2685           {
2686             a1->checkNbOfComps(nbOfComp2,"Nb of components mismatch for array Divide !");
2687             return 0;
2688           }
2689       }
2690     else if(nbOfTuple2==1)
2691       {
2692         a1->checkNbOfComps(nbOfComp2,"Nb of components mismatch for array Divide !");
2693         MCAuto<typename Traits<T>::ArrayType> ret(Traits<T>::ArrayType::New());
2694         ret->alloc(nbOfTuple1,nbOfComp1);
2695         const T *a1ptr=a1->begin(),*a2ptr(a2->begin());
2696         T *pt(ret->getPointer());
2697         for(int i=0;i<nbOfTuple1;i++)
2698           pt=std::transform(a1ptr+i*nbOfComp1,a1ptr+(i+1)*nbOfComp1,a2ptr,pt,FCT());
2699         ret->copyStringInfoFrom(*a1);
2700         return ret.retn();
2701       }
2702     else
2703       {
2704         a1->checkNbOfTuples(nbOfTuple2,"Nb of tuples mismatch for array Divide !");//will always throw an exception
2705         return 0;
2706       }
2707   }
2708   
2709   /*!
2710    * Returns a new DataArrayDouble that is a subtraction of two given arrays. There are 3
2711    * valid cases.
2712    * 1.  The arrays have same number of tuples and components. Then each value of
2713    *   the result array (_a_) is a subtraction of the corresponding values of \a a1 and
2714    *   \a a2, i.e.: _a_ [ i, j ] = _a1_ [ i, j ] - _a2_ [ i, j ].
2715    * 2.  The arrays have same number of tuples and one array, say _a2_, has one
2716    *   component. Then
2717    *   _a_ [ i, j ] = _a1_ [ i, j ] - _a2_ [ i, 0 ].
2718    * 3.  The arrays have same number of components and one array, say _a2_, has one
2719    *   tuple. Then
2720    *   _a_ [ i, j ] = _a1_ [ i, j ] - _a2_ [ 0, j ].
2721    *
2722    * Info on components is copied either from the first array (in the first case) or from
2723    * the array with maximal number of elements (getNbOfElems()).
2724    *  \param [in] a1 - an array to subtract from.
2725    *  \param [in] a2 - an array to subtract.
2726    *  \return DataArrayDouble * - the new instance of DataArrayDouble.
2727    *          The caller is to delete this result array using decrRef() as it is no more
2728    *          needed.
2729    *  \throw If either \a a1 or \a a2 is NULL.
2730    *  \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples() and
2731    *         \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents() and
2732    *         none of them has number of tuples or components equal to 1.
2733    */
2734   template<class T>
2735   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::Substract(const typename Traits<T>::ArrayType *a1, const typename Traits<T>::ArrayType *a2)
2736   {
2737     return DivSub< T,std::minus<T> >(a1,a2);
2738   }
2739   
2740   /*!
2741    * Returns a new DataArrayDouble that is a division of two given arrays. There are 3
2742    * valid cases.
2743    * 1.  The arrays have same number of tuples and components. Then each value of
2744    *   the result array (_a_) is a division of the corresponding values of \a a1 and
2745    *   \a a2, i.e.: _a_ [ i, j ] = _a1_ [ i, j ] / _a2_ [ i, j ].
2746    * 2.  The arrays have same number of tuples and one array, say _a2_, has one
2747    *   component. Then
2748    *   _a_ [ i, j ] = _a1_ [ i, j ] / _a2_ [ i, 0 ].
2749    * 3.  The arrays have same number of components and one array, say _a2_, has one
2750    *   tuple. Then
2751    *   _a_ [ i, j ] = _a1_ [ i, j ] / _a2_ [ 0, j ].
2752    *
2753    * Info on components is copied either from the first array (in the first case) or from
2754    * the array with maximal number of elements (getNbOfElems()).
2755    *  \warning No check of division by zero is performed!
2756    *  \param [in] a1 - a numerator array.
2757    *  \param [in] a2 - a denominator array.
2758    *  \return DataArrayDouble * - the new instance of DataArrayDouble.
2759    *          The caller is to delete this result array using decrRef() as it is no more
2760    *          needed.
2761    *  \throw If either \a a1 or \a a2 is NULL.
2762    *  \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples() and
2763    *         \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents() and
2764    *         none of them has number of tuples or components equal to 1.
2765    */
2766   template<class T>
2767   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::Divide(const typename Traits<T>::ArrayType *a1, const typename Traits<T>::ArrayType *a2)
2768   {
2769     return DivSub< T,std::divides<T> >(a1,a2);
2770   }
2771
2772   template<class T, class FCT>
2773   typename Traits<T>::ArrayType *MulAdd(const typename Traits<T>::ArrayType *a1, const typename Traits<T>::ArrayType *a2)
2774   {
2775     if(!a1 || !a2)
2776       throw INTERP_KERNEL::Exception("DataArrayDouble::MulAdd : input DataArrayDouble instance is NULL !");
2777     int nbOfTuple(a1->getNumberOfTuples()),nbOfTuple2(a2->getNumberOfTuples());
2778     int nbOfComp(a1->getNumberOfComponents()),nbOfComp2(a2->getNumberOfComponents());
2779     MCAuto<typename Traits<T>::ArrayType> ret=0;
2780     if(nbOfTuple==nbOfTuple2)
2781       {
2782         if(nbOfComp==nbOfComp2)
2783           {
2784             ret=Traits<T>::ArrayType::New();
2785             ret->alloc(nbOfTuple,nbOfComp);
2786             std::transform(a1->begin(),a1->end(),a2->begin(),ret->getPointer(),FCT());
2787             ret->copyStringInfoFrom(*a1);
2788           }
2789         else
2790           {
2791             int nbOfCompMin,nbOfCompMax;
2792             const typename Traits<T>::ArrayType *aMin, *aMax;
2793             if(nbOfComp>nbOfComp2)
2794               {
2795                 nbOfCompMin=nbOfComp2; nbOfCompMax=nbOfComp;
2796                 aMin=a2; aMax=a1;
2797               }
2798             else
2799               {
2800                 nbOfCompMin=nbOfComp; nbOfCompMax=nbOfComp2;
2801                 aMin=a1; aMax=a2;
2802               }
2803             if(nbOfCompMin==1)
2804               {
2805                 ret=Traits<T>::ArrayType::New();
2806                 ret->alloc(nbOfTuple,nbOfCompMax);
2807                 const T *aMinPtr(aMin->begin());
2808                 const T *aMaxPtr(aMax->begin());
2809                 T *res=ret->getPointer();
2810                 for(int i=0;i<nbOfTuple;i++)
2811                   res=std::transform(aMaxPtr+i*nbOfCompMax,aMaxPtr+(i+1)*nbOfCompMax,res,std::bind2nd(FCT(),aMinPtr[i]));
2812                 ret->copyStringInfoFrom(*aMax);
2813               }
2814             else
2815               throw INTERP_KERNEL::Exception("Nb of components mismatch for array MulAdd !");
2816           }
2817       }
2818     else if((nbOfTuple==1 && nbOfTuple2>1) || (nbOfTuple>1 && nbOfTuple2==1))
2819       {
2820         if(nbOfComp==nbOfComp2)
2821           {
2822             int nbOfTupleMax=std::max(nbOfTuple,nbOfTuple2);
2823             const typename Traits<T>::ArrayType *aMin(nbOfTuple>nbOfTuple2?a2:a1);
2824             const typename Traits<T>::ArrayType *aMax(nbOfTuple>nbOfTuple2?a1:a2);
2825             const T *aMinPtr(aMin->begin()),*aMaxPtr(aMax->begin());
2826             ret=Traits<T>::ArrayType::New();
2827             ret->alloc(nbOfTupleMax,nbOfComp);
2828             T *res(ret->getPointer());
2829             for(int i=0;i<nbOfTupleMax;i++)
2830               res=std::transform(aMaxPtr+i*nbOfComp,aMaxPtr+(i+1)*nbOfComp,aMinPtr,res,FCT());
2831             ret->copyStringInfoFrom(*aMax);
2832           }
2833         else
2834           throw INTERP_KERNEL::Exception("Nb of components mismatch for array MulAdd !");
2835       }
2836     else
2837       throw INTERP_KERNEL::Exception("Nb of tuples mismatch for array MulAdd !");
2838     return ret.retn();
2839   }
2840   
2841   /*!
2842    * Returns a new DataArrayDouble that is a product of two given arrays. There are 3
2843    * valid cases.
2844    * 1.  The arrays have same number of tuples and components. Then each value of
2845    *   the result array (_a_) is a product of the corresponding values of \a a1 and
2846    *   \a a2, i.e. _a_ [ i, j ] = _a1_ [ i, j ] * _a2_ [ i, j ].
2847    * 2.  The arrays have same number of tuples and one array, say _a2_, has one
2848    *   component. Then
2849    *   _a_ [ i, j ] = _a1_ [ i, j ] * _a2_ [ i, 0 ].
2850    * 3.  The arrays have same number of components and one array, say _a2_, has one
2851    *   tuple. Then
2852    *   _a_ [ i, j ] = _a1_ [ i, j ] * _a2_ [ 0, j ].
2853    *
2854    * Info on components is copied either from the first array (in the first case) or from
2855    * the array with maximal number of elements (getNbOfElems()).
2856    *  \param [in] a1 - a factor array.
2857    *  \param [in] a2 - another factor array.
2858    *  \return DataArrayDouble * - the new instance of DataArrayDouble.
2859    *          The caller is to delete this result array using decrRef() as it is no more
2860    *          needed.
2861    *  \throw If either \a a1 or \a a2 is NULL.
2862    *  \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples() and
2863    *         \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents() and
2864    *         none of them has number of tuples or components equal to 1.
2865    */
2866   template<class T>
2867   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::Multiply(const typename Traits<T>::ArrayType *a1, const typename Traits<T>::ArrayType *a2)
2868   {
2869     return MulAdd< T , std::multiplies<T> >(a1,a2);
2870   }
2871   
2872   /*!
2873    * Returns a new DataArrayDouble that is a sum of two given arrays. There are 3
2874    * valid cases.
2875    * 1.  The arrays have same number of tuples and components. Then each value of
2876    *   the result array (_a_) is a sum of the corresponding values of \a a1 and \a a2,
2877    *   i.e.: _a_ [ i, j ] = _a1_ [ i, j ] + _a2_ [ i, j ].
2878    * 2.  The arrays have same number of tuples and one array, say _a2_, has one
2879    *   component. Then
2880    *   _a_ [ i, j ] = _a1_ [ i, j ] + _a2_ [ i, 0 ].
2881    * 3.  The arrays have same number of components and one array, say _a2_, has one
2882    *   tuple. Then
2883    *   _a_ [ i, j ] = _a1_ [ i, j ] + _a2_ [ 0, j ].
2884    *
2885    * Info on components is copied either from the first array (in the first case) or from
2886    * the array with maximal number of elements (getNbOfElems()).
2887    *  \param [in] a1 - an array to sum up.
2888    *  \param [in] a2 - another array to sum up.
2889    *  \return DataArrayDouble * - the new instance of DataArrayDouble.
2890    *          The caller is to delete this result array using decrRef() as it is no more
2891    *          needed.
2892    *  \throw If either \a a1 or \a a2 is NULL.
2893    *  \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples() and
2894    *         \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents() and
2895    *         none of them has number of tuples or components equal to 1.
2896    */
2897   template<class T>
2898   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::Add(const typename Traits<T>::ArrayType *a1, const typename Traits<T>::ArrayType *a2)
2899   {
2900     return MulAdd< T , std::plus<T> >(a1,a2);
2901   }
2902   
2903   /*!
2904    * Returns either a \a deep or \a shallow copy of this array. For more info see
2905    * \ref MEDCouplingArrayBasicsCopyDeep and \ref MEDCouplingArrayBasicsCopyShallow.
2906    *  \param [in] dCpy - if \a true, a deep copy is returned, else, a shallow one.
2907    *  \return DataArrayDouble * - either a new instance of DataArrayDouble (if \a dCpy
2908    *          == \a true) or \a this instance (if \a dCpy == \a false).
2909    */
2910   template<class T>
2911   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::PerformCopyOrIncrRef(bool dCpy, const typename Traits<T>::ArrayType& self)
2912   {
2913     if(dCpy)
2914       return self.deepCopy();
2915     else
2916       {
2917         self.incrRef();
2918         return const_cast<typename Traits<T>::ArrayType *>(&self);
2919       }
2920   }
2921
2922   template<class T>
2923   struct GreatEqual
2924   {
2925     GreatEqual(T v):_v(v) { }
2926     bool operator()(T v) const { return v>=_v; }
2927     T _v;
2928   };
2929   
2930   template<class T>
2931   struct GreaterThan
2932   {
2933     GreaterThan(T v):_v(v) { }
2934     bool operator()(T v) const { return v>_v; }
2935     T _v;
2936   };
2937   
2938   template<class T>
2939   struct LowerEqual
2940   {
2941     LowerEqual(T v):_v(v) { }
2942     bool operator()(T v) const { return v<=_v; }
2943     T _v;
2944   };
2945   
2946   template<class T>
2947   struct LowerThan
2948   {
2949     LowerThan(T v):_v(v) { }
2950     bool operator()(T v) const { return v<_v; }
2951     T _v;
2952   };
2953   
2954   template<class T>
2955   struct InRange
2956   {
2957     InRange(T a, T b):_a(a),_b(b) { }
2958     bool operator()(T v) const { return v>=_a && v<_b; }
2959     T _a,_b;
2960   };
2961
2962 template<class T>
2963 struct NotInRange
2964 {
2965   NotInRange(T a, T b):_a(a),_b(b) { }
2966   bool operator()(T v) const { return v<_a || v>=_b; }
2967   T _a,_b;
2968 };
2969
2970   /*!
2971    * This method works only on data array with one component. This method returns a newly allocated array storing stored ascendantly of tuple ids in \a this so that this[id]<0.
2972    *
2973    * \return a newly allocated data array that the caller should deal with.
2974    * \sa DataArrayInt::findIdsInRange
2975    */
2976   template<class T>
2977   DataArrayInt *DataArrayTemplateClassic<T>::findIdsStrictlyNegative() const
2978   {
2979     LowerThan<T> lt((T)0);
2980     MCAuto<DataArrayInt> ret(findIdsAdv(lt));
2981     return ret.retn();
2982   }
2983   
2984   template<class T>
2985   MCAuto<DataArrayInt> DataArrayTemplateClassic<T>::findIdsGreaterOrEqualTo(T val) const
2986   {
2987     GreatEqual<T> ge(val);
2988     return findIdsAdv(ge);
2989   }
2990   
2991   template<class T>
2992   MCAuto<DataArrayInt> DataArrayTemplateClassic<T>::findIdsGreaterThan(T val) const
2993   {
2994     GreaterThan<T> gt(val);
2995     return findIdsAdv(gt);
2996   }
2997   
2998   template<class T>
2999   MCAuto<DataArrayInt> DataArrayTemplateClassic<T>::findIdsLowerOrEqualTo(T val) const
3000   {
3001     LowerEqual<T> le(val);
3002     return findIdsAdv(le);
3003   }
3004   
3005   template<class T>
3006   MCAuto<DataArrayInt> DataArrayTemplateClassic<T>::findIdsLowerThan(T val) const
3007   {
3008     LowerThan<T> lt(val);
3009     return findIdsAdv(lt);
3010   }
3011
3012   /*!
3013    * Returns a new DataArrayDouble by aggregating two given arrays, so that (1) the number
3014    * of components in the result array is a sum of the number of components of given arrays
3015    * and (2) the number of tuples in the result array is same as that of each of given
3016    * arrays. In other words the i-th tuple of result array includes all components of
3017    * i-th tuples of all given arrays.
3018    * Number of tuples in the given arrays must be  the same.
3019    *  \param [in] a1 - an array to include in the result array.
3020    *  \param [in] a2 - another array to include in the result array.
3021    *  \return DataArrayDouble * - the new instance of DataArrayDouble.
3022    *          The caller is to delete this result array using decrRef() as it is no more
3023    *          needed.
3024    *  \throw If both \a a1 and \a a2 are NULL.
3025    *  \throw If any given array is not allocated.
3026    *  \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples()
3027    */
3028   template<class T>
3029   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::Meld(const typename Traits<T>::ArrayType *a1, const typename Traits<T>::ArrayType *a2)
3030   {
3031     std::vector<const typename Traits<T>::ArrayType *> arr(2);
3032     arr[0]=a1; arr[1]=a2;
3033     return Meld(arr);
3034   }
3035
3036   /*!
3037    * Returns a new DataArrayDouble by aggregating all given arrays, so that (1) the number
3038    * of components in the result array is a sum of the number of components of given arrays
3039    * and (2) the number of tuples in the result array is same as that of each of given
3040    * arrays. In other words the i-th tuple of result array includes all components of
3041    * i-th tuples of all given arrays.
3042    * Number of tuples in the given arrays must be  the same.
3043    *  \param [in] arr - a sequence of arrays to include in the result array.
3044    *  \return DataArrayDouble * - the new instance of DataArrayDouble.
3045    *          The caller is to delete this result array using decrRef() as it is no more
3046    *          needed.
3047    *  \throw If all arrays within \a arr are NULL.
3048    *  \throw If any given array is not allocated.
3049    *  \throw If getNumberOfTuples() of arrays within \a arr is different.
3050    */
3051   template<class T>
3052   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::Meld(const std::vector<const typename Traits<T>::ArrayType *>& arr)
3053   {
3054     std::vector<const typename Traits<T>::ArrayType *> a;
3055     for(typename std::vector<const typename Traits<T>::ArrayType *>::const_iterator it4=arr.begin();it4!=arr.end();it4++)
3056       if(*it4)
3057         a.push_back(*it4);
3058     if(a.empty())
3059       throw INTERP_KERNEL::Exception("DataArrayDouble::Meld : input list must contain at least one NON EMPTY DataArrayDouble !");
3060     typename std::vector<const typename Traits<T>::ArrayType *>::const_iterator it;
3061     for(it=a.begin();it!=a.end();it++)
3062       (*it)->checkAllocated();
3063     it=a.begin();
3064     std::size_t nbOfTuples((*it)->getNumberOfTuples());
3065     std::vector<int> nbc(a.size());
3066     std::vector<const T *> pts(a.size());
3067     nbc[0]=(*it)->getNumberOfComponents();
3068     pts[0]=(*it++)->getConstPointer();
3069     for(int i=1;it!=a.end();it++,i++)
3070       {
3071         if(nbOfTuples!=(*it)->getNumberOfTuples())
3072           throw INTERP_KERNEL::Exception("DataArrayDouble::Meld : mismatch of number of tuples !");
3073         nbc[i]=(*it)->getNumberOfComponents();
3074         pts[i]=(*it)->getConstPointer();
3075       }
3076     int totalNbOfComp=std::accumulate(nbc.begin(),nbc.end(),0);
3077     typename Traits<T>::ArrayType *ret(Traits<T>::ArrayType::New());
3078     ret->alloc(nbOfTuples,totalNbOfComp);
3079     T *retPtr(ret->getPointer());
3080     for(std::size_t i=0;i<nbOfTuples;i++)
3081       for(std::size_t j=0;j<a.size();j++)
3082         {
3083           retPtr=std::copy(pts[j],pts[j]+nbc[j],retPtr);
3084           pts[j]+=nbc[j];
3085         }
3086     int k=0;
3087     for(int i=0;i<(int)a.size();i++)
3088       for(int j=0;j<nbc[i];j++,k++)
3089         ret->setInfoOnComponent(k,a[i]->getInfoOnComponent(j));
3090     return ret;
3091   }
3092
3093   /*!
3094    * Returns a new DataArrayDouble holding the same values as \a this array but differently
3095    * arranged in memory. If \a this array holds 2 components of 3 values:
3096    * \f$ x_0,x_1,x_2,y_0,y_1,y_2 \f$, then the result array holds these values arranged
3097    * as follows: \f$ x_0,y_0,x_1,y_1,x_2,y_2 \f$.
3098    *  \warning Do not confuse this method with transpose()!
3099    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
3100    *          is to delete using decrRef() as it is no more needed.
3101    *  \throw If \a this is not allocated.
3102    */
3103   template<class T>
3104   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::fromNoInterlace() const
3105   {
3106     if(this->_mem.isNull())
3107       throw INTERP_KERNEL::Exception("DataArrayDouble::fromNoInterlace : Not defined array !");
3108     T *tab(this->_mem.fromNoInterlace(this->getNumberOfComponents()));
3109     MCAuto<typename Traits<T>::ArrayType> ret(Traits<T>::ArrayType::New());
3110     ret->useArray(tab,true,C_DEALLOC,this->getNumberOfTuples(),this->getNumberOfComponents());
3111     return ret.retn();
3112   }
3113
3114   /*!
3115    * Returns a new DataArrayDouble holding the same values as \a this array but differently
3116    * arranged in memory. If \a this array holds 2 components of 3 values:
3117    * \f$ x_0,y_0,x_1,y_1,x_2,y_2 \f$, then the result array holds these values arranged
3118    * as follows: \f$ x_0,x_1,x_2,y_0,y_1,y_2 \f$.
3119    *  \warning Do not confuse this method with transpose()!
3120    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
3121    *          is to delete using decrRef() as it is no more needed.
3122    *  \throw If \a this is not allocated.
3123    */
3124   template<class T>
3125   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::toNoInterlace() const
3126   {
3127     if(this->_mem.isNull())
3128       throw INTERP_KERNEL::Exception("DataArrayDouble::toNoInterlace : Not defined array !");
3129     T *tab(this->_mem.toNoInterlace(this->getNumberOfComponents()));
3130     MCAuto<typename Traits<T>::ArrayType> ret(Traits<T>::ArrayType::New());
3131     ret->useArray(tab,true,C_DEALLOC,this->getNumberOfTuples(),this->getNumberOfComponents());
3132     return ret.retn();
3133   }
3134   
3135   /*!
3136    * Appends components of another array to components of \a this one, tuple by tuple.
3137    * So that the number of tuples of \a this array remains the same and the number of 
3138    * components increases.
3139    *  \param [in] other - the DataArrayDouble to append to \a this one.
3140    *  \throw If \a this is not allocated.
3141    *  \throw If \a this and \a other arrays have different number of tuples.
3142    *
3143    *  \if ENABLE_EXAMPLES
3144    *  \ref cpp_mcdataarraydouble_meldwith "Here is a C++ example".
3145    *
3146    *  \ref py_mcdataarraydouble_meldwith "Here is a Python example".
3147    *  \endif
3148    */
3149   template<class T>
3150   void DataArrayTemplateClassic<T>::meldWith(const typename Traits<T>::ArrayType *other)
3151   {
3152     this->checkAllocated();
3153     other->checkAllocated();
3154     std::size_t nbOfTuples(this->getNumberOfTuples());
3155     if(nbOfTuples!=other->getNumberOfTuples())
3156       throw INTERP_KERNEL::Exception("DataArrayDouble::meldWith : mismatch of number of tuples !");
3157     int nbOfComp1(this->getNumberOfComponents()),nbOfComp2(other->getNumberOfComponents());
3158     T *newArr=(T *)malloc((nbOfTuples*(nbOfComp1+nbOfComp2))*sizeof(T));
3159     T *w=newArr;
3160     const T *inp1(this->begin()),*inp2(other->begin());
3161     for(std::size_t i=0;i<nbOfTuples;i++,inp1+=nbOfComp1,inp2+=nbOfComp2)
3162       {
3163         w=std::copy(inp1,inp1+nbOfComp1,w);
3164         w=std::copy(inp2,inp2+nbOfComp2,w);
3165       }
3166     this->useArray(newArr,true,C_DEALLOC,nbOfTuples,nbOfComp1+nbOfComp2);
3167     std::vector<int> compIds(nbOfComp2);
3168     for(int i=0;i<nbOfComp2;i++)
3169       compIds[i]=nbOfComp1+i;
3170     this->copyPartOfStringInfoFrom2(compIds,*other);
3171   }
3172
3173   /*!
3174    * 
3175    * \param [in] nbTimes specifies the nb of times each tuples in \a this will be duplicated contiguouly in returned DataArrayDouble instance.
3176    *             \a nbTimes  should be at least equal to 1.
3177    * \return a newly allocated DataArrayDouble having one component and number of tuples equal to \a nbTimes * \c this->getNumberOfTuples.
3178    * \throw if \a this is not allocated or if \a this has not number of components set to one or if \a nbTimes is lower than 1.
3179    */
3180   template<class T>
3181   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::duplicateEachTupleNTimes(int nbTimes) const
3182   {
3183     this->checkAllocated();
3184     if(this->getNumberOfComponents()!=1)
3185       throw INTERP_KERNEL::Exception("DataArrayDouble::duplicateEachTupleNTimes : this should have only one component !");
3186     if(nbTimes<1)
3187       throw INTERP_KERNEL::Exception("DataArrayDouble::duplicateEachTupleNTimes : nb times should be >= 1 !");
3188     int nbTuples(this->getNumberOfTuples());
3189     const T *inPtr(this->begin());
3190     MCAuto<typename Traits<T>::ArrayType> ret(Traits<T>::ArrayType::New()); ret->alloc(nbTimes*nbTuples,1);
3191     T *retPtr(ret->getPointer());
3192     for(int i=0;i<nbTuples;i++,inPtr++)
3193       {
3194         T val(*inPtr);
3195         for(int j=0;j<nbTimes;j++,retPtr++)
3196           *retPtr=val;
3197       }
3198     ret->copyStringInfoFrom(*this);
3199     return ret.retn();
3200   }
3201   
3202   template<class T>
3203   void DataArrayTemplateClassic<T>::aggregate(const typename Traits<T>::ArrayType *other)
3204   {
3205     if(!other)
3206       throw INTERP_KERNEL::Exception("DataArrayDouble::aggregate : null pointer !");
3207     if(this->getNumberOfComponents()!=other->getNumberOfComponents())
3208       throw INTERP_KERNEL::Exception("DataArrayDouble::aggregate : mismatch number of components !");
3209     this->_mem.insertAtTheEnd(other->begin(),other->end());
3210   }
3211
3212   /*!
3213    * Converts every value of \a this array to its absolute value.
3214    * \b WARNING this method is non const. If a new DataArrayDouble instance should be built containing the result of abs DataArrayDouble::computeAbs
3215    * should be called instead.
3216    *
3217    * \throw If \a this is not allocated.
3218    * \sa DataArrayDouble::computeAbs
3219    */
3220   template<class T>
3221   void DataArrayTemplateClassic<T>::abs()
3222   {
3223     this->checkAllocated();
3224     T *ptr(this->getPointer());
3225     std::size_t nbOfElems(this->getNbOfElems());
3226     std::transform(ptr,ptr+nbOfElems,ptr,std::ptr_fun<T,T>(std::abs));
3227     this->declareAsNew();
3228   }
3229
3230   /*!
3231    * This method builds a new instance of \a this object containing the result of std::abs applied of all elements in \a this.
3232    * This method is a const method (that do not change any values in \a this) contrary to  DataArrayDouble::abs method.
3233    *
3234    * \return DataArrayDouble * - the new instance of DataArrayDouble containing the
3235    *         same number of tuples and component as \a this array.
3236    *         The caller is to delete this result array using decrRef() as it is no more
3237    *         needed.
3238    * \throw If \a this is not allocated.
3239    * \sa DataArrayDouble::abs
3240    */
3241   template<class T>
3242   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::computeAbs() const
3243   {
3244     this->checkAllocated();
3245     MCAuto<typename Traits<T>::ArrayType> newArr(Traits<T>::ArrayType::New());
3246     int nbOfTuples(this->getNumberOfTuples());
3247     int nbOfComp(this->getNumberOfComponents());
3248     newArr->alloc(nbOfTuples,nbOfComp);
3249     std::transform(this->begin(),this->end(),newArr->getPointer(),std::ptr_fun<T,T>(std::abs));
3250     newArr->copyStringInfoFrom(*this);
3251     return newArr.retn();
3252   }
3253
3254   /*!
3255    * Returns either a \a deep or \a shallow copy of this array. For more info see
3256    * \ref MEDCouplingArrayBasicsCopyDeep and \ref MEDCouplingArrayBasicsCopyShallow.
3257    *  \param [in] dCpy - if \a true, a deep copy is returned, else, a shallow one.
3258    *  \return DataArrayDouble * - either a new instance of DataArrayDouble (if \a dCpy
3259    *          == \a true) or \a this instance (if \a dCpy == \a false).
3260    */
3261   template<class T>
3262   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::performCopyOrIncrRef(bool dCpy) const
3263   {
3264     const typename Traits<T>::ArrayType *thisC(static_cast<const typename Traits<T>::ArrayType *>(this));
3265     return DataArrayTemplateClassic<T>::PerformCopyOrIncrRef(dCpy,*thisC);
3266   }
3267
3268   /*!
3269    * Computes for each tuple the sum of number of components values in the tuple and return it.
3270    * 
3271    * \return DataArrayDouble * - the new instance of DataArrayDouble containing the
3272    *          same number of tuples as \a this array and one component.
3273    *          The caller is to delete this result array using decrRef() as it is no more
3274    *          needed.
3275    *  \throw If \a this is not allocated.
3276    */
3277   template<class T>
3278   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::sumPerTuple() const
3279   {
3280     this->checkAllocated();
3281     std::size_t nbOfComp(this->getNumberOfComponents()),nbOfTuple(this->getNumberOfTuples());
3282     MCAuto<typename Traits<T>::ArrayType> ret(Traits<T>::ArrayType::New());
3283     ret->alloc(nbOfTuple,1);
3284     const T *src(this->begin());
3285     T *dest(ret->getPointer());
3286     for(std::size_t i=0;i<nbOfTuple;i++,dest++,src+=nbOfComp)
3287       *dest=std::accumulate(src,src+nbOfComp,(T)0);
3288     return ret.retn();
3289   }
3290
3291   /*!
3292    * Set all values in \a this array so that the i-th element equals to \a init + i
3293    * (i starts from zero). To know more on filling arrays see \ref MEDCouplingArrayFill.
3294    *  \param [in] init - value to assign to the first element of array.
3295    *  \throw If \a this->getNumberOfComponents() != 1
3296    *  \throw If \a this is not allocated.
3297    */
3298   template<class T>
3299   void DataArrayTemplateClassic<T>::iota(T init)
3300   {
3301     this->checkAllocated();
3302     if(this->getNumberOfComponents()!=1)
3303       throw INTERP_KERNEL::Exception("DataArrayDouble::iota : works only for arrays with only one component, you can call 'rearrange' method before !");
3304     T *ptr(this->getPointer());
3305     std::size_t ntuples(this->getNumberOfTuples());
3306     for(std::size_t i=0;i<ntuples;i++)
3307       ptr[i]=init+(T)i;
3308     this->declareAsNew();
3309   }
3310
3311   template<class T>
3312   struct ImplReprTraits { static void SetPrecision(std::ostream& oss) { } };
3313
3314   template<>
3315   struct ImplReprTraits<double> {  static void SetPrecision(std::ostream& oss) { oss.precision(17); } };
3316   
3317   template<>
3318   struct ImplReprTraits<float> {  static void SetPrecision(std::ostream& oss) { oss.precision(7); } };
3319   
3320   template<class T>
3321   void DataArrayTemplateClassic<T>::reprStream(std::ostream& stream) const
3322   {
3323     stream << "Name of " << Traits<T>::ReprStr << " array : \"" << this->_name << "\"\n";
3324     reprWithoutNameStream(stream);
3325   }
3326
3327   template<class T>
3328   void DataArrayTemplateClassic<T>::reprZipStream(std::ostream& stream) const
3329   {
3330     stream << "Name of " << Traits<T>::ReprStr << " array : \"" << this->_name << "\"\n";
3331     reprZipWithoutNameStream(stream);
3332   }
3333
3334   template<class T>
3335   void DataArrayTemplateClassic<T>::reprNotTooLongStream(std::ostream& stream) const
3336   {
3337     stream << "Name of "<< Traits<T>::ReprStr << " array : \"" << this->_name << "\"\n";
3338     reprNotTooLongWithoutNameStream(stream);
3339   }
3340
3341   template<class T>
3342   void DataArrayTemplateClassic<T>::reprWithoutNameStream(std::ostream& stream) const
3343   {
3344     DataArray::reprWithoutNameStream(stream);
3345     ImplReprTraits<T>::SetPrecision(stream);
3346     this->_mem.repr(this->getNumberOfComponents(),stream);
3347   }
3348
3349   template<class T>
3350   void DataArrayTemplateClassic<T>::reprZipWithoutNameStream(std::ostream& stream) const
3351   {
3352     DataArray::reprWithoutNameStream(stream);
3353     ImplReprTraits<T>::SetPrecision(stream);
3354     this->_mem.reprZip(this->getNumberOfComponents(),stream);
3355   }
3356
3357   template<class T>
3358   void DataArrayTemplateClassic<T>::reprNotTooLongWithoutNameStream(std::ostream& stream) const
3359   {
3360     DataArray::reprWithoutNameStream(stream);
3361     ImplReprTraits<T>::SetPrecision(stream);
3362     this->_mem.reprNotTooLong(this->getNumberOfComponents(),stream);
3363   }
3364
3365   /*!
3366    * This method is close to repr method except that when \a this has more than 1000 tuples, all tuples are not
3367    * printed out to avoid to consume too much space in interpretor.
3368    * \sa repr
3369    */
3370   template<class T>
3371   std::string DataArrayTemplateClassic<T>::reprNotTooLong() const
3372   {
3373     std::ostringstream ret;
3374     reprNotTooLongStream(ret);
3375     return ret.str();
3376   }
3377   
3378   /////////////////////////////////
3379   
3380   /*!
3381    * Checks if all values in \a this array are equal to \a val at precision \a eps.
3382    *  \param [in] val - value to check equality of array values to.
3383    *  \param [in] eps - precision to check the equality.
3384    *  \return bool - \a true if all values are in range (_val_ - _eps_; _val_ + _eps_),
3385    *                 \a false else.
3386    *  \throw If \a this->getNumberOfComponents() != 1
3387    *  \throw If \a this is not allocated.
3388    */
3389   template<class T>
3390   bool DataArrayTemplateFP<T>::isUniform(T val, T eps) const
3391   {
3392     this->checkAllocated();
3393     if(this->getNumberOfComponents()!=1)
3394       throw INTERP_KERNEL::Exception("DataArrayDouble::isUniform : must be applied on DataArrayDouble with only one component, you can call 'rearrange' method before !");
3395     const T *w(this->begin()),*end2(this->end());
3396     const T vmin(val-eps),vmax(val+eps);
3397     for(;w!=end2;w++)
3398       if(*w<vmin || *w>vmax)
3399         return false;
3400     return true;
3401   }
3402
3403   /*!
3404    * Equivalent to DataArrayInt::isEqual except that if false the reason of
3405    * mismatch is given.
3406    * 
3407    * \param [in] other the instance to be compared with \a this
3408    * \param [out] reason In case of inequality returns the reason.
3409    * \sa DataArrayInt::isEqual
3410    */
3411   template<class T>
3412   bool DataArrayDiscrete<T>::isEqualIfNotWhy(const DataArrayDiscrete<T>& other, std::string& reason) const
3413   {
3414     if(!this->areInfoEqualsIfNotWhy(other,reason))
3415       return false;
3416     return this->_mem.isEqual(other._mem,0,reason);
3417   }
3418
3419   /*!
3420    * Checks if \a this and another DataArrayInt are fully equal. For more info see
3421    * \ref MEDCouplingArrayBasicsCompare.
3422    *  \param [in] other - an instance of DataArrayInt to compare with \a this one.
3423    *  \return bool - \a true if the two arrays are equal, \a false else.
3424    */
3425   template<class T>
3426   bool DataArrayDiscrete<T>::isEqual(const DataArrayDiscrete<T>& other) const
3427   {
3428     std::string tmp;
3429     return isEqualIfNotWhy(other,tmp);
3430   }
3431
3432   /*!
3433    * Checks if values of \a this and another DataArrayInt are equal. For more info see
3434    * \ref MEDCouplingArrayBasicsCompare.
3435    *  \param [in] other - an instance of DataArrayInt to compare with \a this one.
3436    *  \return bool - \a true if the values of two arrays are equal, \a false else.
3437    */
3438   template<class T>
3439   bool DataArrayDiscrete<T>::isEqualWithoutConsideringStr(const DataArrayDiscrete<T>& other) const
3440   {
3441     std::string tmp;
3442     return this->_mem.isEqual(other._mem,0,tmp);
3443   }
3444
3445   /*!
3446    * Checks if values of \a this and another DataArrayInt are equal. Comparison is
3447    * performed on sorted value sequences.
3448    * For more info see\ref MEDCouplingArrayBasicsCompare.
3449    *  \param [in] other - an instance of DataArrayInt to compare with \a this one.
3450    *  \return bool - \a true if the sorted values of two arrays are equal, \a false else.
3451    */
3452   template<class T>
3453   bool DataArrayDiscrete<T>::isEqualWithoutConsideringStrAndOrder(const typename Traits<T>::ArrayType& other) const
3454   {
3455     MCAuto<DataArrayInt> a(static_cast<const typename Traits<T>::ArrayType *>(this)->deepCopy()),b(other.deepCopy());
3456     a->sort();
3457     b->sort();
3458     return a->isEqualWithoutConsideringStr(*b);
3459   }
3460   
3461   template<class T>
3462   template<class ALG>
3463   void DataArrayDiscrete<T>::switchOnTupleAlg(T val, std::vector<bool>& vec, ALG algo) const
3464   {
3465     this->checkAllocated();
3466     if(this->getNumberOfComponents()!=1)
3467       throw INTERP_KERNEL::Exception("DataArrayInt::switchOnTupleEqualTo : number of components of this should be equal to one !");
3468     int nbOfTuples(this->getNumberOfTuples());
3469     if(nbOfTuples!=(int)vec.size())
3470       throw INTERP_KERNEL::Exception("DataArrayInt::switchOnTupleEqualTo : number of tuples of this should be equal to size of input vector of bool !");
3471     const T *pt(this->begin());
3472     for(int i=0;i<nbOfTuples;i++)
3473       if(algo(pt[i],val))
3474         vec[i]=true;
3475   }
3476   
3477   /*!
3478    * This method assumes that \a this has one component and is allocated. This method scans all tuples in \a this and for all tuple equal to \a val
3479    * put True to the corresponding entry in \a vec.
3480    * \a vec is expected to be with the same size than the number of tuples of \a this.
3481    *
3482    *  \sa DataArrayInt::switchOnTupleNotEqualTo.
3483    */
3484   template<class T>
3485   void DataArrayDiscrete<T>::switchOnTupleEqualTo(T val, std::vector<bool>& vec) const
3486   {
3487     switchOnTupleAlg(val,vec,std::equal_to<T>());
3488   }
3489
3490   /*!
3491    * This method assumes that \a this has one component and is allocated. This method scans all tuples in \a this and for all tuple different from \a val
3492    * put True to the corresponding entry in \a vec.
3493    * \a vec is expected to be with the same size than the number of tuples of \a this.
3494    * 
3495    *  \sa DataArrayInt::switchOnTupleEqualTo.
3496    */
3497   template<class T>
3498   void DataArrayDiscrete<T>::switchOnTupleNotEqualTo(T val, std::vector<bool>& vec) const
3499   {
3500     switchOnTupleAlg(val,vec,std::not_equal_to<T>());
3501   }
3502
3503   /*!
3504    * Creates a new one-dimensional DataArrayInt of the same size as \a this and a given
3505    * one-dimensional arrays that must be of the same length. The result array describes
3506    * correspondence between \a this and \a other arrays, so that 
3507    * <em> other.getIJ(i,0) == this->getIJ(ret->getIJ(i),0)</em>. If such a permutation is
3508    * not possible because some element in \a other is not in \a this, an exception is thrown.
3509    *  \param [in] other - an array to compute permutation to.
3510    *  \return DataArrayInt * - a new instance of DataArrayInt, which is a permutation array
3511    * from \a this to \a other. The caller is to delete this array using decrRef() as it is
3512    * no more needed.
3513    *  \throw If \a this->getNumberOfComponents() != 1.
3514    *  \throw If \a other->getNumberOfComponents() != 1.
3515    *  \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples().
3516    *  \throw If \a other includes a value which is not in \a this array.
3517    * 
3518    *  \if ENABLE_EXAMPLES
3519    *  \ref cpp_mcdataarrayint_buildpermutationarr "Here is a C++ example".
3520    *
3521    *  \ref py_mcdataarrayint_buildpermutationarr "Here is a Python example".
3522    *  \endif
3523    */
3524   template<class T>
3525   DataArrayIdType *DataArrayDiscrete<T>::buildPermutationArr(const DataArrayDiscrete<T>& other) const
3526   {
3527     this->checkAllocated();
3528     if(this->getNumberOfComponents()!=1 || other.getNumberOfComponents()!=1)
3529       throw INTERP_KERNEL::Exception("DataArrayInt::buildPermutationArr : 'this' and 'other' have to have exactly ONE component !");
3530     std::size_t nbTuple(this->getNumberOfTuples());
3531     other.checkAllocated();
3532     if(nbTuple!=other.getNumberOfTuples())
3533       throw INTERP_KERNEL::Exception("DataArrayInt::buildPermutationArr : 'this' and 'other' must have the same number of tuple !");
3534     MCAuto<DataArrayIdType> ret(DataArrayIdType::New());
3535     ret->alloc(nbTuple,1);
3536     ret->fillWithValue(-1);
3537     const T *pt(this->begin());
3538     std::map<int,mcIdType> mm;
3539     for(std::size_t i=0;i<nbTuple;i++)
3540       mm[pt[i]]=(mcIdType)i;
3541     pt=other.begin();
3542     mcIdType *retToFill(ret->getPointer());
3543     for(std::size_t i=0;i<nbTuple;i++)
3544       {
3545         std::map<int,int>::const_iterator it=mm.find(pt[i]);
3546         if(it==mm.end())
3547           {
3548             std::ostringstream oss; oss << "DataArrayInt::buildPermutationArr : Arrays mismatch : element (" << pt[i] << ") in 'other' not findable in 'this' !";
3549             throw INTERP_KERNEL::Exception(oss.str().c_str());
3550           }
3551         retToFill[i]=(*it).second;
3552       }
3553     return ret.retn();
3554   }
3555
3556   /*!
3557    * Elements of \a partOfThis are expected to be included in \a this.
3558    * The returned array \a ret is so that this[ret]==partOfThis
3559    *
3560    * For example, if \a this array contents are [9,10,0,6,4,11,3,8] and if \a partOfThis contains [6,0,11,8]
3561    * the return array will contain [3,2,5,7].
3562    *
3563    * \a this is expected to be a 1 compo allocated array.
3564    * \param [in] partOfThis - A 1 compo allocated array
3565    * \return - A newly allocated array to be dealed by caller having the same number of tuples than \a partOfThis.
3566    * \throw if two same element is present twice in \a this
3567    * \throw if an element in \a partOfThis is \b NOT in \a this.
3568    */
3569   template<class T>
3570   DataArrayIdType *DataArrayDiscrete<T>::indicesOfSubPart(const DataArrayDiscrete<T>& partOfThis) const
3571   {
3572     if(this->getNumberOfComponents()!=1 || partOfThis.getNumberOfComponents()!=1)
3573       throw INTERP_KERNEL::Exception("DataArrayInt::indicesOfSubPart : this and input array must be one component array !");
3574     this->checkAllocated(); partOfThis.checkAllocated();
3575     std::size_t thisNbTuples(this->getNumberOfTuples()),nbTuples(partOfThis.getNumberOfTuples());
3576     const T *thisPt(this->begin()),*pt(partOfThis.begin());
3577     MCAuto<DataArrayIdType> ret(DataArrayIdType::New());
3578     ret->alloc(nbTuples,1);
3579     T *retPt(ret->getPointer());
3580     std::map<int,mcIdType> m;
3581     for(std::size_t i=0;i<thisNbTuples;i++,thisPt++)
3582       m[*thisPt]=(mcIdType)i;
3583     if(m.size()!=thisNbTuples)
3584       throw INTERP_KERNEL::Exception("DataArrayInt::indicesOfSubPart : some elements appears more than once !");
3585     for(std::size_t i=0;i<nbTuples;i++,retPt++,pt++)
3586       {
3587         std::map<int,mcIdType>::const_iterator it(m.find(*pt));
3588         if(it!=m.end())
3589           *retPt=(*it).second;
3590         else
3591           {
3592             std::ostringstream oss; oss << "DataArrayInt::indicesOfSubPart : At pos #" << i << " of input array value is " << *pt << " not in this !";
3593             throw INTERP_KERNEL::Exception(oss.str());
3594           }
3595       }
3596     return ret.retn();
3597   }
3598
3599   /*!
3600    * Checks that \a this array is consistently **increasing** or **decreasing** in value.
3601    * If not an exception is thrown.
3602    *  \param [in] increasing - if \a true, the array values should be increasing.
3603    *  \throw If sequence of values is not strictly monotonic in agreement with \a
3604    *         increasing arg.
3605    *  \throw If \a this->getNumberOfComponents() != 1.
3606    *  \throw If \a this is not allocated.
3607    */
3608   template<class T>
3609   void DataArrayDiscrete<T>::checkMonotonic(bool increasing) const
3610   {
3611     if(!isMonotonic(increasing))
3612       {
3613         if (increasing)
3614           throw INTERP_KERNEL::Exception("DataArrayInt::checkMonotonic : 'this' is not INCREASING monotonic !");
3615         else
3616           throw INTERP_KERNEL::Exception("DataArrayInt::checkMonotonic : 'this' is not DECREASING monotonic !");
3617       }
3618   }
3619
3620   /*!
3621    * Checks that \a this array is consistently **increasing** or **decreasing** in value.
3622    *  \param [in] increasing - if \a true, array values should be increasing.
3623    *  \return bool - \a true if values change in accordance with \a increasing arg.
3624    *  \throw If \a this->getNumberOfComponents() != 1.
3625    *  \throw If \a this is not allocated.
3626    */
3627   template<class T>
3628   bool DataArrayDiscrete<T>::isMonotonic(bool increasing) const
3629   {
3630     this->checkAllocated();
3631     if(this->getNumberOfComponents()!=1)
3632       throw INTERP_KERNEL::Exception("DataArrayInt::isMonotonic : only supported with 'this' array with ONE component !");
3633     std::size_t nbOfElements(this->getNumberOfTuples());
3634     const T *ptr(this->begin());
3635     if(nbOfElements==0)
3636       return true;
3637     T ref(ptr[0]);
3638     if(increasing)
3639       {
3640         for(std::size_t i=1;i<nbOfElements;i++)
3641           {
3642             if(ptr[i]>=ref)
3643               ref=ptr[i];
3644             else
3645               return false;
3646           }
3647       }
3648     else
3649       {
3650         for(std::size_t i=1;i<nbOfElements;i++)
3651           {
3652             if(ptr[i]<=ref)
3653               ref=ptr[i];
3654             else
3655               return false;
3656           }
3657       }
3658     return true;
3659   }
3660
3661   /*!
3662    * This method check that array consistently INCREASING or DECREASING in value.
3663    */
3664   template<class T>
3665   bool DataArrayDiscrete<T>::isStrictlyMonotonic(bool increasing) const
3666   {
3667     this->checkAllocated();
3668     if(this->getNumberOfComponents()!=1)
3669       throw INTERP_KERNEL::Exception("DataArrayInt::isStrictlyMonotonic : only supported with 'this' array with ONE component !");
3670     std::size_t nbOfElements(this->getNumberOfTuples());
3671     const T *ptr(this->begin());
3672     if(nbOfElements==0)
3673       return true;
3674     T ref(ptr[0]);
3675     if(increasing)
3676       {
3677         for(std::size_t i=1;i<nbOfElements;i++)
3678           {
3679             if(ptr[i]>ref)
3680               ref=ptr[i];
3681             else
3682               return false;
3683           }
3684       }
3685     else
3686       {
3687         for(std::size_t i=1;i<nbOfElements;i++)
3688           {
3689             if(ptr[i]<ref)
3690               ref=ptr[i];
3691             else
3692               return false;
3693           }
3694       }
3695     return true;
3696   }
3697
3698   /*!
3699    * This method check that array consistently INCREASING or DECREASING in value.
3700    */
3701   template<class T>
3702   void DataArrayDiscrete<T>::checkStrictlyMonotonic(bool increasing) const
3703   {
3704     if(!isStrictlyMonotonic(increasing))
3705       {
3706         if (increasing)
3707           throw INTERP_KERNEL::Exception("DataArrayInt::checkStrictlyMonotonic : 'this' is not strictly INCREASING monotonic !");
3708         else
3709           throw INTERP_KERNEL::Exception("DataArrayInt::checkStrictlyMonotonic : 'this' is not strictly DECREASING monotonic !");
3710       }
3711   }
3712
3713   ////////////////////////////////////
3714
3715   /*!
3716    * This method compares content of input vector \a v and \a this.
3717    * If for each id in \a this v[id]==True and for all other ids id2 not in \a this v[id2]==False, true is returned.
3718    * For performance reasons \a this is expected to be sorted ascendingly. If not an exception will be thrown.
3719    *
3720    * \param [in] v - the vector of 'flags' to be compared with \a this.
3721    *
3722    * \throw If \a this is not sorted ascendingly.
3723    * \throw If \a this has not exactly one component.
3724    * \throw If \a this is not allocated.
3725    */
3726   template<class T>
3727   bool DataArrayDiscreteSigned<T>::isFittingWith(const std::vector<bool>& v) const
3728   {
3729     this->checkAllocated();
3730     if(this->getNumberOfComponents()!=1)
3731       throw INTERP_KERNEL::Exception("DataArrayInt::isFittingWith : number of components of this should be equal to one !");
3732     const T *w(this->begin()),*end2(this->end());
3733     T refVal=-std::numeric_limits<T>::max();
3734     int i=0;
3735     std::vector<bool>::const_iterator it(v.begin());
3736     for(;it!=v.end();it++,i++)
3737       {
3738         if(*it)
3739           {
3740             if(w!=end2)
3741               {
3742                 if(*w++==i)
3743                   {
3744                     if(i>refVal)
3745                       refVal=i;
3746                     else
3747                       {
3748                         std::ostringstream oss; oss << "DataArrayInt::isFittingWith : At pos #" << std::distance(this->begin(),w-1) << " this is not sorted ascendingly !";
3749                         throw INTERP_KERNEL::Exception(oss.str().c_str());
3750                       }
3751                   }
3752                 else
3753                   return false;
3754               }
3755             else
3756               return false;
3757           }
3758       }
3759     return w==end2;
3760   }
3761 }
3762
3763 #endif