Salome HOME
373e9201b1e7ca1975973ea5c66e4a720d19d31a
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingMemArray.txx
1 // Copyright (C) 2007-2020  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 #include "MEDCouplingMap.txx"
32
33 #include <sstream>
34 #include <cstdlib>
35 #include <numeric>
36 #include <algorithm>
37
38 namespace MEDCoupling
39 {
40   template<class T>
41   void MEDCouplingPointer<T>::setInternal(T *pointer)
42   {
43     _internal=pointer;
44     _external=0;
45   }
46
47   template<class T>
48   void MEDCouplingPointer<T>::setExternal(const T *pointer)
49   {
50     _external=pointer;
51     _internal=0;
52   }
53
54   template<class T>
55   MemArray<T>::MemArray(const MemArray<T>& other):_nb_of_elem(0),_nb_of_elem_alloc(0),_ownership(false),_dealloc(0),_param_for_deallocator(0)
56   {
57     if(!other._pointer.isNull())
58       {
59         _nb_of_elem_alloc=other._nb_of_elem;
60         T *pointer=(T*)malloc(_nb_of_elem_alloc*sizeof(T));
61         std::copy(other._pointer.getConstPointer(),other._pointer.getConstPointer()+other._nb_of_elem,pointer);
62         useArray(pointer,true,DeallocType::C_DEALLOC,other._nb_of_elem);
63       }
64   }
65
66   template<class T>
67   void MemArray<T>::useArray(const T *array, bool ownership, DeallocType type, std::size_t nbOfElem)
68   {
69     destroy();
70     _nb_of_elem=nbOfElem;
71     _nb_of_elem_alloc=nbOfElem;
72     if(ownership)
73       _pointer.setInternal(const_cast<T *>(array));
74     else
75       _pointer.setExternal(array);
76     _ownership=ownership;
77     _dealloc=BuildFromType(type);
78   }
79
80   template<class T>
81   void MemArray<T>::useExternalArrayWithRWAccess(const T *array, std::size_t nbOfElem)
82   {
83     destroy();
84     _nb_of_elem=nbOfElem;
85     _nb_of_elem_alloc=nbOfElem;
86     _pointer.setInternal(const_cast<T *>(array));
87     _ownership=false;
88     _dealloc=CPPDeallocator;
89   }
90
91   template<class T>
92   void MemArray<T>::writeOnPlace(std::size_t id, T element0, const T *others, std::size_t sizeOfOthers)
93   {
94     if(id+sizeOfOthers>=_nb_of_elem_alloc)
95       reserve(2*_nb_of_elem+sizeOfOthers+1);
96     T *pointer=_pointer.getPointer();
97     pointer[id]=element0;
98     std::copy(others,others+sizeOfOthers,pointer+id+1);
99     _nb_of_elem=std::max<std::size_t>(_nb_of_elem,id+sizeOfOthers+1);
100   }
101
102   template<class T>
103   void MemArray<T>::pushBack(T elem)
104   {
105     if(_nb_of_elem>=_nb_of_elem_alloc)
106       reserve(_nb_of_elem_alloc>0?2*_nb_of_elem_alloc:1);
107     T *pt=getPointer();
108     pt[_nb_of_elem++]=elem;
109   }
110
111   template<class T>
112   T MemArray<T>::popBack()
113   {
114     if(_nb_of_elem>0)
115       {
116         const T *pt=getConstPointer();
117         return pt[--_nb_of_elem];
118       }
119     throw INTERP_KERNEL::Exception("MemArray::popBack : nothing to pop in array !");
120   }
121
122   template<class T>
123   void MemArray<T>::pack() const
124   {
125     (const_cast<MemArray<T> * >(this))->reserve(_nb_of_elem);
126   }
127
128   template<class T>
129   bool MemArray<T>::isEqual(const MemArray<T>& other, T prec, std::string& reason) const
130   {
131     std::ostringstream oss; oss.precision(15);
132     if(_nb_of_elem!=other._nb_of_elem)
133       {
134         oss << "Number of elements in coarse data of DataArray mismatch : this=" << _nb_of_elem << " other=" << other._nb_of_elem;
135         reason=oss.str();
136         return false;
137       }
138     const T *pt1=_pointer.getConstPointer();
139     const T *pt2=other._pointer.getConstPointer();
140     if(pt1==0 && pt2==0)
141       return true;
142     if(pt1==0 || pt2==0)
143       {
144         oss << "coarse data pointer is defined for only one DataArray instance !";
145         reason=oss.str();
146         return false;
147       }
148     if(pt1==pt2)
149       return true;
150     for(std::size_t i=0;i<_nb_of_elem;i++)
151       if(pt1[i]-pt2[i]<-prec || (pt1[i]-pt2[i])>prec)
152         {
153           oss << "The content of data differs at pos #" << i << " of coarse data ! this[i]=" << pt1[i] << " other[i]=" << pt2[i];
154           reason=oss.str();
155           return false;
156         }
157     return true;
158   }
159
160   /*!
161    * \param [in] sl is typically the number of components
162    * \return True if a not null pointer is present, False if not.
163    */
164   template<class T>
165   bool MemArray<T>::reprHeader(mcIdType sl, std::ostream& stream) const
166   {
167     stream << "Number of tuples : ";
168     if(!_pointer.isNull())
169       {
170         if(sl!=0)
171           stream << _nb_of_elem/sl << std::endl << "Internal memory facts : " << _nb_of_elem << "/" << _nb_of_elem_alloc;
172         else
173           stream << "Empty Data";
174       }
175     else
176       stream << "No data";
177     stream << "\n";
178     stream << "Data content :\n";
179     bool ret=!_pointer.isNull();
180     if(!ret)
181       stream << "No data !\n";
182     return ret;
183   }
184
185   /*!
186    * \param [in] sl is typically the number of components
187    */
188   template<class T>
189   void MemArray<T>::repr(mcIdType sl, std::ostream& stream) const
190   {
191     if(reprHeader(sl,stream))
192       {
193         const T *data=getConstPointer();
194         if(_nb_of_elem!=0 && sl!=0)
195           {
196             std::size_t nbOfTuples=_nb_of_elem/std::abs(sl);
197             for(std::size_t i=0;i<nbOfTuples;i++)
198               {
199                 stream << "Tuple #" << i << " : ";
200                 std::copy(data,data+sl,std::ostream_iterator<T>(stream," "));
201                 stream << "\n";
202                 data+=sl;
203               }
204           }
205         else
206           stream << "Empty Data\n";
207       }
208   }
209
210   /*!
211    * \param [in] sl is typically the number of components
212    */
213   template<class T>
214   void MemArray<T>::reprZip(mcIdType sl, std::ostream& stream) const
215   {
216     stream << "Number of tuples : ";
217     if(!_pointer.isNull())
218       {
219         if(sl!=0)
220           stream << _nb_of_elem/sl;
221         else
222           stream << "Empty Data";
223       }
224     else
225       stream << "No data";
226     stream << "\n";
227     stream << "Data content : ";
228     const T *data=getConstPointer();
229     if(!_pointer.isNull())
230       {
231         if(_nb_of_elem!=0 && sl!=0)
232           {
233             std::size_t nbOfTuples=_nb_of_elem/std::abs(sl);
234             for(std::size_t i=0;i<nbOfTuples;i++)
235               {
236                 stream << "|";
237                 std::copy(data,data+sl,std::ostream_iterator<T>(stream," "));
238                 stream << "| ";
239                 data+=sl;
240               }
241             stream << "\n";
242           }
243         else
244           stream << "Empty Data\n";
245       }
246     else
247       stream << "No data !\n";
248   }
249
250   /*!
251    * \param [in] sl is typically the number of components
252    */
253   template<class T>
254   void MemArray<T>::reprNotTooLong(mcIdType sl, std::ostream& stream) const
255   {
256     if(reprHeader(sl,stream))
257       {
258         const T *data=getConstPointer();
259         if(_nb_of_elem!=0 && sl!=0)
260           {
261             std::size_t nbOfTuples=_nb_of_elem/std::abs(sl);
262             if(nbOfTuples<=1000)
263               {
264                 for(std::size_t i=0;i<nbOfTuples;i++)
265                   {
266                     stream << "Tuple #" << i << " : ";
267                     std::copy(data,data+sl,std::ostream_iterator<T>(stream," "));
268                     stream << "\n";
269                     data+=sl;
270                   }
271               }
272             else
273               {// too much tuples -> print the 3 first tuples and 3 last.
274                 stream << "Tuple #0 : ";
275                 std::copy(data,data+sl,std::ostream_iterator<T>(stream," ")); stream << "\n";
276                 stream << "Tuple #1 : ";
277                 std::copy(data+sl,data+2*sl,std::ostream_iterator<T>(stream," ")); stream << "\n";
278                 stream << "Tuple #2 : ";
279                 std::copy(data+2*sl,data+3*sl,std::ostream_iterator<T>(stream," ")); stream << "\n";
280                 stream << "...\n";
281                 stream << "Tuple #" << nbOfTuples-3 << " : ";
282                 std::copy(data+(nbOfTuples-3)*sl,data+(nbOfTuples-2)*sl,std::ostream_iterator<T>(stream," ")); stream << "\n";
283                 stream << "Tuple #" << nbOfTuples-2 << " : ";
284                 std::copy(data+(nbOfTuples-2)*sl,data+(nbOfTuples-1)*sl,std::ostream_iterator<T>(stream," ")); stream << "\n";
285                 stream << "Tuple #" << nbOfTuples-1 << " : ";
286                 std::copy(data+(nbOfTuples-1)*sl,data+nbOfTuples*sl,std::ostream_iterator<T>(stream," ")); stream << "\n";
287               }
288           }
289         else
290           stream << "Empty Data\n";
291       }
292   }
293
294   template<class T>
295   void MemArray<T>::fillWithValue(const T& val)
296   {
297     T *pt=_pointer.getPointer();
298     std::fill(pt,pt+_nb_of_elem,val);
299   }
300
301   template<class T>
302   T *MemArray<T>::fromNoInterlace(std::size_t nbOfComp) const
303   {
304     if(nbOfComp<1)
305       throw INTERP_KERNEL::Exception("MemArray<T>::fromNoInterlace : number of components must be > 0 !");
306     const T *pt=_pointer.getConstPointer();
307     std::size_t nbOfTuples=_nb_of_elem/nbOfComp;
308     T *ret=(T*)malloc(_nb_of_elem*sizeof(T));
309     T *w=ret;
310     for(std::size_t i=0;i<nbOfTuples;i++)
311       for(std::size_t j=0;j<nbOfComp;j++,w++)
312         *w=pt[j*nbOfTuples+i];
313     return ret;
314   }
315
316   template<class T>
317   T *MemArray<T>::toNoInterlace(std::size_t nbOfComp) const
318   {
319     if(nbOfComp<1)
320       throw INTERP_KERNEL::Exception("MemArray<T>::toNoInterlace : number of components must be > 0 !");
321     const T *pt=_pointer.getConstPointer();
322     std::size_t nbOfTuples=_nb_of_elem/nbOfComp;
323     T *ret=(T*)malloc(_nb_of_elem*sizeof(T));
324     T *w=ret;
325     for(std::size_t i=0;i<nbOfComp;i++)
326       for(std::size_t j=0;j<nbOfTuples;j++,w++)
327         *w=pt[j*nbOfComp+i];
328     return ret;
329   }
330
331   template<class T>
332   void MemArray<T>::sort(bool asc)
333   {
334     T *pt=_pointer.getPointer();
335     if(asc)
336       std::sort(pt,pt+_nb_of_elem);
337     else
338       {
339         typename std::reverse_iterator<T *> it1(pt+_nb_of_elem);
340         typename std::reverse_iterator<T *> it2(pt);
341         std::sort(it1,it2);
342       }
343   }
344
345   template<class T>
346   void MemArray<T>::reverse(std::size_t nbOfComp)
347   {
348     if(nbOfComp<1)
349       throw INTERP_KERNEL::Exception("MemArray<T>::reverse : only supported with 'this' array with ONE or more than ONE component !");
350     T *pt=_pointer.getPointer();
351     if(nbOfComp==1)
352       {
353         std::reverse(pt,pt+_nb_of_elem);
354         return ;
355       }
356     else
357       {
358         T *pt2=pt+_nb_of_elem-nbOfComp;
359         std::size_t nbOfTuples=_nb_of_elem/nbOfComp;
360         for(std::size_t i=0;i<nbOfTuples/2;i++,pt+=nbOfComp,pt2-=nbOfComp)
361           {
362             for(std::size_t j=0;j<nbOfComp;j++)
363               std::swap(pt[j],pt2[j]);
364           }
365       }
366   }
367
368   template<class T>
369   void MemArray<T>::alloc(std::size_t nbOfElements)
370   {
371     destroy();
372     _nb_of_elem=nbOfElements;
373     _nb_of_elem_alloc=nbOfElements;
374     _pointer.setInternal((T*)malloc(_nb_of_elem_alloc*sizeof(T)));
375     _ownership=true;
376     _dealloc=CDeallocator;
377   }
378
379   /*!
380    * This method performs systematically an allocation of \a newNbOfElements elements in \a this.
381    * \a _nb_of_elem and \a _nb_of_elem_alloc will \b NOT be systematically equal (contrary to MemArray<T>::reAlloc method.
382    * 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 
383    * \a newNbOfElements. This method is typically used to perform a pushBack to avoid systematic allocations-copy-deallocation.
384    * So after the call of this method the accessible content is perfectly set.
385    * 
386    * So this method should not be confused with MemArray<T>::reserve that is close to MemArray<T>::reAlloc but not same.
387    */
388   template<class T>
389   void MemArray<T>::reserve(std::size_t newNbOfElements)
390   {
391     if(_nb_of_elem_alloc==newNbOfElements)
392       return ;
393     T *pointer=(T*)malloc(newNbOfElements*sizeof(T));
394     std::copy(_pointer.getConstPointer(),_pointer.getConstPointer()+std::min<std::size_t>(_nb_of_elem,newNbOfElements),pointer);
395     if(_ownership)
396       DestroyPointer(const_cast<T *>(_pointer.getConstPointer()),_dealloc,_param_for_deallocator);//Do not use getPointer because in case of _external
397     _pointer.setInternal(pointer);
398     _nb_of_elem=std::min<std::size_t>(_nb_of_elem,newNbOfElements);
399     _nb_of_elem_alloc=newNbOfElements;
400     _ownership=true;
401     _dealloc=CDeallocator;
402     _param_for_deallocator=0;
403   }
404
405   /*!
406    * This method performs systematically an allocation of \a newNbOfElements elements in \a this.
407    * \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 .
408    * The remaining part of the new allocated chunk are available but not set previously !
409    * 
410    * So this method should not be confused with MemArray<T>::reserve that is close to MemArray<T>::reAlloc but not same.
411    */
412   template<class T>
413   void MemArray<T>::reAlloc(std::size_t newNbOfElements)
414   {
415     if(_nb_of_elem==newNbOfElements)
416       return ;
417     T *pointer=(T*)malloc(newNbOfElements*sizeof(T));
418     std::copy(_pointer.getConstPointer(),_pointer.getConstPointer()+std::min<std::size_t>(_nb_of_elem,newNbOfElements),pointer);
419     if(_ownership)
420       DestroyPointer(const_cast<T *>(_pointer.getConstPointer()),_dealloc,_param_for_deallocator);//Do not use getPointer because in case of _external
421     _pointer.setInternal(pointer);
422     _nb_of_elem=newNbOfElements;
423     _nb_of_elem_alloc=newNbOfElements;
424     _ownership=true;
425     _dealloc=CDeallocator;
426     _param_for_deallocator=0;
427   }
428
429   template<class T>
430   void MemArray<T>::CPPDeallocator(void *pt, void *param)
431   {
432     delete [] reinterpret_cast<T*>(pt);
433   }
434
435   template<class T>
436   void MemArray<T>::CDeallocator(void *pt, void *param)
437   {
438     free(pt);
439   }
440
441   template<class T>
442   void MemArray<T>::COffsetDeallocator(void *pt, void *param)
443   {
444     int64_t *offset(reinterpret_cast<int64_t *>(param));
445     char *ptcast(reinterpret_cast<char *>(pt));
446     free(ptcast+*offset);
447   }
448
449   template<class T>
450   typename MemArray<T>::Deallocator MemArray<T>::BuildFromType(DeallocType type)
451   {
452     switch(type)
453     {
454       case DeallocType::CPP_DEALLOC:
455         return CPPDeallocator;
456       case DeallocType::C_DEALLOC:
457         return CDeallocator;
458       case DeallocType::C_DEALLOC_WITH_OFFSET:
459         return COffsetDeallocator;
460       default:
461         throw INTERP_KERNEL::Exception("Invalid deallocation requested ! Unrecognized enum DeallocType !");
462     }
463   }
464
465   template<class T>
466   void MemArray<T>::DestroyPointer(T *pt, typename MemArray<T>::Deallocator dealloc, void *param)
467   {
468     if(dealloc)
469       dealloc(pt,param);
470   }
471
472   template<class T>
473   void MemArray<T>::destroy()
474   {
475     if(_ownership)
476       DestroyPointer(const_cast<T *>(_pointer.getConstPointer()),_dealloc,_param_for_deallocator);//Do not use getPointer because in case of _external
477     _pointer.null();
478     _ownership=false;
479     _dealloc=NULL;
480     _param_for_deallocator=NULL;
481     _nb_of_elem=0;
482     _nb_of_elem_alloc=0;
483   }
484
485   template<class T>
486   MemArray<T> &MemArray<T>::operator=(const MemArray<T>& other)
487   {
488     alloc(other._nb_of_elem);
489     std::copy(other._pointer.getConstPointer(),other._pointer.getConstPointer()+_nb_of_elem,_pointer.getPointer());
490     return *this;
491   }
492
493   //////////////////////////////////
494
495   template<class T>
496   DataArrayIterator<T>::DataArrayIterator(typename Traits<T>::ArrayType *da):_da(da),_tuple_id(0),_nb_comp(0),_nb_tuple(0)
497   {
498     if(_da)
499       {
500         _da->incrRef();
501         if(_da->isAllocated())
502           {
503             _nb_comp=da->getNumberOfComponents();
504             _nb_tuple=da->getNumberOfTuples();
505             _pt=da->getPointer();
506           }
507       }
508   }
509   
510   template<class T>
511   DataArrayIterator<T>::~DataArrayIterator()
512   {
513     if(_da)
514       _da->decrRef();
515   }
516
517   template<class T>
518   typename Traits<T>::ArrayTuple *DataArrayIterator<T>::nextt()
519   {
520     if(_tuple_id<_nb_tuple)
521       {
522         _tuple_id++;
523         typename Traits<T>::ArrayTuple *ret=new typename Traits<T>::ArrayTuple(_pt,_nb_comp);
524         _pt+=_nb_comp;
525         return ret;
526       }
527     else
528       return 0;
529   }
530
531   //////////////////////////////////
532
533   template<class T>
534   DataArrayTuple<T>::DataArrayTuple(T *pt, std::size_t nbOfComp):_pt(pt),_nb_of_compo(nbOfComp)
535   {
536   }
537   
538   template<class T>
539   T DataArrayTuple<T>::zeValue() const
540   {
541     if(_nb_of_compo==1)
542       return *_pt;
543     throw INTERP_KERNEL::Exception("DataArrayTuple<T>::zeValue : DataArrayTuple instance has not exactly 1 component -> Not possible to convert it into a single value !");
544   }
545   
546   template<class T>
547   typename Traits<T>::ArrayType *DataArrayTuple<T>::buildDA(std::size_t nbOfTuples, std::size_t nbOfCompo) const
548   {
549     if((_nb_of_compo==nbOfCompo && nbOfTuples==1) || (_nb_of_compo==nbOfTuples && nbOfCompo==1))
550     {
551       typename Traits<T>::ArrayType *ret=Traits<T>::ArrayType::New();
552       ret->useExternalArrayWithRWAccess(_pt,nbOfTuples,nbOfCompo);
553       return ret;
554     }
555   else
556     {
557       std::ostringstream oss; oss << "DataArrayTuple<T>::buildDA : unable to build a requested DataArrayDouble instance with nbofTuple=" << nbOfTuples << " and nbOfCompo=" << nbOfCompo;
558       oss << ".\nBecause the number of elements in this is " << _nb_of_compo << " !";
559       throw INTERP_KERNEL::Exception(oss.str().c_str());
560     }
561   }
562   
563   //////////////////////////////////
564
565   /*!
566    * This method is useful to slice work among a pool of threads or processes. \a begin, \a end \a step is the input whole slice of work to perform,
567    * typically it is a whole slice of tuples of DataArray or cells, nodes of a mesh...
568    *
569    * The input \a sliceId should be an id in [0, \a nbOfSlices) that specifies the slice of work.
570    *
571    * \param [in] start - the start of the input slice of the whole work to perform split into slices.
572    * \param [in] stop - the stop of the input slice of the whole work to perform split into slices.
573    * \param [in] step - the step (that can be <0) of the input slice of the whole work to perform split into slices.
574    * \param [in] sliceId - the slice id considered
575    * \param [in] nbOfSlices - the number of slices (typically the number of cores on which the work is expected to be sliced)
576    * \param [out] startSlice - the start of the slice considered
577    * \param [out] stopSlice - the stop of the slice consided
578    *
579    * \throw If \a step == 0
580    * \throw If \a nbOfSlices not > 0
581    * \throw If \a sliceId not in [0,nbOfSlices)
582    */
583   template <class T>
584   void DataArrayTools<T>::GetSlice(T start, T stop, T step, mcIdType sliceId, mcIdType nbOfSlices, T& startSlice, T& stopSlice)
585   {
586     if(nbOfSlices<=0)
587       {
588         std::ostringstream oss; oss << "DataArray::GetSlice : nbOfSlices (" << nbOfSlices << ") must be > 0 !";
589         throw INTERP_KERNEL::Exception(oss.str().c_str());
590       }
591     if(sliceId<0 || sliceId>=nbOfSlices)
592       {
593         std::ostringstream oss; oss << "DataArray::GetSlice : sliceId (" << nbOfSlices << ") must be in [0 , nbOfSlices (" << nbOfSlices << ") ) !";
594         throw INTERP_KERNEL::Exception(oss.str().c_str());
595       }
596     mcIdType nbElems=DataArrayTemplate<T>::GetNumberOfItemGivenBESRelative(start,stop,step,"DataArray::GetSlice");
597     mcIdType minNbOfElemsPerSlice=nbElems/nbOfSlices;
598     startSlice=start+minNbOfElemsPerSlice*step*sliceId;
599     if(sliceId<nbOfSlices-1)
600       stopSlice=start+minNbOfElemsPerSlice*step*(sliceId+1);
601     else
602       stopSlice=stop;
603   }
604
605   template <class T>
606   mcIdType DataArrayTools<T>::GetNumberOfItemGivenBES(T begin, T end, T step, const std::string& msg)
607   {
608     if(end<begin)
609       {
610         std::ostringstream oss; oss << msg << " : end before begin !";
611         throw INTERP_KERNEL::Exception(oss.str().c_str());
612       }
613     if(end==begin)
614       return 0;
615     if(step<=0)
616       {
617         std::ostringstream oss; oss << msg << " : invalid step should be > 0 !";
618         throw INTERP_KERNEL::Exception(oss.str().c_str());
619       }
620     return ToIdType((end-1-begin)/step+1);
621   }
622
623   template <class T>
624   mcIdType DataArrayTools<T>::GetNumberOfItemGivenBESRelative(T begin, T end, T step, const std::string& msg)
625   {
626     if(step==0)
627       throw INTERP_KERNEL::Exception("DataArray::GetNumberOfItemGivenBES : step=0 is not allowed !");
628     if(end<begin && step>0)
629       {
630         std::ostringstream oss; oss << msg << " : end before begin whereas step is positive !";
631         throw INTERP_KERNEL::Exception(oss.str().c_str());
632       }
633     if(begin<end && step<0)
634       {
635         std::ostringstream oss; oss << msg << " : invalid step should be > 0 !";
636         throw INTERP_KERNEL::Exception(oss.str().c_str());
637       }
638     if(begin!=end)
639       return ToIdType((std::max(begin,end)-1-std::min(begin,end))/std::abs(step)+1);
640     else
641       return 0;
642   }
643
644   template <class T>
645   mcIdType DataArrayTools<T>::GetPosOfItemGivenBESRelativeNoThrow(T value, T begin, T end, T step)
646   {
647     if (step == 0)
648       return -1;
649
650     if((step>0 && begin<=value && value<end) ||
651        (step<0 && begin>=value && value>end))
652     {
653       mcIdType id = ToIdType((value-begin)/step);
654       if (begin + step * id == value)
655         return id;
656       else
657         return -1;
658     }
659     else
660       return -1;
661   }
662
663   //////////////////////////////////
664
665   template<class T>
666   MCAuto< typename Traits<T>::ArrayTypeCh > DataArrayTemplate<T>::NewFromStdVector(const typename std::vector<T>& v)
667   {
668     std::size_t sz(v.size());
669     MCAuto< typename Traits<T>::ArrayTypeCh > ret(Traits<T>::ArrayTypeCh::New());
670     ret->alloc(sz,1);
671     T *pt(ret->getPointer());
672     std::copy(v.begin(),v.end(),pt);
673     return ret;
674   }
675   
676   template<class T>
677   std::vector< MCAuto< typename Traits<T>::ArrayTypeCh > > DataArrayTemplate<T>::explodeComponents() const
678   {
679     checkAllocated();
680     std::size_t sz(getNumberOfComponents());
681     mcIdType nbTuples(getNumberOfTuples());
682     std::string name(getName());
683     std::vector<std::string> compNames(getInfoOnComponents());
684     std::vector< MCAuto< typename Traits<T>::ArrayTypeCh > > ret(sz);
685     const T *thisPt(begin());
686     for(std::size_t i=0;i<sz;i++)
687       {
688         MCAuto< typename Traits<T>::ArrayTypeCh > part(Traits<T>::ArrayTypeCh::New());
689         part->alloc(nbTuples,1);
690         part->setName(name);
691         part->setInfoOnComponent(0,compNames[i]);
692         T *otherPt(part->getPointer());
693         for(mcIdType j=0;j<nbTuples;j++)
694           otherPt[j]=thisPt[sz*j+i];
695         ret[i]=part;
696       }
697     return ret;
698   }
699   
700   template<class T>
701   std::size_t DataArrayTemplate<T>::getHeapMemorySizeWithoutChildren() const
702   {
703     std::size_t sz(_mem.getNbOfElemAllocated());
704     sz*=sizeof(T);
705     return DataArray::getHeapMemorySizeWithoutChildren()+sz;
706   }
707   
708   /*!
709    * Allocates the raw data in memory. If the memory was already allocated, then it is
710    * freed and re-allocated. See an example of this method use
711    * \ref MEDCouplingArraySteps1WC "here".
712    *  \param [in] nbOfTuple - number of tuples of data to allocate.
713    *  \param [in] nbOfCompo - number of components of data to allocate.
714    *  \throw If \a nbOfTuple < 0 or \a nbOfCompo < 0.
715    */
716   template<class T>
717   void DataArrayTemplate<T>::alloc(std::size_t nbOfTuple, std::size_t nbOfCompo)
718   {
719     _info_on_compo.resize(nbOfCompo);
720     _mem.alloc(nbOfCompo*nbOfTuple);
721     declareAsNew();
722   }
723
724   /*!
725    * Sets a C array to be used as raw data of \a this. The previously set info
726    *  of components is retained and re-sized. 
727    * For more info see \ref MEDCouplingArraySteps1.
728    *  \param [in] array - the C array to be used as raw data of \a this.
729    *  \param [in] ownership - if \a true, \a array will be deallocated at destruction of \a this.
730    *  \param [in] type - specifies how to deallocate \a array. If \a type == MEDCoupling::CPP_DEALLOC,
731    *                     \c delete [] \c array; will be called. If \a type == MEDCoupling::C_DEALLOC,
732    *                     \c free(\c array ) will be called.
733    *  \param [in] nbOfTuple - new number of tuples in \a this.
734    *  \param [in] nbOfCompo - new number of components in \a this.
735    */
736   template<class T>
737   void DataArrayTemplate<T>::useArray(const T *array, bool ownership, DeallocType type, std::size_t nbOfTuple, std::size_t nbOfCompo)
738   {
739     _info_on_compo.resize(nbOfCompo);
740     _mem.useArray(array,ownership,type,nbOfTuple*nbOfCompo);
741     declareAsNew();
742   }
743   
744   template<class T>
745   void DataArrayTemplate<T>::useExternalArrayWithRWAccess(const T *array, std::size_t nbOfTuple, std::size_t nbOfCompo)
746   {
747     _info_on_compo.resize(nbOfCompo);
748     _mem.useExternalArrayWithRWAccess(array,nbOfTuple*nbOfCompo);
749     declareAsNew();
750   }
751
752   /*!
753    * Returns a value located at specified tuple and component.
754    * This method is equivalent to DataArrayTemplate<T>::getIJ() except that validity of
755    * parameters is checked. So this method is safe but expensive if used to go through
756    * all values of \a this.
757    *  \param [in] tupleId - index of tuple of interest.
758    *  \param [in] compoId - index of component of interest.
759    *  \return double - value located by \a tupleId and \a compoId.
760    *  \throw If \a this is not allocated.
761    *  \throw If condition <em>( 0 <= tupleId < this->getNumberOfTuples() )</em> is violated.
762    *  \throw If condition <em>( 0 <= compoId < this->getNumberOfComponents() )</em> is violated.
763    */
764   template<class T>
765   T DataArrayTemplate<T>::getIJSafe(std::size_t tupleId, std::size_t compoId) const
766   {
767     checkAllocated();
768     if(ToIdType(tupleId)>=getNumberOfTuples())
769       {
770         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::getIJSafe : request for tupleId " << tupleId << " should be in [0," << getNumberOfTuples() << ") !";
771         throw INTERP_KERNEL::Exception(oss.str().c_str());
772       }
773     if(compoId>=getNumberOfComponents())
774       {
775         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::getIJSafe : request for compoId " << compoId << " should be in [0," << getNumberOfComponents() << ") !";
776         throw INTERP_KERNEL::Exception(oss.str().c_str());
777       }
778     return _mem[tupleId*_info_on_compo.size()+compoId];
779   }
780
781   /*!
782    * 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.
783    *
784    * \sa DataArray::getHeapMemorySizeWithoutChildren, DataArrayTemplate<T>::reserve
785    */
786   template<class T>
787   void DataArrayTemplate<T>::pack() const
788   {
789     _mem.pack();
790   }
791
792   /*!
793    * Checks if raw data is allocated. Read more on the raw data
794    * in \ref MEDCouplingArrayBasicsTuplesAndCompo "DataArrays infos" for more information.
795    *  \return bool - \a true if the raw data is allocated, \a false else.
796    */
797   template<class T>
798   bool DataArrayTemplate<T>::isAllocated() const
799   {
800     return getConstPointer()!=0;
801   }
802   
803   /*!
804    * Checks if raw data is allocated and throws an exception if it is not the case.
805    *  \throw If the raw data is not allocated.
806    */
807   template<class T>
808   void DataArrayTemplate<T>::checkAllocated() const
809   {
810     if(!isAllocated())
811       {
812         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::checkAllocated : Array is defined but not allocated ! Call alloc or setValues method first !";
813         throw INTERP_KERNEL::Exception(oss.str().c_str());
814       }
815   }
816   
817   /*!
818    * This method deallocated \a this without modification of information relative to the components.
819    * After call of this method, DataArrayDouble::isAllocated will return false.
820    * If \a this is already not allocated, \a this is let unchanged.
821    */
822   template<class T>
823   void DataArrayTemplate<T>::desallocate()
824   {
825     _mem.destroy();
826   }
827
828   /*!
829    * This method reserve nbOfElems elements in memory ( nbOfElems*8 bytes ) \b without impacting the number of tuples in \a this.
830    * 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.
831    * If \a this has not already been allocated, number of components is set to one.
832    * This method allows to reduce number of reallocations on invocation of DataArrayDouble::pushBackSilent and DataArrayDouble::pushBackValsSilent on \a this.
833    * 
834    * \sa DataArrayDouble::pack, DataArrayDouble::pushBackSilent, DataArrayDouble::pushBackValsSilent
835    */
836   template<class T>
837   void DataArrayTemplate<T>::reserve(std::size_t nbOfElems)
838   {
839     std::size_t nbCompo(getNumberOfComponents());
840     if(nbCompo==1)
841       {
842         _mem.reserve(nbOfElems);
843       }
844     else if(nbCompo==0)
845       {
846         _mem.reserve(nbOfElems);
847         _info_on_compo.resize(1);
848       }
849     else
850       {
851         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::reserve : not available for DataArrayDouble with number of components different than 1 !";
852         throw INTERP_KERNEL::Exception(oss.str().c_str());
853       }
854   }
855   
856   /*!
857    * 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
858    * of counter. So the caller is expected to call TimeLabel::declareAsNew on \a this at the end of the push session.
859    *
860    * \param [in] val the value to be added in \a this
861    * \throw If \a this has already been allocated with number of components different from one.
862    * \sa DataArrayDouble::pushBackValsSilent
863    */
864   template<class T>
865   void DataArrayTemplate<T>::pushBackSilent(T val)
866   {
867     std::size_t nbCompo(getNumberOfComponents());
868     if(nbCompo==1)
869       _mem.pushBack(val);
870     else if(nbCompo==0)
871       {
872         _info_on_compo.resize(1);
873         _mem.pushBack(val);
874       }
875     else
876       {
877         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::pushBackSilent : not available for DataArrayDouble with number of components different than 1 !";
878         throw INTERP_KERNEL::Exception(oss.str().c_str());
879       }
880   }
881   
882   /*!
883    * This method adds at the end of \a this a series of values [\c valsBg,\c valsEnd). This method do \b not update its time label to avoid useless incrementation
884    * of counter. So the caller is expected to call TimeLabel::declareAsNew on \a this at the end of the push session.
885    *
886    *  \param [in] valsBg - an array of values to push at the end of \c this.
887    *  \param [in] valsEnd - specifies the end of the array \a valsBg, so that
888    *              the last value of \a valsBg is \a valsEnd[ -1 ].
889    * \throw If \a this has already been allocated with number of components different from one.
890    * \sa DataArrayDouble::pushBackSilent
891    */
892   template<class T>
893   void DataArrayTemplate<T>::pushBackValsSilent(const T *valsBg, const T *valsEnd)
894   {
895     std::size_t nbCompo(getNumberOfComponents());
896     if(nbCompo==1)
897       _mem.insertAtTheEnd(valsBg,valsEnd);
898     else if(nbCompo==0)
899       {
900         _info_on_compo.resize(1);
901         _mem.insertAtTheEnd(valsBg,valsEnd);
902       }
903     else
904       {
905         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::pushBackValsSilent : not available for DataArrayDouble with number of components different than 1 !";
906         throw INTERP_KERNEL::Exception(oss.str().c_str());
907       }
908   }
909   
910   /*!
911    * This method returns silently ( without updating time label in \a this ) the last value, if any and suppress it.
912    * \throw If \a this is already empty.
913    * \throw If \a this has number of components different from one.
914    */
915   template<class T>
916   T DataArrayTemplate<T>::popBackSilent()
917   {
918     if(getNumberOfComponents()==1)
919       return _mem.popBack();
920     else
921       {
922         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::popBackSilent : not available for DataArrayDouble with number of components different than 1 !";
923         throw INTERP_KERNEL::Exception(oss.str().c_str());
924       }
925   }
926   
927   /*!
928    * Allocates the raw data in memory. If exactly same memory as needed already
929    * allocated, it is not re-allocated.
930    *  \param [in] nbOfTuple - number of tuples of data to allocate.
931    *  \param [in] nbOfCompo - number of components of data to allocate.
932    *  \throw If \a nbOfTuple < 0 or \a nbOfCompo < 0.
933    */
934   template<class T>
935   void DataArrayTemplate<T>::allocIfNecessary(std::size_t nbOfTuple, std::size_t nbOfCompo)
936   {
937     if(isAllocated())
938       {
939         if(ToIdType(nbOfTuple)!=getNumberOfTuples() || nbOfCompo!=getNumberOfComponents())
940           alloc(nbOfTuple,nbOfCompo);
941       }
942     else
943       alloc(nbOfTuple,nbOfCompo);
944   }
945
946   /*!
947    * Checks the number of tuples.
948    *  \return bool - \a true if getNumberOfTuples() == 0, \a false else.
949    *  \throw If \a this is not allocated.
950    */
951   template<class T>
952   bool DataArrayTemplate<T>::empty() const
953   {
954     checkAllocated();
955     return getNumberOfTuples()==0;
956   }
957
958   /*!
959    * Copies all the data from another DataArrayDouble. For more info see
960    * \ref MEDCouplingArrayBasicsCopyDeepAssign.
961    *  \param [in] other - another instance of DataArrayDouble to copy data from.
962    *  \throw If the \a other is not allocated.
963    */
964   template<class T>
965   void DataArrayTemplate<T>::deepCopyFrom(const DataArrayTemplate<T>& other)
966   {
967     other.checkAllocated();
968     mcIdType nbOfTuples(other.getNumberOfTuples());
969     std::size_t nbOfComp(other.getNumberOfComponents());
970     allocIfNecessary(nbOfTuples,nbOfComp);
971     std::size_t nbOfElems(nbOfTuples*nbOfComp);
972     T *pt(getPointer());
973     const T *ptI(other.begin());
974     for(std::size_t i=0;i<nbOfElems;i++)
975       pt[i]=ptI[i];
976     copyStringInfoFrom(other);
977   }
978
979   /*!
980    * Reverse the array values.
981    *  \throw If \a this->getNumberOfComponents() < 1.
982    *  \throw If \a this is not allocated.
983    */
984   template<class T>
985   void DataArrayTemplate<T>::reverse()
986   {
987     checkAllocated();
988     _mem.reverse(getNumberOfComponents());
989     declareAsNew();
990   }
991
992   /*!
993    * Assign \a val to all values in \a this array. To know more on filling arrays see
994    * \ref MEDCouplingArrayFill.
995    *  \param [in] val - the value to fill with.
996    *  \throw If \a this is not allocated.
997    */
998   template<class T>
999   void DataArrayTemplate<T>::fillWithValue(T val)
1000   {
1001     checkAllocated();
1002     _mem.fillWithValue(val);
1003     declareAsNew();
1004   }
1005
1006   /*!
1007    * Changes number of tuples in the array. If the new number of tuples is smaller
1008    * than the current number the array is truncated, otherwise the array is extended.
1009    *  \param [in] nbOfTuples - new number of tuples. 
1010    *  \throw If \a this is not allocated.
1011    *  \throw If \a nbOfTuples is negative.
1012    */
1013   template<class T>
1014   void DataArrayTemplate<T>::reAlloc(std::size_t nbOfTuples)
1015   {
1016     checkAllocated();
1017     _mem.reAlloc(getNumberOfComponents()*nbOfTuples);
1018     declareAsNew();
1019   }
1020
1021   /*!
1022    * Permutes values of \a this array as required by \a old2New array. The values are
1023    * permuted so that \c new[ \a old2New[ i ]] = \c old[ i ]. Number of tuples remains
1024    * the same as in \c this one.
1025    * If a permutation reduction is needed, subArray() or selectByTupleId() should be used.
1026    * For more info on renumbering see \ref numbering.
1027    *  \param [in] old2New - C array of length equal to \a this->getNumberOfTuples()
1028    *     giving a new position for i-th old value.
1029    */
1030   template<class T>
1031   void DataArrayTemplate<T>::renumberInPlace(const mcIdType *old2New)
1032   {
1033     checkAllocated();
1034     mcIdType nbTuples(getNumberOfTuples());
1035     std::size_t nbOfCompo(getNumberOfComponents());
1036     T *tmp(new T[nbTuples*nbOfCompo]);
1037     const T *iptr(begin());
1038     for(mcIdType i=0;i<nbTuples;i++)
1039       {
1040         mcIdType v=old2New[i];
1041         if(v>=0 && v<nbTuples)
1042           std::copy(iptr+nbOfCompo*i,iptr+nbOfCompo*(i+1),tmp+nbOfCompo*v);
1043         else
1044           {
1045             std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::renumberInPlace : At place #" << i << " value is " << v << " ! Should be in [0," << nbTuples << ") !";
1046             throw INTERP_KERNEL::Exception(oss.str().c_str());
1047           }
1048       }
1049     std::copy(tmp,tmp+nbTuples*nbOfCompo,getPointer());
1050     delete [] tmp;
1051     declareAsNew();
1052   }
1053
1054
1055   /*!
1056    * Permutes values of \a this array as required by \a new2Old array. The values are
1057    * permuted so that \c new[ i ] = \c old[ \a new2Old[ i ]]. Number of tuples remains
1058    * the same as in \c this one.
1059    * For more info on renumbering see \ref numbering.
1060    *  \param [in] new2Old - C array of length equal to \a this->getNumberOfTuples()
1061    *     giving a previous position of i-th new value.
1062    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1063    *          is to delete using decrRef() as it is no more needed.
1064    */
1065   template<class T>
1066   void DataArrayTemplate<T>::renumberInPlaceR(const mcIdType *new2Old)
1067   {
1068     checkAllocated();
1069     mcIdType nbTuples(getNumberOfTuples());
1070     std::size_t nbOfCompo(getNumberOfComponents());
1071     T *tmp(new T[nbTuples*nbOfCompo]);
1072     const T *iptr(begin());
1073     for(mcIdType i=0;i<nbTuples;i++)
1074       {
1075         mcIdType v=new2Old[i];
1076         if(v>=0 && v<nbTuples)
1077           std::copy(iptr+nbOfCompo*v,iptr+nbOfCompo*(v+1),tmp+nbOfCompo*i);
1078         else
1079           {
1080             std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::renumberInPlaceR : At place #" << i << " value is " << v << " ! Should be in [0," << nbTuples << ") !";
1081             throw INTERP_KERNEL::Exception(oss.str().c_str());
1082           }
1083       }
1084     std::copy(tmp,tmp+nbTuples*nbOfCompo,getPointer());
1085     delete [] tmp;
1086     declareAsNew();
1087   }
1088
1089   /*!
1090    * Sorts values of the array.
1091    *  \param [in] asc - \a true means ascending order, \a false, descending.
1092    *  \throw If \a this is not allocated.
1093    *  \throw If \a this->getNumberOfComponents() != 1.
1094    */
1095   template<class T>
1096   void DataArrayTemplate<T>::sort(bool asc)
1097   {
1098     checkAllocated();
1099     if(getNumberOfComponents()!=1)
1100       {
1101         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::sort : only supported with 'this' array with ONE component !";
1102         throw INTERP_KERNEL::Exception(oss.str().c_str());
1103       }
1104     _mem.sort(asc);
1105     declareAsNew();
1106   }
1107
1108   /*!
1109    * Returns a copy of \a this array with values permuted as required by \a old2New array.
1110    * The values are permuted so that  \c new[ \a old2New[ i ]] = \c old[ i ].
1111    * Number of tuples in the result array remains the same as in \c this one.
1112    * If a permutation reduction is needed, renumberAndReduce() should be used.
1113    * For more info on renumbering see \ref numbering.
1114    *  \param [in] old2New - C array of length equal to \a this->getNumberOfTuples()
1115    *          giving a new position for i-th old value.
1116    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1117    *          is to delete using decrRef() as it is no more needed.
1118    *  \throw If \a this is not allocated.
1119    */
1120   template<class T>
1121   typename Traits<T>::ArrayType *DataArrayTemplate<T>::renumber(const mcIdType *old2New) const
1122   {
1123     checkAllocated();
1124     mcIdType nbTuples(getNumberOfTuples());
1125     std::size_t nbOfCompo(getNumberOfComponents());
1126     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1127     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1128     ret->alloc(nbTuples,nbOfCompo);
1129     ret->copyStringInfoFrom(*this);
1130     const T *iptr(begin());
1131     T *optr(ret->getPointer());
1132     for(mcIdType i=0;i<nbTuples;i++)
1133       std::copy(iptr+nbOfCompo*i,iptr+nbOfCompo*(i+1),optr+nbOfCompo*old2New[i]);
1134     ret->copyStringInfoFrom(*this);
1135     return ret.retn();
1136   }
1137
1138   /*!
1139    * Returns a copy of \a this array with values permuted as required by \a new2Old array.
1140    * The values are permuted so that  \c new[ i ] = \c old[ \a new2Old[ i ]]. Number of
1141    * tuples in the result array remains the same as in \c this one.
1142    * If a permutation reduction is needed, subArray() or selectByTupleId() should be used.
1143    * For more info on renumbering see \ref numbering.
1144    *  \param [in] new2Old - C array of length equal to \a this->getNumberOfTuples()
1145    *     giving a previous position of i-th new value.
1146    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1147    *          is to delete using decrRef() as it is no more needed.
1148    */
1149   template<class T>
1150   typename Traits<T>::ArrayType *DataArrayTemplate<T>::renumberR(const mcIdType *new2Old) const
1151   {
1152     checkAllocated();
1153     mcIdType nbTuples(getNumberOfTuples());
1154     std::size_t nbOfCompo(getNumberOfComponents());
1155     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1156     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1157     ret->alloc(nbTuples,nbOfCompo);
1158     ret->copyStringInfoFrom(*this);
1159     const T *iptr(getConstPointer());
1160     T *optr(ret->getPointer());
1161     for(mcIdType i=0;i<nbTuples;i++)
1162       std::copy(iptr+nbOfCompo*new2Old[i],iptr+nbOfCompo*(new2Old[i]+1),optr+i*nbOfCompo);
1163     ret->copyStringInfoFrom(*this);
1164     return ret.retn();
1165   }
1166
1167   /*!
1168    * Returns a shorten and permuted copy of \a this array. The new DataArrayDouble is
1169    * of size \a newNbOfTuple and it's values are permuted as required by \a old2New array.
1170    * The values are permuted so that  \c new[ \a old2New[ i ]] = \c old[ i ] for all
1171    * \a old2New[ i ] >= 0. In other words every i-th tuple in \a this array, for which 
1172    * \a old2New[ i ] is negative, is missing from the result array.
1173    * For more info on renumbering see \ref numbering.
1174    *  \param [in] old2New - C array of length equal to \a this->getNumberOfTuples()
1175    *     giving a new position for i-th old tuple and giving negative position for
1176    *     for i-th old tuple that should be omitted.
1177    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1178    *          is to delete using decrRef() as it is no more needed.
1179    */
1180   template<class T>
1181   typename Traits<T>::ArrayType *DataArrayTemplate<T>::renumberAndReduce(const mcIdType *old2New, mcIdType newNbOfTuple) const
1182   {
1183     checkAllocated();
1184     mcIdType nbTuples(getNumberOfTuples());
1185     std::size_t nbOfCompo(getNumberOfComponents());
1186     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1187     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1188     ret->alloc(newNbOfTuple,nbOfCompo);
1189     const T *iptr=getConstPointer();
1190     T *optr=ret->getPointer();
1191     for(mcIdType i=0;i<nbTuples;i++)
1192       {
1193         mcIdType w=old2New[i];
1194         if(w>=0)
1195           std::copy(iptr+i*nbOfCompo,iptr+(i+1)*nbOfCompo,optr+w*nbOfCompo);
1196       }
1197     ret->copyStringInfoFrom(*this);
1198     return ret.retn();
1199   }
1200
1201   /*!
1202    * Returns a shorten and permuted copy of \a this array. The new DataArrayDouble is
1203    * of size \a new2OldEnd - \a new2OldBg and it's values are permuted as required by
1204    * \a new2OldBg array.
1205    * The values are permuted so that  \c new[ i ] = \c old[ \a new2OldBg[ i ]].
1206    * This method is equivalent to renumberAndReduce() except that convention in input is
1207    * \c new2old and \b not \c old2new.
1208    * For more info on renumbering see \ref numbering.
1209    *  \param [in] new2OldBg - pointer to the beginning of a permutation array that gives a
1210    *              tuple index in \a this array to fill the i-th tuple in the new array.
1211    *  \param [in] new2OldEnd - specifies the end of the permutation array that starts at
1212    *              \a new2OldBg, so that pointer to a tuple index (\a pi) varies as this:
1213    *              \a new2OldBg <= \a pi < \a new2OldEnd.
1214    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1215    *          is to delete using decrRef() as it is no more needed.
1216    */
1217   template<class T>
1218   typename Traits<T>::ArrayType *DataArrayTemplate<T>::mySelectByTupleId(const mcIdType *new2OldBg, const mcIdType *new2OldEnd) const
1219   {
1220     checkAllocated();
1221     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1222     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1223     std::size_t nbComp(getNumberOfComponents());
1224     ret->alloc(std::distance(new2OldBg,new2OldEnd),nbComp);
1225     ret->copyStringInfoFrom(*this);
1226     T *pt(ret->getPointer());
1227     const T *srcPt(getConstPointer());
1228     std::size_t i(0);
1229     for(const mcIdType *w=new2OldBg;w!=new2OldEnd;w++,i++)
1230       std::copy(srcPt+(*w)*nbComp,srcPt+((*w)+1)*nbComp,pt+i*nbComp);
1231     ret->copyStringInfoFrom(*this);
1232     return ret.retn();
1233   }
1234
1235   template<class T>
1236   typename Traits<T>::ArrayType *DataArrayTemplate<T>::mySelectByTupleId(const DataArrayIdType& di) const
1237   {
1238     return this->mySelectByTupleId(di.begin(),di.end());
1239   }
1240
1241   template<class T>
1242   MCAuto<typename Traits<T>::ArrayTypeCh> DataArrayTemplate<T>::selectPartDef(const PartDefinition *pd) const
1243   {
1244     if(!pd)
1245       throw INTERP_KERNEL::Exception("DataArrayTemplate<T>::selectPartDef : null input pointer !");
1246     MCAuto<typename Traits<T>::ArrayTypeCh> ret(Traits<T>::ArrayTypeCh::New());
1247     const SlicePartDefinition *spd(dynamic_cast<const SlicePartDefinition *>(pd));
1248     if(spd)
1249       {
1250         mcIdType a,b,c;
1251         spd->getSlice(a,b,c);
1252         if(a==0 && b==getNumberOfTuples() && c==1)
1253           {
1254             DataArrayTemplate<T> *directRet(const_cast<DataArrayTemplate<T> *>(this));
1255             directRet->incrRef();
1256             MCAuto<DataArrayTemplate<T> > ret2(directRet);
1257             return DynamicCastSafe<DataArrayTemplate<T>,typename Traits<T>::ArrayTypeCh>(ret2);
1258           }
1259         else
1260           {
1261             MCAuto<DataArray> ret2(selectByTupleIdSafeSlice(a,b,c));
1262             return DynamicCastSafe<DataArray,typename Traits<T>::ArrayTypeCh>(ret2);
1263           }
1264       }
1265     const DataArrayPartDefinition *dpd(dynamic_cast<const DataArrayPartDefinition *>(pd));
1266     if(dpd)
1267       {
1268         MCAuto<DataArrayIdType> arr(dpd->toDAI());
1269         MCAuto<DataArray> ret2(selectByTupleIdSafe(arr->begin(),arr->end()));
1270         return DynamicCastSafe<DataArray,typename Traits<T>::ArrayTypeCh>(ret2);
1271         
1272       }
1273     throw INTERP_KERNEL::Exception("DataArrayTemplate<T>::selectPartDef : unrecognized part def !");
1274   }
1275   
1276   /*!
1277    * Returns a shorten and permuted copy of \a this array. The new DataArrayDouble is
1278    * of size \a new2OldEnd - \a new2OldBg and it's values are permuted as required by
1279    * \a new2OldBg array.
1280    * The values are permuted so that  \c new[ i ] = \c old[ \a new2OldBg[ i ]].
1281    * This method is equivalent to renumberAndReduce() except that convention in input is
1282    * \c new2old and \b not \c old2new.
1283    * This method is equivalent to selectByTupleId() except that it prevents coping data
1284    * from behind the end of \a this array.
1285    * For more info on renumbering see \ref numbering.
1286    *  \param [in] new2OldBg - pointer to the beginning of a permutation array that gives a
1287    *              tuple index in \a this array to fill the i-th tuple in the new array.
1288    *  \param [in] new2OldEnd - specifies the end of the permutation array that starts at
1289    *              \a new2OldBg, so that pointer to a tuple index (\a pi) varies as this:
1290    *              \a new2OldBg <= \a pi < \a new2OldEnd.
1291    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1292    *          is to delete using decrRef() as it is no more needed.
1293    *  \throw If \a new2OldEnd - \a new2OldBg > \a this->getNumberOfTuples().
1294    */
1295   template<class T>
1296   typename Traits<T>::ArrayType *DataArrayTemplate<T>::mySelectByTupleIdSafe(const mcIdType *new2OldBg, const mcIdType *new2OldEnd) const
1297   {
1298     checkAllocated();
1299     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1300     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1301     std::size_t nbComp(getNumberOfComponents());
1302     mcIdType oldNbOfTuples(getNumberOfTuples());
1303     ret->alloc(std::distance(new2OldBg,new2OldEnd),nbComp);
1304     ret->copyStringInfoFrom(*this);
1305     T *pt(ret->getPointer());
1306     const T *srcPt(getConstPointer());
1307     mcIdType i(0);
1308     for(const mcIdType *w=new2OldBg;w!=new2OldEnd;w++,i++)
1309       if(*w>=0 && *w<oldNbOfTuples)
1310         std::copy(srcPt+(*w)*nbComp,srcPt+((*w)+1)*nbComp,pt+i*nbComp);
1311       else
1312         {
1313           std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::selectByTupleIdSafe : some ids has been detected to be out of [0,this->getNumberOfTuples) !";
1314           throw INTERP_KERNEL::Exception(oss.str().c_str());
1315         }
1316     ret->copyStringInfoFrom(*this);
1317     return ret.retn();
1318   }
1319
1320   /*!
1321    * Changes the number of components within \a this array so that its raw data **does
1322    * not** change, instead splitting this data into tuples changes.
1323    *  \warning This method erases all (name and unit) component info set before!
1324    *  \param [in] newNbOfComp - number of components for \a this array to have.
1325    *  \throw If \a this is not allocated
1326    *  \throw If getNbOfElems() % \a newNbOfCompo != 0.
1327    *  \throw If \a newNbOfCompo is lower than 1.
1328    *  \throw If the rearrange method would lead to a number of tuples higher than 2147483647 (maximal capacity of int32 !).
1329    *  \warning This method erases all (name and unit) component info set before!
1330    */
1331   template<class T>
1332   void DataArrayTemplate<T>::rearrange(std::size_t newNbOfCompo)
1333   {
1334     checkAllocated();
1335     if(newNbOfCompo<1)
1336       {
1337         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::rearrange : input newNbOfCompo must be > 0 !";
1338         throw INTERP_KERNEL::Exception(oss.str().c_str());
1339       }
1340     std::size_t nbOfElems=getNbOfElems();
1341     if(nbOfElems%newNbOfCompo!=0)
1342       {
1343         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::rearrange : nbOfElems%newNbOfCompo!=0 !";
1344         throw INTERP_KERNEL::Exception(oss.str().c_str());
1345       }
1346     if(nbOfElems/newNbOfCompo>(std::size_t)std::numeric_limits<mcIdType>::max())
1347       {
1348         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::rearrange : the rearrangement leads to too high number of tuples (> 2147483647) !";
1349         throw INTERP_KERNEL::Exception(oss.str().c_str());
1350       }
1351     _info_on_compo.clear();
1352     _info_on_compo.resize(newNbOfCompo);
1353     declareAsNew();
1354   }
1355
1356   /*!
1357    * Changes the number of components within \a this array to be equal to its number
1358    * of tuples, and inversely its number of tuples to become equal to its number of 
1359    * components. So that its raw data **does not** change, instead splitting this
1360    * data into tuples changes.
1361    *  \warning This method erases all (name and unit) component info set before!
1362    *  \warning Do not confuse this method with fromNoInterlace() and toNoInterlace()!
1363    *  \throw If \a this is not allocated.
1364    *  \sa rearrange()
1365    */
1366   template<class T>
1367   void DataArrayTemplate<T>::transpose()
1368   {
1369     checkAllocated();
1370     rearrange(getNumberOfTuples());
1371   }
1372
1373   /*!
1374    * Returns a shorten or extended copy of \a this array. If \a newNbOfComp is less
1375    * than \a this->getNumberOfComponents() then the result array is shorten as each tuple
1376    * is truncated to have \a newNbOfComp components, keeping first components. If \a
1377    * newNbOfComp is more than \a this->getNumberOfComponents() then the result array is
1378    * expanded as each tuple is populated with \a dftValue to have \a newNbOfComp
1379    * components.  
1380    *  \param [in] newNbOfComp - number of components for the new array to have.
1381    *  \param [in] dftValue - value assigned to new values added to the new array.
1382    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1383    *          is to delete using decrRef() as it is no more needed.
1384    *  \throw If \a this is not allocated.
1385    */
1386   template<class T>
1387   typename Traits<T>::ArrayType *DataArrayTemplate<T>::changeNbOfComponents(std::size_t newNbOfComp, T dftValue) const
1388   {
1389     checkAllocated();
1390     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1391     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1392     ret->alloc(getNumberOfTuples(),newNbOfComp);
1393     const T *oldc(getConstPointer());
1394     T *nc(ret->getPointer());
1395     mcIdType nbOfTuples=getNumberOfTuples();
1396     std::size_t oldNbOfComp=getNumberOfComponents();
1397     std::size_t dim(std::min(oldNbOfComp,newNbOfComp));
1398     for(mcIdType i=0;i<nbOfTuples;i++)
1399       {
1400         std::size_t j=0;
1401         for(;j<dim;j++)
1402           nc[newNbOfComp*i+j]=oldc[i*oldNbOfComp+j];
1403         for(;j<newNbOfComp;j++)
1404           nc[newNbOfComp*i+j]=dftValue;
1405       }
1406     ret->setName(getName());
1407     for(std::size_t i=0;i<dim;i++)
1408       ret->setInfoOnComponent(i,getInfoOnComponent(i));
1409     ret->setName(getName());
1410     return ret.retn();
1411   }
1412
1413   /*!
1414    * Returns a copy of \a this array composed of selected components.
1415    * The new DataArrayDouble has the same number of tuples but includes components
1416    * specified by \a compoIds parameter. So that getNbOfElems() of the result array
1417    * can be either less, same or more than \a this->getNbOfElems().
1418    *  \param [in] compoIds - sequence of zero based indices of components to include
1419    *              into the new array.
1420    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1421    *          is to delete using decrRef() as it is no more needed.
1422    *  \throw If \a this is not allocated.
1423    *  \throw If a component index (\a i) is not valid: 
1424    *         \a i < 0 || \a i >= \a this->getNumberOfComponents().
1425    *
1426    *  \if ENABLE_EXAMPLES
1427    *  \ref py_mcdataarraydouble_KeepSelectedComponents "Here is a Python example".
1428    *  \endif
1429    */
1430   template<class T>
1431   typename Traits<T>::ArrayType *DataArrayTemplate<T>::myKeepSelectedComponents(const std::vector<std::size_t>& compoIds) const
1432   {
1433     checkAllocated();
1434     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1435     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1436     std::size_t newNbOfCompo=compoIds.size();
1437     std::size_t oldNbOfCompo=getNumberOfComponents();
1438     for(std::vector<std::size_t>::const_iterator it=compoIds.begin();it!=compoIds.end();it++)
1439       if((*it)<0 || (*it)>=oldNbOfCompo)
1440         {
1441           std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::keepSelectedComponents : invalid requested component : " << *it << " whereas it should be in [0," << oldNbOfCompo << ") !";
1442           throw INTERP_KERNEL::Exception(oss.str().c_str());
1443         }
1444     mcIdType nbOfTuples(getNumberOfTuples());
1445     ret->alloc(nbOfTuples,newNbOfCompo);
1446     ret->copyPartOfStringInfoFrom(*this,compoIds);
1447     const T *oldc(getConstPointer());
1448     T *nc(ret->getPointer());
1449     for(mcIdType i=0;i<nbOfTuples;i++)
1450       for(std::size_t j=0;j<newNbOfCompo;j++,nc++)
1451         *nc=oldc[i*oldNbOfCompo+compoIds[j]];
1452     return ret.retn();
1453   }
1454
1455   /*!
1456    * Returns a shorten copy of \a this array. The new DataArrayDouble contains all
1457    * tuples starting from the \a tupleIdBg-th tuple and including all tuples located before
1458    * the \a tupleIdEnd-th one. This methods has a similar behavior as std::string::substr().
1459    * This method is a specialization of selectByTupleIdSafeSlice().
1460    *  \param [in] tupleIdBg - index of the first tuple to copy from \a this array.
1461    *  \param [in] tupleIdEnd - index of the tuple before which the tuples to copy are located.
1462    *          If \a tupleIdEnd == -1, all the tuples till the end of \a this array are copied.
1463    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1464    *          is to delete using decrRef() as it is no more needed.
1465    *  \throw If \a tupleIdBg < 0.
1466    *  \throw If \a tupleIdBg > \a this->getNumberOfTuples().
1467    *  \throw If \a tupleIdEnd != -1 && \a tupleIdEnd < \a this->getNumberOfTuples().
1468    *  \sa DataArrayDouble::selectByTupleIdSafeSlice
1469    */
1470   template<class T>
1471   typename Traits<T>::ArrayType *DataArrayTemplate<T>::subArray(mcIdType tupleIdBg, mcIdType tupleIdEnd) const
1472   {
1473     checkAllocated();
1474     mcIdType nbt=getNumberOfTuples();
1475     if(tupleIdBg<0)
1476       {
1477         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::subArray : The tupleIdBg parameter must be greater than 0 !";
1478         throw INTERP_KERNEL::Exception(oss.str().c_str());
1479       }
1480     if(tupleIdBg>nbt)
1481       {
1482         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << ":subArray : The tupleIdBg parameter is greater than number of tuples !";
1483         throw INTERP_KERNEL::Exception(oss.str().c_str());
1484       }
1485     mcIdType trueEnd=tupleIdEnd;
1486     if(tupleIdEnd!=-1)
1487       {
1488         if(tupleIdEnd>nbt)
1489           {
1490             std::ostringstream oss; oss << Traits<T>::ArrayTypeName << ":subArray : The tupleIdBg parameter is greater than number of tuples !";
1491             throw INTERP_KERNEL::Exception(oss.str().c_str());
1492           }
1493       }
1494     else
1495       trueEnd=nbt;
1496     std::size_t nbComp=getNumberOfComponents();
1497     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1498     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1499     ret->alloc(trueEnd-tupleIdBg,nbComp);
1500     ret->copyStringInfoFrom(*this);
1501     std::copy(getConstPointer()+tupleIdBg*nbComp,getConstPointer()+trueEnd*nbComp,ret->getPointer());
1502     return ret.retn();
1503   }
1504
1505   /*!
1506    * Returns a shorten copy of \a this array. The new DataArrayDouble contains every
1507    * (\a bg + \c i * \a step)-th tuple of \a this array located before the \a end2-th
1508    * tuple. Indices of the selected tuples are the same as ones returned by the Python
1509    * command \c range( \a bg, \a end2, \a step ).
1510    * This method is equivalent to selectByTupleIdSafe() except that the input array is
1511    * not constructed explicitly.
1512    * For more info on renumbering see \ref numbering.
1513    *  \param [in] bg - index of the first tuple to copy from \a this array.
1514    *  \param [in] end2 - index of the tuple before which the tuples to copy are located.
1515    *  \param [in] step - index increment to get index of the next tuple to copy.
1516    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1517    *          is to delete using decrRef() as it is no more needed.
1518    *  \sa DataArrayDouble::subArray.
1519    */
1520   template<class T>
1521   typename Traits<T>::ArrayType *DataArrayTemplate<T>::mySelectByTupleIdSafeSlice(mcIdType bg, mcIdType end2, mcIdType step) const
1522   {
1523     checkAllocated();
1524     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1525     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1526     std::size_t nbComp(getNumberOfComponents());
1527     std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::selectByTupleIdSafeSlice : ";
1528     mcIdType newNbOfTuples(GetNumberOfItemGivenBESRelative(bg,end2,step,oss.str()));
1529     ret->alloc(newNbOfTuples,nbComp);
1530     T *pt(ret->getPointer());
1531     const T *srcPt(getConstPointer()+bg*nbComp);
1532     for(mcIdType i=0;i<newNbOfTuples;i++,srcPt+=step*nbComp)
1533       std::copy(srcPt,srcPt+nbComp,pt+i*nbComp);
1534     ret->copyStringInfoFrom(*this);
1535     return ret.retn();
1536   }
1537   
1538   /*!
1539    * Copy all values from another DataArrayDouble into specified tuples and components
1540    * of \a this array. Textual data is not copied.
1541    * The tree parameters defining set of indices of tuples and components are similar to
1542    * the tree parameters of the Python function \c range(\c start,\c stop,\c step).
1543    *  \param [in] a - the array to copy values from.
1544    *  \param [in] bgTuples - index of the first tuple of \a this array to assign values to.
1545    *  \param [in] endTuples - index of the tuple before which the tuples to assign to
1546    *              are located.
1547    *  \param [in] stepTuples - index increment to get index of the next tuple to assign to.
1548    *  \param [in] bgComp - index of the first component of \a this array to assign values to.
1549    *  \param [in] endComp - index of the component before which the components to assign
1550    *              to are located.
1551    *  \param [in] stepComp - index increment to get index of the next component to assign to.
1552    *  \param [in] strictCompoCompare - if \a true (by default), then \a a->getNumberOfComponents() 
1553    *              must be equal to the number of columns to assign to, else an
1554    *              exception is thrown; if \a false, then it is only required that \a
1555    *              a->getNbOfElems() equals to number of values to assign to (this condition
1556    *              must be respected even if \a strictCompoCompare is \a true). The number of 
1557    *              values to assign to is given by following Python expression:
1558    *              \a nbTargetValues = 
1559    *              \c len(\c range(\a bgTuples,\a endTuples,\a stepTuples)) *
1560    *              \c len(\c range(\a bgComp,\a endComp,\a stepComp)).
1561    *  \throw If \a a is NULL.
1562    *  \throw If \a a is not allocated.
1563    *  \throw If \a this is not allocated.
1564    *  \throw If parameters specifying tuples and components to assign to do not give a
1565    *            non-empty range of increasing indices.
1566    *  \throw If \a a->getNbOfElems() != \a nbTargetValues.
1567    *  \throw If \a strictCompoCompare == \a true && \a a->getNumberOfComponents() !=
1568    *            \c len(\c range(\a bgComp,\a endComp,\a stepComp)).
1569    *
1570    *  \if ENABLE_EXAMPLES
1571    *  \ref py_mcdataarraydouble_setpartofvalues1 "Here is a Python example".
1572    *  \endif
1573    */
1574   template<class T>
1575   void DataArrayTemplate<T>::setPartOfValues1(const typename Traits<T>::ArrayType *a, mcIdType bgTuples, mcIdType endTuples, mcIdType stepTuples, mcIdType bgComp, mcIdType endComp, mcIdType stepComp, bool strictCompoCompare)
1576   {
1577     if(!a)
1578       {
1579         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::setPartOfValues1 : input DataArrayDouble is NULL !";
1580         throw INTERP_KERNEL::Exception(oss.str().c_str());
1581       }
1582     const char msg[]="DataArrayTemplate::setPartOfValues1";
1583     checkAllocated();
1584     a->checkAllocated();
1585     mcIdType newNbOfTuples(DataArray::GetNumberOfItemGivenBES(bgTuples,endTuples,stepTuples,msg));
1586     mcIdType newNbOfComp(DataArray::GetNumberOfItemGivenBES(bgComp,endComp,stepComp,msg));
1587     std::size_t nbComp(getNumberOfComponents());
1588     mcIdType nbOfTuples(getNumberOfTuples());
1589     DataArray::CheckValueInRangeEx(nbOfTuples,bgTuples,endTuples,"invalid tuple value");
1590     DataArray::CheckValueInRangeEx(ToIdType(nbComp),bgComp,endComp,"invalid component value");
1591     bool assignTech(true);
1592     if(a->getNbOfElems()==newNbOfTuples*newNbOfComp)
1593       {
1594         if(strictCompoCompare)
1595           a->checkNbOfTuplesAndComp(newNbOfTuples,newNbOfComp,msg);
1596       }
1597     else
1598       {
1599         a->checkNbOfTuplesAndComp(1,newNbOfComp,msg);
1600         assignTech=false;
1601       }
1602     const T *srcPt(a->getConstPointer());
1603     T *pt(getPointer()+bgTuples*nbComp+bgComp);
1604     if(assignTech)
1605       {
1606         for(mcIdType i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
1607           for(mcIdType j=0;j<newNbOfComp;j++,srcPt++)
1608             pt[j*stepComp]=*srcPt;
1609       }
1610     else
1611       {
1612         for(mcIdType i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
1613           {
1614             const T*srcPt2=srcPt;
1615             for(mcIdType j=0;j<newNbOfComp;j++,srcPt2++)
1616               pt[j*stepComp]=*srcPt2;
1617           }
1618       }
1619   }
1620   
1621   /*!
1622  * Assign a given value to values at specified tuples and components of \a this array.
1623  * The tree parameters defining set of indices of tuples and components are similar to
1624  * the tree parameters of the Python function \c range(\c start,\c stop,\c step)..
1625  *  \param [in] a - the value to assign.
1626  *  \param [in] bgTuples - index of the first tuple of \a this array to assign to.
1627  *  \param [in] endTuples - index of the tuple before which the tuples to assign to
1628  *              are located.
1629  *  \param [in] stepTuples - index increment to get index of the next tuple to assign to.
1630  *  \param [in] bgComp - index of the first component of \a this array to assign to.
1631  *  \param [in] endComp - index of the component before which the components to assign
1632  *              to are located.
1633  *  \param [in] stepComp - index increment to get index of the next component to assign to.
1634  *  \throw If \a this is not allocated.
1635  *  \throw If parameters specifying tuples and components to assign to, do not give a
1636  *            non-empty range of increasing indices or indices are out of a valid range
1637  *            for \c this array.
1638  *
1639  *  \if ENABLE_EXAMPLES
1640  *  \ref py_mcdataarraydouble_setpartofvaluessimple1 "Here is a Python example".
1641  *  \endif
1642  */
1643   template<class T>
1644   void DataArrayTemplate<T>::setPartOfValuesSimple1(T a, mcIdType bgTuples, mcIdType endTuples, mcIdType stepTuples, mcIdType bgComp, mcIdType endComp, mcIdType stepComp)
1645   {
1646     const char msg[]="DataArrayTemplate::setPartOfValuesSimple1";
1647     checkAllocated();
1648     mcIdType newNbOfTuples(DataArray::GetNumberOfItemGivenBES(bgTuples,endTuples,stepTuples,msg));
1649     mcIdType newNbOfComp(DataArray::GetNumberOfItemGivenBES(bgComp,endComp,stepComp,msg));
1650     std::size_t nbComp(getNumberOfComponents());
1651     mcIdType nbOfTuples(getNumberOfTuples());
1652     DataArray::CheckValueInRangeEx(nbOfTuples,bgTuples,endTuples,"invalid tuple value");
1653     DataArray::CheckValueInRangeEx(ToIdType(nbComp),bgComp,endComp,"invalid component value");
1654     T *pt=getPointer()+bgTuples*nbComp+bgComp;
1655     for(mcIdType i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
1656       for(mcIdType j=0;j<newNbOfComp;j++)
1657         pt[j*stepComp]=a;
1658   }
1659   
1660   /*!
1661    * Copy all values from another DataArrayDouble (\a a) into specified tuples and 
1662    * components of \a this array. Textual data is not copied.
1663    * The tuples and components to assign to are defined by C arrays of indices.
1664    * There are two *modes of usage*:
1665    * - If \a a->getNbOfElems() equals to number of values to assign to, then every value
1666    *   of \a a is assigned to its own location within \a this array. 
1667    * - If \a a includes one tuple, then all values of \a a are assigned to the specified
1668    *   components of every specified tuple of \a this array. In this mode it is required
1669    *   that \a a->getNumberOfComponents() equals to the number of specified components.
1670    *
1671    *  \param [in] a - the array to copy values from.
1672    *  \param [in] bgTuples - pointer to an array of tuple indices of \a this array to
1673    *              assign values of \a a to.
1674    *  \param [in] endTuples - specifies the end of the array \a bgTuples, so that
1675    *              pointer to a tuple index <em>(pi)</em> varies as this: 
1676    *              \a bgTuples <= \a pi < \a endTuples.
1677    *  \param [in] bgComp - pointer to an array of component indices of \a this array to
1678    *              assign values of \a a to.
1679    *  \param [in] endComp - specifies the end of the array \a bgTuples, so that
1680    *              pointer to a component index <em>(pi)</em> varies as this: 
1681    *              \a bgComp <= \a pi < \a endComp.
1682    *  \param [in] strictCompoCompare - this parameter is checked only if the
1683    *               *mode of usage* is the first; if it is \a true (default), 
1684    *               then \a a->getNumberOfComponents() must be equal 
1685    *               to the number of specified columns, else this is not required.
1686    *  \throw If \a a is NULL.
1687    *  \throw If \a a is not allocated.
1688    *  \throw If \a this is not allocated.
1689    *  \throw If any index of tuple/component given by <em>bgTuples / bgComp</em> is
1690    *         out of a valid range for \a this array.
1691    *  \throw In the first *mode of usage*, if <em>strictCompoCompare == true </em> and
1692    *         if <em> a->getNumberOfComponents() != (endComp - bgComp) </em>.
1693    *  \throw In the second *mode of usage*, if \a a->getNumberOfTuples() != 1 or
1694    *         <em> a->getNumberOfComponents() != (endComp - bgComp)</em>.
1695    *
1696    *  \if ENABLE_EXAMPLES
1697    *  \ref py_mcdataarraydouble_setpartofvalues2 "Here is a Python example".
1698    *  \endif
1699    */
1700   template<class T>
1701   void DataArrayTemplate<T>::setPartOfValues2(const typename Traits<T>::ArrayType *a, const mcIdType *bgTuples, const mcIdType *endTuples, const mcIdType *bgComp, const mcIdType *endComp, bool strictCompoCompare)
1702   {
1703     if(!a)
1704       throw INTERP_KERNEL::Exception("DataArrayDouble::setPartOfValues2 : input DataArrayDouble is NULL !");
1705     const char msg[]="DataArrayTemplate::setPartOfValues2";
1706     checkAllocated();
1707     a->checkAllocated();
1708     std::size_t nbComp(getNumberOfComponents());
1709     mcIdType nbOfTuples(getNumberOfTuples());
1710     for(const mcIdType *z=bgComp;z!=endComp;z++)
1711       DataArray::CheckValueInRange(ToIdType(nbComp),*z,"invalid component id");
1712     mcIdType newNbOfTuples(ToIdType(std::distance(bgTuples,endTuples)));
1713     mcIdType newNbOfComp(ToIdType(std::distance(bgComp,endComp)));
1714     bool assignTech(true);
1715     if(a->getNbOfElems()==newNbOfTuples*newNbOfComp)
1716       {
1717         if(strictCompoCompare)
1718           a->checkNbOfTuplesAndComp(newNbOfTuples,newNbOfComp,msg);
1719       }
1720     else
1721       {
1722         a->checkNbOfTuplesAndComp(1,newNbOfComp,msg);
1723         assignTech=false;
1724       }
1725     T *pt(getPointer());
1726     const T *srcPt(a->getConstPointer());
1727     if(assignTech)
1728       {    
1729         for(const mcIdType *w=bgTuples;w!=endTuples;w++)
1730           {
1731             DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1732             for(const mcIdType *z=bgComp;z!=endComp;z++,srcPt++)
1733               {    
1734                 pt[(std::size_t)(*w)*nbComp+(*z)]=*srcPt;
1735               }
1736           }
1737       }
1738     else
1739       {
1740         for(const mcIdType *w=bgTuples;w!=endTuples;w++)
1741           {
1742             const T *srcPt2=srcPt;
1743             DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1744             for(const mcIdType *z=bgComp;z!=endComp;z++,srcPt2++)
1745               {    
1746                 pt[(std::size_t)(*w)*nbComp+(*z)]=*srcPt2;
1747               }
1748           }
1749       }
1750   }
1751   
1752   /*!
1753    * Assign a given value to values at specified tuples and components of \a this array.
1754    * The tuples and components to assign to are defined by C arrays of indices.
1755    *  \param [in] a - the value to assign.
1756    *  \param [in] bgTuples - pointer to an array of tuple indices of \a this array to
1757    *              assign \a a to.
1758    *  \param [in] endTuples - specifies the end of the array \a bgTuples, so that
1759    *              pointer to a tuple index (\a pi) varies as this: 
1760    *              \a bgTuples <= \a pi < \a endTuples.
1761    *  \param [in] bgComp - pointer to an array of component indices of \a this array to
1762    *              assign \a a to.
1763    *  \param [in] endComp - specifies the end of the array \a bgTuples, so that
1764    *              pointer to a component index (\a pi) varies as this: 
1765    *              \a bgComp <= \a pi < \a endComp.
1766    *  \throw If \a this is not allocated.
1767    *  \throw If any index of tuple/component given by <em>bgTuples / bgComp</em> is
1768    *         out of a valid range for \a this array.
1769    *
1770    *  \if ENABLE_EXAMPLES
1771    *  \ref py_mcdataarraydouble_setpartofvaluessimple2 "Here is a Python example".
1772    *  \endif
1773    */
1774   template<class T>
1775   void DataArrayTemplate<T>::setPartOfValuesSimple2(T a, const mcIdType *bgTuples, const mcIdType *endTuples, const mcIdType *bgComp, const mcIdType *endComp)
1776   {
1777     checkAllocated();
1778     std::size_t nbComp=getNumberOfComponents();
1779     mcIdType nbOfTuples=getNumberOfTuples();
1780     for(const mcIdType *z=bgComp;z!=endComp;z++)
1781       DataArray::CheckValueInRange(ToIdType(nbComp),*z,"invalid component id");
1782     T *pt(getPointer());
1783     for(const mcIdType *w=bgTuples;w!=endTuples;w++)
1784       for(const mcIdType *z=bgComp;z!=endComp;z++)
1785         {
1786           DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1787           pt[(std::size_t)(*w)*nbComp+(*z)]=a;
1788         }
1789   }
1790   
1791   /*!
1792    * Copy all values from another DataArrayDouble (\a a) into specified tuples and 
1793    * components of \a this array. Textual data is not copied.
1794    * The tuples to assign to are defined by a C array of indices.
1795    * The components to assign to are defined by three values similar to parameters of
1796    * the Python function \c range(\c start,\c stop,\c step).
1797    * There are two *modes of usage*:
1798    * - If \a a->getNbOfElems() equals to number of values to assign to, then every value
1799    *   of \a a is assigned to its own location within \a this array. 
1800    * - If \a a includes one tuple, then all values of \a a are assigned to the specified
1801    *   components of every specified tuple of \a this array. In this mode it is required
1802    *   that \a a->getNumberOfComponents() equals to the number of specified components.
1803    *
1804    *  \param [in] a - the array to copy values from.
1805    *  \param [in] bgTuples - pointer to an array of tuple indices of \a this array to
1806    *              assign values of \a a to.
1807    *  \param [in] endTuples - specifies the end of the array \a bgTuples, so that
1808    *              pointer to a tuple index <em>(pi)</em> varies as this: 
1809    *              \a bgTuples <= \a pi < \a endTuples.
1810    *  \param [in] bgComp - index of the first component of \a this array to assign to.
1811    *  \param [in] endComp - index of the component before which the components to assign
1812    *              to are located.
1813    *  \param [in] stepComp - index increment to get index of the next component to assign to.
1814    *  \param [in] strictCompoCompare - this parameter is checked only in the first
1815    *               *mode of usage*; if \a strictCompoCompare is \a true (default), 
1816    *               then \a a->getNumberOfComponents() must be equal 
1817    *               to the number of specified columns, else this is not required.
1818    *  \throw If \a a is NULL.
1819    *  \throw If \a a is not allocated.
1820    *  \throw If \a this is not allocated.
1821    *  \throw If any index of tuple given by \a bgTuples is out of a valid range for 
1822    *         \a this array.
1823    *  \throw In the first *mode of usage*, if <em>strictCompoCompare == true </em> and
1824    *         if <em> a->getNumberOfComponents()</em> is unequal to the number of components
1825    *         defined by <em>(bgComp,endComp,stepComp)</em>.
1826    *  \throw In the second *mode of usage*, if \a a->getNumberOfTuples() != 1 or
1827    *         <em> a->getNumberOfComponents()</em> is unequal to the number of components
1828    *         defined by <em>(bgComp,endComp,stepComp)</em>.
1829    *  \throw If parameters specifying components to assign to, do not give a
1830    *            non-empty range of increasing indices or indices are out of a valid range
1831    *            for \c this array.
1832    *
1833    *  \if ENABLE_EXAMPLES
1834    *  \ref py_mcdataarraydouble_setpartofvalues3 "Here is a Python example".
1835    *  \endif
1836    */
1837   template<class T>
1838   void DataArrayTemplate<T>::setPartOfValues3(const typename Traits<T>::ArrayType *a, const mcIdType *bgTuples, const mcIdType *endTuples, mcIdType bgComp, mcIdType endComp, mcIdType stepComp, bool strictCompoCompare)
1839   {
1840     if(!a)
1841       throw INTERP_KERNEL::Exception("DataArrayTemplate::setPartOfValues3 : input DataArrayDouble is NULL !");
1842     const char msg[]="DataArrayTemplate::setPartOfValues3";
1843     checkAllocated();
1844     a->checkAllocated();
1845     mcIdType newNbOfComp=DataArray::GetNumberOfItemGivenBES(bgComp,endComp,stepComp,msg);
1846     std::size_t nbComp(getNumberOfComponents());
1847     mcIdType nbOfTuples(getNumberOfTuples());
1848     DataArray::CheckValueInRangeEx(ToIdType(nbComp),bgComp,endComp,"invalid component value");
1849     mcIdType newNbOfTuples=ToIdType(std::distance(bgTuples,endTuples));
1850     bool assignTech=true;
1851     if(a->getNbOfElems()==newNbOfTuples*newNbOfComp)
1852       {
1853         if(strictCompoCompare)
1854           a->checkNbOfTuplesAndComp(newNbOfTuples,newNbOfComp,msg);
1855       }
1856     else
1857       {
1858         a->checkNbOfTuplesAndComp(1,newNbOfComp,msg);
1859         assignTech=false;
1860       }
1861     T *pt(getPointer()+bgComp);
1862     const T *srcPt(a->getConstPointer());
1863     if(assignTech)
1864       {
1865         for(const mcIdType *w=bgTuples;w!=endTuples;w++)
1866           for(mcIdType j=0;j<newNbOfComp;j++,srcPt++)
1867             {
1868               DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1869               pt[(std::size_t)(*w)*nbComp+j*stepComp]=*srcPt;
1870             }
1871       }
1872     else
1873       {
1874         for(const mcIdType *w=bgTuples;w!=endTuples;w++)
1875           {
1876             const T *srcPt2=srcPt;
1877             for(mcIdType j=0;j<newNbOfComp;j++,srcPt2++)
1878               {
1879                 DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1880                 pt[(std::size_t)(*w)*nbComp+j*stepComp]=*srcPt2;
1881               }
1882           }
1883       }
1884   }
1885   
1886   /*!
1887    * Assign a given value to values at specified tuples and components of \a this array.
1888    * The tuples to assign to are defined by a C array of indices.
1889    * The components to assign to are defined by three values similar to parameters of
1890    * the Python function \c range(\c start,\c stop,\c step).
1891    *  \param [in] a - the value to assign.
1892    *  \param [in] bgTuples - pointer to an array of tuple indices of \a this array to
1893    *              assign \a a to.
1894    *  \param [in] endTuples - specifies the end of the array \a bgTuples, so that
1895    *              pointer to a tuple index <em>(pi)</em> varies as this: 
1896    *              \a bgTuples <= \a pi < \a endTuples.
1897    *  \param [in] bgComp - index of the first component of \a this array to assign to.
1898    *  \param [in] endComp - index of the component before which the components to assign
1899    *              to are located.
1900    *  \param [in] stepComp - index increment to get index of the next component to assign to.
1901    *  \throw If \a this is not allocated.
1902    *  \throw If any index of tuple given by \a bgTuples is out of a valid range for 
1903    *         \a this array.
1904    *  \throw If parameters specifying components to assign to, do not give a
1905    *            non-empty range of increasing indices or indices are out of a valid range
1906    *            for \c this array.
1907    *
1908    *  \if ENABLE_EXAMPLES
1909    *  \ref py_mcdataarraydouble_setpartofvaluessimple3 "Here is a Python example".
1910    *  \endif
1911    */
1912   template<class T>
1913   void DataArrayTemplate<T>::setPartOfValuesSimple3(T a, const mcIdType *bgTuples, const mcIdType *endTuples, mcIdType bgComp, mcIdType endComp, mcIdType stepComp)
1914   {
1915     const char msg[]="DataArrayTemplate::setPartOfValuesSimple3";
1916     checkAllocated();
1917     std::size_t newNbOfComp(DataArray::GetNumberOfItemGivenBES(bgComp,endComp,stepComp,msg));
1918     std::size_t nbComp(getNumberOfComponents());
1919     mcIdType nbOfTuples(getNumberOfTuples());
1920     DataArray::CheckValueInRangeEx(ToIdType(nbComp),bgComp,endComp,"invalid component value");
1921     T *pt(getPointer()+bgComp);
1922     for(const mcIdType *w=bgTuples;w!=endTuples;w++)
1923       for(std::size_t j=0;j<newNbOfComp;j++)
1924         {
1925           DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1926           pt[(std::size_t)(*w)*nbComp+j*stepComp]=a;
1927         }
1928   }
1929
1930   /*!
1931    * Copy all values from another DataArrayDouble into specified tuples and components
1932    * of \a this array. Textual data is not copied.
1933    * The tree parameters defining set of indices of tuples and components are similar to
1934    * the tree parameters of the Python function \c range(\c start,\c stop,\c step).
1935    *  \param [in] a - the array to copy values from.
1936    *  \param [in] bgTuples - index of the first tuple of \a this array to assign values to.
1937    *  \param [in] endTuples - index of the tuple before which the tuples to assign to
1938    *              are located.
1939    *  \param [in] stepTuples - index increment to get index of the next tuple to assign to.
1940    *  \param [in] bgComp - pointer to an array of component indices of \a this array to
1941    *              assign \a a to.
1942    *  \param [in] endComp - specifies the end of the array \a bgTuples, so that
1943    *              pointer to a component index (\a pi) varies as this: 
1944    *              \a bgComp <= \a pi < \a endComp.
1945    *  \param [in] strictCompoCompare - if \a true (by default), then \a a->getNumberOfComponents() 
1946    *              must be equal to the number of columns to assign to, else an
1947    *              exception is thrown; if \a false, then it is only required that \a
1948    *              a->getNbOfElems() equals to number of values to assign to (this condition
1949    *              must be respected even if \a strictCompoCompare is \a true). The number of 
1950    *              values to assign to is given by following Python expression:
1951    *              \a nbTargetValues = 
1952    *              \c len(\c range(\a bgTuples,\a endTuples,\a stepTuples)) *
1953    *              \c len(\c range(\a bgComp,\a endComp,\a stepComp)).
1954    *  \throw If \a a is NULL.
1955    *  \throw If \a a is not allocated.
1956    *  \throw If \a this is not allocated.
1957    *  \throw If parameters specifying tuples and components to assign to do not give a
1958    *            non-empty range of increasing indices.
1959    *  \throw If \a a->getNbOfElems() != \a nbTargetValues.
1960    *  \throw If \a strictCompoCompare == \a true && \a a->getNumberOfComponents() !=
1961    *            \c len(\c range(\a bgComp,\a endComp,\a stepComp)).
1962    *
1963    */
1964   template<class T>
1965   void DataArrayTemplate<T>::setPartOfValues4(const typename Traits<T>::ArrayType *a, mcIdType bgTuples, mcIdType endTuples, mcIdType stepTuples, const mcIdType *bgComp, const mcIdType *endComp, bool strictCompoCompare)
1966   {if(!a)
1967       throw INTERP_KERNEL::Exception("DataArrayTemplate::setPartOfValues4 : input DataArrayTemplate is NULL !");
1968     const char msg[]="DataArrayTemplate::setPartOfValues4";
1969     checkAllocated();
1970     a->checkAllocated();
1971     mcIdType newNbOfTuples(DataArray::GetNumberOfItemGivenBES(bgTuples,endTuples,stepTuples,msg));
1972     std::size_t newNbOfComp(std::distance(bgComp,endComp));
1973     std::size_t nbComp(getNumberOfComponents());
1974     for(const mcIdType *z=bgComp;z!=endComp;z++)
1975       DataArray::CheckValueInRange(ToIdType(nbComp),*z,"invalid component id");
1976     mcIdType nbOfTuples(getNumberOfTuples());
1977     DataArray::CheckValueInRangeEx(nbOfTuples,bgTuples,endTuples,"invalid tuple value");
1978     bool assignTech(true);
1979     if(a->getNbOfElems()==ToIdType(newNbOfTuples*newNbOfComp))
1980       {
1981         if(strictCompoCompare)
1982           a->checkNbOfTuplesAndComp(newNbOfTuples,newNbOfComp,msg);
1983       }
1984     else
1985       {
1986         a->checkNbOfTuplesAndComp(1,newNbOfComp,msg);
1987         assignTech=false;
1988       }
1989     const T *srcPt(a->getConstPointer());
1990     T *pt(getPointer()+bgTuples*nbComp);
1991     if(assignTech)
1992       {
1993         for(mcIdType i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
1994           for(const mcIdType *z=bgComp;z!=endComp;z++,srcPt++)
1995             pt[*z]=*srcPt;
1996       }
1997     else
1998       {
1999       for(mcIdType i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
2000         {
2001           const T *srcPt2(srcPt);
2002           for(const mcIdType *z=bgComp;z!=endComp;z++,srcPt2++)
2003             pt[*z]=*srcPt2;
2004         }
2005       }
2006   }
2007
2008   template<class T>
2009   void DataArrayTemplate<T>::setPartOfValuesSimple4(T a, mcIdType bgTuples, mcIdType endTuples, mcIdType stepTuples, const mcIdType *bgComp, const mcIdType *endComp)
2010   {
2011     const char msg[]="DataArrayTemplate::setPartOfValuesSimple4";
2012     checkAllocated();
2013     mcIdType newNbOfTuples(DataArray::GetNumberOfItemGivenBES(bgTuples,endTuples,stepTuples,msg));
2014     std::size_t nbComp(getNumberOfComponents());
2015     for(const mcIdType *z=bgComp;z!=endComp;z++)
2016       DataArray::CheckValueInRange(ToIdType(nbComp),*z,"invalid component id");
2017     mcIdType nbOfTuples(getNumberOfTuples());
2018     DataArray::CheckValueInRangeEx(nbOfTuples,bgTuples,endTuples,"invalid tuple value");
2019     T *pt=getPointer()+bgTuples*nbComp;
2020     for(mcIdType i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
2021       for(const mcIdType *z=bgComp;z!=endComp;z++)
2022         pt[*z]=a;
2023   }
2024   
2025   /*!
2026    * Copy some tuples from another DataArrayDouble into specified tuples
2027    * of \a this array. Textual data is not copied. Both arrays must have equal number of
2028    * components.
2029    * Both the tuples to assign and the tuples to assign to are defined by a DataArrayInt.
2030    * All components of selected tuples are copied.
2031    *  \param [in] a - the array to copy values from.
2032    *  \param [in] tuplesSelec - the array specifying both source tuples of \a a and
2033    *              target tuples of \a this. \a tuplesSelec has two components, and the
2034    *              first component specifies index of the source tuple and the second
2035    *              one specifies index of the target tuple.
2036    *  \throw If \a this is not allocated.
2037    *  \throw If \a a is NULL.
2038    *  \throw If \a a is not allocated.
2039    *  \throw If \a tuplesSelec is NULL.
2040    *  \throw If \a tuplesSelec is not allocated.
2041    *  \throw If <em>this->getNumberOfComponents() != a->getNumberOfComponents()</em>.
2042    *  \throw If \a tuplesSelec->getNumberOfComponents() != 2.
2043    *  \throw If any tuple index given by \a tuplesSelec is out of a valid range for 
2044    *         the corresponding (\a this or \a a) array.
2045    */
2046   template<class T>
2047   void DataArrayTemplate<T>::setPartOfValuesAdv(const typename Traits<T>::ArrayType *a, const DataArrayIdType *tuplesSelec)
2048   {
2049     if(!a || !tuplesSelec)
2050       throw INTERP_KERNEL::Exception("DataArrayTemplate::setPartOfValuesAdv : input DataArrayTemplate is NULL !");
2051     checkAllocated();
2052     a->checkAllocated();
2053     tuplesSelec->checkAllocated();
2054     std::size_t nbOfComp(getNumberOfComponents());
2055     if(nbOfComp!=a->getNumberOfComponents())
2056       throw INTERP_KERNEL::Exception("DataArrayTemplate::setPartOfValuesAdv : This and a do not have the same number of components !");
2057     if(tuplesSelec->getNumberOfComponents()!=2)
2058       throw INTERP_KERNEL::Exception("DataArrayTemplate::setPartOfValuesAdv : Expecting to have a tuple selector DataArrayInt instance with exactly 2 components !");
2059     mcIdType thisNt(getNumberOfTuples());
2060     mcIdType aNt(a->getNumberOfTuples());
2061     T *valsToSet(getPointer());
2062     const T *valsSrc(a->getConstPointer());
2063     for(const mcIdType *tuple=tuplesSelec->begin();tuple!=tuplesSelec->end();tuple+=2)
2064     {
2065       if(tuple[1]>=0 && tuple[1]<aNt)
2066         {
2067           if(tuple[0]>=0 && tuple[0]<thisNt)
2068             std::copy(valsSrc+nbOfComp*tuple[1],valsSrc+nbOfComp*(tuple[1]+1),valsToSet+nbOfComp*tuple[0]);
2069           else
2070             {
2071               std::ostringstream oss; oss << "DataArrayTemplate::setPartOfValuesAdv : Tuple #" << std::distance(tuplesSelec->begin(),tuple)/2;
2072               oss << " of 'tuplesSelec' request of tuple id #" << tuple[0] << " in 'this' ! It should be in [0," << thisNt << ") !";
2073               throw INTERP_KERNEL::Exception(oss.str().c_str());
2074             }
2075         }
2076       else
2077         {
2078           std::ostringstream oss; oss << "DataArrayTemplate::setPartOfValuesAdv : Tuple #" << std::distance(tuplesSelec->begin(),tuple)/2;
2079           oss << " of 'tuplesSelec' request of tuple id #" << tuple[1] << " in 'a' ! It should be in [0," << aNt << ") !";
2080           throw INTERP_KERNEL::Exception(oss.str().c_str());
2081         }
2082     }
2083   }
2084   
2085   /*!
2086    * Copy some tuples from another DataArrayDouble (\a aBase) into contiguous tuples
2087    * of \a this array. Textual data is not copied. Both arrays must have equal number of
2088    * components.
2089    * The tuples to assign to are defined by index of the first tuple, and
2090    * their number is defined by \a tuplesSelec->getNumberOfTuples().
2091    * The tuples to copy are defined by values of a DataArrayInt.
2092    * All components of selected tuples are copied.
2093    *  \param [in] tupleIdStart - index of the first tuple of \a this array to assign
2094    *              values to.
2095    *  \param [in] aBase - the array to copy values from.
2096    *  \param [in] tuplesSelec - the array specifying tuples of \a a to copy.
2097    *  \throw If \a this is not allocated.
2098    *  \throw If \a aBase is NULL.
2099    *  \throw If \a aBase is not allocated.
2100    *  \throw If \a tuplesSelec is NULL.
2101    *  \throw If \a tuplesSelec is not allocated.
2102    *  \throw If <em>this->getNumberOfComponents() != aBase->getNumberOfComponents()</em>.
2103    *  \throw If \a tuplesSelec->getNumberOfComponents() != 1.
2104    *  \throw If <em>tupleIdStart + tuplesSelec->getNumberOfTuples() > this->getNumberOfTuples().</em>
2105    *  \throw If any tuple index given by \a tuplesSelec is out of a valid range for 
2106    *         \a aBase array.
2107  */
2108   template<class T>
2109   void DataArrayTemplate<T>::setContigPartOfSelectedValues(mcIdType tupleIdStart, const DataArray *aBase, const DataArrayIdType *tuplesSelec)
2110   {
2111     if(!aBase || !tuplesSelec)
2112       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValues : input DataArray is NULL !");
2113     const typename Traits<T>::ArrayType *a(dynamic_cast<const typename Traits<T>::ArrayType *>(aBase));
2114     if(!a)
2115       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValues : input DataArray aBase is not a DataArrayDouble !");
2116     checkAllocated();
2117     a->checkAllocated();
2118     tuplesSelec->checkAllocated();
2119     std::size_t nbOfComp(getNumberOfComponents());
2120     if(nbOfComp!=a->getNumberOfComponents())
2121       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValues : This and a do not have the same number of components !");
2122     if(tuplesSelec->getNumberOfComponents()!=1)
2123       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValues : Expecting to have a tuple selector DataArrayInt instance with exactly 1 component !");
2124     mcIdType thisNt(getNumberOfTuples());
2125     mcIdType aNt(a->getNumberOfTuples());
2126     mcIdType nbOfTupleToWrite(tuplesSelec->getNumberOfTuples());
2127     T *valsToSet(getPointer()+tupleIdStart*nbOfComp);
2128     if(tupleIdStart+nbOfTupleToWrite>thisNt)
2129       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValues : invalid number range of values to write !");
2130     const T *valsSrc=a->getConstPointer();
2131     for(const mcIdType *tuple=tuplesSelec->begin();tuple!=tuplesSelec->end();tuple++,valsToSet+=nbOfComp)
2132       {
2133         if(*tuple>=0 && *tuple<aNt)
2134           {
2135             std::copy(valsSrc+nbOfComp*(*tuple),valsSrc+nbOfComp*(*tuple+1),valsToSet);
2136           }
2137         else
2138           {
2139             std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::setContigPartOfSelectedValues : Tuple #" << std::distance(tuplesSelec->begin(),tuple);
2140             oss << " of 'tuplesSelec' request of tuple id #" << *tuple << " in 'a' ! It should be in [0," << aNt << ") !";
2141             throw INTERP_KERNEL::Exception(oss.str().c_str());
2142           }
2143       }
2144   }
2145   
2146   /*!
2147    * Copy some tuples from another DataArrayDouble (\a aBase) into contiguous tuples
2148    * of \a this array. Textual data is not copied. Both arrays must have equal number of
2149    * components.
2150    * The tuples to copy are defined by three values similar to parameters of
2151    * the Python function \c range(\c start,\c stop,\c step).
2152    * The tuples to assign to are defined by index of the first tuple, and
2153    * their number is defined by number of tuples to copy.
2154    * All components of selected tuples are copied.
2155    *  \param [in] tupleIdStart - index of the first tuple of \a this array to assign
2156    *              values to.
2157    *  \param [in] aBase - the array to copy values from.
2158    *  \param [in] bg - index of the first tuple to copy of the array \a aBase.
2159    *  \param [in] end2 - index of the tuple of \a aBase before which the tuples to copy
2160    *              are located.
2161    *  \param [in] step - index increment to get index of the next tuple to copy.
2162    *  \throw If \a this is not allocated.
2163    *  \throw If \a aBase is NULL.
2164    *  \throw If \a aBase is not allocated.
2165    *  \throw If <em>this->getNumberOfComponents() != aBase->getNumberOfComponents()</em>.
2166    *  \throw If <em>tupleIdStart + len(range(bg,end2,step)) > this->getNumberOfTuples().</em>
2167    *  \throw If parameters specifying tuples to copy, do not give a
2168    *            non-empty range of increasing indices or indices are out of a valid range
2169    *            for the array \a aBase.
2170    */
2171   template<class T>
2172   void DataArrayTemplate<T>::setContigPartOfSelectedValuesSlice(mcIdType tupleIdStart, const DataArray *aBase, mcIdType bg, mcIdType end2, mcIdType step)
2173   {
2174     if(!aBase)
2175       {
2176         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::setContigPartOfSelectedValuesSlice : input DataArray is NULL !";
2177         throw INTERP_KERNEL::Exception(oss.str().c_str());
2178       }
2179     const typename Traits<T>::ArrayType *a(dynamic_cast<const typename Traits<T>::ArrayType *>(aBase));
2180     if(!a)
2181       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValuesSlice : input DataArray aBase is not a DataArrayDouble !");
2182     checkAllocated();
2183     a->checkAllocated();
2184     std::size_t nbOfComp(getNumberOfComponents());
2185     const char msg[]="DataArrayDouble::setContigPartOfSelectedValuesSlice";
2186     mcIdType nbOfTupleToWrite(DataArray::GetNumberOfItemGivenBES(bg,end2,step,msg));
2187     if(nbOfComp!=a->getNumberOfComponents())
2188       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValuesSlice : This and a do not have the same number of components !");
2189     mcIdType thisNt(getNumberOfTuples());
2190     mcIdType aNt(a->getNumberOfTuples());
2191     T *valsToSet(getPointer()+tupleIdStart*nbOfComp);
2192     if(tupleIdStart+nbOfTupleToWrite>thisNt)
2193       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValuesSlice : invalid number range of values to write !");
2194     if(end2>aNt)
2195       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValuesSlice : invalid range of values to read !");
2196     const T *valsSrc(a->getConstPointer()+bg*nbOfComp);
2197     for(mcIdType i=0;i<nbOfTupleToWrite;i++,valsToSet+=nbOfComp,valsSrc+=step*nbOfComp)
2198       {
2199         std::copy(valsSrc,valsSrc+nbOfComp,valsToSet);
2200       }
2201   }
2202
2203   /*!
2204    * Returns a shorten copy of \a this array. The new DataArrayDouble contains ranges
2205    * of tuples specified by \a ranges parameter.
2206    * For more info on renumbering see \ref numbering.
2207    *  \param [in] ranges - std::vector of std::pair's each of which defines a range
2208    *              of tuples in [\c begin,\c end) format.
2209    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
2210    *          is to delete using decrRef() as it is no more needed.
2211    *  \throw If \a end < \a begin.
2212    *  \throw If \a end > \a this->getNumberOfTuples().
2213    *  \throw If \a this is not allocated.
2214    */
2215   template<class T>
2216   typename Traits<T>::ArrayType *DataArrayTemplate<T>::mySelectByTupleRanges(const std::vector<std::pair<mcIdType,mcIdType> >& ranges) const
2217   {
2218     checkAllocated();
2219     std::size_t nbOfComp(getNumberOfComponents());
2220     mcIdType nbOfTuplesThis(getNumberOfTuples());
2221     if(ranges.empty())
2222       {
2223         MCAuto<DataArray> ret0(buildNewEmptyInstance());
2224         MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
2225         ret->alloc(0,nbOfComp);
2226         ret->copyStringInfoFrom(*this);
2227         return ret.retn();
2228       }
2229     mcIdType ref(ranges.front().first),nbOfTuples(0);
2230     bool isIncreasing(true);
2231     for(std::vector<std::pair<mcIdType,mcIdType> >::const_iterator it=ranges.begin();it!=ranges.end();it++)
2232       {
2233         if((*it).first<=(*it).second)
2234           {
2235             if((*it).first>=0 && (*it).second<=nbOfTuplesThis)
2236               {
2237                 nbOfTuples+=(*it).second-(*it).first;
2238                 if(isIncreasing)
2239                   isIncreasing=ref<=(*it).first;
2240                 ref=(*it).second;
2241               }
2242             else
2243               {
2244                 std::ostringstream oss; oss << "DataArrayTemplate::selectByTupleRanges : on range #" << std::distance(ranges.begin(),it);
2245                 oss << " (" << (*it).first << "," << (*it).second << ") is greater than number of tuples of this :" << nbOfTuples << " !";
2246                 throw INTERP_KERNEL::Exception(oss.str().c_str());
2247               }
2248           }
2249         else
2250           {
2251             std::ostringstream oss; oss << "DataArrayTemplate::selectByTupleRanges : on range #" << std::distance(ranges.begin(),it);
2252             oss << " (" << (*it).first << "," << (*it).second << ") end is before begin !";
2253             throw INTERP_KERNEL::Exception(oss.str().c_str());
2254           }
2255       }
2256     if(isIncreasing && nbOfTuplesThis==nbOfTuples)
2257       return static_cast<typename Traits<T>::ArrayType *>(deepCopy());
2258     MCAuto<DataArray> ret0(buildNewEmptyInstance());
2259     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
2260     ret->alloc(nbOfTuples,nbOfComp);
2261     ret->copyStringInfoFrom(*this);
2262     const T *src(getConstPointer());
2263     T *work(ret->getPointer());
2264     for(std::vector<std::pair<mcIdType,mcIdType> >::const_iterator it=ranges.begin();it!=ranges.end();it++)
2265       work=std::copy(src+(*it).first*nbOfComp,src+(*it).second*nbOfComp,work);
2266     return ret.retn();
2267   }
2268
2269   /*!
2270    * Returns the first value of \a this. 
2271    *  \return double - the last value of \a this array.
2272    *  \throw If \a this is not allocated.
2273    *  \throw If \a this->getNumberOfComponents() != 1.
2274    *  \throw If \a this->getNumberOfTuples() < 1.
2275    */
2276   template<class T>
2277   T DataArrayTemplate<T>::front() const
2278   {
2279     checkAllocated();
2280     if(getNumberOfComponents()!=1)
2281       throw INTERP_KERNEL::Exception("DataArrayTemplate::front : number of components not equal to one !");
2282     mcIdType nbOfTuples=getNumberOfTuples();
2283     if(nbOfTuples<1)
2284       throw INTERP_KERNEL::Exception("DataArrayTemplate::front : number of tuples must be >= 1 !");
2285     return *(getConstPointer());
2286   }
2287   
2288   /*!
2289    * Returns the last value of \a this. 
2290    *  \return double - the last value of \a this array.
2291    *  \throw If \a this is not allocated.
2292    *  \throw If \a this->getNumberOfComponents() != 1.
2293    *  \throw If \a this->getNumberOfTuples() < 1.
2294    */
2295   template<class T>
2296   T DataArrayTemplate<T>::back() const
2297   {
2298     checkAllocated();
2299     if(getNumberOfComponents()!=1)
2300       throw INTERP_KERNEL::Exception("DataArrayTemplate::back : number of components not equal to one !");
2301     mcIdType nbOfTuples=getNumberOfTuples();
2302     if(nbOfTuples<1)
2303       throw INTERP_KERNEL::Exception("DataArrayTemplate::back : number of tuples must be >= 1 !");
2304     return *(getConstPointer()+nbOfTuples-1);
2305   }
2306   
2307   /*!
2308    * Returns the maximal value and its location within \a this one-dimensional array.
2309    *  \param [out] tupleId - index of the tuple holding the maximal value.
2310    *  \return double - the maximal value among all values of \a this array.
2311    *  \throw If \a this->getNumberOfComponents() != 1
2312    *  \throw If \a this->getNumberOfTuples() < 1
2313    *  \sa getMaxAbsValue, getMinValue
2314    */
2315   template<class T>
2316   T DataArrayTemplate<T>::getMaxValue(mcIdType& tupleId) const
2317   {
2318     checkAllocated();
2319     if(getNumberOfComponents()!=1)
2320       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 !");
2321     mcIdType nbOfTuples=getNumberOfTuples();
2322     if(nbOfTuples<=0)
2323       throw INTERP_KERNEL::Exception("DataArrayDouble::getMaxValue : array exists but number of tuples must be > 0 !");
2324     const T *vals(getConstPointer());
2325     const T *loc(std::max_element(vals,vals+nbOfTuples));
2326     tupleId=ToIdType(std::distance(vals,loc));
2327     return *loc;
2328   }
2329   
2330   /*!
2331    * Returns the maximal value within \a this array that is allowed to have more than
2332    *  one component.
2333    *  \return double - the maximal value among all values of \a this array.
2334    *  \throw If \a this is not allocated.
2335    *  \sa getMaxAbsValueInArray, getMinValueInArray
2336    */
2337   template<class T>
2338   T DataArrayTemplate<T>::getMaxValueInArray() const
2339   {
2340     checkAllocated();
2341     const T *loc(std::max_element(begin(),end()));
2342     return *loc;
2343   }
2344   
2345   /*!
2346    * Returns the maximal absolute value in \a this and the first occurrence location associated to it.
2347    * \return the element in this (positive or negative) having the max abs value in \a this.
2348    *  \throw If \a this is not allocated.
2349    *  \throw If \a this is non one component array.
2350    *  \throw If \a this is empty.
2351    */
2352   template<class T>
2353   T DataArrayTemplate<T>::getMaxAbsValue(std::size_t& tupleId) const
2354   {
2355     checkAllocated();
2356     if(getNumberOfComponents()!=1)
2357       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 !");
2358     mcIdType nbTuples(this->getNumberOfTuples());
2359     if(nbTuples==0)
2360       throw INTERP_KERNEL::Exception("DataArrayTemplate<T>::getMaxAbsValue : empty array !");
2361     T ret((T)-1);
2362     tupleId=0;
2363     const T *pt(begin());
2364     for(mcIdType i=0;i<nbTuples;i++,pt++)
2365       {
2366         T cand((T)std::abs(*pt));
2367         if(cand>ret)
2368           {
2369             ret=cand;
2370             tupleId=i;
2371           }
2372       }
2373     return this->getIJ(ToIdType(tupleId),0);
2374   }
2375
2376   /*!
2377    * Returns the maximal absolute value in \a this.
2378    *  \throw If \a this is not allocated.
2379    *  \throw If \a this is non one component array.
2380    *  \throw If \a this is empty.
2381    */
2382   template<class T>
2383   T DataArrayTemplate<T>::getMaxAbsValueInArray() const
2384   {
2385     std::size_t dummy;
2386     return getMaxAbsValue(dummy);
2387   }
2388
2389   /*!
2390    * Returns the minimal value and its location within \a this one-dimensional array.
2391    *  \param [out] tupleId - index of the tuple holding the minimal value.
2392    *  \return double - the minimal value among all values of \a this array.
2393    *  \throw If \a this->getNumberOfComponents() != 1
2394    *  \throw If \a this->getNumberOfTuples() < 1
2395    */
2396   template<class T>
2397   T DataArrayTemplate<T>::getMinValue(mcIdType& tupleId) const
2398   {
2399     checkAllocated();
2400     if(getNumberOfComponents()!=1)
2401       throw INTERP_KERNEL::Exception("DataArrayDouble::getMinValue : must be applied on DataArrayDouble with only one component, you can call 'rearrange' method before call 'getMinValueInArray' method !");
2402     mcIdType nbOfTuples=getNumberOfTuples();
2403     if(nbOfTuples<=0)
2404       throw INTERP_KERNEL::Exception("DataArrayDouble::getMinValue : array exists but number of tuples must be > 0 !");
2405     const T *vals(getConstPointer());
2406     const T *loc(std::min_element(vals,vals+nbOfTuples));
2407     tupleId=ToIdType(std::distance(vals,loc));
2408     return *loc;
2409   }
2410   
2411   /*!
2412    * Returns the minimal value within \a this array that is allowed to have more than
2413    *  one component.
2414    *  \return double - the minimal value among all values of \a this array.
2415    *  \throw If \a this is not allocated.
2416    */
2417   template<class T>
2418   T DataArrayTemplate<T>::getMinValueInArray() const
2419   {
2420     checkAllocated();
2421     const T *loc=std::min_element(begin(),end());
2422     return *loc;
2423   }
2424   
2425   template<class T>
2426   void DataArrayTemplate<T>::circularPermutation(mcIdType nbOfShift)
2427   {
2428     checkAllocated();
2429     std::size_t nbOfCompo(getNumberOfComponents());
2430     mcIdType nbTuples(getNumberOfTuples());
2431     mcIdType effNbSh(EffectiveCircPerm(nbOfShift,nbTuples));
2432     if(effNbSh==0)
2433       return ;
2434     T *work(getPointer());
2435     if(effNbSh<nbTuples-effNbSh)
2436       {
2437         typename INTERP_KERNEL::AutoPtr<T> buf(new T[effNbSh*nbOfCompo]);
2438         std::copy(work,work+effNbSh*nbOfCompo,(T *)buf);
2439         std::copy(work+effNbSh*nbOfCompo,work+nbTuples*nbOfCompo,work);// ze big shift
2440         std::copy((T *)buf,(T *)buf+effNbSh*nbOfCompo,work+(nbTuples-effNbSh)*nbOfCompo);
2441       }
2442     else
2443       {
2444         typename INTERP_KERNEL::AutoPtr<T> buf(new T[(nbTuples-effNbSh)*nbOfCompo]);
2445         std::copy(work+effNbSh*nbOfCompo,work+nbTuples*nbOfCompo,(T *)buf);
2446         std::copy(work,work+effNbSh*nbOfCompo,work+(nbTuples-effNbSh)*nbOfCompo);// ze big shift
2447         std::copy((T*)buf,(T *)buf+(nbTuples-effNbSh)*nbOfCompo,work);
2448       }
2449   }
2450   
2451   template<class T>
2452   void DataArrayTemplate<T>::circularPermutationPerTuple(mcIdType nbOfShift)
2453   {
2454     checkAllocated();
2455     std::size_t nbOfCompo(getNumberOfComponents());
2456     mcIdType nbTuples(getNumberOfTuples());
2457     mcIdType effNbSh(EffectiveCircPerm(nbOfShift,ToIdType(nbOfCompo)));
2458     if(effNbSh==0)
2459       return ;
2460     T *work(getPointer());
2461     if(effNbSh<ToIdType(nbOfCompo)-effNbSh)
2462       {
2463         typename INTERP_KERNEL::AutoPtr<T> buf(new T[effNbSh]);
2464         for(mcIdType i=0;i<nbTuples;i++,work+=nbOfCompo)
2465           {
2466             std::copy(work,work+effNbSh,(T *)buf);
2467             std::copy(work+effNbSh,work+nbOfCompo,work);// ze big shift
2468             std::copy((T *)buf,(T *)buf+effNbSh,work+(nbOfCompo-effNbSh));
2469           }
2470       }
2471     else
2472       {
2473         typename INTERP_KERNEL::AutoPtr<T> buf(new T[nbOfCompo-effNbSh]);
2474         for(mcIdType i=0;i<nbTuples;i++,work+=nbOfCompo)
2475           {
2476             std::copy(work+effNbSh,work+nbOfCompo,(T *)buf);
2477             std::copy(work,work+effNbSh,work+(nbOfCompo-effNbSh));// ze big shift
2478             std::copy((T*)buf,(T *)buf+(nbOfCompo-effNbSh),work);
2479           }
2480       }
2481     std::vector<std::string> sts(nbOfCompo);
2482     for(std::size_t i=0;i<nbOfCompo;i++)
2483       sts[i]=_info_on_compo[(i+effNbSh)%nbOfCompo];
2484     setInfoOnComponents(sts);
2485   }
2486   
2487   template<class T>
2488   void DataArrayTemplate<T>::reversePerTuple()
2489   {
2490     checkAllocated();
2491     std::size_t nbOfCompo(getNumberOfComponents());
2492     mcIdType nbTuples(getNumberOfTuples());
2493     if(nbOfCompo<=1)
2494       return ;
2495     T *work(getPointer());
2496     for(mcIdType i=0;i<nbTuples;i++,work+=nbOfCompo)
2497       std::reverse(work,work+nbOfCompo);
2498     std::reverse(_info_on_compo.begin(),_info_on_compo.end());
2499   }
2500
2501   /*!
2502    * Assign pointer to one array to a pointer to another appay. Reference counter of
2503    * \a arrayToSet is incremented / decremented.
2504    *  \param [in] newArray - the pointer to array to assign to \a arrayToSet.
2505    *  \param [in,out] arrayToSet - the pointer to array to assign to.
2506    */
2507   template<class T>
2508   void DataArrayTemplate<T>::SetArrayIn(typename Traits<T>::ArrayType *newArray, typename Traits<T>::ArrayType* &arrayToSet)
2509   {
2510     if(newArray!=arrayToSet)
2511       {
2512         if(arrayToSet)
2513           arrayToSet->decrRef();
2514         arrayToSet=newArray;
2515         if(arrayToSet)
2516           arrayToSet->incrRef();
2517       }
2518   }
2519
2520     /*!
2521    * Assign zero to all values in \a this array. To know more on filling arrays see
2522    * \ref MEDCouplingArrayFill.
2523    * \throw If \a this is not allocated.
2524    */
2525   template<class T>
2526   void DataArrayTemplate<T>::fillWithZero()
2527   {
2528     fillWithValue((T)0);
2529   }
2530
2531   //////////////////////////////
2532
2533   namespace
2534   {
2535     // local static function to copy arrays without warnings
2536     template <class TIn, class TOut>
2537     static void copyCast (const TIn *begin, const TIn *end, TOut* dest)
2538     {
2539       for (const TIn *src = begin; src != end; ++src, ++dest)
2540         *dest=static_cast<TOut>(*src);
2541     }
2542   }
2543
2544   template<class T>
2545   template<class U>
2546   MCAuto< typename Traits<U>::ArrayType > DataArrayTemplateClassic<T>::convertToOtherTypeOfArr() const
2547   {
2548     this->checkAllocated();
2549     MCAuto<typename Traits<U>::ArrayType> ret(Traits<U>::ArrayType::New());
2550     ret->alloc(this->getNumberOfTuples(),this->getNumberOfComponents());
2551     std::size_t nbOfVals(this->getNbOfElems());
2552     const T *src(this->begin());
2553     U *dest(ret->getPointer());
2554     // to make Visual C++ happy : instead of std::size_t nbOfVals=getNbOfElems(); std::copy(src,src+nbOfVals,dest);
2555     copyCast(src, src+nbOfVals, dest);
2556     //std::copy(src,src+nbOfVals,dest);
2557     ret->copyStringInfoFrom(*this);
2558     return ret;
2559   }
2560   
2561   /*!
2562    * Creates a new DataArrayDouble and assigns all (textual and numerical) data of \a this
2563    * array to the new one.
2564    *  \return DataArrayDouble * - the new instance of DataArrayInt.
2565    */
2566   template<class T>
2567   MCAuto<DataArrayDouble> DataArrayTemplateClassic<T>::convertToDblArr() const
2568   {
2569     return convertToOtherTypeOfArr<double>();
2570   }
2571
2572   /*!
2573    * Creates a new DataArrayInt and assigns all (textual and numerical) data of \a this
2574    * array to the new one.
2575    *  \return DataArrayInt * - the new instance of DataArrayInt.
2576    */
2577   template<class T>
2578   MCAuto<DataArrayInt> DataArrayTemplateClassic<T>::convertToIntArr() const
2579   {
2580     return convertToOtherTypeOfArr<int>();
2581   }
2582
2583   /*!
2584    * Creates a new DataArrayFloat and assigns all (textual and numerical) data of \a this
2585    * array to the new one.
2586    *  \return DataArrayFloat * - the new instance of DataArrayInt.
2587    */
2588   template<class T>
2589   MCAuto<DataArrayFloat> DataArrayTemplateClassic<T>::convertToFloatArr() const
2590   {
2591     return convertToOtherTypeOfArr<float>();
2592   }
2593
2594   /*!
2595    * Apply a linear function to a given component of \a this array, so that
2596    * an array element <em>(x)</em> becomes \f$ a * x + b \f$.
2597    *  \param [in] a - the first coefficient of the function.
2598    *  \param [in] b - the second coefficient of the function.
2599    *  \param [in] compoId - the index of component to modify.
2600    *  \throw If \a this is not allocated, or \a compoId is not in [0,\c this->getNumberOfComponents() ).
2601    */
2602   template<class T>
2603   void DataArrayTemplateClassic<T>::applyLin(T a, T b, std::size_t compoId)
2604   {
2605     this->checkAllocated();
2606     std::size_t nbOfComp=this->getNumberOfComponents();
2607     if(compoId>=nbOfComp)
2608       {
2609         std::ostringstream oss; oss << "DataArrayDouble::applyLin : The compoId requested (" << compoId << ") is not valid ! Must be in [0," << nbOfComp << ") !";
2610         throw INTERP_KERNEL::Exception(oss.str().c_str());
2611       }
2612     T *ptr(this->getPointer()+compoId);
2613     mcIdType nbOfTuple=this->getNumberOfTuples();
2614     for(mcIdType i=0;i<nbOfTuple;i++,ptr+=nbOfComp)
2615       *ptr=a*(*ptr)+b;
2616     this->declareAsNew();
2617   }
2618
2619   /*!
2620    * Apply a linear function to all elements of \a this array, so that
2621    * an element _x_ becomes \f$ a * x + b \f$.
2622    *  \param [in] a - the first coefficient of the function.
2623    *  \param [in] b - the second coefficient of the function.
2624    *  \throw If \a this is not allocated.
2625    */
2626   template<class T>
2627   void DataArrayTemplateClassic<T>::applyLin(T a, T b)
2628   {
2629     this->checkAllocated();
2630     T *ptr(this->getPointer());
2631     std::size_t nbOfElems(this->getNbOfElems());
2632     for(std::size_t i=0;i<nbOfElems;i++,ptr++)
2633       *ptr=a*(*ptr)+b;
2634     this->declareAsNew();
2635   }
2636   
2637   /*!
2638    * Returns a full copy of \a this array except that sign of all elements is reversed.
2639    *  \return DataArrayDouble * - the new instance of DataArrayDouble containing the
2640    *          same number of tuples and component as \a this array.
2641    *          The caller is to delete this result array using decrRef() as it is no more
2642    *          needed.
2643    *  \throw If \a this is not allocated.
2644    */
2645   template<class T>
2646   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::negate() const
2647   {
2648     this->checkAllocated();
2649     MCAuto<typename Traits<T>::ArrayType> newArr(Traits<T>::ArrayType::New());
2650     mcIdType nbOfTuples(this->getNumberOfTuples());
2651     std::size_t nbOfComp(this->getNumberOfComponents());
2652     newArr->alloc(nbOfTuples,nbOfComp);
2653     const T *cptr(this->begin());
2654     std::transform(cptr,cptr+nbOfTuples*nbOfComp,newArr->getPointer(),std::negate<T>());
2655     newArr->copyStringInfoFrom(*this);
2656     return newArr.retn();
2657   }
2658
2659   template<class T>
2660   template<class FCT>
2661   void DataArrayTemplateClassic<T>::somethingEqual(const typename Traits<T>::ArrayType *other)
2662   {
2663     if(!other)
2664       throw INTERP_KERNEL::Exception("DataArray<T>::SomethingEqual : input DataArray<T> instance is NULL !");
2665     const char *msg="Nb of tuples mismatch for DataArrayDouble::multiplyEqual !";
2666     this->checkAllocated();
2667     other->checkAllocated();
2668     mcIdType nbOfTuple(this->getNumberOfTuples());
2669     mcIdType nbOfTuple2(other->getNumberOfTuples());
2670     std::size_t nbOfComp(this->getNumberOfComponents());
2671     std::size_t nbOfComp2(other->getNumberOfComponents());
2672     if(nbOfTuple==nbOfTuple2)
2673       {
2674         if(nbOfComp==nbOfComp2)
2675           {
2676             std::transform(this->begin(),this->end(),other->begin(),this->getPointer(),FCT());
2677           }
2678         else if(nbOfComp2==1)
2679           {
2680             T *ptr(this->getPointer());
2681             const T *ptrc(other->begin());
2682             for(mcIdType i=0;i<nbOfTuple;i++)
2683               std::transform(ptr+i*nbOfComp,ptr+(i+1)*nbOfComp,ptr+i*nbOfComp,std::bind2nd(FCT(),*ptrc++));
2684           }
2685         else
2686           throw INTERP_KERNEL::Exception(msg);
2687       }
2688     else if(nbOfTuple2==1)
2689       {
2690         if(nbOfComp2==nbOfComp)
2691           {
2692             T *ptr(this->getPointer());
2693             const T *ptrc(other->begin());
2694             for(mcIdType i=0;i<nbOfTuple;i++)
2695               std::transform(ptr+i*nbOfComp,ptr+(i+1)*nbOfComp,ptrc,ptr+i*nbOfComp,FCT());
2696           }
2697         else
2698           throw INTERP_KERNEL::Exception(msg);
2699       }
2700     else
2701       throw INTERP_KERNEL::Exception(msg);
2702     this->declareAsNew();
2703   }
2704   
2705   /*!
2706    * Adds values of another DataArrayDouble to values of \a this one. There are 3
2707    * valid cases.
2708    * 1.  The arrays have same number of tuples and components. Then each value of
2709    *   \a other array is added to the corresponding value of \a this array, i.e.:
2710    *   _a_ [ i, j ] += _other_ [ i, j ].
2711    * 2.  The arrays have same number of tuples and \a other array has one component. Then
2712    *   _a_ [ i, j ] += _other_ [ i, 0 ].
2713    * 3.  The arrays have same number of components and \a other array has one tuple. Then
2714    *   _a_ [ i, j ] += _a2_ [ 0, j ].
2715    *
2716    *  \param [in] other - an array to add to \a this one.
2717    *  \throw If \a other is NULL.
2718    *  \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples() and
2719    *         \a this->getNumberOfComponents() != \a other->getNumberOfComponents() and
2720    *         \a other has number of both tuples and components not equal to 1.
2721    */
2722   template<class T>
2723   void DataArrayTemplateClassic<T>::addEqual(const typename Traits<T>::ArrayType *other)
2724   {
2725     this->somethingEqual< std::plus<T> >(other);
2726   }
2727
2728   /*!
2729    * Subtract values of another DataArrayDouble from values of \a this one. There are 3
2730    * valid cases.
2731    * 1.  The arrays have same number of tuples and components. Then each value of
2732    *   \a other array is subtracted from the corresponding value of \a this array, i.e.:
2733    *   _a_ [ i, j ] -= _other_ [ i, j ].
2734    * 2.  The arrays have same number of tuples and \a other array has one component. Then
2735    *   _a_ [ i, j ] -= _other_ [ i, 0 ].
2736    * 3.  The arrays have same number of components and \a other array has one tuple. Then
2737    *   _a_ [ i, j ] -= _a2_ [ 0, j ].
2738    *
2739    *  \param [in] other - an array to subtract from \a this one.
2740    *  \throw If \a other is NULL.
2741    *  \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples() and
2742    *         \a this->getNumberOfComponents() != \a other->getNumberOfComponents() and
2743    *         \a other has number of both tuples and components not equal to 1.
2744    */
2745   template<class T>
2746   void DataArrayTemplateClassic<T>::substractEqual(const typename Traits<T>::ArrayType *other)
2747   {
2748     this->somethingEqual< std::minus<T> >(other);
2749   }
2750   
2751   /*!
2752    * Multiply values of another DataArrayDouble to values of \a this one. There are 3
2753    * valid cases.
2754    * 1.  The arrays have same number of tuples and components. Then each value of
2755    *   \a other array is multiplied to the corresponding value of \a this array, i.e.
2756    *   _this_ [ i, j ] *= _other_ [ i, j ].
2757    * 2.  The arrays have same number of tuples and \a other array has one component. Then
2758    *   _this_ [ i, j ] *= _other_ [ i, 0 ].
2759    * 3.  The arrays have same number of components and \a other array has one tuple. Then
2760    *   _this_ [ i, j ] *= _a2_ [ 0, j ].
2761    *
2762    *  \param [in] other - an array to multiply to \a this one.
2763    *  \throw If \a other is NULL.
2764    *  \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples() and
2765    *         \a this->getNumberOfComponents() != \a other->getNumberOfComponents() and
2766    *         \a other has number of both tuples and components not equal to 1.
2767    */
2768   template<class T>
2769   void DataArrayTemplateClassic<T>::multiplyEqual(const typename Traits<T>::ArrayType *other)
2770   {
2771     this->somethingEqual< std::multiplies<T> >(other);
2772   }
2773
2774   /*!
2775    * Divide values of \a this array by values of another DataArrayDouble. There are 3
2776    * valid cases.
2777    * 1.  The arrays have same number of tuples and components. Then each value of
2778    *    \a this array is divided by the corresponding value of \a other one, i.e.:
2779    *   _a_ [ i, j ] /= _other_ [ i, j ].
2780    * 2.  The arrays have same number of tuples and \a other array has one component. Then
2781    *   _a_ [ i, j ] /= _other_ [ i, 0 ].
2782    * 3.  The arrays have same number of components and \a other array has one tuple. Then
2783    *   _a_ [ i, j ] /= _a2_ [ 0, j ].
2784    *
2785    *  \warning No check of division by zero is performed!
2786    *  \param [in] other - an array to divide \a this one by.
2787    *  \throw If \a other is NULL.
2788    *  \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples() and
2789    *         \a this->getNumberOfComponents() != \a other->getNumberOfComponents() and
2790    *         \a other has number of both tuples and components not equal to 1.
2791    */
2792   template<class T>
2793   void DataArrayTemplateClassic<T>::divideEqual(const typename Traits<T>::ArrayType *other)
2794   {
2795     this->somethingEqual< std::divides<T> >(other);
2796   }
2797   
2798   template<class T, class FCT>
2799   typename Traits<T>::ArrayType *DivSub(const typename Traits<T>::ArrayType *a1, const typename Traits<T>::ArrayType *a2)
2800   {
2801     if(!a1 || !a2)
2802       throw INTERP_KERNEL::Exception("DivSub : input DataArrayDouble instance is NULL !");
2803     mcIdType nbOfTuple1(a1->getNumberOfTuples());
2804     mcIdType nbOfTuple2(a2->getNumberOfTuples());
2805     std::size_t nbOfComp1(a1->getNumberOfComponents());
2806     std::size_t nbOfComp2(a2->getNumberOfComponents());
2807     if(nbOfTuple2==nbOfTuple1)
2808       {
2809         if(nbOfComp1==nbOfComp2)
2810           {
2811             MCAuto<typename Traits<T>::ArrayType> ret(Traits<T>::ArrayType::New());
2812             ret->alloc(nbOfTuple2,nbOfComp1);
2813             std::transform(a1->begin(),a1->end(),a2->begin(),ret->getPointer(),FCT());
2814             ret->copyStringInfoFrom(*a1);
2815             return ret.retn();
2816           }
2817         else if(nbOfComp2==1)
2818           {
2819             MCAuto<typename Traits<T>::ArrayType> ret(Traits<T>::ArrayType::New());
2820             ret->alloc(nbOfTuple1,nbOfComp1);
2821             const T *a2Ptr(a2->begin()),*a1Ptr(a1->begin());
2822             T *res(ret->getPointer());
2823             for(mcIdType i=0;i<nbOfTuple1;i++)
2824               res=std::transform(a1Ptr+i*nbOfComp1,a1Ptr+(i+1)*nbOfComp1,res,std::bind2nd(FCT(),a2Ptr[i]));
2825             ret->copyStringInfoFrom(*a1);
2826             return ret.retn();
2827           }
2828         else
2829           {
2830             a1->checkNbOfComps(nbOfComp2,"Nb of components mismatch for array Divide !");
2831             return 0;
2832           }
2833       }
2834     else if(nbOfTuple2==1)
2835       {
2836         a1->checkNbOfComps(nbOfComp2,"Nb of components mismatch for array Divide !");
2837         MCAuto<typename Traits<T>::ArrayType> ret(Traits<T>::ArrayType::New());
2838         ret->alloc(nbOfTuple1,nbOfComp1);
2839         const T *a1ptr=a1->begin(),*a2ptr(a2->begin());
2840         T *pt(ret->getPointer());
2841         for(mcIdType i=0;i<nbOfTuple1;i++)
2842           pt=std::transform(a1ptr+i*nbOfComp1,a1ptr+(i+1)*nbOfComp1,a2ptr,pt,FCT());
2843         ret->copyStringInfoFrom(*a1);
2844         return ret.retn();
2845       }
2846     else
2847       {
2848         a1->checkNbOfTuples(nbOfTuple2,"Nb of tuples mismatch for array Divide !");//will always throw an exception
2849         return 0;
2850       }
2851   }
2852   
2853   /*!
2854    * Returns a new DataArrayDouble that is a subtraction of two given arrays. There are 3
2855    * valid cases.
2856    * 1.  The arrays have same number of tuples and components. Then each value of
2857    *   the result array (_a_) is a subtraction of the corresponding values of \a a1 and
2858    *   \a a2, i.e.: _a_ [ i, j ] = _a1_ [ i, j ] - _a2_ [ i, j ].
2859    * 2.  The arrays have same number of tuples and one array, say _a2_, has one
2860    *   component. Then
2861    *   _a_ [ i, j ] = _a1_ [ i, j ] - _a2_ [ i, 0 ].
2862    * 3.  The arrays have same number of components and one array, say _a2_, has one
2863    *   tuple. Then
2864    *   _a_ [ i, j ] = _a1_ [ i, j ] - _a2_ [ 0, j ].
2865    *
2866    * Info on components is copied either from the first array (in the first case) or from
2867    * the array with maximal number of elements (getNbOfElems()).
2868    *  \param [in] a1 - an array to subtract from.
2869    *  \param [in] a2 - an array to subtract.
2870    *  \return DataArrayDouble * - the new instance of DataArrayDouble.
2871    *          The caller is to delete this result array using decrRef() as it is no more
2872    *          needed.
2873    *  \throw If either \a a1 or \a a2 is NULL.
2874    *  \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples() and
2875    *         \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents() and
2876    *         none of them has number of tuples or components equal to 1.
2877    */
2878   template<class T>
2879   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::Substract(const typename Traits<T>::ArrayType *a1, const typename Traits<T>::ArrayType *a2)
2880   {
2881     return DivSub< T,std::minus<T> >(a1,a2);
2882   }
2883   
2884   /*!
2885    * Returns a new DataArrayDouble that is a division of two given arrays. There are 3
2886    * valid cases.
2887    * 1.  The arrays have same number of tuples and components. Then each value of
2888    *   the result array (_a_) is a division of the corresponding values of \a a1 and
2889    *   \a a2, i.e.: _a_ [ i, j ] = _a1_ [ i, j ] / _a2_ [ i, j ].
2890    * 2.  The arrays have same number of tuples and one array, say _a2_, has one
2891    *   component. Then
2892    *   _a_ [ i, j ] = _a1_ [ i, j ] / _a2_ [ i, 0 ].
2893    * 3.  The arrays have same number of components and one array, say _a2_, has one
2894    *   tuple. Then
2895    *   _a_ [ i, j ] = _a1_ [ i, j ] / _a2_ [ 0, j ].
2896    *
2897    * Info on components is copied either from the first array (in the first case) or from
2898    * the array with maximal number of elements (getNbOfElems()).
2899    *  \warning No check of division by zero is performed!
2900    *  \param [in] a1 - a numerator array.
2901    *  \param [in] a2 - a denominator array.
2902    *  \return DataArrayDouble * - the new instance of DataArrayDouble.
2903    *          The caller is to delete this result array using decrRef() as it is no more
2904    *          needed.
2905    *  \throw If either \a a1 or \a a2 is NULL.
2906    *  \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples() and
2907    *         \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents() and
2908    *         none of them has number of tuples or components equal to 1.
2909    */
2910   template<class T>
2911   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::Divide(const typename Traits<T>::ArrayType *a1, const typename Traits<T>::ArrayType *a2)
2912   {
2913     return DivSub< T,std::divides<T> >(a1,a2);
2914   }
2915
2916   template<class T, class FCT>
2917   typename Traits<T>::ArrayType *MulAdd(const typename Traits<T>::ArrayType *a1, const typename Traits<T>::ArrayType *a2)
2918   {
2919     if(!a1 || !a2)
2920       throw INTERP_KERNEL::Exception("DataArrayDouble::MulAdd : input DataArrayDouble instance is NULL !");
2921     mcIdType nbOfTuple(a1->getNumberOfTuples());
2922     mcIdType nbOfTuple2(a2->getNumberOfTuples());
2923     std::size_t nbOfComp(a1->getNumberOfComponents());
2924     std::size_t nbOfComp2(a2->getNumberOfComponents());
2925     MCAuto<typename Traits<T>::ArrayType> ret=0;
2926     if(nbOfTuple==nbOfTuple2)
2927       {
2928         if(nbOfComp==nbOfComp2)
2929           {
2930             ret=Traits<T>::ArrayType::New();
2931             ret->alloc(nbOfTuple,nbOfComp);
2932             std::transform(a1->begin(),a1->end(),a2->begin(),ret->getPointer(),FCT());
2933             ret->copyStringInfoFrom(*a1);
2934           }
2935         else
2936           {
2937             std::size_t nbOfCompMin,nbOfCompMax;
2938             const typename Traits<T>::ArrayType *aMin, *aMax;
2939             if(nbOfComp>nbOfComp2)
2940               {
2941                 nbOfCompMin=nbOfComp2; nbOfCompMax=nbOfComp;
2942                 aMin=a2; aMax=a1;
2943               }
2944             else
2945               {
2946                 nbOfCompMin=nbOfComp; nbOfCompMax=nbOfComp2;
2947                 aMin=a1; aMax=a2;
2948               }
2949             if(nbOfCompMin==1)
2950               {
2951                 ret=Traits<T>::ArrayType::New();
2952                 ret->alloc(nbOfTuple,nbOfCompMax);
2953                 const T *aMinPtr(aMin->begin());
2954                 const T *aMaxPtr(aMax->begin());
2955                 T *res=ret->getPointer();
2956                 for(mcIdType i=0;i<nbOfTuple;i++)
2957                   res=std::transform(aMaxPtr+i*nbOfCompMax,aMaxPtr+(i+1)*nbOfCompMax,res,std::bind2nd(FCT(),aMinPtr[i]));
2958                 ret->copyStringInfoFrom(*aMax);
2959               }
2960             else
2961               throw INTERP_KERNEL::Exception("Nb of components mismatch for array MulAdd !");
2962           }
2963       }
2964     else if((nbOfTuple==1 && nbOfTuple2>1) || (nbOfTuple>1 && nbOfTuple2==1))
2965       {
2966         if(nbOfComp==nbOfComp2)
2967           {
2968             mcIdType nbOfTupleMax=std::max(nbOfTuple,nbOfTuple2);
2969             const typename Traits<T>::ArrayType *aMin(nbOfTuple>nbOfTuple2?a2:a1);
2970             const typename Traits<T>::ArrayType *aMax(nbOfTuple>nbOfTuple2?a1:a2);
2971             const T *aMinPtr(aMin->begin()),*aMaxPtr(aMax->begin());
2972             ret=Traits<T>::ArrayType::New();
2973             ret->alloc(nbOfTupleMax,nbOfComp);
2974             T *res(ret->getPointer());
2975             for(mcIdType i=0;i<nbOfTupleMax;i++)
2976               res=std::transform(aMaxPtr+i*nbOfComp,aMaxPtr+(i+1)*nbOfComp,aMinPtr,res,FCT());
2977             ret->copyStringInfoFrom(*aMax);
2978           }
2979         else
2980           throw INTERP_KERNEL::Exception("Nb of components mismatch for array MulAdd !");
2981       }
2982     else
2983       throw INTERP_KERNEL::Exception("Nb of tuples mismatch for array MulAdd !");
2984     return ret.retn();
2985   }
2986   
2987   /*!
2988    * Returns a new DataArrayDouble that is a product of two given arrays. There are 3
2989    * valid cases.
2990    * 1.  The arrays have same number of tuples and components. Then each value of
2991    *   the result array (_a_) is a product of the corresponding values of \a a1 and
2992    *   \a a2, i.e. _a_ [ i, j ] = _a1_ [ i, j ] * _a2_ [ i, j ].
2993    * 2.  The arrays have same number of tuples and one array, say _a2_, has one
2994    *   component. Then
2995    *   _a_ [ i, j ] = _a1_ [ i, j ] * _a2_ [ i, 0 ].
2996    * 3.  The arrays have same number of components and one array, say _a2_, has one
2997    *   tuple. Then
2998    *   _a_ [ i, j ] = _a1_ [ i, j ] * _a2_ [ 0, j ].
2999    *
3000    * Info on components is copied either from the first array (in the first case) or from
3001    * the array with maximal number of elements (getNbOfElems()).
3002    *  \param [in] a1 - a factor array.
3003    *  \param [in] a2 - another factor array.
3004    *  \return DataArrayDouble * - the new instance of DataArrayDouble.
3005    *          The caller is to delete this result array using decrRef() as it is no more
3006    *          needed.
3007    *  \throw If either \a a1 or \a a2 is NULL.
3008    *  \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples() and
3009    *         \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents() and
3010    *         none of them has number of tuples or components equal to 1.
3011    */
3012   template<class T>
3013   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::Multiply(const typename Traits<T>::ArrayType *a1, const typename Traits<T>::ArrayType *a2)
3014   {
3015     return MulAdd< T , std::multiplies<T> >(a1,a2);
3016   }
3017   
3018   /*!
3019    * Returns a new DataArrayDouble that is a sum of two given arrays. There are 3
3020    * valid cases.
3021    * 1.  The arrays have same number of tuples and components. Then each value of
3022    *   the result array (_a_) is a sum of the corresponding values of \a a1 and \a a2,
3023    *   i.e.: _a_ [ i, j ] = _a1_ [ i, j ] + _a2_ [ i, j ].
3024    * 2.  The arrays have same number of tuples and one array, say _a2_, has one
3025    *   component. Then
3026    *   _a_ [ i, j ] = _a1_ [ i, j ] + _a2_ [ i, 0 ].
3027    * 3.  The arrays have same number of components and one array, say _a2_, has one
3028    *   tuple. Then
3029    *   _a_ [ i, j ] = _a1_ [ i, j ] + _a2_ [ 0, j ].
3030    *
3031    * Info on components is copied either from the first array (in the first case) or from
3032    * the array with maximal number of elements (getNbOfElems()).
3033    *  \param [in] a1 - an array to sum up.
3034    *  \param [in] a2 - another array to sum up.
3035    *  \return DataArrayDouble * - the new instance of DataArrayDouble.
3036    *          The caller is to delete this result array using decrRef() as it is no more
3037    *          needed.
3038    *  \throw If either \a a1 or \a a2 is NULL.
3039    *  \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples() and
3040    *         \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents() and
3041    *         none of them has number of tuples or components equal to 1.
3042    */
3043   template<class T>
3044   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::Add(const typename Traits<T>::ArrayType *a1, const typename Traits<T>::ArrayType *a2)
3045   {
3046     return MulAdd< T , std::plus<T> >(a1,a2);
3047   }
3048   
3049   /*!
3050    * Returns either a \a deep or \a shallow copy of this array. For more info see
3051    * \ref MEDCouplingArrayBasicsCopyDeep and \ref MEDCouplingArrayBasicsCopyShallow.
3052    *  \param [in] dCpy - if \a true, a deep copy is returned, else, a shallow one.
3053    *  \return DataArrayDouble * - either a new instance of DataArrayDouble (if \a dCpy
3054    *          == \a true) or \a this instance (if \a dCpy == \a false).
3055    */
3056   template<class T>
3057   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::PerformCopyOrIncrRef(bool dCpy, const typename Traits<T>::ArrayType& self)
3058   {
3059     if(dCpy)
3060       return self.deepCopy();
3061     else
3062       {
3063         self.incrRef();
3064         return const_cast<typename Traits<T>::ArrayType *>(&self);
3065       }
3066   }
3067
3068   template<class T>
3069   struct GreatEqual
3070   {
3071     GreatEqual(T v):_v(v) { }
3072     bool operator()(T v) const { return v>=_v; }
3073     T _v;
3074   };
3075   
3076   template<class T>
3077   struct GreaterThan
3078   {
3079     GreaterThan(T v):_v(v) { }
3080     bool operator()(T v) const { return v>_v; }
3081     T _v;
3082   };
3083   
3084   template<class T>
3085   struct LowerEqual
3086   {
3087     LowerEqual(T v):_v(v) { }
3088     bool operator()(T v) const { return v<=_v; }
3089     T _v;
3090   };
3091   
3092   template<class T>
3093   struct LowerThan
3094   {
3095     LowerThan(T v):_v(v) { }
3096     bool operator()(T v) const { return v<_v; }
3097     T _v;
3098   };
3099   
3100   template<class T>
3101   struct InRange
3102   {
3103     InRange(T a, T b):_a(a),_b(b) { }
3104     bool operator()(T v) const { return v>=_a && v<_b; }
3105     T _a,_b;
3106   };
3107
3108 template<class T>
3109 struct NotInRange
3110 {
3111   NotInRange(T a, T b):_a(a),_b(b) { }
3112   bool operator()(T v) const { return v<_a || v>=_b; }
3113   T _a,_b;
3114 };
3115
3116   /*!
3117    * 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.
3118    *
3119    * \return a newly allocated data array that the caller should deal with.
3120    * \sa DataArrayInt::findIdsInRange
3121    */
3122   template<class T>
3123   DataArrayIdType *DataArrayTemplateClassic<T>::findIdsStrictlyNegative() const
3124   {
3125     LowerThan<T> lt((T)0);
3126     MCAuto<DataArrayIdType> ret(findIdsAdv(lt));
3127     return ret.retn();
3128   }
3129   
3130   template<class T>
3131   MCAuto<DataArrayIdType> DataArrayTemplateClassic<T>::findIdsGreaterOrEqualTo(T val) const
3132   {
3133     GreatEqual<T> ge(val);
3134     return findIdsAdv(ge);
3135   }
3136   
3137   template<class T>
3138   MCAuto<DataArrayIdType> DataArrayTemplateClassic<T>::findIdsGreaterThan(T val) const
3139   {
3140     GreaterThan<T> gt(val);
3141     return findIdsAdv(gt);
3142   }
3143   
3144   template<class T>
3145   MCAuto<DataArrayIdType> DataArrayTemplateClassic<T>::findIdsLowerOrEqualTo(T val) const
3146   {
3147     LowerEqual<T> le(val);
3148     return findIdsAdv(le);
3149   }
3150   
3151   template<class T>
3152   MCAuto<DataArrayIdType> DataArrayTemplateClassic<T>::findIdsLowerThan(T val) const
3153   {
3154     LowerThan<T> lt(val);
3155     return findIdsAdv(lt);
3156   }
3157
3158   /*!
3159    * Returns a new DataArrayDouble by aggregating two given arrays, so that (1) the number
3160    * of components in the result array is a sum of the number of components of given arrays
3161    * and (2) the number of tuples in the result array is same as that of each of given
3162    * arrays. In other words the i-th tuple of result array includes all components of
3163    * i-th tuples of all given arrays.
3164    * Number of tuples in the given arrays must be  the same.
3165    *  \param [in] a1 - an array to include in the result array.
3166    *  \param [in] a2 - another array to include in the result array.
3167    *  \return DataArrayDouble * - the new instance of DataArrayDouble.
3168    *          The caller is to delete this result array using decrRef() as it is no more
3169    *          needed.
3170    *  \throw If both \a a1 and \a a2 are NULL.
3171    *  \throw If any given array is not allocated.
3172    *  \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples()
3173    */
3174   template<class T>
3175   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::Meld(const typename Traits<T>::ArrayType *a1, const typename Traits<T>::ArrayType *a2)
3176   {
3177     std::vector<const typename Traits<T>::ArrayType *> arr(2);
3178     arr[0]=a1; arr[1]=a2;
3179     return Meld(arr);
3180   }
3181
3182   /*!
3183    * Returns a new DataArrayDouble by aggregating all given arrays, so that (1) the number
3184    * of components in the result array is a sum of the number of components of given arrays
3185    * and (2) the number of tuples in the result array is same as that of each of given
3186    * arrays. In other words the i-th tuple of result array includes all components of
3187    * i-th tuples of all given arrays.
3188    * Number of tuples in the given arrays must be  the same.
3189    *  \param [in] arr - a sequence of arrays to include in the result array.
3190    *  \return DataArrayDouble * - the new instance of DataArrayDouble.
3191    *          The caller is to delete this result array using decrRef() as it is no more
3192    *          needed.
3193    *  \throw If all arrays within \a arr are NULL.
3194    *  \throw If any given array is not allocated.
3195    *  \throw If getNumberOfTuples() of arrays within \a arr is different.
3196    */
3197   template<class T>
3198   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::Meld(const std::vector<const typename Traits<T>::ArrayType *>& arr)
3199   {
3200     std::vector<const typename Traits<T>::ArrayType *> a;
3201     for(typename std::vector<const typename Traits<T>::ArrayType *>::const_iterator it4=arr.begin();it4!=arr.end();it4++)
3202       if(*it4)
3203         a.push_back(*it4);
3204     if(a.empty())
3205       throw INTERP_KERNEL::Exception("DataArrayDouble::Meld : input list must contain at least one NON EMPTY DataArrayDouble !");
3206     typename std::vector<const typename Traits<T>::ArrayType *>::const_iterator it;
3207     for(it=a.begin();it!=a.end();it++)
3208       (*it)->checkAllocated();
3209     it=a.begin();
3210     mcIdType nbOfTuples((*it)->getNumberOfTuples());
3211     std::vector<std::size_t> nbc(a.size());
3212     std::vector<const T *> pts(a.size());
3213     nbc[0]=(*it)->getNumberOfComponents();
3214     pts[0]=(*it++)->getConstPointer();
3215     for(mcIdType i=1;it!=a.end();it++,i++)
3216       {
3217         if(nbOfTuples!=(*it)->getNumberOfTuples())
3218           throw INTERP_KERNEL::Exception("DataArrayDouble::Meld : mismatch of number of tuples !");
3219         nbc[i]=(*it)->getNumberOfComponents();
3220         pts[i]=(*it)->getConstPointer();
3221       }
3222     std::size_t totalNbOfComp=std::accumulate(nbc.begin(),nbc.end(),(std::size_t)0);
3223     typename Traits<T>::ArrayType *ret(Traits<T>::ArrayType::New());
3224     ret->alloc(nbOfTuples,totalNbOfComp);
3225     T *retPtr(ret->getPointer());
3226     for(mcIdType i=0;i<nbOfTuples;i++)
3227       for(std::size_t j=0;j<a.size();j++)
3228         {
3229           retPtr=std::copy(pts[j],pts[j]+nbc[j],retPtr);
3230           pts[j]+=nbc[j];
3231         }
3232     std::size_t k=0;
3233     for(std::size_t i=0;i<a.size();i++)
3234       for(std::size_t j=0;j<nbc[i];j++,k++)
3235         ret->setInfoOnComponent(k,a[i]->getInfoOnComponent(j));
3236     return ret;
3237   }
3238
3239   /*!
3240    * Returns a new DataArrayDouble holding the same values as \a this array but differently
3241    * arranged in memory. If \a this array holds 2 components of 3 values:
3242    * \f$ x_0,x_1,x_2,y_0,y_1,y_2 \f$, then the result array holds these values arranged
3243    * as follows: \f$ x_0,y_0,x_1,y_1,x_2,y_2 \f$.
3244    *  \warning Do not confuse this method with transpose()!
3245    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
3246    *          is to delete using decrRef() as it is no more needed.
3247    *  \throw If \a this is not allocated.
3248    */
3249   template<class T>
3250   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::fromNoInterlace() const
3251   {
3252     if(this->_mem.isNull())
3253       throw INTERP_KERNEL::Exception("DataArrayDouble::fromNoInterlace : Not defined array !");
3254     T *tab(this->_mem.fromNoInterlace(this->getNumberOfComponents()));
3255     MCAuto<typename Traits<T>::ArrayType> ret(Traits<T>::ArrayType::New());
3256     ret->useArray(tab,true,DeallocType::C_DEALLOC,this->getNumberOfTuples(),this->getNumberOfComponents());
3257     return ret.retn();
3258   }
3259
3260   /*!
3261    * Returns a new DataArrayDouble holding the same values as \a this array but differently
3262    * arranged in memory. If \a this array holds 2 components of 3 values:
3263    * \f$ x_0,y_0,x_1,y_1,x_2,y_2 \f$, then the result array holds these values arranged
3264    * as follows: \f$ x_0,x_1,x_2,y_0,y_1,y_2 \f$.
3265    *  \warning Do not confuse this method with transpose()!
3266    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
3267    *          is to delete using decrRef() as it is no more needed.
3268    *  \throw If \a this is not allocated.
3269    */
3270   template<class T>
3271   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::toNoInterlace() const
3272   {
3273     if(this->_mem.isNull())
3274       throw INTERP_KERNEL::Exception("DataArrayDouble::toNoInterlace : Not defined array !");
3275     T *tab(this->_mem.toNoInterlace(this->getNumberOfComponents()));
3276     MCAuto<typename Traits<T>::ArrayType> ret(Traits<T>::ArrayType::New());
3277     ret->useArray(tab,true,DeallocType::C_DEALLOC,this->getNumberOfTuples(),this->getNumberOfComponents());
3278     return ret.retn();
3279   }
3280   
3281   /*!
3282    * Appends components of another array to components of \a this one, tuple by tuple.
3283    * So that the number of tuples of \a this array remains the same and the number of 
3284    * components increases.
3285    *  \param [in] other - the DataArrayDouble to append to \a this one.
3286    *  \throw If \a this is not allocated.
3287    *  \throw If \a this and \a other arrays have different number of tuples.
3288    *
3289    *  \if ENABLE_EXAMPLES
3290    *  \ref cpp_mcdataarraydouble_meldwith "Here is a C++ example".
3291    *
3292    *  \ref py_mcdataarraydouble_meldwith "Here is a Python example".
3293    *  \endif
3294    */
3295   template<class T>
3296   void DataArrayTemplateClassic<T>::meldWith(const typename Traits<T>::ArrayType *other)
3297   {
3298     this->checkAllocated();
3299     other->checkAllocated();
3300     mcIdType nbOfTuples(this->getNumberOfTuples());
3301     if(nbOfTuples!=other->getNumberOfTuples())
3302       throw INTERP_KERNEL::Exception("DataArrayDouble::meldWith : mismatch of number of tuples !");
3303     std::size_t nbOfComp1=this->getNumberOfComponents();
3304     std::size_t nbOfComp2=other->getNumberOfComponents();
3305     T *newArr=(T *)malloc((nbOfTuples*(nbOfComp1+nbOfComp2))*sizeof(T));
3306     T *w=newArr;
3307     const T *inp1(this->begin()),*inp2(other->begin());
3308     for(mcIdType i=0;i<nbOfTuples;i++,inp1+=nbOfComp1,inp2+=nbOfComp2)
3309       {
3310         w=std::copy(inp1,inp1+nbOfComp1,w);
3311         w=std::copy(inp2,inp2+nbOfComp2,w);
3312       }
3313     this->useArray(newArr,true,DeallocType::C_DEALLOC,nbOfTuples,nbOfComp1+nbOfComp2);
3314     std::vector<std::size_t> compIds(nbOfComp2);
3315     for(std::size_t i=0;i<nbOfComp2;i++)
3316       compIds[i]=nbOfComp1+i;
3317     this->copyPartOfStringInfoFrom2(compIds,*other);
3318   }
3319
3320   /*!
3321    * 
3322    * \param [in] nbTimes specifies the nb of times each tuples in \a this will be duplicated contiguouly in returned DataArrayDouble instance.
3323    *             \a nbTimes  should be at least equal to 1.
3324    * \return a newly allocated DataArrayDouble having one component and number of tuples equal to \a nbTimes * \c this->getNumberOfTuples.
3325    * \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.
3326    */
3327   template<class T>
3328   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::duplicateEachTupleNTimes(mcIdType nbTimes) const
3329   {
3330     this->checkAllocated();
3331     if(this->getNumberOfComponents()!=1)
3332       throw INTERP_KERNEL::Exception("DataArrayDouble::duplicateEachTupleNTimes : this should have only one component !");
3333     if(nbTimes<1)
3334       throw INTERP_KERNEL::Exception("DataArrayDouble::duplicateEachTupleNTimes : nb times should be >= 1 !");
3335     mcIdType nbTuples=this->getNumberOfTuples();
3336     const T *inPtr(this->begin());
3337     MCAuto<typename Traits<T>::ArrayType> ret(Traits<T>::ArrayType::New()); ret->alloc(nbTimes*nbTuples,1);
3338     T *retPtr(ret->getPointer());
3339     for(mcIdType i=0;i<nbTuples;i++,inPtr++)
3340       {
3341         T val(*inPtr);
3342         for(mcIdType j=0;j<nbTimes;j++,retPtr++)
3343           *retPtr=val;
3344       }
3345     ret->copyStringInfoFrom(*this);
3346     return ret.retn();
3347   }
3348   
3349   template<class T>
3350   void DataArrayTemplateClassic<T>::aggregate(const typename Traits<T>::ArrayType *other)
3351   {
3352     if(!other)
3353       throw INTERP_KERNEL::Exception("DataArrayDouble::aggregate : null pointer !");
3354     if(this->getNumberOfComponents()!=other->getNumberOfComponents())
3355       throw INTERP_KERNEL::Exception("DataArrayDouble::aggregate : mismatch number of components !");
3356     this->_mem.insertAtTheEnd(other->begin(),other->end());
3357   }
3358
3359   /*!
3360    * Converts every value of \a this array to its absolute value.
3361    * \b WARNING this method is non const. If a new DataArrayDouble instance should be built containing the result of abs DataArrayDouble::computeAbs
3362    * should be called instead.
3363    *
3364    * \throw If \a this is not allocated.
3365    * \sa DataArrayDouble::computeAbs
3366    */
3367   template<class T>
3368   void DataArrayTemplateClassic<T>::abs()
3369   {
3370     this->checkAllocated();
3371     T *ptr(this->getPointer());
3372     std::size_t nbOfElems(this->getNbOfElems());
3373     std::transform(ptr,ptr+nbOfElems,ptr,std::ptr_fun<T,T>(std::abs));
3374     this->declareAsNew();
3375   }
3376
3377   /*!
3378    * This method builds a new instance of \a this object containing the result of std::abs applied of all elements in \a this.
3379    * This method is a const method (that do not change any values in \a this) contrary to  DataArrayDouble::abs method.
3380    *
3381    * \return DataArrayDouble * - the new instance of DataArrayDouble containing the
3382    *         same number of tuples and component as \a this array.
3383    *         The caller is to delete this result array using decrRef() as it is no more
3384    *         needed.
3385    * \throw If \a this is not allocated.
3386    * \sa DataArrayDouble::abs
3387    */
3388   template<class T>
3389   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::computeAbs() const
3390   {
3391     this->checkAllocated();
3392     MCAuto<typename Traits<T>::ArrayType> newArr(Traits<T>::ArrayType::New());
3393     mcIdType nbOfTuples(this->getNumberOfTuples());
3394     std::size_t nbOfComp(this->getNumberOfComponents());
3395     newArr->alloc(nbOfTuples,nbOfComp);
3396     std::transform(this->begin(),this->end(),newArr->getPointer(),std::ptr_fun<T,T>(std::abs));
3397     newArr->copyStringInfoFrom(*this);
3398     return newArr.retn();
3399   }
3400
3401   /*!
3402    * Returns either a \a deep or \a shallow copy of this array. For more info see
3403    * \ref MEDCouplingArrayBasicsCopyDeep and \ref MEDCouplingArrayBasicsCopyShallow.
3404    *  \param [in] dCpy - if \a true, a deep copy is returned, else, a shallow one.
3405    *  \return DataArrayDouble * - either a new instance of DataArrayDouble (if \a dCpy
3406    *          == \a true) or \a this instance (if \a dCpy == \a false).
3407    */
3408   template<class T>
3409   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::performCopyOrIncrRef(bool dCpy) const
3410   {
3411     const typename Traits<T>::ArrayType *thisC(static_cast<const typename Traits<T>::ArrayType *>(this));
3412     return DataArrayTemplateClassic<T>::PerformCopyOrIncrRef(dCpy,*thisC);
3413   }
3414
3415   /*!
3416    * Computes for each tuple the sum of number of components values in the tuple and return it.
3417    * 
3418    * \return DataArrayDouble * - the new instance of DataArrayDouble containing the
3419    *          same number of tuples as \a this array and one component.
3420    *          The caller is to delete this result array using decrRef() as it is no more
3421    *          needed.
3422    *  \throw If \a this is not allocated.
3423    */
3424   template<class T>
3425   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::sumPerTuple() const
3426   {
3427     this->checkAllocated();
3428     std::size_t nbOfComp(this->getNumberOfComponents());
3429     mcIdType nbOfTuple(this->getNumberOfTuples());
3430     MCAuto<typename Traits<T>::ArrayType> ret(Traits<T>::ArrayType::New());
3431     ret->alloc(nbOfTuple,1);
3432     const T *src(this->begin());
3433     T *dest(ret->getPointer());
3434     for(mcIdType i=0;i<nbOfTuple;i++,dest++,src+=nbOfComp)
3435       *dest=std::accumulate(src,src+nbOfComp,(T)0);
3436     return ret.retn();
3437   }
3438
3439   /*!
3440    * Set all values in \a this array so that the i-th element equals to \a init + i
3441    * (i starts from zero). To know more on filling arrays see \ref MEDCouplingArrayFill.
3442    *  \param [in] init - value to assign to the first element of array.
3443    *  \throw If \a this->getNumberOfComponents() != 1
3444    *  \throw If \a this is not allocated.
3445    */
3446   template<class T>
3447   void DataArrayTemplateClassic<T>::iota(T init)
3448   {
3449     this->checkAllocated();
3450     if(this->getNumberOfComponents()!=1)
3451       throw INTERP_KERNEL::Exception("DataArrayDouble::iota : works only for arrays with only one component, you can call 'rearrange' method before !");
3452     T *ptr(this->getPointer());
3453     mcIdType ntuples(this->getNumberOfTuples());
3454     for(mcIdType i=0;i<ntuples;i++)
3455       ptr[i]=init+(T)i;
3456     this->declareAsNew();
3457   }
3458
3459   template<class T>
3460   struct ImplReprTraits { static void SetPrecision(std::ostream& oss) { } };
3461
3462   template<>
3463   struct ImplReprTraits<double> {  static void SetPrecision(std::ostream& oss) { oss.precision(17); } };
3464   
3465   template<>
3466   struct ImplReprTraits<float> {  static void SetPrecision(std::ostream& oss) { oss.precision(7); } };
3467   
3468   template<class T>
3469   void DataArrayTemplateClassic<T>::reprStream(std::ostream& stream) const
3470   {
3471     stream << "Name of " << Traits<T>::ReprStr << " array : \"" << this->_name << "\"\n";
3472     reprWithoutNameStream(stream);
3473   }
3474
3475   template<class T>
3476   void DataArrayTemplateClassic<T>::reprZipStream(std::ostream& stream) const
3477   {
3478     stream << "Name of " << Traits<T>::ReprStr << " array : \"" << this->_name << "\"\n";
3479     reprZipWithoutNameStream(stream);
3480   }
3481
3482   template<class T>
3483   void DataArrayTemplateClassic<T>::reprNotTooLongStream(std::ostream& stream) const
3484   {
3485     stream << "Name of "<< Traits<T>::ReprStr << " array : \"" << this->_name << "\"\n";
3486     reprNotTooLongWithoutNameStream(stream);
3487   }
3488
3489   template<class T>
3490   void DataArrayTemplateClassic<T>::reprWithoutNameStream(std::ostream& stream) const
3491   {
3492     DataArray::reprWithoutNameStream(stream);
3493     ImplReprTraits<T>::SetPrecision(stream);
3494     this->_mem.repr(ToIdType(this->getNumberOfComponents()),stream);
3495   }
3496
3497   template<class T>
3498   void DataArrayTemplateClassic<T>::reprZipWithoutNameStream(std::ostream& stream) const
3499   {
3500     DataArray::reprWithoutNameStream(stream);
3501     ImplReprTraits<T>::SetPrecision(stream);
3502     this->_mem.reprZip(ToIdType(this->getNumberOfComponents()),stream);
3503   }
3504
3505   template<class T>
3506   void DataArrayTemplateClassic<T>::reprNotTooLongWithoutNameStream(std::ostream& stream) const
3507   {
3508     DataArray::reprWithoutNameStream(stream);
3509     ImplReprTraits<T>::SetPrecision(stream);
3510     this->_mem.reprNotTooLong(ToIdType(this->getNumberOfComponents()),stream);
3511   }
3512
3513   /*!
3514    * This method is close to repr method except that when \a this has more than 1000 tuples, all tuples are not
3515    * printed out to avoid to consume too much space in interpretor.
3516    * \sa repr
3517    */
3518   template<class T>
3519   std::string DataArrayTemplateClassic<T>::reprNotTooLong() const
3520   {
3521     std::ostringstream ret;
3522     reprNotTooLongStream(ret);
3523     return ret.str();
3524   }
3525   
3526   /*!
3527    * Returns a textual and human readable representation of \a this instance of
3528    * DataArrayInt. This text is shown when a DataArrayInt is printed in Python.
3529    * \return std::string - text describing \a this DataArrayInt.
3530    *
3531    * \sa reprNotTooLong, reprZip
3532    */
3533   template<class T>
3534   std::string DataArrayTemplateClassic<T>::repr() const
3535   {
3536     std::ostringstream ret;
3537     DataArrayTemplateClassic<T>::reprStream(ret);
3538     return ret.str();
3539   }
3540   
3541   template<class T>
3542   std::string DataArrayTemplateClassic<T>::reprZip() const
3543   {
3544     std::ostringstream ret;
3545     DataArrayTemplateClassic<T>::reprZipStream(ret);
3546     return ret.str();
3547   }
3548   
3549   /////////////////////////////////
3550   
3551   /*!
3552    * Checks if all values in \a this array are equal to \a val at precision \a eps.
3553    *  \param [in] val - value to check equality of array values to.
3554    *  \param [in] eps - precision to check the equality.
3555    *  \return bool - \a true if all values are in range (_val_ - _eps_; _val_ + _eps_),
3556    *                 \a false else.
3557    *  \throw If \a this->getNumberOfComponents() != 1
3558    *  \throw If \a this is not allocated.
3559    */
3560   template<class T>
3561   bool DataArrayTemplateFP<T>::isUniform(T val, T eps) const
3562   {
3563     this->checkAllocated();
3564     if(this->getNumberOfComponents()!=1)
3565       throw INTERP_KERNEL::Exception("DataArrayDouble::isUniform : must be applied on DataArrayDouble with only one component, you can call 'rearrange' method before !");
3566     const T *w(this->begin()),*end2(this->end());
3567     const T vmin(val-eps),vmax(val+eps);
3568     for(;w!=end2;w++)
3569       if(*w<vmin || *w>vmax)
3570         return false;
3571     return true;
3572   }
3573
3574   /////////////////////////////////
3575
3576   /*!
3577    * Returns the only one value in \a this, if and only if number of elements
3578    * (nb of tuples * nb of components) is equal to 1, and that \a this is allocated.
3579    *  \return double - the sole value stored in \a this array.
3580    *  \throw If at least one of conditions stated above is not fulfilled.
3581    */
3582   template <class T>
3583   T DataArrayDiscrete<T>::intValue() const
3584   {
3585     if(this->isAllocated())
3586       {
3587         if(this->getNbOfElems()==1)
3588           {
3589             return *this->getConstPointer();
3590           }
3591         else
3592           throw INTERP_KERNEL::Exception("DataArrayInt::intValue : DataArrayInt instance is allocated but number of elements is not equal to 1 !");
3593       }
3594     else
3595       throw INTERP_KERNEL::Exception("DataArrayInt::intValue : DataArrayInt instance is not allocated !");
3596   }
3597
3598   /*!
3599    * Equivalent to DataArrayInt::isEqual except that if false the reason of
3600    * mismatch is given.
3601    * 
3602    * \param [in] other the instance to be compared with \a this
3603    * \param [out] reason In case of inequality returns the reason.
3604    * \sa DataArrayInt::isEqual
3605    */
3606   template<class T>
3607   bool DataArrayDiscrete<T>::isEqualIfNotWhy(const DataArrayDiscrete<T>& other, std::string& reason) const
3608   {
3609     if(!this->areInfoEqualsIfNotWhy(other,reason))
3610       return false;
3611     return this->_mem.isEqual(other._mem,0,reason);
3612   }
3613
3614   /*!
3615    * Checks if \a this and another DataArrayInt are fully equal. For more info see
3616    * \ref MEDCouplingArrayBasicsCompare.
3617    *  \param [in] other - an instance of DataArrayInt to compare with \a this one.
3618    *  \return bool - \a true if the two arrays are equal, \a false else.
3619    */
3620   template<class T>
3621   bool DataArrayDiscrete<T>::isEqual(const DataArrayDiscrete<T>& other) const
3622   {
3623     std::string tmp;
3624     return isEqualIfNotWhy(other,tmp);
3625   }
3626   
3627   /*!
3628    * Returns a new instance of DataArrayInt. The caller is to delete this array
3629    * using decrRef() as it is no more needed.
3630    */
3631   template<class T>
3632   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::New()
3633   {
3634     return new typename Traits<T>::ArrayType;
3635   }
3636   
3637   /*!
3638    * Returns a newly created array containing a copy of the input array defined by [ \a arrBegin, \a arrEnd )
3639    */
3640   template<class T>
3641   MCAuto< typename Traits<T>::ArrayType > DataArrayDiscrete<T>::NewFromArray(const T *arrBegin, const T *arrEnd)
3642   {
3643     MCAuto< typename Traits<T>::ArrayType > ret(DataArrayDiscrete<T>::New());
3644     std::size_t nbElts(std::distance(arrBegin,arrEnd));
3645     ret->alloc(nbElts,1);
3646     std::copy(arrBegin,arrEnd,ret->getPointer());
3647     return ret;
3648   }
3649   
3650   /*!
3651    * Checks if values of \a this and another DataArrayInt are equal. For more info see
3652    * \ref MEDCouplingArrayBasicsCompare.
3653    *  \param [in] other - an instance of DataArrayInt to compare with \a this one.
3654    *  \return bool - \a true if the values of two arrays are equal, \a false else.
3655    */
3656   template<class T>
3657   bool DataArrayDiscrete<T>::isEqualWithoutConsideringStr(const DataArrayDiscrete<T>& other) const
3658   {
3659     std::string tmp;
3660     return this->_mem.isEqual(other._mem,0,tmp);
3661   }
3662
3663   /*!
3664    * Checks if values of \a this and another DataArrayInt are equal. Comparison is
3665    * performed on sorted value sequences.
3666    * For more info see\ref MEDCouplingArrayBasicsCompare.
3667    *  \param [in] other - an instance of DataArrayInt to compare with \a this one.
3668    *  \return bool - \a true if the sorted values of two arrays are equal, \a false else.
3669    */
3670   template<class T>
3671   bool DataArrayDiscrete<T>::isEqualWithoutConsideringStrAndOrder(const typename Traits<T>::ArrayType& other) const
3672   {
3673     MCAuto<typename Traits<T>::ArrayType> a((static_cast<const typename Traits<T>::ArrayType *>(this))->deepCopy());
3674     MCAuto<typename Traits<T>::ArrayType> b((static_cast<const typename Traits<T>::ArrayType *>(&other))->deepCopy());
3675     a->sort();
3676     b->sort();
3677     return a->isEqualWithoutConsideringStr(*b);
3678   }
3679   
3680   template<class T>
3681   template<class ALG>
3682   void DataArrayDiscrete<T>::switchOnTupleAlg(T val, std::vector<bool>& vec, ALG algo) const
3683   {
3684     this->checkAllocated();
3685     if(this->getNumberOfComponents()!=1)
3686       throw INTERP_KERNEL::Exception("DataArrayInt::switchOnTupleEqualTo : number of components of this should be equal to one !");
3687     mcIdType nbOfTuples(this->getNumberOfTuples());
3688     if(nbOfTuples!=ToIdType(vec.size()))
3689       throw INTERP_KERNEL::Exception("DataArrayInt::switchOnTupleEqualTo : number of tuples of this should be equal to size of input vector of bool !");
3690     const T *pt(this->begin());
3691     for(mcIdType i=0;i<nbOfTuples;i++)
3692       if(algo(pt[i],val))
3693         vec[i]=true;
3694   }
3695   
3696   /*!
3697    * 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
3698    * put True to the corresponding entry in \a vec.
3699    * \a vec is expected to be with the same size than the number of tuples of \a this.
3700    *
3701    *  \sa DataArrayInt::switchOnTupleNotEqualTo.
3702    */
3703   template<class T>
3704   void DataArrayDiscrete<T>::switchOnTupleEqualTo(T val, std::vector<bool>& vec) const
3705   {
3706     switchOnTupleAlg(val,vec,std::equal_to<T>());
3707   }
3708
3709   /*!
3710    * 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
3711    * put True to the corresponding entry in \a vec.
3712    * \a vec is expected to be with the same size than the number of tuples of \a this.
3713    * 
3714    *  \sa DataArrayInt::switchOnTupleEqualTo.
3715    */
3716   template<class T>
3717   void DataArrayDiscrete<T>::switchOnTupleNotEqualTo(T val, std::vector<bool>& vec) const
3718   {
3719     switchOnTupleAlg(val,vec,std::not_equal_to<T>());
3720   }
3721
3722   /*!
3723    * Compute for each element in \a this the occurence rank of that element. This method is typically useful of one-component array having a same element
3724    * appearing several times. If each element in \a this appears once an 1 component array containing only 0 will be returned.
3725    *
3726    * \b Example:
3727    * - \a this : [5, 3, 2, 1, 4, 5, 2, 1, 0, 11, 5, 4]
3728    * - \a return is : [0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 2, 1] because at pos #0 of \a this (ie value 5) is the first occurrence ->0. At pos #10 of \a this (ie value 5 also) is the third occurrence of 5 -> 2.
3729    *
3730    * \return DataArrayInt * - a new instance of DataArrayInt with same number of tuples than \a this. The caller is to delete this
3731    *          array using decrRef() as it is no more needed.
3732    * \throw If either this not allocated or not with one component.
3733    *
3734    * \sa DataArrayInt::FindPermutationFromFirstToSecond
3735    */
3736   template<class T>
3737   DataArrayIdType *DataArrayDiscrete<T>::occurenceRankInThis() const
3738   {
3739     constexpr char MSG0[] = "occurenceRankInThis :";
3740     this->checkAllocated();
3741     this->checkNbOfComps(1,MSG0);
3742     MCAuto<DataArrayIdType> ret(DataArrayIdType::New());
3743     ret->alloc(this->getNumberOfTuples(),1);
3744     mcIdType *retPtr(ret->getPointer());
3745     std::map<T,mcIdType> m;
3746     for(const T *pt = this->begin() ; pt != this->end() ; ++pt, ++retPtr )
3747     {
3748       auto it = m.find(*pt);
3749       if( it == m.end() )
3750       {
3751         *retPtr = 0;
3752         m[*pt] = 1;
3753       }
3754       else
3755       {
3756         *retPtr = (*it).second++;
3757       }
3758     }
3759     return ret.retn();
3760   }
3761
3762   /*!
3763    * Creates a new one-dimensional DataArrayInt of the same size as \a this and a given
3764    * one-dimensional arrays that must be of the same length. The result array describes
3765    * correspondence between \a this and \a other arrays, so that 
3766    * <em> other.getIJ(i,0) == this->getIJ(ret->getIJ(i),0)</em>. If such a permutation is
3767    * not possible because some element in \a other is not in \a this, an exception is thrown.
3768    *  \param [in] other - an array to compute permutation to.
3769    *  \return DataArrayInt * - a new instance of DataArrayInt, which is a permutation array
3770    * from \a this to \a other. The caller is to delete this array using decrRef() as it is
3771    * no more needed.
3772    *  \throw If \a this->getNumberOfComponents() != 1.
3773    *  \throw If \a other->getNumberOfComponents() != 1.
3774    *  \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples().
3775    *  \throw If \a other includes a value which is not in \a this array.
3776    * 
3777    *  \if ENABLE_EXAMPLES
3778    *  \ref cpp_mcdataarrayint_buildpermutationarr "Here is a C++ example".
3779    *
3780    *  \ref py_mcdataarrayint_buildpermutationarr "Here is a Python example".
3781    *  \endif
3782    */
3783   template<class T>
3784   DataArrayIdType *DataArrayDiscrete<T>::buildPermutationArr(const DataArrayDiscrete<T>& other) const
3785   {
3786     this->checkAllocated();
3787     if(this->getNumberOfComponents()!=1 || other.getNumberOfComponents()!=1)
3788       throw INTERP_KERNEL::Exception("DataArrayInt::buildPermutationArr : 'this' and 'other' have to have exactly ONE component !");
3789     mcIdType nbTuple(this->getNumberOfTuples());
3790     other.checkAllocated();
3791     if(nbTuple!=other.getNumberOfTuples())
3792       throw INTERP_KERNEL::Exception("DataArrayInt::buildPermutationArr : 'this' and 'other' must have the same number of tuple !");
3793     MCAuto<DataArrayIdType> ret(DataArrayIdType::New());
3794     ret->alloc(nbTuple,1);
3795     ret->fillWithValue(-1);
3796     const T *pt(this->begin());
3797     std::map<mcIdType,mcIdType> mm;
3798     for(mcIdType i=0;i<nbTuple;i++)
3799       mm[ToIdType(pt[i])]=i;
3800     pt=other.begin();
3801     mcIdType *retToFill(ret->getPointer());
3802     for(mcIdType i=0;i<nbTuple;i++)
3803       {
3804         std::map<mcIdType,mcIdType>::const_iterator it=mm.find(ToIdType(pt[i]));
3805         if(it==mm.end())
3806           {
3807             std::ostringstream oss; oss << "DataArrayInt::buildPermutationArr : Arrays mismatch : element (" << pt[i] << ") in 'other' not findable in 'this' !";
3808             throw INTERP_KERNEL::Exception(oss.str().c_str());
3809           }
3810         retToFill[i]=(*it).second;
3811       }
3812     return ret.retn();
3813   }
3814
3815   /*!
3816    * Elements of \a partOfThis are expected to be included in \a this.
3817    * The returned array \a ret is so that this[ret]==partOfThis
3818    *
3819    * 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]
3820    * the return array will contain [3,2,5,7].
3821    *
3822    * \a this is expected to be a 1 compo allocated array.
3823    * \param [in] partOfThis - A 1 compo allocated array
3824    * \return - A newly allocated array to be dealed by caller having the same number of tuples than \a partOfThis.
3825    * \throw if two same element is present twice in \a this
3826    * \throw if an element in \a partOfThis is \b NOT in \a this.
3827    */
3828   template<class T>
3829   DataArrayIdType *DataArrayDiscrete<T>::indicesOfSubPart(const DataArrayDiscrete<T>& partOfThis) const
3830   {
3831     if(this->getNumberOfComponents()!=1 || partOfThis.getNumberOfComponents()!=1)
3832       throw INTERP_KERNEL::Exception("DataArrayInt::indicesOfSubPart : this and input array must be one component array !");
3833     this->checkAllocated(); partOfThis.checkAllocated();
3834     mcIdType thisNbTuples(this->getNumberOfTuples()),nbTuples(partOfThis.getNumberOfTuples());
3835     const T *thisPt(this->begin()),*pt(partOfThis.begin());
3836     MCAuto<DataArrayIdType> ret(DataArrayIdType::New());
3837     ret->alloc(nbTuples,1);
3838     mcIdType *retPt(ret->getPointer());
3839     std::map<mcIdType,mcIdType> m;
3840     for(mcIdType i=0;i<thisNbTuples;i++,thisPt++)
3841       m[ToIdType(*thisPt)]=i;
3842     if(ToIdType(m.size())!=thisNbTuples)
3843       throw INTERP_KERNEL::Exception("DataArrayInt::indicesOfSubPart : some elements appears more than once !");
3844     for(mcIdType i=0;i<nbTuples;i++,retPt++,pt++)
3845       {
3846         std::map<mcIdType,mcIdType>::const_iterator it(m.find(ToIdType(*pt)));
3847         if(it!=m.end())
3848           *retPt=(*it).second;
3849         else
3850           {
3851             std::ostringstream oss; oss << "DataArrayInt::indicesOfSubPart : At pos #" << i << " of input array value is " << *pt << " not in this !";
3852             throw INTERP_KERNEL::Exception(oss.str());
3853           }
3854       }
3855     return ret.retn();
3856   }
3857
3858   /*!
3859    * Checks that \a this array is consistently **increasing** or **decreasing** in value.
3860    * If not an exception is thrown.
3861    *  \param [in] increasing - if \a true, the array values should be increasing.
3862    *  \throw If sequence of values is not strictly monotonic in agreement with \a
3863    *         increasing arg.
3864    *  \throw If \a this->getNumberOfComponents() != 1.
3865    *  \throw If \a this is not allocated.
3866    */
3867   template<class T>
3868   void DataArrayDiscrete<T>::checkMonotonic(bool increasing) const
3869   {
3870     if(!isMonotonic(increasing))
3871       {
3872         if (increasing)
3873           throw INTERP_KERNEL::Exception("DataArrayInt::checkMonotonic : 'this' is not INCREASING monotonic !");
3874         else
3875           throw INTERP_KERNEL::Exception("DataArrayInt::checkMonotonic : 'this' is not DECREASING monotonic !");
3876       }
3877   }
3878
3879   /*!
3880    * Checks that \a this array is consistently **increasing** or **decreasing** in value.
3881    *  \param [in] increasing - if \a true, array values should be increasing.
3882    *  \return bool - \a true if values change in accordance with \a increasing arg.
3883    *  \throw If \a this->getNumberOfComponents() != 1.
3884    *  \throw If \a this is not allocated.
3885    */
3886   template<class T>
3887   bool DataArrayDiscrete<T>::isMonotonic(bool increasing) const
3888   {
3889     this->checkAllocated();
3890     if(this->getNumberOfComponents()!=1)
3891       throw INTERP_KERNEL::Exception("DataArrayInt::isMonotonic : only supported with 'this' array with ONE component !");
3892     std::size_t nbOfElements(this->getNumberOfTuples());
3893     const T *ptr(this->begin());
3894     if(nbOfElements==0)
3895       return true;
3896     T ref(ptr[0]);
3897     if(increasing)
3898       {
3899         for(std::size_t i=1;i<nbOfElements;i++)
3900           {
3901             if(ptr[i]>=ref)
3902               ref=ptr[i];
3903             else
3904               return false;
3905           }
3906       }
3907     else
3908       {
3909         for(std::size_t i=1;i<nbOfElements;i++)
3910           {
3911             if(ptr[i]<=ref)
3912               ref=ptr[i];
3913             else
3914               return false;
3915           }
3916       }
3917     return true;
3918   }
3919
3920   /*!
3921    * This method check that array consistently INCREASING or DECREASING in value.
3922    */
3923   template<class T>
3924   bool DataArrayDiscrete<T>::isStrictlyMonotonic(bool increasing) const
3925   {
3926     this->checkAllocated();
3927     if(this->getNumberOfComponents()!=1)
3928       throw INTERP_KERNEL::Exception("DataArrayInt::isStrictlyMonotonic : only supported with 'this' array with ONE component !");
3929     std::size_t nbOfElements(this->getNumberOfTuples());
3930     const T *ptr(this->begin());
3931     if(nbOfElements==0)
3932       return true;
3933     T ref(ptr[0]);
3934     if(increasing)
3935       {
3936         for(std::size_t i=1;i<nbOfElements;i++)
3937           {
3938             if(ptr[i]>ref)
3939               ref=ptr[i];
3940             else
3941               return false;
3942           }
3943       }
3944     else
3945       {
3946         for(std::size_t i=1;i<nbOfElements;i++)
3947           {
3948             if(ptr[i]<ref)
3949               ref=ptr[i];
3950             else
3951               return false;
3952           }
3953       }
3954     return true;
3955   }
3956
3957   /*!
3958    * This method check that array consistently INCREASING or DECREASING in value.
3959    */
3960   template<class T>
3961   void DataArrayDiscrete<T>::checkStrictlyMonotonic(bool increasing) const
3962   {
3963     if(!isStrictlyMonotonic(increasing))
3964       {
3965         if (increasing)
3966           throw INTERP_KERNEL::Exception("DataArrayInt::checkStrictlyMonotonic : 'this' is not strictly INCREASING monotonic !");
3967         else
3968           throw INTERP_KERNEL::Exception("DataArrayInt::checkStrictlyMonotonic : 'this' is not strictly DECREASING monotonic !");
3969       }
3970   }
3971
3972   /*!
3973    * Returns an integer value characterizing \a this array, which is useful for a quick
3974    * comparison of many instances of DataArrayInt.
3975    *  \return mcIdType - the hash value.
3976    *  \throw If \a this is not allocated.
3977    */
3978   template<class T>
3979   mcIdType DataArrayDiscrete<T>::getHashCode() const
3980   {
3981     this->checkAllocated();
3982     mcIdType nbOfElems=ToIdType(this->getNbOfElems());
3983     mcIdType ret=nbOfElems*65536;
3984     mcIdType delta=3;
3985     if(nbOfElems>48)
3986       delta=nbOfElems/8;
3987     T ret0(0);
3988     const T *pt(this->begin());
3989     for(mcIdType i=0;i<nbOfElems;i+=delta)
3990       ret0+=pt[i] & 0x1FFF;
3991     return ToIdType(ret+ret0);
3992   }
3993
3994   template<class T>
3995   void DataArrayDiscrete<T>::reprCppStream(const std::string& varName, std::ostream& stream) const
3996   {
3997     mcIdType nbTuples(this->getNumberOfTuples());
3998     std::size_t nbComp(this->getNumberOfComponents());
3999     const T *data(this->getConstPointer());
4000     stream << Traits<T>::ArrayTypeName << " *" << varName << "=" << Traits<T>::ArrayTypeName << "::New();" << std::endl;
4001     if(nbTuples*nbComp>=1)
4002       {
4003         stream << "const mcIdType " << varName << "Data[" << nbTuples*nbComp << "]={";
4004         std::copy(data,data+nbTuples*nbComp-1,std::ostream_iterator<T>(stream,","));
4005         stream << data[nbTuples*nbComp-1] << "};" << std::endl;
4006         stream << varName << "->useArray(" << varName << "Data,false,CPP_DEALLOC," << nbTuples << "," << nbComp << ");" << std::endl;
4007       }
4008     else
4009       stream << varName << "->alloc(" << nbTuples << "," << nbComp << ");" << std::endl;
4010     stream << varName << "->setName(\"" << this->getName() << "\");" << std::endl;
4011   }
4012
4013   /*!
4014    * Method that gives a quick overvien of \a this for python.
4015    */
4016   template<class T>
4017   void DataArrayDiscrete<T>::reprQuickOverview(std::ostream& stream) const
4018   {
4019     static const std::size_t MAX_NB_OF_BYTE_IN_REPR=300;
4020     stream << Traits<T>::ArrayTypeName << " C++ instance at " << this << ". ";
4021     if(this->isAllocated())
4022       {
4023         std::size_t nbOfCompo(this->getNumberOfComponents());
4024         if(nbOfCompo>=1)
4025           {
4026             mcIdType nbOfTuples(this->getNumberOfTuples());
4027             stream << "Number of tuples : " << nbOfTuples << ". Number of components : " << nbOfCompo << "." << std::endl;
4028             reprQuickOverviewData(stream,MAX_NB_OF_BYTE_IN_REPR);
4029           }
4030         else
4031           stream << "Number of components : 0.";
4032       }
4033     else
4034       stream << "*** No data allocated ****";
4035   }
4036
4037   template<class T>
4038   void DataArrayDiscrete<T>::reprQuickOverviewData(std::ostream& stream, std::size_t maxNbOfByteInRepr) const
4039   {
4040     const T *data(this->begin());
4041     mcIdType nbOfTuples(this->getNumberOfTuples());
4042     std::size_t nbOfCompo(this->getNumberOfComponents());
4043     std::ostringstream oss2; oss2 << "[";
4044     std::string oss2Str(oss2.str());
4045     bool isFinished=true;
4046     for(mcIdType i=0;i<nbOfTuples && isFinished;i++)
4047       {
4048         if(nbOfCompo>1)
4049           {
4050             oss2 << "(";
4051             for(std::size_t j=0;j<nbOfCompo;j++,data++)
4052               {
4053                 oss2 << *data;
4054                 if(j!=nbOfCompo-1) oss2 << ", ";
4055               }
4056             oss2 << ")";
4057           }
4058         else
4059           oss2 << *data++;
4060         if(i!=nbOfTuples-1) oss2 << ", ";
4061         std::string oss3Str(oss2.str());
4062         if(oss3Str.length()<maxNbOfByteInRepr)
4063           oss2Str=oss3Str;
4064         else
4065           isFinished=false;
4066       }
4067     stream << oss2Str;
4068     if(!isFinished)
4069       stream << "... ";
4070     stream << "]";
4071   }
4072
4073   template<class T>
4074   void DataArrayDiscrete<T>::writeVTK(std::ostream& ofs, mcIdType indent, const std::string& type, const std::string& nameInFile, DataArrayByte *byteArr) const
4075   {
4076     static const char SPACE[4]={' ',' ',' ',' '};
4077     this->checkAllocated();
4078     std::string idt(indent,' ');
4079     ofs << idt << "<DataArray type=\"" << type << "\" Name=\"" << nameInFile << "\" NumberOfComponents=\"" << this->getNumberOfComponents() << "\"";
4080     if(byteArr)
4081       {
4082         ofs << " format=\"appended\" offset=\"" << byteArr->getNumberOfTuples() << "\">";
4083         if(std::string(type)==Traits<T>::VTKReprStr)
4084           {
4085             const char *data(reinterpret_cast<const char *>(this->begin()));
4086             std::size_t sz(this->getNbOfElems()*sizeof(T));
4087             byteArr->insertAtTheEnd(data,data+sz);
4088             byteArr->insertAtTheEnd(SPACE,SPACE+4);
4089           }
4090         else if(std::string(type)=="Int8")
4091           {
4092             INTERP_KERNEL::AutoPtr<char> tmp(new char[this->getNbOfElems()]);
4093             copyCast(this->begin(),this->end(),(char *)tmp);
4094             byteArr->insertAtTheEnd((char *)tmp,(char *)tmp+this->getNbOfElems());
4095             byteArr->insertAtTheEnd(SPACE,SPACE+4);
4096           }
4097         else if(std::string(type)=="UInt8")
4098           {
4099             INTERP_KERNEL::AutoPtr<unsigned char> tmp(new unsigned char[this->getNbOfElems()]);
4100             copyCast(this->begin(),this->end(),(unsigned char *)tmp);
4101             byteArr->insertAtTheEnd((unsigned char *)tmp,(unsigned char *)tmp+this->getNbOfElems());
4102             byteArr->insertAtTheEnd(SPACE,SPACE+4);
4103           }
4104         else
4105           {
4106             std::ostringstream oss;
4107             oss << Traits<T>::ArrayTypeName << "::writeVTK : Only " << Traits<T>::VTKReprStr << ", Int8 and UInt8 supported !";
4108             throw INTERP_KERNEL::Exception(oss.str());
4109           }
4110       }
4111     else
4112       {
4113         ofs << " RangeMin=\"" << this->getMinValueInArray() << "\" RangeMax=\"" << this->getMaxValueInArray() << "\" format=\"ascii\">\n" << idt;
4114         std::copy(this->begin(),this->end(),std::ostream_iterator<T>(ofs," "));
4115       }
4116       ofs << std::endl << idt << "</DataArray>\n";
4117   }
4118
4119   /*!
4120    * Modifies in place \a this one-dimensional array so that each value \a v = \a indArrBg[ \a v ],
4121    * i.e. a current value is used as in index to get a new value from \a indArrBg.
4122    *  \param [in] indArrBg - pointer to the first element of array of new values to assign
4123    *         to \a this array.
4124    *  \param [in] indArrEnd - specifies the end of the array \a indArrBg, so that
4125    *              the last value of \a indArrBg is \a indArrEnd[ -1 ].
4126    *  \throw If \a this->getNumberOfComponents() != 1
4127    *  \throw If any value of \a this can't be used as a valid index for
4128    *         [\a indArrBg, \a indArrEnd).
4129    *
4130    *  \sa changeValue, findIdForEach
4131    */
4132   template<class T>
4133   void DataArrayDiscrete<T>::transformWithIndArr(const T *indArrBg, const T *indArrEnd)
4134   {
4135     this->checkAllocated();
4136     if(this->getNumberOfComponents()!=1)
4137       throw INTERP_KERNEL::Exception("Call transformWithIndArr method on DataArrayInt with only one component, you can call 'rearrange' method before !");
4138     mcIdType nbElemsIn=ToIdType(std::distance(indArrBg,indArrEnd));
4139     mcIdType nbOfTuples(this->getNumberOfTuples());
4140     T *pt(this->getPointer());
4141     for(mcIdType i=0;i<nbOfTuples;i++,pt++)
4142       {
4143         if(*pt>=0 && *pt<nbElemsIn)
4144           *pt=indArrBg[*pt];
4145         else
4146           {
4147             std::ostringstream oss; oss << "DataArrayInt::transformWithIndArr : error on tuple #" << i << " of this value is " << *pt << ", should be in [0," << nbElemsIn << ") !";
4148             throw INTERP_KERNEL::Exception(oss.str());
4149           }
4150       }
4151     this->declareAsNew();
4152   }
4153
4154   template<class T>
4155   void DataArrayDiscrete<T>::transformWithIndArr(const MapKeyVal<T, T>& m)
4156   {
4157     this->checkAllocated();
4158     if(this->getNumberOfComponents()!=1)
4159       throw INTERP_KERNEL::Exception("Call transformWithIndArr method on DataArrayInt with only one component, you can call 'rearrange' method before !");
4160     const typename std::map<T,T>& dat(m.data());
4161     mcIdType nbOfTuples(this->getNumberOfTuples());
4162     T *pt(this->getPointer());
4163     for(mcIdType i=0;i<nbOfTuples;i++,pt++)
4164       {
4165         typename std::map<T,T>::const_iterator it(dat.find(*pt));
4166         if(it!=dat.end())
4167           *pt=(*it).second;
4168         else
4169           {
4170             std::ostringstream oss; oss << "DataArrayInt::transformWithIndArr : error on tuple #" << i << " of this value is " << *pt << " not in map !";
4171             throw INTERP_KERNEL::Exception(oss.str());
4172           }
4173       }
4174     this->declareAsNew();
4175   }
4176
4177   /*!
4178    * Creates a new DataArrayInt containing IDs (indices) of tuples holding value equal to a
4179    * given one. The ids are sorted in the ascending order.
4180    *  \param [in] val - the value to find within \a this.
4181    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
4182    *          array using decrRef() as it is no more needed.
4183    *  \throw If \a this is not allocated.
4184    *  \throw If \a this->getNumberOfComponents() != 1.
4185    *  \sa DataArrayInt::findIdsEqualTuple
4186    */
4187   template<class T>
4188   DataArrayIdType *DataArrayDiscrete<T>::findIdsEqual(T val) const
4189   {
4190     this->checkAllocated();
4191     if(this->getNumberOfComponents()!=1)
4192       throw INTERP_KERNEL::Exception("DataArrayInt::findIdsEqual : the array must have only one component, you can call 'rearrange' method before !");
4193     const T *cptr(this->getConstPointer());
4194     MCAuto<DataArrayIdType> ret(DataArrayIdType::New()); ret->alloc(0,1);
4195     mcIdType nbOfTuples(this->getNumberOfTuples());
4196     for(mcIdType i=0;i<nbOfTuples;i++,cptr++)
4197       if(*cptr==val)
4198         ret->pushBackSilent(ToIdType(i));
4199     return ret.retn();
4200   }
4201
4202   /*!
4203    * Creates a one-dimensional DataArrayInt (\a res) whose contents are computed from
4204    * values of \a this (\a a) and the given (\a indArr) arrays as follows:
4205    * \a res[ \a indArr[ \a a[ i ]]] = i. I.e. for each value in place i \a v = \a a[ i ],
4206    * new value in place \a indArr[ \a v ] is i.
4207    *  \param [in] indArrBg - the array holding indices within the result array to assign
4208    *         indices of values of \a this array pointing to values of \a indArrBg.
4209    *  \param [in] indArrEnd - specifies the end of the array \a indArrBg, so that
4210    *              the last value of \a indArrBg is \a indArrEnd[ -1 ].
4211    *  \return DataArrayInt * - the new instance of DataArrayInt.
4212    *          The caller is to delete this result array using decrRef() as it is no more
4213    *          needed.
4214    *  \throw If \a this->getNumberOfComponents() != 1.
4215    *  \throw If any value of \a this array is not a valid index for \a indArrBg array.
4216    *  \throw If any value of \a indArrBg is not a valid index for \a this array.
4217    */
4218   template<class T>
4219   DataArrayIdType *DataArrayDiscrete<T>::transformWithIndArrR(const T *indArrBg, const T *indArrEnd) const
4220   {
4221     this->checkAllocated();
4222     if(this->getNumberOfComponents()!=1)
4223       throw INTERP_KERNEL::Exception("Call transformWithIndArrR method on DataArrayInt with only one component, you can call 'rearrange' method before !");
4224     mcIdType nbElemsIn=ToIdType(std::distance(indArrBg,indArrEnd));
4225     mcIdType nbOfTuples(this->getNumberOfTuples());
4226     const T *pt=this->getConstPointer();
4227     MCAuto<DataArrayIdType> ret=DataArrayIdType::New();
4228     ret->alloc(nbOfTuples,1);
4229     ret->fillWithValue(-1);
4230     mcIdType *tmp=ret->getPointer();
4231     for(mcIdType i=0;i<nbOfTuples;i++,pt++)
4232       {
4233         if(*pt>=0 && *pt<nbElemsIn)
4234           {
4235             T pos=indArrBg[*pt];
4236             if(pos>=0 && pos<nbOfTuples)
4237               tmp[ToIdType(pos)]=i;
4238             else
4239               {
4240                 std::ostringstream oss; oss << "DataArrayInt::transformWithIndArrR : error on tuple #" << i << " value of new pos is " << pos << " ( indArrBg[" << *pt << "]) ! Should be in [0," << nbOfTuples << ") !";
4241                 throw INTERP_KERNEL::Exception(oss.str().c_str());
4242               }
4243           }
4244         else
4245           {
4246             std::ostringstream oss; oss << "DataArrayInt::transformWithIndArrR : error on tuple #" << i << " value is " << *pt << " and indirectionnal array as a size equal to " << nbElemsIn << " !";
4247             throw INTERP_KERNEL::Exception(oss.str().c_str());
4248           }
4249       }
4250     return ret.retn();
4251   }
4252
4253   /*!
4254    * Computes distribution of values of \a this one-dimensional array between given value
4255    * ranges (casts). This method is typically useful for entity number splitting by types,
4256    * for example. 
4257    *  \warning The values contained in \a arrBg should be sorted ascendently. No
4258    *           check of this is be done. If not, the result is not warranted. 
4259    *  \param [in] arrBg - the array of ascending values defining the value ranges. The i-th
4260    *         value of \a arrBg (\a arrBg[ i ]) gives the lowest value of the i-th range,
4261    *         and the greatest value of the i-th range equals to \a arrBg[ i+1 ] - 1. \a
4262    *         arrBg containing \a n values defines \a n-1 ranges. The last value of \a arrBg
4263    *         should be more than every value in \a this array.
4264    *  \param [in] arrEnd - specifies the end of the array \a arrBg, so that
4265    *              the last value of \a arrBg is \a arrEnd[ -1 ].
4266    *  \param [out] castArr - a new instance of DataArrayInt, of same size as \a this array
4267    *         (same number of tuples and components), the caller is to delete
4268    *         using decrRef() as it is no more needed.
4269    *         This array contains indices of ranges for every value of \a this array. I.e.
4270    *         the i-th value of \a castArr gives the index of range the i-th value of \a this
4271    *         belongs to. Or, in other words, this parameter contains for each tuple in \a
4272    *         this in which cast it holds.
4273    *  \param [out] rankInsideCast - a new instance of DataArrayInt, of same size as \a this
4274    *         array, the caller is to delete using decrRef() as it is no more needed.
4275    *         This array contains ranks of values of \a this array within ranges
4276    *         they belongs to. I.e. the i-th value of \a rankInsideCast gives the rank of
4277    *         the i-th value of \a this array within the \a castArr[ i ]-th range, to which
4278    *         the i-th value of \a this belongs to. Or, in other words, this param contains
4279    *         for each tuple its rank inside its cast. The rank is computed as difference
4280    *         between the value and the lowest value of range.
4281    *  \param [out] castsPresent - a new instance of DataArrayInt, containing indices of
4282    *         ranges (casts) to which at least one value of \a this array belongs.
4283    *         Or, in other words, this param contains the casts that \a this contains.
4284    *         The caller is to delete this array using decrRef() as it is no more needed.
4285    *
4286    * \b Example: If \a this contains [6,5,0,3,2,7,8,1,4] and \a arrBg contains [0,4,9] then
4287    *            the output of this method will be :
4288    * - \a castArr       : [1,1,0,0,0,1,1,0,1]
4289    * - \a rankInsideCast: [2,1,0,3,2,3,4,1,0]
4290    * - \a castsPresent  : [0,1]
4291    *
4292    * I.e. values of \a this array belong to 2 ranges: #0 and #1. Value 6 belongs to the
4293    * range #1 and its rank within this range is 2; etc.
4294    *
4295    *  \throw If \a this->getNumberOfComponents() != 1.
4296    *  \throw If \a arrEnd - arrBg < 2.
4297    *  \throw If any value of \a this is not less than \a arrEnd[-1].
4298    */
4299   template<class T>
4300   void DataArrayDiscrete<T>::splitByValueRange(const T *arrBg, const T *arrEnd,
4301                                                DataArrayType *& castArr, DataArrayType *& rankInsideCast, DataArrayType *& castsPresent) const
4302   {
4303     this->checkAllocated();
4304     if(this->getNumberOfComponents()!=1)
4305       throw INTERP_KERNEL::Exception("Call splitByValueRange  method on DataArrayInt with only one component, you can call 'rearrange' method before !");
4306     mcIdType nbOfTuples=this->getNumberOfTuples();
4307     std::size_t nbOfCast=std::distance(arrBg,arrEnd);
4308     if(nbOfCast<2)
4309       throw INTERP_KERNEL::Exception("DataArrayInt::splitByValueRange : The input array giving the cast range values should be of size >=2 !");
4310     nbOfCast--;
4311     const T *work=this->getConstPointer();
4312     typedef std::reverse_iterator<const T *> rintstart;
4313     rintstart bg(arrEnd);//OK no problem because size of 'arr' is greater or equal 2
4314     rintstart end2(arrBg);
4315     MCAuto<DataArrayType> ret1=DataArrayType::New();
4316     MCAuto<DataArrayType> ret2=DataArrayType::New();
4317     MCAuto<DataArrayType> ret3=DataArrayType::New();
4318     ret1->alloc(nbOfTuples,1);
4319     ret2->alloc(nbOfTuples,1);
4320     T *ret1Ptr=ret1->getPointer();
4321     T *ret2Ptr=ret2->getPointer();
4322     std::set<T> castsDetected;
4323     for(mcIdType i=0;i<nbOfTuples;i++)
4324       {
4325         rintstart res=std::find_if(bg,end2,std::bind2nd(std::less_equal<T>(), work[i]));
4326         std::size_t pos=std::distance(bg,res);
4327         std::size_t pos2=nbOfCast-pos;
4328         if(pos2<nbOfCast)
4329           {
4330             ret1Ptr[i]=static_cast<T>(pos2);
4331             ret2Ptr[i]=work[i]-arrBg[pos2];
4332             castsDetected.insert(ret1Ptr[i]);
4333           }
4334         else
4335           {
4336             std::ostringstream oss; oss << "DataArrayInt::splitByValueRange : At rank #" << i << " the value is " << work[i] << " should be in [0," << *bg << ") !";
4337             throw INTERP_KERNEL::Exception(oss.str().c_str());
4338           }
4339       }
4340     ret3->alloc(castsDetected.size(),1);
4341     std::copy(castsDetected.begin(),castsDetected.end(),ret3->getPointer());
4342     castArr=ret1.retn();
4343     rankInsideCast=ret2.retn();
4344     castsPresent=ret3.retn();
4345   }
4346
4347   /*!
4348    * This method look at \a this if it can be considered as a range defined by the 3-tuple ( \a strt , \a sttoopp , \a stteepp ).
4349    * If false is returned the tuple must be ignored. If true is returned \a this can be considered by a range( \a strt , \a sttoopp , \a stteepp ).
4350    * This method works only if \a this is allocated and single component. If not an exception will be thrown.
4351    *
4352    * \param [out] strt - the start of the range (included) if true is returned.
4353    * \param [out] sttoopp - the end of the range (not included) if true is returned.
4354    * \param [out] stteepp - the step of the range if true is returned.
4355    * \return the verdict of the check.
4356    *
4357    * \sa DataArray::GetNumberOfItemGivenBES
4358    */
4359   template<class T>
4360   bool DataArrayDiscrete<T>::isRange(T& strt, T& sttoopp, T& stteepp) const
4361   {
4362     this->checkAllocated();
4363     if(this->getNumberOfComponents()!=1)
4364       throw INTERP_KERNEL::Exception("DataArrayInt::isRange : this must be single component array !");
4365     mcIdType nbTuples(this->getNumberOfTuples());
4366     if(nbTuples==0)
4367       { strt=0; sttoopp=0; stteepp=1; return true; }
4368     const T *pt(this->begin());
4369     strt=*pt;
4370     if(nbTuples==1)
4371       { sttoopp=strt+1; stteepp=1; return true; }
4372     strt=*pt; sttoopp=pt[nbTuples-1];
4373     if(strt==sttoopp)
4374       return false;
4375     if(sttoopp>strt)
4376       {
4377         sttoopp++;
4378         T a(sttoopp-1-strt),tmp(strt);
4379         if(a%(nbTuples-1)!=0)
4380           return false;
4381         stteepp=a/(FromIdType<T>(nbTuples)-1);
4382         for(mcIdType i=0;i<nbTuples;i++,tmp+=stteepp)
4383           if(pt[i]!=tmp)
4384             return false;
4385         return true;
4386       }
4387     else
4388       {
4389         sttoopp--;
4390         T a(strt-sttoopp-1),tmp(strt);
4391         if(a%(nbTuples-1)!=0)
4392           return false;
4393         stteepp=-(a/(FromIdType<T>(nbTuples)-1));
4394         for(mcIdType i=0;i<nbTuples;i++,tmp+=stteepp)
4395           if(pt[i]!=tmp)
4396             return false;
4397         return true;
4398       }
4399   }
4400
4401   /*!
4402    * Creates a one-dimensional DataArrayInt of given length, whose contents are computed
4403    * from values of \a this array, which is supposed to contain a renumbering map in
4404    * "Old to New" mode. The result array contains a renumbering map in "New to Old" mode.
4405    * To know how to use the renumbering maps see \ref numbering.
4406    *  \param [in] newNbOfElem - the number of tuples in the result array.
4407    *  \return DataArrayInt * - the new instance of DataArrayInt.
4408    *          The caller is to delete this result array using decrRef() as it is no more
4409    *          needed.
4410    *
4411    *  \if ENABLE_EXAMPLES
4412    *  \ref cpp_mcdataarrayint_invertarrayo2n2n2o "Here is a C++ example".<br>
4413    *  \ref py_mcdataarrayint_invertarrayo2n2n2o  "Here is a Python example".
4414    *  \endif
4415    */
4416   template<class T>
4417   DataArrayIdType * DataArrayDiscrete<T>::invertArrayO2N2N2O(mcIdType newNbOfElem) const
4418   {
4419     MCAuto<DataArrayIdType> ret(DataArrayIdType::New());
4420     ret->alloc(newNbOfElem,1);
4421     mcIdType nbOfOldNodes(this->getNumberOfTuples());
4422     const T *old2New(this->begin());
4423     mcIdType *pt(ret->getPointer());
4424     for(mcIdType i=0;i!=nbOfOldNodes;i++)
4425       {
4426         T newp(old2New[i]);
4427         if(newp!=-1)
4428           {
4429             if(newp>=0 && newp<newNbOfElem)
4430               pt[newp]=i;
4431             else
4432               {
4433                 std::ostringstream oss; oss << "DataArrayInt::invertArrayO2N2N2O : At place #" << i << " the newplace is " << newp << " must be in [0," << newNbOfElem << ") !";
4434                 throw INTERP_KERNEL::Exception(oss.str().c_str());
4435               }
4436           }
4437       }
4438     return ret.retn();
4439   }
4440
4441   /*!
4442    * Creates a one-dimensional DataArrayInt of given length, whose contents are computed
4443    * from values of \a this array, which is supposed to contain a renumbering map in
4444    * "New to Old" mode. The result array contains a renumbering map in "Old to New" mode.
4445    * To know how to use the renumbering maps see \ref numbering.
4446    *  \param [in] newNbOfElem - the number of tuples in the result array.
4447    *  \return DataArrayInt * - the new instance of DataArrayInt.
4448    *          The caller is to delete this result array using decrRef() as it is no more
4449    *          needed.
4450    *
4451    *  \if ENABLE_EXAMPLES
4452    *  \ref cpp_mcdataarrayint_invertarrayn2o2o2n "Here is a C++ example".
4453    *
4454    *  \ref py_mcdataarrayint_invertarrayn2o2o2n "Here is a Python example".
4455    *  \sa invertArrayN2O2O2NOptimized
4456    *  \endif
4457    */
4458   template <class T>
4459   DataArrayIdType *DataArrayDiscrete<T>::invertArrayN2O2O2N(mcIdType oldNbOfElem) const
4460   {
4461     this->checkAllocated();
4462     MCAuto<DataArrayIdType> ret=DataArrayIdType::New();
4463     ret->alloc(oldNbOfElem,1);
4464     const T *new2Old=this->getConstPointer();
4465     mcIdType *pt=ret->getPointer();
4466     std::fill(pt,pt+oldNbOfElem,-1);
4467     mcIdType nbOfNewElems(this->getNumberOfTuples());
4468     for(mcIdType i=0;i<nbOfNewElems;i++)
4469       {
4470         T v(new2Old[i]);
4471         if(v>=0 && v<oldNbOfElem)
4472           pt[v]=i;
4473         else
4474           {
4475             std::ostringstream oss; oss << "DataArrayInt::invertArrayN2O2O2N : in new id #" << i << " old value is " << v << " expected to be in [0," << oldNbOfElem << ") !";
4476             throw INTERP_KERNEL::Exception(oss.str().c_str());
4477           }
4478       }
4479     return ret.retn();
4480   }
4481
4482   /*!
4483    * This method is similar to DataArrayInt::invertArrayO2N2N2O except that
4484    * Example : If \a this contains [0,1,2,0,3,4,5,4,6,4] this method will return [0,1,2,4,5,6,8] whereas DataArrayInt::invertArrayO2N2N2O returns [3,1,2,4,9,6,8]
4485    */
4486   template <class T>
4487   DataArrayIdType *DataArrayDiscrete<T>::invertArrayO2N2N2OBis(mcIdType newNbOfElem) const
4488   {
4489     MCAuto<DataArrayIdType> ret=DataArrayIdType::New();
4490     ret->alloc(newNbOfElem,1);
4491     mcIdType nbOfOldNodes(this->getNumberOfTuples());
4492     const T *old2New=this->getConstPointer();
4493     mcIdType *pt=ret->getPointer();
4494     for(mcIdType i=nbOfOldNodes-1;i>=0;i--)
4495       {
4496         T newp(old2New[i]);
4497         if(newp!=-1)
4498           {
4499             if(newp>=0 && newp<newNbOfElem)
4500               pt[newp]=i;
4501             else
4502               {
4503                 std::ostringstream oss; oss << "DataArrayInt::invertArrayO2N2N2OBis : At place #" << i << " the newplace is " << newp << " must be in [0," << newNbOfElem << ") !";
4504                 throw INTERP_KERNEL::Exception(oss.str().c_str());
4505               }
4506           }
4507       }
4508     return ret.retn();
4509   }
4510
4511   /*!
4512    * Creates a map, whose contents are computed
4513    * from values of \a this array, which is supposed to contain a renumbering map in
4514    * "New to Old" mode. The result array contains a renumbering map in "Old to New" mode.
4515    * To know how to use the renumbering maps see \ref numbering.
4516    *  \param [in] newNbOfElem - the number of tuples in the result array.
4517    *  \return MapII  - the new instance of Map.
4518    *
4519    *  \if ENABLE_EXAMPLES
4520    *  \ref cpp_mcdataarrayint_invertarrayn2o2o2n "Here is a C++ example".
4521    *
4522    *  \ref py_mcdataarrayint_invertarrayn2o2o2n "Here is a Python example".
4523    *  \sa invertArrayN2O2O2N, giveN2OOptimized, MEDCouplingPointSet::renumberNodesInConn
4524    *  \endif
4525    */
4526   template <class T>
4527   MCAuto< MapKeyVal<T, mcIdType> > DataArrayDiscrete<T>::invertArrayN2O2O2NOptimized() const
4528   {
4529     this->checkAllocated();
4530     if(this->getNumberOfComponents()!=1)
4531       throw INTERP_KERNEL::Exception("DataArrayInt::invertArrayN2O2O2NOptimized : single component expected !");
4532     MCAuto< MapKeyVal<T, mcIdType> > ret(MapKeyVal<T, mcIdType>::New());
4533     std::map<T, mcIdType>& m(ret->data());
4534     const T *new2Old(this->begin());
4535     mcIdType nbOfNewElems(this->getNumberOfTuples());
4536     for(mcIdType i=0;i<nbOfNewElems;i++)
4537       {
4538         T v(new2Old[i]);
4539         m[v]=i;
4540       }
4541     return ret;
4542   }
4543
4544   /*!
4545    * Creates a map, whose contents are computed
4546    * from values of \a this array, which is supposed to contain a renumbering map in 
4547    * "New to Old" mode. The result array contains a renumbering map in "New to Old" mode as C++ map for performance reasons.
4548    *
4549    * \sa invertArrayN2O2O2NOptimized, MEDCouplingPointSet::renumberNodesInConn
4550    */
4551   template <class T>
4552   MCAuto< MapKeyVal<mcIdType, T> > DataArrayDiscrete<T>::giveN2OOptimized() const
4553   {
4554     this->checkAllocated();
4555     if(this->getNumberOfComponents()!=1)
4556       throw INTERP_KERNEL::Exception("DataArrayInt::giveN2OOptimized : single component expected !");
4557     MCAuto< MapKeyVal<mcIdType, T> > ret(MapKeyVal<mcIdType, T>::New());
4558     std::map<mcIdType,T>& m(ret->data());
4559     const T *new2Old(this->begin());
4560     mcIdType nbOfNewElems(this->getNumberOfTuples());
4561     for(mcIdType i=0;i<nbOfNewElems;i++)
4562       {
4563         T v(new2Old[i]);
4564         m[i]=v;
4565       }
4566     return ret;
4567   }
4568
4569   /*!
4570    * This method finds for each element \a ELT in [valsBg,valsEnd) elements in \a this equal to it. Associated to ELT
4571    * this method will return the tuple id of last element found. If there is no element in \a this equal to ELT
4572    * an exception will be thrown.
4573    *
4574    * In case of success this[ret]==vals. Samely ret->transformWithIndArr(this->begin(),this->end())==vals.
4575    * Where \a vals is the [valsBg,valsEnd) array and \a ret the array returned by this method.
4576    * This method can be seen as an extension of FindPermutationFromFirstToSecond.
4577    * <br>
4578    * \b Example: <br>
4579    * - \a this: [17,27,2,10,-4,3,12,27,16]
4580    * - \a val : [3,16,-4,27,17]
4581    * - result: [5,8,4,7,0]
4582    *
4583    * \return - An array of size std::distance(valsBg,valsEnd)
4584    *
4585    * \sa DataArrayInt::FindPermutationFromFirstToSecond , DataArrayInt::FindPermutationFromFirstToSecondDuplicate
4586    */
4587   template <class T>
4588   MCAuto<DataArrayIdType> DataArrayDiscrete<T>::findIdForEach(const T *valsBg, const T *valsEnd) const
4589   {
4590     MCAuto<DataArrayIdType> ret(DataArrayIdType::New());
4591     std::size_t nbOfTuplesOut(std::distance(valsBg,valsEnd));
4592     ret->alloc(nbOfTuplesOut,1);
4593     MCAuto< MapKeyVal<T, mcIdType> > zeMap(this->invertArrayN2O2O2NOptimized());
4594     const std::map<T, mcIdType>& dat(zeMap->data());
4595     mcIdType *ptToFeed(ret->getPointer());
4596     for(const T *pt=valsBg;pt!=valsEnd;pt++)
4597       {
4598         typename std::map<T,mcIdType>::const_iterator it(dat.find(*pt));
4599         if(it!=dat.end())
4600           *ptToFeed++=(*it).second;
4601         else
4602           {
4603             std::ostringstream oss; oss << "DataArrayInt::findIdForEach : error for element at place " << std::distance(valsBg,pt);
4604             oss << " of input array value is " << *pt << " which is not in this !";
4605             throw INTERP_KERNEL::Exception(oss.str());
4606           }
4607       }
4608     return ret;
4609   }
4610
4611   /*!
4612    * Returns a new DataArrayInt containing a renumbering map in "Old to New" mode.
4613    * This map, if applied to \a this array, would make it sorted. For example, if
4614    * \a this array contents are [9,10,0,6,4,11,3,7] then the contents of the result array
4615    * are [5,6,0,3,2,7,1,4]; if this result array (\a res) is used as an argument in call
4616    * \a this->renumber(\a res) then the returned array contains [0,3,4,6,7,9,10,11].
4617    * This method is useful for renumbering (in MED file for example). For more info
4618    * on renumbering see \ref numbering.
4619    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
4620    *          array using decrRef() as it is no more needed.
4621    *  \throw If \a this is not allocated.
4622    *  \throw If \a this->getNumberOfComponents() != 1.
4623    *  \throw If there are equal values in \a this array.
4624    */
4625   template <class T>
4626   DataArrayIdType *DataArrayDiscrete<T>::checkAndPreparePermutation() const
4627   {
4628     this->checkAllocated();
4629     if(this->getNumberOfComponents()!=1)
4630       throw INTERP_KERNEL::Exception("DataArrayInt::checkAndPreparePermutation : number of components must == 1 !");
4631     mcIdType nbTuples(this->getNumberOfTuples());
4632     const T *pt=this->getConstPointer();
4633     mcIdType *pt2=this->CheckAndPreparePermutation(pt,pt+nbTuples);
4634     DataArrayIdType *ret=DataArrayIdType::New();
4635     ret->useArray(pt2,true,DeallocType::C_DEALLOC,nbTuples,1);
4636     return ret;
4637   }
4638
4639   /*!
4640    * Returns two arrays describing a surjective mapping from \a this set of values (\a A)
4641    * onto a set of values of size \a targetNb (\a B). The surjective function is
4642    * \a B[ \a A[ i ]] = i. That is to say that for each \a id in [0,\a targetNb), where \a
4643    * targetNb < \a this->getNumberOfTuples(), there exists at least one tupleId (\a tid) so
4644    * that <em> this->getIJ( tid, 0 ) == id</em>. <br>
4645    * The first of out arrays returns indices of elements of \a this array, grouped by their
4646    * place in the set \a B. The second out array is the index of the first one; it shows how
4647    * many elements of \a A are mapped into each element of \a B. <br>
4648    * For more info on
4649    * mapping and its usage in renumbering see \ref numbering. <br>
4650    * \b Example:
4651    * - \a this: [0,3,2,3,2,2,1,2]
4652    * - \a targetNb: 4
4653    * - \a arr:  [0,  6,  2,4,5,7,  1,3]
4654    * - \a arrI: [0,1,2,6,8]
4655    *
4656    * This result means: <br>
4657    * the element of \a B 0 encounters within \a A once (\a arrI[ 0+1 ] - \a arrI[ 0 ]) and
4658    * its index within \a A is 0 ( \a arr[ 0:1 ] == \a arr[ \a arrI[ 0 ] : \a arrI[ 0+1 ]]);<br>
4659    * the element of \a B 2 encounters within \a A 4 times (\a arrI[ 2+1 ] - \a arrI[ 2 ]) and
4660    * its indices within \a A are [2,4,5,7] ( \a arr[ 2:6 ] == \a arr[ \a arrI[ 2 ] :
4661    * \a arrI[ 2+1 ]]); <br> etc.
4662    *  \param [in] targetNb - the size of the set \a B. \a targetNb must be equal or more
4663    *         than the maximal value of \a A.
4664    *  \param [out] arr - a new instance of DataArrayInt returning indices of
4665    *         elements of \a this, grouped by their place in the set \a B. The caller is to delete
4666    *         this array using decrRef() as it is no more needed.
4667    *  \param [out] arrI - a new instance of DataArrayInt returning size of groups of equal
4668    *         elements of \a this. The caller is to delete this array using decrRef() as it
4669    *         is no more needed.
4670    *  \throw If \a this is not allocated.
4671    *  \throw If \a this->getNumberOfComponents() != 1.
4672    *  \throw If any value in \a this is more or equal to \a targetNb.
4673    */
4674   template <class T>
4675   void DataArrayDiscrete<T>::changeSurjectiveFormat(T targetNb, DataArrayIdType *&arr, DataArrayIdType *&arrI) const
4676   {
4677     this->checkAllocated();
4678     if(this->getNumberOfComponents()!=1)
4679       throw INTERP_KERNEL::Exception("DataArrayInt::changeSurjectiveFormat : number of components must == 1 !");
4680     mcIdType nbOfTuples(this->getNumberOfTuples());
4681     const T *input=this->getConstPointer();
4682     std::vector< std::vector<mcIdType> > tmp(targetNb);
4683     for(mcIdType i=0;i<nbOfTuples;i++)
4684       {
4685         T tmp2=input[i];
4686         if(tmp2>=0 && tmp2<targetNb)
4687           tmp[tmp2].push_back(i);
4688         else
4689           {
4690             std::ostringstream oss; oss << "DataArrayInt::changeSurjectiveFormat : At pos " << i << " presence of element " << tmp2 << " ! should be in [0," << targetNb << ") !";
4691             throw INTERP_KERNEL::Exception(oss.str().c_str());
4692           }
4693       }
4694
4695     MCAuto<DataArrayIdType> retI(DataArrayIdType::New());
4696     retI->alloc(targetNb+1,1);
4697     mcIdType *retIPtr=retI->getPointer();
4698     *retIPtr=0;
4699     for(std::vector< std::vector<mcIdType> >::const_iterator it1=tmp.begin();it1!=tmp.end();it1++,retIPtr++)
4700       retIPtr[1]=retIPtr[0]+ToIdType((*it1).size());
4701     if(nbOfTuples!=retI->getIJ(ToIdType(targetNb),0))
4702       throw INTERP_KERNEL::Exception("DataArrayInt::changeSurjectiveFormat : big problem should never happen !");
4703     MCAuto<DataArrayIdType> ret(DataArrayIdType::New());
4704     ret->alloc(nbOfTuples,1);
4705     mcIdType *retPtr=ret->getPointer();
4706     for(std::vector< std::vector<mcIdType> >::const_iterator it1=tmp.begin();it1!=tmp.end();it1++)
4707       retPtr=std::copy((*it1).begin(),(*it1).end(),retPtr);
4708     arr=ret.retn();
4709     arrI=retI.retn();
4710   }
4711
4712   /*!
4713    * Returns a new DataArrayInt containing a renumbering map in "New to Old" mode,
4714    * which if applied to \a this array would make it sorted ascendingly.
4715    * For more info on renumbering see \ref numbering. <br>
4716    * \b Example: <br>
4717    * - \a this: [2,0,1,1,0,1,2,0,1,1,0,0]
4718    * - result: [10,0,5,6,1,7,11,2,8,9,3,4]
4719    * - after applying result to \a this: [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2]
4720    *
4721    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
4722    *          array using decrRef() as it is no more needed.
4723    *  \throw If \a this is not allocated.
4724    *  \throw If \a this->getNumberOfComponents() != 1.
4725    */
4726   template <class T>
4727   DataArrayIdType *DataArrayDiscrete<T>::buildPermArrPerLevel() const
4728   {
4729     this->checkAllocated();
4730     if(this->getNumberOfComponents()!=1)
4731       throw INTERP_KERNEL::Exception("DataArrayInt::buildPermArrPerLevel : number of components must == 1 !");
4732     mcIdType nbOfTuples=this->getNumberOfTuples();
4733     const T *pt=this->getConstPointer();
4734     std::map<T,mcIdType> m;
4735     MCAuto<DataArrayIdType> ret=DataArrayIdType::New();
4736     ret->alloc(nbOfTuples,1);
4737     mcIdType *opt=ret->getPointer();
4738     for(mcIdType i=0;i<nbOfTuples;i++,pt++,opt++)
4739       {
4740         T val=*pt;
4741         typename std::map<T,mcIdType>::iterator it=m.find(val);
4742         if(it!=m.end())
4743           {
4744             *opt=(*it).second;
4745             (*it).second++;
4746           }
4747         else
4748           {
4749             *opt=0;
4750             m.insert(std::pair<T,mcIdType>(val,1));
4751           }
4752       }
4753     mcIdType sum=0;
4754     for(typename std::map<T,mcIdType>::iterator it=m.begin();it!=m.end();it++)
4755       {
4756         mcIdType vt=(*it).second;
4757         (*it).second=sum;
4758         sum+=vt;
4759       }
4760     pt=this->getConstPointer();
4761     opt=ret->getPointer();
4762     for(mcIdType i=0;i<nbOfTuples;i++,pt++,opt++)
4763       *opt+=m[*pt];
4764     //
4765     return ret.retn();
4766   }
4767
4768   /*!
4769    * Checks if \a this array has the given size, and if its contents is equal to an array filled with
4770    * iota(). This method is particularly useful for DataArrayInt instances that represent
4771    * a renumbering array, to check if there is a real need in renumbering.
4772    * This method checks than \a this can be considered as an identity mapping
4773    * of a set having \a sizeExpected elements into itself.
4774    *
4775    *  \param [in] sizeExpected - The number of elements expected.
4776    *  \return bool - \a true if \a this array contents == \a range( \a this->getNumberOfTuples())
4777    *  \throw If \a this is not allocated.
4778    *  \throw If \a this->getNumberOfComponents() != 1.
4779    */
4780   template <class T>
4781   bool DataArrayDiscrete<T>::isIota(mcIdType sizeExpected) const
4782   {
4783     this->checkAllocated();
4784     if(this->getNumberOfComponents()!=1)
4785       return false;
4786     mcIdType nbOfTuples(this->getNumberOfTuples());
4787     if(nbOfTuples!=sizeExpected)
4788       return false;
4789     const T *pt=this->getConstPointer();
4790     for(mcIdType i=0;i<nbOfTuples;i++,pt++)
4791       if(*pt!=i)
4792         return false;
4793     return true;
4794   }
4795
4796   /*!
4797    * Checks if all values in \a this array are equal to \a val.
4798    *  \param [in] val - value to check equality of array values to.
4799    *  \return bool - \a true if all values are \a val.
4800    *  \throw If \a this is not allocated.
4801    *  \throw If \a this->getNumberOfComponents() != 1
4802    *  \sa DataArrayInt::checkUniformAndGuess
4803    */
4804   template <class T>
4805   bool DataArrayDiscrete<T>::isUniform(T val) const
4806   {
4807     this->checkAllocated();
4808     if(this->getNumberOfComponents()!=1)
4809       throw INTERP_KERNEL::Exception("DataArrayInt::isUniform : must be applied on DataArrayInt with only one component, you can call 'rearrange' method before !");
4810     const T *w(this->begin()),*end2(this->end());
4811     for(;w!=end2;w++)
4812       if(*w!=val)
4813         return false;
4814     return true;
4815   }
4816
4817   /*!
4818    * This method checks that \a this is uniform. If not and exception will be thrown.
4819    * In case of uniformity the corresponding value is returned.
4820    *
4821    * \return mcIdType - the unique value contained in this
4822    * \throw If \a this is not allocated.
4823    * \throw If \a this->getNumberOfComponents() != 1
4824    * \throw If \a this is not uniform.
4825    * \sa DataArrayInt::isUniform
4826    */
4827   template <class T>
4828   T DataArrayDiscrete<T>::checkUniformAndGuess() const
4829   {
4830     this->checkAllocated();
4831     if(this->getNumberOfComponents()!=1)
4832       throw INTERP_KERNEL::Exception("DataArrayInt::checkUniformAndGuess : must be applied on DataArrayInt with only one component, you can call 'rearrange' method before !");
4833     if(this->empty())
4834       throw INTERP_KERNEL::Exception("DataArrayInt::checkUniformAndGuess : this is empty !");
4835     const T *w(this->begin()),*end2(this->end());
4836     T ret(*w);
4837     for(;w!=end2;w++)
4838       if(*w!=ret)
4839         throw INTERP_KERNEL::Exception("DataArrayInt::checkUniformAndGuess : this is not uniform !");
4840     return ret;
4841   }
4842
4843   /*!
4844    * Checks if all values in \a this array are unique.
4845    *  \return bool - \a true if condition above is true
4846    *  \throw If \a this is not allocated.
4847    *  \throw If \a this->getNumberOfComponents() != 1
4848    */
4849   template <class T>
4850   bool DataArrayDiscrete<T>::hasUniqueValues() const
4851   {
4852     this->checkAllocated();
4853     if(this->getNumberOfComponents()!=1)
4854       throw INTERP_KERNEL::Exception("DataArrayInt::hasOnlyUniqueValues: must be applied on DataArrayInt with only one component, you can call 'rearrange' method before !");
4855     std::size_t nbOfElements(this->getNumberOfTuples());
4856     std::set<T> s(this->begin(),this->end());  // in C++11, should use unordered_set (O(1) complexity)
4857     if (s.size() != nbOfElements)
4858       return false;
4859     return true;
4860   }
4861
4862   /*!
4863    * Copy all components in a specified order from another DataArrayInt.
4864    * The specified components become the first ones in \a this array.
4865    * Both numerical and textual data is copied. The number of tuples in \a this and
4866    * the other array can be different.
4867    *  \param [in] a - the array to copy data from.
4868    *  \param [in] compoIds - sequence of zero based indices of components, data of which is
4869    *              to be copied.
4870    *  \throw If \a a is NULL.
4871    *  \throw If \a compoIds.size() != \a a->getNumberOfComponents().
4872    *  \throw If \a compoIds[i] < 0 or \a compoIds[i] > \a this->getNumberOfComponents().
4873    *
4874    *  \if ENABLE_EXAMPLES
4875    *  \ref py_mcdataarrayint_setselectedcomponents "Here is a Python example".
4876    *  \endif
4877    */
4878   template <class T>
4879   void DataArrayDiscrete<T>::setSelectedComponents(const DataArrayType *a, const std::vector<std::size_t>& compoIds)
4880   {
4881     if(!a)
4882       throw INTERP_KERNEL::Exception("DataArrayInt::setSelectedComponents : input DataArrayInt is NULL !");
4883     this->checkAllocated();
4884     a->checkAllocated();
4885     this->copyPartOfStringInfoFrom2(compoIds,*a);
4886     std::size_t partOfCompoSz=compoIds.size();
4887     std::size_t nbOfCompo = this->getNumberOfComponents();
4888     mcIdType nbOfTuples=std::min(this->getNumberOfTuples(),a->getNumberOfTuples());
4889     const T *ac=a->getConstPointer();
4890     T *nc=this->getPointer();
4891     for(mcIdType i=0;i<nbOfTuples;i++)
4892       for(std::size_t j=0;j<partOfCompoSz;j++,ac++)
4893         nc[nbOfCompo*i+compoIds[j]]=*ac;
4894   }
4895
4896   /*!
4897    * Creates a new DataArrayInt containing IDs (indices) of tuples holding value \b not
4898    * equal to a given one.
4899    *  \param [in] val - the value to ignore within \a this.
4900    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
4901    *          array using decrRef() as it is no more needed.
4902    *  \throw If \a this is not allocated.
4903    *  \throw If \a this->getNumberOfComponents() != 1.
4904    */
4905   template <class T>
4906   DataArrayIdType *DataArrayDiscrete<T>::findIdsNotEqual(T val) const
4907   {
4908     this->checkAllocated();
4909     if(this->getNumberOfComponents()!=1)
4910       throw INTERP_KERNEL::Exception("DataArrayInt::findIdsNotEqual : the array must have only one component, you can call 'rearrange' method before !");
4911     const T *cptr(this->getConstPointer());
4912     MCAuto<DataArrayIdType> ret(DataArrayIdType::New());
4913     ret->alloc(0,1);
4914     mcIdType nbOfTuples(this->getNumberOfTuples());
4915     for(mcIdType i=0;i<nbOfTuples;i++,cptr++)
4916       if(*cptr!=val)
4917         ret->pushBackSilent(i);
4918     return ret.retn();
4919   }
4920   
4921   /*!
4922    * Creates a new DataArrayInt containing IDs (indices) of tuples holding tuple equal to those defined by [ \a tupleBg , \a tupleEnd )
4923    * This method is an extension of  DataArrayInt::findIdsEqual method.
4924    *
4925    *  \param [in] tupleBg - the begin (included) of the input tuple to find within \a this.
4926    *  \param [in] tupleEnd - the end (excluded) of the input tuple to find within \a this.
4927    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
4928    *          array using decrRef() as it is no more needed.
4929    *  \throw If \a this is not allocated.
4930    *  \throw If \a this->getNumberOfComponents() != std::distance(tupleBg,tupleEnd).
4931    * \throw If \a this->getNumberOfComponents() is equal to 0.
4932    * \sa DataArrayInt::findIdsEqual
4933    */
4934   template <class T>
4935   DataArrayIdType *DataArrayDiscrete<T>::findIdsEqualTuple(const T *tupleBg, const T *tupleEnd) const
4936   {
4937     std::size_t nbOfCompoExp=std::distance(tupleBg,tupleEnd);
4938     this->checkAllocated();
4939     if(this->getNumberOfComponents()!=nbOfCompoExp)
4940       {
4941         std::ostringstream oss; oss << "DataArrayInt::findIdsEqualTuple : mismatch of number of components. Input tuple has " << nbOfCompoExp << " whereas this array has " << this->getNumberOfComponents() << " components !";
4942         throw INTERP_KERNEL::Exception(oss.str().c_str());
4943       }
4944     if(nbOfCompoExp==0)
4945       throw INTERP_KERNEL::Exception("DataArrayInt::findIdsEqualTuple : number of components should be > 0 !");
4946     MCAuto<DataArrayIdType> ret(DataArrayIdType::New());
4947     ret->alloc(0,1);
4948     const T *bg(this->begin()),*end2(this->end()),*work(this->begin());
4949     while(work!=end2)
4950       {
4951         work=std::search(work,end2,tupleBg,tupleEnd);
4952         if(work!=end2)
4953           {
4954             std::ptrdiff_t pos=std::distance(bg,work);
4955             if(pos%nbOfCompoExp==0)
4956               ret->pushBackSilent(ToIdType(pos/nbOfCompoExp));
4957             work++;
4958           }
4959       }
4960     return ret.retn();
4961   }
4962
4963   /*!
4964    * Creates a new DataArrayInt containing IDs (indices) of tuples holding value equal to
4965    * one of given values.
4966    *  \param [in] valsBg - an array of values to find within \a this array.
4967    *  \param [in] valsEnd - specifies the end of the array \a valsBg, so that
4968    *              the last value of \a valsBg is \a valsEnd[ -1 ].
4969    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
4970    *          array using decrRef() as it is no more needed.
4971    *  \throw If \a this->getNumberOfComponents() != 1.
4972    */
4973   template <class T>
4974   DataArrayIdType *DataArrayDiscrete<T>::findIdsEqualList(const T *valsBg, const T *valsEnd) const
4975   {
4976     if(this->getNumberOfComponents()!=1)
4977       throw INTERP_KERNEL::Exception("DataArrayInt::findIdsEqualList : the array must have only one component, you can call 'rearrange' method before !");
4978     std::set<T> vals2(valsBg,valsEnd);
4979     const T *cptr(this->getConstPointer());
4980     mcIdType nbOfTuples(this->getNumberOfTuples());
4981     MCAuto<DataArrayIdType> ret(DataArrayIdType::New()); ret->alloc(0,1);
4982     for(mcIdType i=0;i<nbOfTuples;i++,cptr++)
4983       if(vals2.find(*cptr)!=vals2.end())
4984         ret->pushBackSilent(i);
4985     return ret.retn();
4986   }
4987   
4988   /*!
4989    * Creates a new DataArrayInt containing IDs (indices) of tuples holding values \b not
4990    * equal to any of given values.
4991    *  \param [in] valsBg - an array of values to ignore within \a this array.
4992    *  \param [in] valsEnd - specifies the end of the array \a valsBg, so that
4993    *              the last value of \a valsBg is \a valsEnd[ -1 ].
4994    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
4995    *          array using decrRef() as it is no more needed.
4996    *  \throw If \a this->getNumberOfComponents() != 1.
4997    */
4998   template <class T>
4999   DataArrayIdType *DataArrayDiscrete<T>::findIdsNotEqualList(const T *valsBg, const T *valsEnd) const
5000   {
5001     if(this->getNumberOfComponents()!=1)
5002       throw INTERP_KERNEL::Exception("DataArrayInt::findIdsNotEqualList : the array must have only one component, you can call 'rearrange' method before !");
5003     std::set<T> vals2(valsBg,valsEnd);
5004     const T *cptr=this->getConstPointer();
5005     mcIdType nbOfTuples(this->getNumberOfTuples());
5006     MCAuto<DataArrayIdType> ret(DataArrayIdType::New()); ret->alloc(0,1);
5007     for(mcIdType i=0;i<nbOfTuples;i++,cptr++)
5008       if(vals2.find(*cptr)==vals2.end())
5009         ret->pushBackSilent(i);
5010     return ret.retn();
5011   }
5012
5013   /*!
5014    * This method expects to be called when number of components of this is equal to one.
5015    * This method returns the tuple id, if it exists, of the first tuple equal to \b value.
5016    * If not any tuple contains \b value -1 is returned.
5017    * \sa DataArrayInt::presenceOfValue
5018    */
5019   template <class T>
5020   mcIdType DataArrayDiscrete<T>::findIdFirstEqual(T value) const
5021   {
5022     this->checkAllocated();
5023     if(this->getNumberOfComponents()!=1)
5024       throw INTERP_KERNEL::Exception("DataArrayInt::presenceOfValue : the array must have only one component, you can call 'rearrange' method before !");
5025     const T *cptr=this->getConstPointer();
5026     mcIdType nbOfTuples(this->getNumberOfTuples());
5027     const T *ret=std::find(cptr,cptr+nbOfTuples,value);
5028     if(ret!=cptr+nbOfTuples)
5029       return ToIdType(std::distance(cptr,ret));
5030     return -1;
5031   }
5032   
5033   /*!
5034    * This method expects to be called when number of components of this is equal to one.
5035    * This method returns the tuple id, if it exists, of the first tuple so that the value is contained in \b vals.
5036    * If not any tuple contains one of the values contained in 'vals' -1 is returned.
5037    * \sa DataArrayInt::presenceOfValue
5038    */
5039   template <class T>
5040   mcIdType DataArrayDiscrete<T>::findIdFirstEqual(const std::vector<T>& vals) const
5041   {
5042     this->checkAllocated();
5043     if(this->getNumberOfComponents()!=1)
5044       throw INTERP_KERNEL::Exception("DataArrayInt::presenceOfValue : the array must have only one component, you can call 'rearrange' method before !");
5045     std::set<T> vals2(vals.begin(),vals.end());
5046     const T *cptr=this->getConstPointer();
5047     mcIdType nbOfTuples(this->getNumberOfTuples());
5048     for(const T *w=cptr;w!=cptr+nbOfTuples;w++)
5049       if(vals2.find(*w)!=vals2.end())
5050         return ToIdType(std::distance(cptr,w));
5051     return -1;
5052   }
5053
5054   /*!
5055    * This method is an extension of DataArrayInt::findIdFirstEqual method because this method works for DataArrayInt with
5056    * any number of components excepted 0 (an INTERP_KERNEL::Exception is thrown in this case).
5057    * This method searches in \b this is there is a tuple that matched the input parameter \b tupl.
5058    * If any the tuple id is returned. If not -1 is returned.
5059    *
5060    * This method throws an INTERP_KERNEL::Exception if the number of components in \b this mismatches with the size of
5061    * the input vector. An INTERP_KERNEL::Exception is thrown too if \b this is not allocated.
5062    *
5063    * \return tuple id where \b tupl is. -1 if no such tuple exists in \b this.
5064    * \sa DataArrayInt::findIdSequence, DataArrayInt::presenceOfTuple.
5065    */
5066   template <class T>
5067   mcIdType DataArrayDiscrete<T>::findIdFirstEqualTuple(const std::vector<T>& tupl) const
5068   {
5069     this->checkAllocated();
5070     std::size_t nbOfCompo(this->getNumberOfComponents());
5071     if(nbOfCompo==0)
5072       throw INTERP_KERNEL::Exception("DataArrayInt::findIdFirstEqualTuple : 0 components in 'this' !");
5073     if(nbOfCompo!=tupl.size())
5074       {
5075         std::ostringstream oss; oss << "DataArrayInt::findIdFirstEqualTuple : 'this' contains " << nbOfCompo << " components and searching for a tuple of length " << tupl.size() << " !";
5076         throw INTERP_KERNEL::Exception(oss.str().c_str());
5077       }
5078     const T *cptr=this->getConstPointer();
5079     std::size_t nbOfVals=this->getNbOfElems();
5080     for(const T *work=cptr;work!=cptr+nbOfVals;)
5081       {
5082         work=std::search(work,cptr+nbOfVals,tupl.begin(),tupl.end());
5083         if(work!=cptr+nbOfVals)
5084           {
5085             if(std::distance(cptr,work)%nbOfCompo!=0)
5086               work++;
5087             else
5088               return ToIdType (std::distance(cptr,work)/nbOfCompo);
5089           }
5090       }
5091     return -1;
5092   }
5093
5094   /*!
5095    * This method searches the sequence specified in input parameter \b vals in \b this.
5096    * This works only for DataArrayInt having number of components equal to one (if not an INTERP_KERNEL::Exception will be thrown).
5097    * This method differs from DataArrayInt::findIdFirstEqualTuple in that the position is internal raw data is not considered here contrary to DataArrayInt::findIdFirstEqualTuple.
5098    * \sa DataArrayInt::findIdFirstEqualTuple
5099    */
5100   template <class T>
5101   mcIdType DataArrayDiscrete<T>::findIdSequence(const std::vector<T>& vals) const
5102   {
5103     this->checkAllocated();
5104     std::size_t nbOfCompo=this->getNumberOfComponents();
5105     if(nbOfCompo!=1)
5106       throw INTERP_KERNEL::Exception("DataArrayInt::findIdSequence : works only for DataArrayInt instance with one component !");
5107     const T *cptr=this->getConstPointer();
5108     std::size_t nbOfVals=this->getNbOfElems();
5109     const T *loc=std::search(cptr,cptr+nbOfVals,vals.begin(),vals.end());
5110     if(loc!=cptr+nbOfVals)
5111       return ToIdType(std::distance(cptr,loc));
5112     return -1;
5113   }
5114
5115   /*!
5116    * Assigns \a newValue to all elements holding \a oldValue within \a this
5117    * one-dimensional array.
5118    *  \param [in] oldValue - the value to replace.
5119    *  \param [in] newValue - the value to assign.
5120    *  \return mcIdType - number of replacements performed.
5121    *  \throw If \a this is not allocated.
5122    *  \throw If \a this->getNumberOfComponents() != 1.
5123    */
5124   template <class T>
5125   mcIdType DataArrayDiscrete<T>::changeValue(T oldValue, T newValue)
5126   {
5127     this->checkAllocated();
5128     if(this->getNumberOfComponents()!=1)
5129       throw INTERP_KERNEL::Exception("DataArrayInt::changeValue : the array must have only one component, you can call 'rearrange' method before !");
5130     if(oldValue==newValue)
5131       return 0;
5132     T *start(this->getPointer()),*end2(start+this->getNbOfElems());
5133     mcIdType ret(0);
5134     for(T *val=start;val!=end2;val++)
5135       {
5136         if(*val==oldValue)
5137           {
5138             *val=newValue;
5139             ret++;
5140           }
5141       }
5142     if(ret>0)
5143       this->declareAsNew();
5144     return ret;
5145   }
5146
5147   /*!
5148    * This method returns the number of values in \a this that are equals to input parameter \a value.
5149    * This method only works for single component array.
5150    *
5151    * \return a value in [ 0, \c this->getNumberOfTuples() )
5152    *
5153    * \throw If \a this is not allocated
5154    *
5155    */
5156   template <class T>
5157   mcIdType DataArrayDiscrete<T>::count(T value) const
5158   {
5159     mcIdType ret=0;
5160     this->checkAllocated();
5161     if(this->getNumberOfComponents()!=1)
5162       throw INTERP_KERNEL::Exception("DataArrayInt::count : must be applied on DataArrayInt with only one component, you can call 'rearrange' method before !");
5163     const T *vals=this->begin();
5164     std::size_t nbOfElements=this->getNumberOfTuples();
5165     for(std::size_t i=0;i<nbOfElements;i++,vals++)
5166       if(*vals==value)
5167         ret++;
5168     return ret;
5169   }
5170
5171   /*!
5172    * This method is an extension of DataArrayInt::presenceOfValue method because this method works for DataArrayInt with
5173    * any number of components excepted 0 (an INTERP_KERNEL::Exception is thrown in this case).
5174    * This method searches in \b this is there is a tuple that matched the input parameter \b tupl.
5175    * This method throws an INTERP_KERNEL::Exception if the number of components in \b this mismatches with the size of
5176    * the input vector. An INTERP_KERNEL::Exception is thrown too if \b this is not allocated.
5177    * \sa DataArrayInt::findIdFirstEqualTuple
5178    */
5179   template <class T>
5180   bool DataArrayDiscrete<T>::presenceOfTuple(const std::vector<T>& tupl) const
5181   {
5182     return this->findIdFirstEqualTuple(tupl)!=-1;
5183   }
5184   
5185   
5186   /*!
5187    * Returns \a true if a given value is present within \a this one-dimensional array.
5188    *  \param [in] value - the value to find within \a this array.
5189    *  \return bool - \a true in case if \a value is present within \a this array.
5190    *  \throw If \a this is not allocated.
5191    *  \throw If \a this->getNumberOfComponents() != 1.
5192    *  \sa findIdFirstEqual()
5193    */
5194   template <class T>
5195   bool DataArrayDiscrete<T>::presenceOfValue(T value) const
5196   {
5197     return this->findIdFirstEqual(value)!=-1;
5198   }
5199   
5200   /*!
5201    * This method expects to be called when number of components of this is equal to one.
5202    * This method returns true if it exists a tuple so that the value is contained in \b vals.
5203    * If not any tuple contains one of the values contained in 'vals' false is returned.
5204    * \sa DataArrayInt::findIdFirstEqual
5205    */
5206   template <class T>
5207   bool DataArrayDiscrete<T>::presenceOfValue(const std::vector<T>& vals) const
5208   {
5209     return this->findIdFirstEqual(vals)!=-1;
5210   }
5211
5212   /*!
5213    * Accumulates values of each component of \a this array.
5214    *  \param [out] res - an array of length \a this->getNumberOfComponents(), allocated
5215    *         by the caller, that is filled by this method with sum value for each
5216    *         component.
5217    *  \throw If \a this is not allocated.
5218    */
5219   template <class T>
5220   void DataArrayDiscrete<T>::accumulate(T *res) const
5221   {
5222     this->checkAllocated();
5223     const T *ptr=this->getConstPointer();
5224     mcIdType nbTuple(this->getNumberOfTuples());
5225     std::size_t nbComps(this->getNumberOfComponents());
5226     std::fill(res,res+nbComps,0);
5227     for(mcIdType i=0;i<nbTuple;i++)
5228       std::transform(ptr+i*nbComps,ptr+(i+1)*nbComps,res,res,std::plus<T>());
5229   }
5230   
5231   template <class T>
5232   T DataArrayDiscrete<T>::accumulate(std::size_t compId) const
5233   {
5234     this->checkAllocated();
5235     const T *ptr=this->getConstPointer();
5236     mcIdType nbTuple(this->getNumberOfTuples());
5237     std::size_t nbComps(this->getNumberOfComponents());
5238     if(compId<0 || compId>=nbComps)
5239       throw INTERP_KERNEL::Exception("DataArrayInt::accumulate : Invalid compId specified : No such nb of components !");
5240     T ret=0;
5241     for(mcIdType i=0;i<nbTuple;i++)
5242       ret+=ptr[i*nbComps+compId];
5243     return ret;
5244   }
5245
5246   /*!
5247    * This method accumulate using addition tuples in \a this using input index array [ \a bgOfIndex, \a endOfIndex ).
5248    * The returned array will have same number of components than \a this and number of tuples equal to
5249    * \c std::distance(bgOfIndex,endOfIndex) \b minus \b one.
5250    *
5251    * The input index array is expected to be ascendingly sorted in which the all referenced ids should be in [0, \c this->getNumberOfTuples).
5252    *
5253    * \param [in] bgOfIndex - begin (included) of the input index array.
5254    * \param [in] endOfIndex - end (excluded) of the input index array.
5255    * \return DataArrayInt * - the new instance having the same number of components than \a this.
5256    *
5257    * \throw If bgOfIndex or end is NULL.
5258    * \throw If input index array is not ascendingly sorted.
5259    * \throw If there is an id in [ \a bgOfIndex, \a endOfIndex ) not in [0, \c this->getNumberOfTuples).
5260    * \throw If std::distance(bgOfIndex,endOfIndex)==0.
5261    */
5262   template <class T>
5263   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::accumulatePerChunck(const mcIdType *bgOfIndex, const mcIdType *endOfIndex) const
5264   {
5265     if(!bgOfIndex || !endOfIndex)
5266       throw INTERP_KERNEL::Exception("DataArrayInt::accumulatePerChunck : input pointer NULL !");
5267     this->checkAllocated();
5268     std::size_t nbCompo(this->getNumberOfComponents());
5269     mcIdType nbOfTuples(this->getNumberOfTuples());
5270     mcIdType sz=ToIdType(std::distance(bgOfIndex,endOfIndex));
5271     if(sz<1)
5272       throw INTERP_KERNEL::Exception("DataArrayInt::accumulatePerChunck : invalid size of input index array !");
5273     sz--;
5274     MCAuto<DataArrayType> ret=DataArrayType::New(); ret->alloc(sz,nbCompo);
5275     const mcIdType *w=bgOfIndex;
5276     if(*w<0 || *w>=nbOfTuples)
5277       throw INTERP_KERNEL::Exception("DataArrayInt::accumulatePerChunck : The first element of the input index not in [0,nbOfTuples) !");
5278     const T *srcPt=this->begin()+(*w)*nbCompo;
5279     T *tmp=ret->getPointer();
5280     for(mcIdType i=0;i<sz;i++,tmp+=nbCompo,w++)
5281       {
5282         std::fill(tmp,tmp+nbCompo,0);
5283         if(w[1]>=w[0])
5284           {
5285             for(mcIdType j=w[0];j<w[1];j++,srcPt+=nbCompo)
5286               {
5287                 if(j>=0 && j<nbOfTuples)
5288                   std::transform(srcPt,srcPt+nbCompo,tmp,tmp,std::plus<T>());
5289                 else
5290                   {
5291                     std::ostringstream oss; oss << "DataArrayInt::accumulatePerChunck : At rank #" << i << " the input index array points to id " << j << " should be in [0," << nbOfTuples << ") !";
5292                     throw INTERP_KERNEL::Exception(oss.str().c_str());
5293                   }
5294               }
5295           }
5296         else
5297           {
5298             std::ostringstream oss; oss << "DataArrayInt::accumulatePerChunck : At rank #" << i << " the input index array is not in ascendingly sorted.";
5299             throw INTERP_KERNEL::Exception(oss.str().c_str());
5300           }
5301       }
5302     ret->copyStringInfoFrom(*this);
5303     return ret.retn();
5304   }
5305
5306   /*!
5307    * Returns in a single walk in \a this the min value and the max value in \a this.
5308    * \a this is expected to be single component array.
5309    *
5310    * \param [out] minValue - the min value in \a this.
5311    * \param [out] maxValue - the max value in \a this.
5312    *
5313    * \sa getMinValueInArray, getMinValue, getMaxValueInArray, getMaxValue
5314    */
5315   template <class T>
5316   void DataArrayDiscrete<T>::getMinMaxValues(T& minValue, T& maxValue) const
5317   {
5318     this->checkAllocated();
5319     if(this->getNumberOfComponents()!=1)
5320       throw INTERP_KERNEL::Exception("DataArrayInt::getMinMaxValues : must be applied on DataArrayInt with only one component !");
5321     std::size_t nbElements(this->getNumberOfTuples());
5322     const T *pt(this->begin());
5323     minValue=std::numeric_limits<T>::max(); maxValue=-std::numeric_limits<T>::max();
5324     for(std::size_t i=0;i<nbElements;i++,pt++)
5325       {
5326         if(*pt<minValue)
5327           minValue=*pt;
5328         if(*pt>maxValue)
5329           maxValue=*pt;
5330       }
5331   }
5332
5333   /*!
5334    * Modify all elements of \a this array, so that
5335    * an element _x_ becomes \f$ numerator / x \f$.
5336    *  \warning If an exception is thrown because of presence of 0 element in \a this
5337    *           array, all elements processed before detection of the zero element remain
5338    *           modified.
5339    *  \param [in] numerator - the numerator used to modify array elements.
5340    *  \throw If \a this is not allocated.
5341    *  \throw If there is an element equal to 0 in \a this array.
5342    */
5343   template <class T>
5344   void DataArrayDiscrete<T>::applyInv(T numerator)
5345   {
5346     this->checkAllocated();
5347     T *ptr=this->getPointer();
5348     std::size_t nbOfElems=this->getNbOfElems();
5349     for(std::size_t i=0;i<nbOfElems;i++,ptr++)
5350       {
5351         if(*ptr!=0)
5352           {
5353             *ptr=numerator/(*ptr);
5354           }
5355         else
5356           {
5357             std::ostringstream oss; oss << "DataArrayInt::applyInv : presence of null value in tuple #" << i/(this->getNumberOfComponents()) << " component #" << i%(this->getNumberOfComponents());
5358             oss << " !";
5359             throw INTERP_KERNEL::Exception(oss.str().c_str());
5360           }
5361       }
5362     this->declareAsNew();
5363   }
5364
5365   /*!
5366    * Modify all elements of \a this array, so that
5367    * an element _x_ becomes \f$ x / val \f$.
5368    *  \param [in] val - the denominator used to modify array elements.
5369    *  \throw If \a this is not allocated.
5370    *  \throw If \a val == 0.
5371    */
5372   template <class T>
5373   void DataArrayDiscrete<T>::applyDivideBy(T val)
5374   {
5375     if(val==0)
5376       throw INTERP_KERNEL::Exception("DataArrayInt::applyDivideBy : Trying to divide by 0 !");
5377     this->checkAllocated();
5378     T *ptr=this->getPointer();
5379     std::size_t nbOfElems=this->getNbOfElems();
5380     std::transform(ptr,ptr+nbOfElems,ptr,std::bind2nd(std::divides<T>(),val));
5381     this->declareAsNew();
5382   }
5383
5384   /*!
5385    * Modify all elements of \a this array, so that
5386    * an element _x_ becomes  <em> x % val </em>.
5387    *  \param [in] val - the divisor used to modify array elements.
5388    *  \throw If \a this is not allocated.
5389    *  \throw If \a val <= 0.
5390    */
5391   template <class T>
5392   void DataArrayDiscrete<T>::applyModulus(T val)
5393   {
5394     if(val<=0)
5395       throw INTERP_KERNEL::Exception("DataArrayInt::applyDivideBy : Trying to operate modulus on value <= 0 !");
5396     this->checkAllocated();
5397     T *ptr=this->getPointer();
5398     std::size_t nbOfElems=this->getNbOfElems();
5399     std::transform(ptr,ptr+nbOfElems,ptr,std::bind2nd(std::modulus<T>(),val));
5400     this->declareAsNew();
5401   }
5402
5403   /*!
5404    * Modify all elements of \a this array, so that
5405    * an element _x_ becomes <em> val % x </em>.
5406    *  \warning If an exception is thrown because of presence of an element <= 0 in \a this
5407    *           array, all elements processed before detection of the zero element remain
5408    *           modified.
5409    *  \param [in] val - the divident used to modify array elements.
5410    *  \throw If \a this is not allocated.
5411    *  \throw If there is an element equal to or less than 0 in \a this array.
5412    */
5413   template <class T>
5414   void DataArrayDiscrete<T>::applyRModulus(T val)
5415   {
5416     this->checkAllocated();
5417     T *ptr=this->getPointer();
5418     std::size_t nbOfElems=this->getNbOfElems();
5419     for(std::size_t i=0;i<nbOfElems;i++,ptr++)
5420       {
5421         if(*ptr>0)
5422           {
5423             *ptr=val%(*ptr);
5424           }
5425         else
5426           {
5427             std::ostringstream oss; oss << "DataArrayInt::applyRModulus : presence of value <=0 in tuple #" << i/(this->getNumberOfComponents()) << " component #" << i%(this->getNumberOfComponents());
5428             oss << " !";
5429             throw INTERP_KERNEL::Exception(oss.str().c_str());
5430           }
5431       }
5432     this->declareAsNew();
5433   }
5434
5435   /*!
5436    * Modify all elements of \a this array, so that
5437    * an element _x_ becomes <em> val ^ x </em>.
5438    *  \param [in] val - the value used to apply pow on all array elements.
5439    *  \throw If \a this is not allocated.
5440    *  \throw If \a val < 0.
5441    */
5442   template <class T>
5443   void DataArrayDiscrete<T>::applyPow(T val)
5444   {
5445     this->checkAllocated();
5446     if(val<0)
5447       throw INTERP_KERNEL::Exception("DataArrayInt::applyPow : input pow in < 0 !");
5448     T *ptr=this->getPointer();
5449     std::size_t nbOfElems=this->getNbOfElems();
5450     if(val==0)
5451       {
5452         std::fill(ptr,ptr+nbOfElems,1);
5453         return ;
5454       }
5455     for(std::size_t i=0;i<nbOfElems;i++,ptr++)
5456       {
5457         T tmp=1;
5458         for(T j=0;j<val;j++)
5459           tmp*=*ptr;
5460         *ptr=tmp;
5461       }
5462     this->declareAsNew();
5463   }
5464   
5465   /*!
5466    * Modify all elements of \a this array, so that
5467    * an element _x_ becomes \f$ val ^ x \f$.
5468    *  \param [in] val - the value used to apply pow on all array elements.
5469    *  \throw If \a this is not allocated.
5470    *  \throw If there is an element < 0 in \a this array.
5471    *  \warning If an exception is thrown because of presence of 0 element in \a this
5472    *           array, all elements processed before detection of the zero element remain
5473    *           modified.
5474    */
5475   template <class T>
5476   void DataArrayDiscrete<T>::applyRPow(T val)
5477   {
5478     this->checkAllocated();
5479     T *ptr=this->getPointer();
5480     std::size_t nbOfElems=this->getNbOfElems();
5481     for(std::size_t i=0;i<nbOfElems;i++,ptr++)
5482       {
5483         if(*ptr>=0)
5484           {
5485             T tmp=1;
5486             for(T j=0;j<*ptr;j++)
5487               tmp*=val;
5488             *ptr=tmp;
5489           }
5490         else
5491           {
5492             std::ostringstream oss; oss << "DataArrayInt::applyRPow : presence of negative value in tuple #" << i/(this->getNumberOfComponents()) << " component #" << i%(this->getNumberOfComponents());
5493             oss << " !";
5494             throw INTERP_KERNEL::Exception(oss.str().c_str());
5495           }
5496       }
5497     this->declareAsNew();
5498   }
5499
5500   /*!
5501    * This method works only on data array with one component.
5502    * This method returns a newly allocated array storing stored ascendantly tuple ids in \b this so that
5503    * this[*id] in [\b vmin,\b vmax)
5504    *
5505    * \param [in] vmin begin of range. This value is included in range (included).
5506    * \param [in] vmax end of range. This value is \b not included in range (excluded).
5507    * \return a newly allocated data array that the caller should deal with.
5508    *
5509    * \sa DataArrayInt::findIdsNotInRange , DataArrayInt::findIdsStricltyNegative
5510    */
5511   template <class T>
5512   DataArrayIdType *DataArrayDiscrete<T>::findIdsInRange(T vmin, T vmax) const
5513   {
5514     InRange<T> ir(vmin,vmax);
5515     MCAuto<DataArrayIdType> ret(this->findIdsAdv(ir));
5516     return ret.retn();
5517   }
5518   
5519   /*!
5520    * This method works only on data array with one component.
5521    * This method returns a newly allocated array storing stored ascendantly tuple ids in \b this so that
5522    * this[*id] \b not in [\b vmin,\b vmax)
5523    *
5524    * \param [in] vmin begin of range. This value is \b not included in range (excluded).
5525    * \param [in] vmax end of range. This value is included in range (included).
5526    * \return a newly allocated data array that the caller should deal with.
5527    *
5528    * \sa DataArrayInt::findIdsInRange , DataArrayInt::findIdsStricltyNegative
5529    */
5530   template <class T>
5531   DataArrayIdType *DataArrayDiscrete<T>::findIdsNotInRange(T vmin, T vmax) const
5532   {
5533     NotInRange<T> nir(vmin,vmax);
5534     MCAuto<DataArrayIdType> ret(this->findIdsAdv(nir));
5535     return ret.retn();
5536   }
5537
5538   /*!
5539    * This method works only on data array with one component.
5540    * This method checks that all ids in \b this are in [ \b vmin, \b vmax ). If there is at least one element in \a this not in [ \b vmin, \b vmax ) an exception will be thrown.
5541    *
5542    * \param [in] vmin begin of range. This value is included in range (included).
5543    * \param [in] vmax end of range. This value is \b not included in range (excluded).
5544    * \return if all ids in \a this are so that (*this)[i]==i for all i in [ 0, \c this->getNumberOfTuples() ). */
5545   template <class T>
5546   bool DataArrayDiscrete<T>::checkAllIdsInRange(T vmin, T vmax) const
5547   {
5548     this->checkAllocated();
5549     if(this->getNumberOfComponents()!=1)
5550       throw INTERP_KERNEL::Exception("DataArrayInt::checkAllIdsInRange : this must have exactly one component !");
5551     mcIdType nbOfTuples(this->getNumberOfTuples());
5552     bool ret=true;
5553     const T *cptr=this->getConstPointer();
5554     for(mcIdType i=0;i<nbOfTuples;i++,cptr++)
5555       {
5556         if(*cptr>=vmin && *cptr<vmax)
5557           { ret=ret && *cptr==i; }
5558         else
5559           {
5560             std::ostringstream oss; oss << "DataArrayInt::checkAllIdsInRange : tuple #" << i << " has value " << *cptr << " should be in [" << vmin << "," << vmax << ") !";
5561             throw INTERP_KERNEL::Exception(oss.str().c_str());
5562           }
5563       }
5564     return ret;
5565   }
5566
5567   /*!
5568    * Returns a new DataArrayInt which contains a complement of elements of \a this
5569    * one-dimensional array. I.e. the result array contains all elements from the range [0,
5570    * \a nbOfElement) not present in \a this array.
5571    *  \param [in] nbOfElement - maximal size of the result array.
5572    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
5573    *         array using decrRef() as it is no more needed.
5574    *  \throw If \a this is not allocated.
5575    *  \throw If \a this->getNumberOfComponents() != 1.
5576    *  \throw If any element \a x of \a this array violates condition ( 0 <= \a x < \a
5577    *         nbOfElement ).
5578    */
5579   template <class T>
5580   DataArrayIdType *DataArrayDiscrete<T>::buildComplement(mcIdType nbOfElement) const
5581   {
5582     this->checkAllocated();
5583     if(this->getNumberOfComponents()!=1)
5584       throw INTERP_KERNEL::Exception("DataArrayInt::buildComplement : only single component allowed !");
5585     std::vector<bool> tmp(nbOfElement);
5586     const T *pt=this->getConstPointer();
5587     std::size_t nbOfElements=this->getNumberOfTuples();
5588     for(const T *w=pt;w!=pt+nbOfElements;w++)
5589       if(*w>=0 && *w<nbOfElement)
5590         tmp[*w]=true;
5591       else
5592         throw INTERP_KERNEL::Exception("DataArrayInt::buildComplement : an element is not in valid range : [0,nbOfElement) !");
5593     std::size_t nbOfRetVal=std::count(tmp.begin(),tmp.end(),false);
5594     DataArrayIdType *ret=DataArrayIdType::New();
5595     ret->alloc(nbOfRetVal,1);
5596     mcIdType j=0;
5597     mcIdType *retPtr=ret->getPointer();
5598     for(mcIdType i=0;i<nbOfElement;i++)
5599       if(!tmp[i])
5600         retPtr[j++]=i;
5601     return ret;
5602   }
5603
5604   /*!
5605    * Returns a new DataArrayInt containing elements of \a this one-dimensional missing
5606    * from an \a other one-dimensional array.
5607    *  \param [in] other - a DataArrayInt containing elements not to include in the result array.
5608    *  \return DataArrayInt * - a new instance of DataArrayInt with one component. The
5609    *         caller is to delete this array using decrRef() as it is no more needed.
5610    *  \throw If \a other is NULL.
5611    *  \throw If \a other is not allocated.
5612    *  \throw If \a other->getNumberOfComponents() != 1.
5613    *  \throw If \a this is not allocated.
5614    *  \throw If \a this->getNumberOfComponents() != 1.
5615    *  \sa DataArrayInt::buildSubstractionOptimized()
5616    */
5617   template <class T>
5618   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::buildSubstraction(const DataArrayType *other) const
5619   {
5620     if(!other)
5621       throw INTERP_KERNEL::Exception("DataArrayInt::buildSubstraction : DataArrayInt pointer in input is NULL !");
5622     this->checkAllocated();
5623     other->checkAllocated();
5624     if(this->getNumberOfComponents()!=1)
5625       throw INTERP_KERNEL::Exception("DataArrayInt::buildSubstraction : only single component allowed !");
5626     if(other->getNumberOfComponents()!=1)
5627       throw INTERP_KERNEL::Exception("DataArrayInt::buildSubstraction : only single component allowed for other type !");
5628     const T *pt=this->getConstPointer();
5629     std::size_t nbOfElements=this->getNumberOfTuples();
5630     std::set<T> s1(pt,pt+nbOfElements);
5631     pt=other->getConstPointer();
5632     nbOfElements=other->getNumberOfTuples();
5633     std::set<T> s2(pt,pt+nbOfElements);
5634     std::vector<T> r;
5635     std::set_difference(s1.begin(),s1.end(),s2.begin(),s2.end(),std::back_insert_iterator< std::vector<T> >(r));
5636     DataArrayType *ret=DataArrayType::New();
5637     ret->alloc(r.size(),1);
5638     std::copy(r.begin(),r.end(),ret->getPointer());
5639     return ret;
5640   }
5641
5642   /*!
5643    * \a this is expected to have one component and to be sorted ascendingly (as for \a other).
5644    * \a other is expected to be a part of \a this. If not DataArrayInt::buildSubstraction should be called instead.
5645    *
5646    * \param [in] other an array with one component and expected to be sorted ascendingly.
5647    * \ret list of ids in \a this but not in \a other.
5648    * \sa DataArrayInt::buildSubstraction
5649    */
5650   template <class T>
5651   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::buildSubstractionOptimized(const DataArrayType *other) const
5652   {
5653     static const char *MSG="DataArrayInt::buildSubstractionOptimized : only single component allowed !";
5654     if(!other) throw INTERP_KERNEL::Exception("DataArrayInt::buildSubstractionOptimized : NULL input array !");
5655     this->checkAllocated(); other->checkAllocated();
5656     if(this->getNumberOfComponents()!=1) throw INTERP_KERNEL::Exception(MSG);
5657     if(other->getNumberOfComponents()!=1) throw INTERP_KERNEL::Exception(MSG);
5658     const T *pt1Bg(this->begin()),*pt1End(this->end()),*pt2Bg(other->begin()),*pt2End(other->end());
5659     const T *work1(pt1Bg),*work2(pt2Bg);
5660     MCAuto<DataArrayType> ret(DataArrayType::New()); ret->alloc(0,1);
5661     for(;work1!=pt1End;work1++)
5662       {
5663         if(work2!=pt2End && *work1==*work2)
5664           work2++;
5665         else
5666           ret->pushBackSilent(*work1);
5667       }
5668     return ret.retn();
5669   }
5670
5671   /*!
5672    * Returns a new DataArrayInt which contains all elements of \a this and a given
5673    * one-dimensional arrays. The result array does not contain any duplicates
5674    * and its values are sorted in ascending order.
5675    *  \param [in] other - an array to unite with \a this one.
5676    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
5677    *         array using decrRef() as it is no more needed.
5678    *  \throw If \a this or \a other is not allocated.
5679    *  \throw If \a this->getNumberOfComponents() != 1.
5680    *  \throw If \a other->getNumberOfComponents() != 1.
5681    */
5682   template <class T>
5683   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::buildUnion(const DataArrayType *other) const
5684   {
5685     std::vector<const DataArrayType *>arrs(2);
5686     arrs[0]=dynamic_cast<const DataArrayType *>(this); arrs[1]=other;
5687     return DataArrayDiscrete<T>::BuildUnion(arrs);
5688   }
5689
5690   /*!
5691    * Returns a new DataArrayInt which contains elements present in both \a this and a given
5692    * one-dimensional arrays. The result array does not contain any duplicates
5693    * and its values are sorted in ascending order.
5694    *  \param [in] other - an array to intersect with \a this one.
5695    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
5696    *         array using decrRef() as it is no more needed.
5697    *  \throw If \a this or \a other is not allocated.
5698    *  \throw If \a this->getNumberOfComponents() != 1.
5699    *  \throw If \a other->getNumberOfComponents() != 1.
5700    */
5701   template <class T>
5702   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::buildIntersection(const DataArrayType *other) const
5703   {
5704     std::vector<const DataArrayType *>arrs(2);
5705     arrs[0]=dynamic_cast<const DataArrayType *>(this); arrs[1]=other;
5706     return DataArrayDiscrete<T>::BuildIntersection(arrs);
5707   }
5708   /*!
5709    * This method can be applied on allocated with one component DataArrayInt instance.
5710    * Locate groups of all consecutive same values in \a this and return them into an indexed array of positions pointing to \a this starting with 0.
5711    * Number of tuples of returned array is equal to size of \a this->buildUnique() + 1.
5712    * Last value of returned array is equal to \a this->getNumberOfTuples()
5713    * 
5714    * \b Example:
5715    * - \a this : [0, 1, 1, 2, 2, 3, 4, 4, 5, 5, 5, 11]
5716    * - \a return is : [0, 1, 3, 5, 6, 8, 11, 12]
5717    *
5718    * \return a newly allocated array containing the indexed array of
5719    * \throw if \a this is not allocated or if \a this has not exactly one component or if number of tuples is equal to 0.
5720    * \sa DataArrayInt::buildUnique, MEDCouplingSkyLineArray::groupPacks
5721    */
5722   template <class T>
5723   DataArrayIdType *DataArrayDiscrete<T>::indexOfSameConsecutiveValueGroups() const
5724   {
5725     this->checkAllocated();
5726     if(this->getNumberOfComponents()!=1)
5727       throw INTERP_KERNEL::Exception("DataArrayInt::indexOfSameConsecutiveValueGroups : only single component allowed !");
5728     if(this->getNumberOfTuples()==0)
5729       throw INTERP_KERNEL::Exception("DataArrayInt::indexOfSameConsecutiveValueGroups : number of tuples must be > 0 !");
5730     const T *pt(this->begin());
5731     const T *const ptEnd(this->end()) , * const ptBg(this->begin());
5732     const T *oldPt(pt);
5733     // first find nb of different values in this
5734     std::size_t nbOfTuplesOut(0);
5735     while( pt != ptEnd )
5736     {
5737       T val(*pt);
5738       const T *endOfPack(std::find_if(pt+1,ptEnd,[val](T elt){ return val!=elt; }));
5739       pt = endOfPack;
5740       ++nbOfTuplesOut;
5741     }
5742     MCAuto<DataArrayIdType> ret(DataArrayIdType::New()); ret->alloc(nbOfTuplesOut+1,1);
5743     mcIdType *retPtr(ret->getPointer()); *retPtr++ = 0;
5744     pt = this->begin();
5745     while( pt != ptEnd )
5746     {
5747       T val(*pt);
5748       const T *endOfPack(std::find_if(pt+1,ptEnd,[val](T elt){ return val!=elt; }));
5749       *retPtr++ = ToIdType( std::distance(ptBg,endOfPack) );
5750       pt = endOfPack;
5751       ++nbOfTuplesOut;
5752     }
5753     return ret.retn();
5754   }
5755
5756   /*!
5757    * This method can be applied on allocated with one component DataArrayInt instance.
5758    * This method is typically relevant for sorted arrays. All consecutive duplicated items in \a this will appear only once in returned DataArrayInt instance.
5759    * Example : if \a this contains [1,2,2,3,3,3,3,4,5,5,7,7,7,19] the returned array will contain [1,2,3,4,5,7,19]
5760    *
5761    * \return a newly allocated array that contain the result of the unique operation applied on \a this.
5762    * \throw if \a this is not allocated or if \a this has not exactly one component.
5763    * \sa DataArrayInt::buildUniqueNotSorted, DataArrayInt::indexOfSameConsecutiveValueGroups
5764    */
5765   template <class T>
5766   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::buildUnique() const
5767   {
5768     this->checkAllocated();
5769     if(this->getNumberOfComponents()!=1)
5770       throw INTERP_KERNEL::Exception("DataArrayInt::buildUnique : only single component allowed !");
5771     std::size_t nbOfElements(this->getNumberOfTuples());
5772     MCAuto<DataArrayType> tmp(DataArrayType::New());
5773     tmp->deepCopyFrom(*this);
5774     T *data(tmp->getPointer());
5775     T *last(std::unique(data,data+nbOfElements));
5776     MCAuto<DataArrayType> ret(DataArrayType::New());
5777     ret->alloc(std::distance(data,last),1);
5778     std::copy(data,last,ret->getPointer());
5779     return ret.retn();
5780   }
5781
5782   /*!
5783    * This method can be applied on allocated with one component DataArrayInt instance.
5784    * This method keep elements only once by keeping the same order in \a this that is not expected to be sorted.
5785    *
5786    * \return a newly allocated array that contain the result of the unique operation applied on \a this.
5787    *
5788    * \throw if \a this is not allocated or if \a this has not exactly one component.
5789    *
5790    * \sa DataArrayInt::buildUnique
5791    */
5792   template <class T>
5793   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::buildUniqueNotSorted() const
5794   {
5795     this->checkAllocated();
5796     if(this->getNumberOfComponents()!=1)
5797       throw INTERP_KERNEL::Exception("DataArrayInt::buildUniqueNotSorted : only single component allowed !");
5798     T minVal,maxVal;
5799     this->getMinMaxValues(minVal,maxVal);
5800     std::vector<bool> b(maxVal-minVal+1,false);
5801     const T *ptBg(this->begin()),*endBg(this->end());
5802     MCAuto<DataArrayType> ret(DataArrayType::New()); ret->alloc(0,1);
5803     for(const T *pt=ptBg;pt!=endBg;pt++)
5804       {
5805         if(!b[*pt-minVal])
5806           {
5807             ret->pushBackSilent(*pt);
5808             b[*pt-minVal]=true;
5809           }
5810       }
5811     ret->copyStringInfoFrom(*this);
5812     return ret.retn();
5813   }
5814
5815   /*!
5816    * Returns a new DataArrayInt which contains size of every of groups described by \a this
5817    * "index" array. Such "index" array is returned for example by
5818    * \ref MEDCoupling::MEDCouplingUMesh::buildDescendingConnectivity
5819    * "MEDCouplingUMesh::buildDescendingConnectivity" and
5820    * \ref MEDCoupling::MEDCouplingUMesh::getNodalConnectivityIndex
5821    * "MEDCouplingUMesh::getNodalConnectivityIndex" etc.
5822    * This method performs the reverse operation of DataArrayInt::computeOffsetsFull.
5823    *  \return DataArrayInt * - a new instance of DataArrayInt, whose number of tuples
5824    *          equals to \a this->getNumberOfComponents() - 1, and number of components is 1.
5825    *          The caller is to delete this array using decrRef() as it is no more needed.
5826    *  \throw If \a this is not allocated.
5827    *  \throw If \a this->getNumberOfComponents() != 1.
5828    *  \throw If \a this->getNumberOfTuples() < 2.
5829    *
5830    *  \b Example: <br>
5831    *         - this contains [1,3,6,7,7,9,15]
5832    *         - result array contains [2,3,1,0,2,6],
5833    *          where 2 = 3 - 1, 3 = 6 - 3, 1 = 7 - 6 etc.
5834    *
5835    * \sa DataArrayInt::computeOffsetsFull
5836    */
5837   template <class T>
5838   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::deltaShiftIndex() const
5839   {
5840     this->checkAllocated();
5841     if(this->getNumberOfComponents()!=1)
5842       throw INTERP_KERNEL::Exception("DataArrayInt::deltaShiftIndex : only single component allowed !");
5843     std::size_t nbOfElements=this->getNumberOfTuples();
5844     if(nbOfElements<2)
5845       throw INTERP_KERNEL::Exception("DataArrayInt::deltaShiftIndex : 1 tuple at least must be present in 'this' !");
5846     const T *ptr=this->getConstPointer();
5847     DataArrayType *ret=DataArrayType::New();
5848     ret->alloc(nbOfElements-1,1);
5849     T *out=ret->getPointer();
5850     std::transform(ptr+1,ptr+nbOfElements,ptr,out,std::minus<T>());
5851     return ret;
5852   }
5853
5854   /*!
5855    * Modifies \a this one-dimensional array so that value of each element \a x
5856    * of \a this array (\a a) is computed as \f$ x_i = \sum_{j=0}^{i-1} a[ j ] \f$.
5857    * Or: for each i>0 new[i]=new[i-1]+old[i-1] for i==0 new[i]=0. Number of tuples
5858    * and components remains the same.<br>
5859    * This method is useful for allToAllV in MPI with contiguous policy. This method
5860    * differs from computeOffsetsFull() in that the number of tuples is \b not changed by
5861    * this one.
5862    *  \throw If \a this is not allocated.
5863    *  \throw If \a this->getNumberOfComponents() != 1.
5864    *
5865    *  \b Example: <br>
5866    *          - Before \a this contains [3,5,1,2,0,8]
5867    *          - After \a this contains  [0,3,8,9,11,11]<br>
5868    *          Note that the last element 19 = 11 + 8 is missing because size of \a this
5869    *          array is retained and thus there is no space to store the last element.
5870    */
5871   template <class T>
5872   void DataArrayDiscrete<T>::computeOffsets()
5873   {
5874     this->checkAllocated();
5875     if(this->getNumberOfComponents()!=1)
5876       throw INTERP_KERNEL::Exception("DataArrayInt::computeOffsets : only single component allowed !");
5877     std::size_t nbOfElements=this->getNumberOfTuples();
5878     if(nbOfElements==0)
5879       return ;
5880     T *work=this->getPointer();
5881     T tmp=work[0];
5882     work[0]=0;
5883     for(std::size_t i=1;i<nbOfElements;i++)
5884       {
5885         T tmp2=work[i];
5886         work[i]=work[i-1]+tmp;
5887         tmp=tmp2;
5888       }
5889     this->declareAsNew();
5890   }
5891
5892   /*!
5893    * Modifies \a this one-dimensional array so that value of each element \a x
5894    * of \a this array (\a a) is computed as \f$ x_i = \sum_{j=0}^{i-1} a[ j ] \f$.
5895    * Or: for each i>0 new[i]=new[i-1]+old[i-1] for i==0 new[i]=0. Number
5896    * components remains the same and number of tuples is inceamented by one.<br>
5897    * This method is useful for allToAllV in MPI with contiguous policy. This method
5898    * differs from computeOffsets() in that the number of tuples is changed by this one.
5899    * This method performs the reverse operation of DataArrayInt::deltaShiftIndex.
5900    *  \throw If \a this is not allocated.
5901    *  \throw If \a this->getNumberOfComponents() != 1.
5902    *
5903    *  \b Example: <br>
5904    *          - Before \a this contains [3,5,1,2,0,8]
5905    *          - After \a this contains  [0,3,8,9,11,11,19]<br>
5906    * \sa DataArrayInt::deltaShiftIndex
5907    */
5908   template <class T>
5909   void DataArrayDiscrete<T>::computeOffsetsFull()
5910   {
5911     this->checkAllocated();
5912     if(this->getNumberOfComponents()!=1)
5913       throw INTERP_KERNEL::Exception("DataArrayInt::computeOffsetsFull : only single component allowed !");
5914     std::size_t nbOfElements=this->getNumberOfTuples();
5915     T *ret=(T *)malloc((nbOfElements+1)*sizeof(T));
5916     const T *work=this->getConstPointer();
5917     ret[0]=0;
5918     for(std::size_t i=0;i<nbOfElements;i++)
5919       ret[i+1]=work[i]+ret[i];
5920     this->useArray(ret,true,DeallocType::C_DEALLOC,nbOfElements+1,1);
5921     this->declareAsNew();
5922   }
5923
5924   /*!
5925    * Returns two new DataArrayInt instances whose contents is computed from that of \a this and \a listOfIds arrays as follows.
5926    * \a this is expected to be an offset format ( as returned by DataArrayInt::computeOffsetsFull ) that is to say with one component
5927    * and ** sorted strictly increasingly **. \a listOfIds is expected to be sorted ascendingly (not strictly needed for \a listOfIds).
5928    * This methods searches in \a this, considered as a set of contiguous \c this->getNumberOfComponents() ranges, all ids in \a listOfIds
5929    * filling completely one of the ranges in \a this.
5930    *
5931    * \param [in] listOfIds a list of ids that has to be sorted ascendingly.
5932    * \param [out] rangeIdsFetched the range ids fetched
5933    * \param [out] idsInInputListThatFetch contains the list of ids in \a listOfIds that are \b fully included in a range in \a this. So
5934    *              \a idsInInputListThatFetch is a part of input \a listOfIds.
5935    *
5936    * \sa DataArrayInt::computeOffsetsFull
5937    *
5938    *  \b Example: <br>
5939    *          - \a this : [0,3,7,9,15,18]
5940    *          - \a listOfIds contains  [0,1,2,3,7,8,15,16,17]
5941    *          - \a rangeIdsFetched result array: [0,2,4]
5942    *          - \a idsInInputListThatFetch result array: [0,1,2,7,8,15,16,17]
5943    * In this example id 3 in input \a listOfIds is alone so it do not appear in output \a idsInInputListThatFetch.
5944    * <br>
5945    */
5946   template <class T>
5947   void DataArrayDiscrete<T>::findIdsRangesInListOfIds(const DataArrayType *listOfIds, DataArrayIdType *& rangeIdsFetched, DataArrayType *& idsInInputListThatFetch) const
5948   {
5949     if(!listOfIds)
5950       throw INTERP_KERNEL::Exception("DataArrayInt::findIdsRangesInListOfIds : input list of ids is null !");
5951     listOfIds->checkAllocated(); this->checkAllocated();
5952     if(listOfIds->getNumberOfComponents()!=1)
5953       throw INTERP_KERNEL::Exception("DataArrayInt::findIdsRangesInListOfIds : input list of ids must have exactly one component !");
5954     if(this->getNumberOfComponents()!=1)
5955       throw INTERP_KERNEL::Exception("DataArrayInt::findIdsRangesInListOfIds : this must have exactly one component !");
5956     MCAuto<DataArrayIdType> ret0=DataArrayIdType::New(); ret0->alloc(0,1);
5957     MCAuto<DataArrayType> ret1=DataArrayType::New(); ret1->alloc(0,1);
5958     const T *tupPtr(listOfIds->begin()), *tupEnd(listOfIds->end());
5959     const T *offBg(this->begin()),*offEnd(this->end()-1);
5960     const T *offPtr(offBg);
5961     while(tupPtr!=tupEnd && offPtr!=offEnd)
5962       {
5963         if(*tupPtr==*offPtr)
5964           {
5965             T i=offPtr[0];
5966             while(i<offPtr[1] && *tupPtr==i && tupPtr!=tupEnd) { i++; tupPtr++; }
5967             if(i==offPtr[1])
5968               {
5969                 ret0->pushBackSilent(ToIdType(std::distance(offBg,offPtr)));
5970                 ret1->pushBackValsSilent(tupPtr-(offPtr[1]-offPtr[0]),tupPtr);
5971                 offPtr++;
5972               }
5973           }
5974         else
5975           { if(*tupPtr<*offPtr) tupPtr++; else offPtr++; }
5976       }
5977     rangeIdsFetched=ret0.retn();
5978     idsInInputListThatFetch=ret1.retn();
5979   }
5980
5981   /*!
5982    * Returns a new DataArrayInt whose contents is computed from that of \a this and \a
5983    * offsets arrays as follows. \a offsets is a one-dimensional array considered as an
5984    * "index" array of a "iota" array, thus, whose each element gives an index of a group
5985    * beginning within the "iota" array. And \a this is a one-dimensional array
5986    * considered as a selector of groups described by \a offsets to include into the result array.
5987    *  \throw If \a offsets is NULL.
5988    *  \throw If \a offsets is not allocated.
5989    *  \throw If \a offsets->getNumberOfComponents() != 1.
5990    *  \throw If \a offsets is not monotonically increasing.
5991    *  \throw If \a this is not allocated.
5992    *  \throw If \a this->getNumberOfComponents() != 1.
5993    *  \throw If any element of \a this is not a valid index for \a offsets array.
5994    *
5995    *  \b Example: <br>
5996    *          - \a this: [0,2,3]
5997    *          - \a offsets: [0,3,6,10,14,20]
5998    *          - result array: [0,1,2,6,7,8,9,10,11,12,13] == <br>
5999    *            \c range(0,3) + \c range(6,10) + \c range(10,14) ==<br>
6000    *            \c range( \a offsets[ \a this[0] ], offsets[ \a this[0]+1 ]) +
6001    *            \c range( \a offsets[ \a this[1] ], offsets[ \a this[1]+1 ]) +
6002    *            \c range( \a offsets[ \a this[2] ], offsets[ \a this[2]+1 ])
6003    */
6004   template <class T>
6005   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::buildExplicitArrByRanges(const DataArrayType *offsets) const
6006   {
6007     if(!offsets)
6008       throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrByRanges : DataArrayInt pointer in input is NULL !");
6009     this->checkAllocated();
6010     if(this->getNumberOfComponents()!=1)
6011       throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrByRanges : only single component allowed !");
6012     offsets->checkAllocated();
6013     if(offsets->getNumberOfComponents()!=1)
6014       throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrByRanges : input array should have only single component !");
6015     mcIdType othNbTuples=offsets->getNumberOfTuples()-1;
6016     mcIdType nbOfTuples=this->getNumberOfTuples();
6017     T retNbOftuples=0;
6018     const T *work=this->getConstPointer();
6019     const T *offPtr=offsets->getConstPointer();
6020     for(mcIdType i=0;i<nbOfTuples;i++)
6021       {
6022         T val=work[i];
6023         if(val>=0 && val<othNbTuples)
6024           {
6025             T delta=offPtr[val+1]-offPtr[val];
6026             if(delta>=0)
6027               retNbOftuples+=delta;
6028             else
6029               {
6030                 std::ostringstream oss; oss << "DataArrayInt::buildExplicitArrByRanges : Tuple #" << val << " of offset array has a delta < 0 !";
6031                 throw INTERP_KERNEL::Exception(oss.str().c_str());
6032               }
6033           }
6034         else
6035           {
6036             std::ostringstream oss; oss << "DataArrayInt::buildExplicitArrByRanges : Tuple #" << i << " in this contains " << val;
6037             oss << " whereas offsets array is of size " << othNbTuples+1 << " !";
6038             throw INTERP_KERNEL::Exception(oss.str().c_str());
6039           }
6040       }
6041     MCAuto<DataArrayType> ret=DataArrayType::New();
6042     ret->alloc(retNbOftuples,1);
6043     T *retPtr=ret->getPointer();
6044     for(mcIdType i=0;i<nbOfTuples;i++)
6045       {
6046         T val=work[i];
6047         T start=offPtr[val];
6048         T off=offPtr[val+1]-start;
6049         for(T j=0;j<off;j++,retPtr++)
6050           *retPtr=start+j;
6051       }
6052     return ret.retn();
6053   }
6054
6055   /*!
6056    * Returns a new DataArrayInt whose contents is computed using \a this that must be a
6057    * scaled array (monotonically increasing).
6058   from that of \a this and \a
6059    * offsets arrays as follows. \a offsets is a one-dimensional array considered as an
6060    * "index" array of a "iota" array, thus, whose each element gives an index of a group
6061    * beginning within the "iota" array. And \a this is a one-dimensional array
6062    * considered as a selector of groups described by \a offsets to include into the result array.
6063    *  \throw If \a  is NULL.
6064    *  \throw If \a this is not allocated.
6065    *  \throw If \a this->getNumberOfComponents() != 1.
6066    *  \throw If \a this->getNumberOfTuples() == 0.
6067    *  \throw If \a this is not monotonically increasing.
6068    *  \throw If any element of ids in ( \a bg \a stop \a step ) points outside the scale in \a this.
6069    *
6070    *  \b Example: <br>
6071    *          - \a bg , \a stop and \a step : (0,5,2)
6072    *          - \a this: [0,3,6,10,14,20]
6073    *          - result array: [0,0,0, 2,2,2,2, 4,4,4,4,4,4] == <br>
6074    */
6075   template <class T>
6076   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::buildExplicitArrOfSliceOnScaledArr(T bg, T stop, T step) const
6077   {
6078     if(!this->isAllocated())
6079       throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrOfSliceOnScaledArr : not allocated array !");
6080     if(this->getNumberOfComponents()!=1)
6081       throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrOfSliceOnScaledArr : number of components is expected to be equal to one !");
6082     mcIdType nbOfTuples(this->getNumberOfTuples());
6083     if(nbOfTuples==0)
6084       throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrOfSliceOnScaledArr : number of tuples must be != 0 !");
6085     const T *ids(this->begin());
6086     mcIdType nbOfEltsInSlc=DataArrayTools<T>::GetNumberOfItemGivenBESRelative(bg,stop,step,"DataArrayInt::buildExplicitArrOfSliceOnScaledArr");
6087     T sz(0),pos(bg);
6088     for(mcIdType i=0;i<nbOfEltsInSlc;i++,pos+=step)
6089       {
6090         if(pos>=0 && pos<nbOfTuples-1)
6091           {
6092             T delta(ids[pos+1]-ids[pos]);
6093             sz+=delta;
6094             if(delta<0)
6095               {
6096                 std::ostringstream oss; oss << "DataArrayInt::buildExplicitArrOfSliceOnScaledArr : At pos #" << i << " of input slice, value is " << pos << " and at this pos this is not monotonically increasing !";
6097                 throw INTERP_KERNEL::Exception(oss.str().c_str());
6098               }
6099           }
6100         else
6101           {
6102             std::ostringstream oss; oss << "DataArrayInt::buildExplicitArrOfSliceOnScaledArr : At pos #" << i << " of input slice, value is " << pos << " should be in [0," << nbOfTuples-1 << ") !";
6103             throw INTERP_KERNEL::Exception(oss.str().c_str());
6104           }
6105       }
6106     MCAuto<DataArrayType> ret(DataArrayType::New()); ret->alloc(sz,1);
6107     T *retPtr(ret->getPointer());
6108     pos=bg;
6109     for(mcIdType i=0;i<nbOfEltsInSlc;i++,pos+=step)
6110       {
6111         T delta(ids[pos+1]-ids[pos]);
6112         for(T j=0;j<delta;j++,retPtr++)
6113           *retPtr=pos;
6114       }
6115     return ret.retn();
6116   }
6117
6118   /*!
6119    * Given in input ranges \a ranges, it returns a newly allocated DataArrayInt instance having one component and the same number of tuples than \a this.
6120    * For each tuple at place **i** in \a this it tells which is the first range in \a ranges that contains value \c this->getIJ(i,0) and put the result
6121    * in tuple **i** of returned DataArrayInt.
6122    * If ranges overlapped (in theory it should not) this method do not detect it and always returns the first range.
6123    *
6124    * For example if \a this contains : [1,24,7,8,10,17] and \a ranges contains [(0,3),(3,8),(8,15),(15,22),(22,30)]
6125    * The return DataArrayInt will contain : **[0,4,1,2,2,3]**
6126    *
6127    * \param [in] ranges typically come from output of MEDCouplingUMesh::ComputeRangesFromTypeDistribution. Each range is specified like this : 1st component is
6128    *             for lower value included and 2nd component is the upper value of corresponding range **excluded**.
6129    * \throw If offsets is a null pointer or does not have 2 components or if \a this is not allocated or \a this do not have exactly one component. To finish an exception
6130    *        is thrown if no ranges in \a ranges contains value in \a this.
6131    *
6132    * \sa DataArrayInt::findIdInRangeForEachTuple
6133    */
6134   template <class T>
6135   DataArrayIdType *DataArrayDiscrete<T>::findRangeIdForEachTuple(const DataArrayType *ranges) const
6136   {
6137     if(!ranges)
6138       throw INTERP_KERNEL::Exception("DataArrayInt::findRangeIdForEachTuple : null input pointer !");
6139     if(ranges->getNumberOfComponents()!=2)
6140       throw INTERP_KERNEL::Exception("DataArrayInt::findRangeIdForEachTuple : input DataArrayInt instance should have 2 components !");
6141     this->checkAllocated();
6142     if(this->getNumberOfComponents()!=1)
6143       throw INTERP_KERNEL::Exception("DataArrayInt::findRangeIdForEachTuple : this should have only one component !");
6144     mcIdType nbTuples(this->getNumberOfTuples());
6145     MCAuto<DataArrayIdType> ret=DataArrayIdType::New(); ret->alloc(nbTuples,1);
6146     mcIdType nbOfRanges(ranges->getNumberOfTuples());
6147     const T *rangesPtr=ranges->getConstPointer();
6148     mcIdType *retPtr=ret->getPointer();
6149     const T *inPtr=this->getConstPointer();
6150     for(mcIdType i=0;i<nbTuples;i++,retPtr++)
6151       {
6152         T val=inPtr[i];
6153         bool found=false;
6154         for(mcIdType j=0;j<nbOfRanges && !found;j++)
6155           if(val>=rangesPtr[2*j] && val<rangesPtr[2*j+1])
6156             { *retPtr=j; found=true; }
6157         if(found)
6158           continue;
6159         else
6160           {
6161             std::ostringstream oss; oss << "DataArrayInt::findRangeIdForEachTuple : tuple #" << i << " not found by any ranges !";
6162             throw INTERP_KERNEL::Exception(oss.str().c_str());
6163           }
6164       }
6165     return ret.retn();
6166   }
6167
6168   /*!
6169    * Given in input ranges \a ranges, it returns a newly allocated DataArrayInt instance having one component and the same number of tuples than \a this.
6170    * For each tuple at place **i** in \a this it tells which is the sub position of the first range in \a ranges that contains value \c this->getIJ(i,0) and put the result
6171    * in tuple **i** of returned DataArrayInt.
6172    * If ranges overlapped (in theory it should not) this method do not detect it and always returns the sub position of the first range.
6173    *
6174    * For example if \a this contains : [1,24,7,8,10,17] and \a ranges contains [(0,3),(3,8),(8,15),(15,22),(22,30)]
6175    * The return DataArrayInt will contain : **[1,2,4,0,2,2]**
6176    * This method is often called in pair with DataArrayInt::findRangeIdForEachTuple method.
6177    *
6178    * \param [in] ranges typically come from output of MEDCouplingUMesh::ComputeRangesFromTypeDistribution. Each range is specified like this : 1st component is
6179    *             for lower value included and 2nd component is the upper value of corresponding range **excluded**.
6180    * \throw If offsets is a null pointer or does not have 2 components or if \a this is not allocated or \a this do not have exactly one component. To finish an exception
6181    *        is thrown if no ranges in \a ranges contains value in \a this.
6182    * \sa DataArrayInt::findRangeIdForEachTuple
6183    */
6184   template <class T>
6185   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::findIdInRangeForEachTuple(const DataArrayType *ranges) const
6186   {
6187     if(!ranges)
6188       throw INTERP_KERNEL::Exception("DataArrayInt::findIdInRangeForEachTuple : null input pointer !");
6189     if(ranges->getNumberOfComponents()!=2)
6190       throw INTERP_KERNEL::Exception("DataArrayInt::findIdInRangeForEachTuple : input DataArrayInt instance should have 2 components !");
6191     this->checkAllocated();
6192     if(this->getNumberOfComponents()!=1)
6193       throw INTERP_KERNEL::Exception("DataArrayInt::findIdInRangeForEachTuple : this should have only one component !");
6194     mcIdType nbTuples=this->getNumberOfTuples();
6195     MCAuto<DataArrayType> ret=DataArrayType::New(); ret->alloc(nbTuples,1);
6196     mcIdType nbOfRanges=ranges->getNumberOfTuples();
6197     const T *rangesPtr=ranges->getConstPointer();
6198     T *retPtr=ret->getPointer();
6199     const T *inPtr=this->getConstPointer();
6200     for(mcIdType i=0;i<nbTuples;i++,retPtr++)
6201       {
6202         T val=inPtr[i];
6203         bool found=false;
6204         for(mcIdType j=0;j<nbOfRanges && !found;j++)
6205           if(val>=rangesPtr[2*j] && val<rangesPtr[2*j+1])
6206             { *retPtr=val-rangesPtr[2*j]; found=true; }
6207         if(found)
6208           continue;
6209         else
6210           {
6211             std::ostringstream oss; oss << "DataArrayInt::findIdInRangeForEachTuple : tuple #" << i << " not found by any ranges !";
6212             throw INTERP_KERNEL::Exception(oss.str().c_str());
6213           }
6214       }
6215     return ret.retn();
6216   }
6217
6218   /*!
6219    * \b WARNING this method is a \b non \a const \b method. This method works tuple by tuple. Each tuple is expected to be pairs (number of components must be equal to 2).
6220    * This method rearrange each pair in \a this so that, tuple with id \b tid will be after the call \c this->getIJ(tid,0)==this->getIJ(tid-1,1) and \c this->getIJ(tid,1)==this->getIJ(tid+1,0).
6221    * If it is impossible to reach such condition an exception will be thrown ! \b WARNING In case of throw \a this can be partially modified !
6222    * If this method has correctly worked, \a this will be able to be considered as a linked list.
6223    * This method does nothing if number of tuples is lower of equal to 1.
6224    *
6225    * This method is useful for users having an unstructured mesh having only SEG2 to rearrange internally the connectivity without any coordinates consideration.
6226    *
6227    * \sa MEDCouplingUMesh::orderConsecutiveCells1D, DataArrayInt::fromLinkedListOfPairToList
6228    */
6229   template <class T>
6230   void DataArrayDiscrete<T>::sortEachPairToMakeALinkedList()
6231   {
6232     this->checkAllocated();
6233     if(this->getNumberOfComponents()!=2)
6234       throw INTERP_KERNEL::Exception("DataArrayInt::sortEachPairToMakeALinkedList : Only works on DataArrayInt instance with nb of components equal to 2 !");
6235     mcIdType nbOfTuples(this->getNumberOfTuples());
6236     if(nbOfTuples<=1)
6237       return ;
6238     T *conn(this->getPointer());
6239     for(mcIdType i=1;i<nbOfTuples;i++,conn+=2)
6240       {
6241         if(i>1)
6242           {
6243             if(conn[2]==conn[3])
6244               {
6245                 std::ostringstream oss; oss << "DataArrayInt::sortEachPairToMakeALinkedList : In the tuple #" << i << " presence of a pair filled with same ids !";
6246                 throw INTERP_KERNEL::Exception(oss.str().c_str());
6247               }
6248             if(conn[2]!=conn[1] && conn[3]==conn[1] && conn[2]!=conn[0])
6249               std::swap(conn[2],conn[3]);
6250             //not(conn[2]==conn[1] && conn[3]!=conn[1] && conn[3]!=conn[0])
6251             if(conn[2]!=conn[1] || conn[3]==conn[1] || conn[3]==conn[0])
6252               {
6253                 std::ostringstream oss; oss << "DataArrayInt::sortEachPairToMakeALinkedList : In the tuple #" << i << " something is invalid !";
6254                 throw INTERP_KERNEL::Exception(oss.str().c_str());
6255               }
6256           }
6257         else
6258           {
6259             if(conn[0]==conn[1] || conn[2]==conn[3])
6260               throw INTERP_KERNEL::Exception("DataArrayInt::sortEachPairToMakeALinkedList : In the 2 first tuples presence of a pair filled with same ids !");
6261             T tmp[4];
6262             std::set<T> s;
6263             s.insert(conn,conn+4);
6264             if(s.size()!=3)
6265               throw INTERP_KERNEL::Exception("DataArrayInt::sortEachPairToMakeALinkedList : This can't be considered as a linked list regarding 2 first tuples !");
6266             if(std::count(conn,conn+4,conn[0])==2)
6267               {
6268                 tmp[0]=conn[1];
6269                 tmp[1]=conn[0];
6270                 tmp[2]=conn[0];
6271                 if(conn[2]==conn[0])
6272                   { tmp[3]=conn[3]; }
6273                 else
6274                   { tmp[3]=conn[2];}
6275                 std::copy(tmp,tmp+4,conn);
6276               }
6277             else
6278               {//here we are sure to have (std::count(conn,conn+4,conn[1])==2)
6279                 if(conn[1]==conn[3])
6280                   std::swap(conn[2],conn[3]);
6281               }
6282           }
6283       }
6284   }
6285
6286   /*!
6287    * \a this is expected to be a correctly linked list of pairs.
6288    *
6289    * \sa DataArrayInt::sortEachPairToMakeALinkedList
6290    */
6291   template <class T>
6292   MCAuto<typename Traits<T>::ArrayType> DataArrayDiscrete<T>::fromLinkedListOfPairToList() const
6293   {
6294     this->checkAllocated();
6295     this->checkNbOfComps(2,"DataArrayInt::fromLinkedListOfPairToList : this is expected to have 2 components");
6296     mcIdType nbTuples(this->getNumberOfTuples());
6297     if(nbTuples<1)
6298       throw INTERP_KERNEL::Exception("DataArrayInt::fromLinkedListOfPairToList : no tuples in this ! Not a linked list !");
6299     MCAuto<DataArrayType> ret(DataArrayType::New()); ret->alloc(nbTuples+1,1);
6300     const T *thisPtr(this->begin());
6301     T *retPtr(ret->getPointer());
6302     retPtr[0]=thisPtr[0];
6303     for(mcIdType i=0;i<nbTuples;i++)
6304       {
6305         retPtr[i+1]=thisPtr[2*i+1];
6306         if(i<nbTuples-1)
6307           if(thisPtr[2*i+1]!=thisPtr[2*(i+1)+0])
6308             {
6309               std::ostringstream oss; oss << "DataArrayInt::fromLinkedListOfPairToList : this is not a proper linked list of pair. The link is broken between tuple #" << i << " and tuple #" << i+1 << " ! Call sortEachPairToMakeALinkedList ?";
6310               throw INTERP_KERNEL::Exception(oss.str());
6311             }
6312       }
6313     return ret;
6314   }
6315
6316   /*!
6317    * This method returns all different values found in \a this. This method throws if \a this has not been allocated.
6318    * But the number of components can be different from one.
6319    * \return a newly allocated array (that should be dealt by the caller) containing different values in \a this.
6320    */
6321   template <class T>
6322   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::getDifferentValues() const
6323   {
6324     this->checkAllocated();
6325     std::set<T> ret;
6326     ret.insert(this->begin(),this->end());
6327     MCAuto<DataArrayType> ret2=DataArrayType::New();
6328     ret2->alloc(ret.size(),1);
6329     std::copy(ret.begin(),ret.end(),ret2->getPointer());
6330     return ret2.retn();
6331   }
6332
6333   /*!
6334    * This method is a refinement of DataArrayInt::getDifferentValues because it returns not only different values in \a this but also, for each of
6335    * them it tells which tuple id have this id.
6336    * This method works only on arrays with one component (if it is not the case call DataArrayInt::rearrange(1) ).
6337    * This method returns two arrays having same size.
6338    * The instances of DataArrayInt in the returned vector have be specially allocated and computed by this method. Each of them should be dealt by the caller of this method.
6339    * Example : if this is equal to [1,0,1,2,0,2,2,-3,2] -> differentIds=[-3,0,1,2] and returned array will be equal to [[7],[1,4],[0,2],[3,5,6,8]]
6340    */
6341   template <class T>
6342   std::vector<DataArrayIdType *> DataArrayDiscrete<T>::partitionByDifferentValues(std::vector<T>& differentIds) const
6343   {
6344     this->checkAllocated();
6345     if(this->getNumberOfComponents()!=1)
6346       throw INTERP_KERNEL::Exception("DataArrayInt::partitionByDifferentValues : this should have only one component !");
6347     mcIdType id=0;
6348     std::map<T,mcIdType> m,m2,m3;
6349     for(const T *w=this->begin();w!=this->end();w++)
6350       m[*w]++;
6351     differentIds.resize(m.size());
6352     std::vector<DataArrayIdType *> ret(m.size());
6353     std::vector<mcIdType *> retPtr(m.size());
6354     for(typename std::map<T,mcIdType>::const_iterator it=m.begin();it!=m.end();it++,id++)
6355       {
6356         m2[(*it).first]=id;
6357         ret[id]=DataArrayIdType::New();
6358         ret[id]->alloc((*it).second,1);
6359         retPtr[id]=ret[id]->getPointer();
6360         differentIds[id]=(*it).first;
6361       }
6362     id=0;
6363     for(const T *w=this->begin();w!=this->end();w++,id++)
6364       {
6365         retPtr[m2[*w]][m3[*w]++]=id;
6366       }
6367     return ret;
6368   }
6369
6370   /*!
6371    * This method split ids in [0, \c this->getNumberOfTuples() ) using \a this array as a field of weight (>=0 each).
6372    * The aim of this method is to return a set of \a nbOfSlices chunk of contiguous ids as balanced as possible.
6373    *
6374    * \param [in] nbOfSlices - number of slices expected.
6375    * \return - a vector having a size equal to \a nbOfSlices giving the start (included) and the stop (excluded) of each chunks.
6376    *
6377    * \sa DataArray::GetSlice
6378    * \throw If \a this is not allocated or not with exactly one component.
6379    * \throw If an element in \a this if < 0.
6380    */
6381   template <class T>
6382   std::vector< std::pair<mcIdType,mcIdType> > DataArrayDiscrete<T>::splitInBalancedSlices(mcIdType nbOfSlices) const
6383   {
6384     if(!this->isAllocated() || this->getNumberOfComponents()!=1)
6385       throw INTERP_KERNEL::Exception("DataArrayInt::splitInBalancedSlices : this array should have number of components equal to one and must be allocated !");
6386     if(nbOfSlices<=0)
6387       throw INTERP_KERNEL::Exception("DataArrayInt::splitInBalancedSlices : number of slices must be >= 1 !");
6388     T sum(this->accumulate((std::size_t)0));
6389     mcIdType nbOfTuples(this->getNumberOfTuples());
6390     T sumPerSlc(sum/FromIdType<T>(nbOfSlices));
6391     mcIdType pos(0);
6392     const T *w(this->begin());
6393     std::vector< std::pair<mcIdType,mcIdType> > ret(nbOfSlices);
6394     for(mcIdType i=0;i<nbOfSlices;i++)
6395       {
6396         std::pair<mcIdType, mcIdType> p(pos,-1);
6397         T locSum(0);
6398         while(locSum<sumPerSlc && pos<nbOfTuples) { pos++; locSum+=*w++; }
6399         if(i!=nbOfSlices-1)
6400           p.second=pos;
6401         else
6402           p.second=nbOfTuples;
6403         ret[i]=p;
6404       }
6405     return ret;
6406   }
6407
6408   /*!
6409    * Modify \a this array so that each value becomes a modulus of division of this value by
6410    * a value of another DataArrayInt. There are 3 valid cases.
6411    * 1.  The arrays have same number of tuples and components. Then each value of
6412    *    \a this array is divided by the corresponding value of \a other one, i.e.:
6413    *   _a_ [ i, j ] %= _other_ [ i, j ].
6414    * 2.  The arrays have same number of tuples and \a other array has one component. Then
6415    *   _a_ [ i, j ] %= _other_ [ i, 0 ].
6416    * 3.  The arrays have same number of components and \a other array has one tuple. Then
6417    *   _a_ [ i, j ] %= _a2_ [ 0, j ].
6418    *
6419    *  \warning No check of division by zero is performed!
6420    *  \param [in] other - a divisor array.
6421    *  \throw If \a other is NULL.
6422    *  \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples() and
6423    *         \a this->getNumberOfComponents() != \a other->getNumberOfComponents() and
6424    *         \a other has number of both tuples and components not equal to 1.
6425    */
6426   template <class T>
6427   void DataArrayDiscrete<T>::modulusEqual(const DataArrayType *other)
6428   {
6429     if(!other)
6430       throw INTERP_KERNEL::Exception("DataArrayInt::modulusEqual : input DataArrayInt instance is NULL !");
6431     const char *msg="Nb of tuples mismatch for DataArrayInt::modulusEqual !";
6432     this->checkAllocated(); other->checkAllocated();
6433     mcIdType nbOfTuple(this->getNumberOfTuples());
6434     mcIdType nbOfTuple2(other->getNumberOfTuples());
6435     std::size_t nbOfComp(this->getNumberOfComponents());
6436     std::size_t nbOfComp2(other->getNumberOfComponents());
6437     if(nbOfTuple==nbOfTuple2)
6438       {
6439         if(nbOfComp==nbOfComp2)
6440           {
6441             std::transform(this->begin(),this->end(),other->begin(),this->getPointer(),std::modulus<T>());
6442           }
6443         else if(nbOfComp2==1)
6444           {
6445             if(nbOfComp2==nbOfComp)
6446               {
6447                 T *ptr=this->getPointer();
6448                 const T *ptrc=other->getConstPointer();
6449                 for(mcIdType i=0;i<nbOfTuple;i++)
6450                   std::transform(ptr+i*nbOfComp,ptr+(i+1)*nbOfComp,ptr+i*nbOfComp,std::bind2nd(std::modulus<T>(),*ptrc++));
6451               }
6452             else
6453               throw INTERP_KERNEL::Exception(msg);
6454           }
6455         else
6456           throw INTERP_KERNEL::Exception(msg);
6457       }
6458     else if(nbOfTuple2==1)
6459       {
6460         T *ptr=this->getPointer();
6461         const T *ptrc=other->getConstPointer();
6462         for(mcIdType i=0;i<nbOfTuple;i++)
6463           std::transform(ptr+i*nbOfComp,ptr+(i+1)*nbOfComp,ptrc,ptr+i*nbOfComp,std::modulus<T>());
6464       }
6465     else
6466       throw INTERP_KERNEL::Exception(msg);
6467     this->declareAsNew();
6468   }
6469
6470   /*!
6471    * Apply pow on values of another DataArrayInt to values of \a this one.
6472    *
6473    *  \param [in] other - an array to pow to \a this one.
6474    *  \throw If \a other is NULL.
6475    *  \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples()
6476    *  \throw If \a this->getNumberOfComponents() != 1 or \a other->getNumberOfComponents() != 1
6477    *  \throw If there is a negative value in \a other.
6478    */
6479   template <class T>
6480   void DataArrayDiscrete<T>::powEqual(const DataArrayType *other)
6481   {
6482     if(!other)
6483       throw INTERP_KERNEL::Exception("DataArrayInt::powEqual : input instance is null !");
6484     mcIdType nbOfTuple=this->getNumberOfTuples();
6485     mcIdType nbOfTuple2=other->getNumberOfTuples();
6486     std::size_t nbOfComp=this->getNumberOfComponents();
6487     std::size_t nbOfComp2=other->getNumberOfComponents();
6488     if(nbOfTuple!=nbOfTuple2)
6489       throw INTERP_KERNEL::Exception("DataArrayInt::powEqual : number of tuples mismatches !");
6490     if(nbOfComp!=1 || nbOfComp2!=1)
6491       throw INTERP_KERNEL::Exception("DataArrayInt::powEqual : number of components of both arrays must be equal to 1 !");
6492     T *ptr=this->getPointer();
6493     const T *ptrc=other->begin();
6494     for(mcIdType i=0;i<nbOfTuple;i++,ptrc++,ptr++)
6495       {
6496         if(*ptrc>=0)
6497           {
6498             T tmp=1;
6499             for(T j=0;j<*ptrc;j++)
6500               tmp*=*ptr;
6501             *ptr=tmp;
6502           }
6503         else
6504           {
6505             std::ostringstream oss; oss << "DataArrayInt::powEqual : on tuple #" << i << " of other value is < 0 (" << *ptrc << ") !";
6506             throw INTERP_KERNEL::Exception(oss.str().c_str());
6507           }
6508       }
6509     this->declareAsNew();
6510   }
6511
6512   ////////////////////////////////////
6513   /*!
6514    * Useless method for end user. Only for MPI/Corba/File serialsation for multi arrays class.
6515    * Server side.
6516    */
6517   template <class T>
6518   void DataArrayDiscrete<T>::getTinySerializationIntInformation(std::vector<mcIdType>& tinyInfo) const
6519   {
6520     tinyInfo.resize(2);
6521     if(this->isAllocated())
6522       {
6523         tinyInfo[0]=this->getNumberOfTuples();
6524         tinyInfo[1]=ToIdType(this->getNumberOfComponents());
6525       }
6526     else
6527       {
6528         tinyInfo[0]=-1;
6529         tinyInfo[1]=-1;
6530       }
6531   }
6532
6533   /*!
6534    * Useless method for end user. Only for MPI/Corba/File serialsation for multi arrays class.
6535    * Server side.
6536    */
6537   template <class T>
6538   void DataArrayDiscrete<T>::getTinySerializationStrInformation(std::vector<std::string>& tinyInfo) const
6539   {
6540     if(this->isAllocated())
6541       {
6542         std::size_t nbOfCompo(this->getNumberOfComponents());
6543         tinyInfo.resize(nbOfCompo+1);
6544         tinyInfo[0]=this->getName();
6545         for(std::size_t i=0;i<nbOfCompo;i++)
6546           tinyInfo[i+1]=this->getInfoOnComponent(i);
6547       }
6548     else
6549       {
6550         tinyInfo.resize(1);
6551         tinyInfo[0]=this->getName();
6552       }
6553   }
6554
6555   /*!
6556    * Useless method for end user. Only for MPI/Corba/File serialsation for multi arrays class.
6557    * This method returns if a feeding is needed.
6558    */
6559   template <class T>
6560   bool DataArrayDiscrete<T>::resizeForUnserialization(const std::vector<mcIdType>& tinyInfoI)
6561   {
6562     mcIdType nbOfTuple=tinyInfoI[0];
6563     mcIdType nbOfComp=tinyInfoI[1];
6564     if(nbOfTuple!=-1 || nbOfComp!=-1)
6565       {
6566         this->alloc(nbOfTuple,nbOfComp);
6567         return true;
6568       }
6569     return false;
6570   }
6571
6572   /*!
6573    * Useless method for end user. Only for MPI/Corba/File serialsation for multi arrays class.
6574    * This method returns if a feeding is needed.
6575    */
6576   template <class T>
6577   void DataArrayDiscrete<T>::finishUnserialization(const std::vector<mcIdType>& tinyInfoI, const std::vector<std::string>& tinyInfoS)
6578   {
6579     this->setName(tinyInfoS[0]);
6580     if(this->isAllocated())
6581       {
6582         mcIdType nbOfCompo=tinyInfoI[1];
6583         for(mcIdType i=0;i<nbOfCompo;i++)
6584           this->setInfoOnComponent(i,tinyInfoS[i+1]);
6585       }
6586   }
6587
6588   ////////////////////////////////////
6589
6590   /*!
6591    * Returns a new DataArrayInt that is the result of pow of two given arrays. There are 3
6592    * valid cases.
6593    *
6594    *  \param [in] a1 - an array to pow up.
6595    *  \param [in] a2 - another array to sum up.
6596    *  \return DataArrayInt * - the new instance of DataArrayInt.
6597    *          The caller is to delete this result array using decrRef() as it is no more
6598    *          needed.
6599    *  \throw If either \a a1 or \a a2 is NULL.
6600    *  \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples()
6601    *  \throw If \a a1->getNumberOfComponents() != 1 or \a a2->getNumberOfComponents() != 1.
6602    *  \throw If there is a negative value in \a a2.
6603    */
6604   template <class T>
6605   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::Pow(const DataArrayType *a1, const DataArrayType *a2)
6606   {
6607     if(!a1 || !a2)
6608       throw INTERP_KERNEL::Exception("DataArrayInt::Pow : at least one of input instances is null !");
6609     mcIdType nbOfTuple=a1->getNumberOfTuples();
6610     mcIdType nbOfTuple2=a2->getNumberOfTuples();
6611     std::size_t nbOfComp=a1->getNumberOfComponents();
6612     std::size_t nbOfComp2=a2->getNumberOfComponents();
6613     if(nbOfTuple!=nbOfTuple2)
6614       throw INTERP_KERNEL::Exception("DataArrayInt::Pow : number of tuples mismatches !");
6615     if(nbOfComp!=1 || nbOfComp2!=1)
6616       throw INTERP_KERNEL::Exception("DataArrayInt::Pow : number of components of both arrays must be equal to 1 !");
6617     MCAuto<DataArrayType> ret=DataArrayType::New(); ret->alloc(nbOfTuple,1);
6618     const T *ptr1(a1->begin()),*ptr2(a2->begin());
6619     T *ptr=ret->getPointer();
6620     for(mcIdType i=0;i<nbOfTuple;i++,ptr1++,ptr2++,ptr++)
6621       {
6622         if(*ptr2>=0)
6623           {
6624             T tmp=1;
6625             for(T j=0;j<*ptr2;j++)
6626               tmp*=*ptr1;
6627             *ptr=tmp;
6628           }
6629         else
6630           {
6631             std::ostringstream oss; oss << "DataArrayInt::Pow : on tuple #" << i << " of a2 value is < 0 (" << *ptr2 << ") !";
6632             throw INTERP_KERNEL::Exception(oss.str().c_str());
6633           }
6634       }
6635     return ret.retn();
6636   }
6637
6638   /*!
6639    * Returns a new DataArrayInt that is a modulus of two given arrays. There are 3
6640    * valid cases.
6641    * 1.  The arrays have same number of tuples and components. Then each value of
6642    *   the result array (_a_) is a division of the corresponding values of \a a1 and
6643    *   \a a2, i.e.: _a_ [ i, j ] = _a1_ [ i, j ] % _a2_ [ i, j ].
6644    * 2.  The arrays have same number of tuples and one array, say _a2_, has one
6645    *   component. Then
6646    *   _a_ [ i, j ] = _a1_ [ i, j ] % _a2_ [ i, 0 ].
6647    * 3.  The arrays have same number of components and one array, say _a2_, has one
6648    *   tuple. Then
6649    *   _a_ [ i, j ] = _a1_ [ i, j ] % _a2_ [ 0, j ].
6650    *
6651    * Info on components is copied either from the first array (in the first case) or from
6652    * the array with maximal number of elements (getNbOfElems()).
6653    *  \warning No check of division by zero is performed!
6654    *  \param [in] a1 - a dividend array.
6655    *  \param [in] a2 - a divisor array.
6656    *  \return DataArrayInt * - the new instance of DataArrayInt.
6657    *          The caller is to delete this result array using decrRef() as it is no more
6658    *          needed.
6659    *  \throw If either \a a1 or \a a2 is NULL.
6660    *  \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples() and
6661    *         \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents() and
6662    *         none of them has number of tuples or components equal to 1.
6663    */
6664   template <class T>
6665   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::Modulus(const DataArrayType *a1, const DataArrayType *a2)
6666   {
6667     if(!a1 || !a2)
6668       throw INTERP_KERNEL::Exception("DataArrayInt::Modulus : input DataArrayInt instance is NULL !");
6669     mcIdType nbOfTuple1(a1->getNumberOfTuples());
6670     mcIdType nbOfTuple2(a2->getNumberOfTuples());
6671     std::size_t nbOfComp1(a1->getNumberOfComponents());
6672     std::size_t nbOfComp2(a2->getNumberOfComponents());
6673     if(nbOfTuple2==nbOfTuple1)
6674       {
6675         if(nbOfComp1==nbOfComp2)
6676           {
6677             MCAuto<DataArrayType> ret=DataArrayType::New();
6678             ret->alloc(nbOfTuple2,nbOfComp1);
6679             std::transform(a1->begin(),a1->end(),a2->begin(),ret->getPointer(),std::modulus<T>());
6680             ret->copyStringInfoFrom(*a1);
6681             return ret.retn();
6682           }
6683         else if(nbOfComp2==1)
6684           {
6685             MCAuto<DataArrayType> ret=DataArrayType::New();
6686             ret->alloc(nbOfTuple1,nbOfComp1);
6687             const T *a2Ptr=a2->getConstPointer();
6688             const T *a1Ptr=a1->getConstPointer();
6689             T *res=ret->getPointer();
6690             for(mcIdType i=0;i<nbOfTuple1;i++)
6691               res=std::transform(a1Ptr+i*nbOfComp1,a1Ptr+(i+1)*nbOfComp1,res,std::bind2nd(std::modulus<T>(),a2Ptr[i]));
6692             ret->copyStringInfoFrom(*a1);
6693             return ret.retn();
6694           }
6695         else
6696           {
6697             a1->checkNbOfComps(nbOfComp2,"Nb of components mismatch for array Modulus !");
6698             return 0;
6699           }
6700       }
6701     else if(nbOfTuple2==1)
6702       {
6703         a1->checkNbOfComps(nbOfComp2,"Nb of components mismatch for array Modulus !");
6704         MCAuto<DataArrayType> ret=DataArrayType::New();
6705         ret->alloc(nbOfTuple1,nbOfComp1);
6706         const T *a1ptr=a1->getConstPointer(),*a2ptr=a2->getConstPointer();
6707         T *pt=ret->getPointer();
6708         for(mcIdType i=0;i<nbOfTuple1;i++)
6709           pt=std::transform(a1ptr+i*nbOfComp1,a1ptr+(i+1)*nbOfComp1,a2ptr,pt,std::modulus<T>());
6710         ret->copyStringInfoFrom(*a1);
6711         return ret.retn();
6712       }
6713     else
6714       {
6715         a1->checkNbOfTuples(nbOfTuple2,"Nb of tuples mismatch for array Modulus !");//will always throw an exception
6716         return 0;
6717       }
6718   }
6719
6720   /*!
6721    * This method tries to find the permutation to apply to the first input \a ids1 to obtain the same array (without considering strings information) the second
6722    * input array \a ids2.
6723    * \a ids1 and \a ids2 are expected to be both a list of ids (both with number of components equal to one) not sorted and with values that can be negative.
6724    * This method will throw an exception is no such permutation array can be obtained. It is typically the case if there is some ids in \a ids1 not in \a ids2 or
6725    * inversely.
6726    * In case of success both assertion will be true (no throw) :
6727    * \c ids1->renumber(ret)->isEqual(ids2) where \a ret is the return of this method.
6728    * \c ret->transformWithIndArr(ids2)->isEqual(ids1)
6729    *
6730    * \b Example:
6731    * - \a ids1 : [3,1,103,4,6,10,-7,205]
6732    * - \a ids2 : [-7,1,205,10,6,3,103,4]
6733    * - \a return is : [5,1,6,7,4,3,0,2] because ids2[5]==ids1[0], ids2[1]==ids1[1], ids2[6]==ids1[2]...
6734    *
6735    * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
6736    *          array using decrRef() as it is no more needed.
6737    * \throw If either ids1 or ids2 is null not allocated or not with one components.
6738    *
6739    * \sa DataArrayInt::findIdForEach, DataArrayInt::FindPermutationFromFirstToSecondDuplicate, DataArrayInt::rankOfElementInThis
6740    */
6741   template<class T>
6742   DataArrayIdType *DataArrayDiscrete<T>::FindPermutationFromFirstToSecond(const DataArrayType *ids1, const DataArrayType *ids2)
6743   {
6744     if(!ids1 || !ids2)
6745       throw INTERP_KERNEL::Exception("DataArrayInt::FindPermutationFromFirstToSecond : the two input arrays must be not null !");
6746     if(!ids1->isAllocated() || !ids2->isAllocated())
6747       throw INTERP_KERNEL::Exception("DataArrayInt::FindPermutationFromFirstToSecond : the two input arrays must be allocated !");
6748     if(ids1->getNumberOfComponents()!=1 || ids2->getNumberOfComponents()!=1)
6749       throw INTERP_KERNEL::Exception("DataArrayInt::FindPermutationFromFirstToSecond : the two input arrays have exactly one component !");
6750     if(ids1->getNumberOfTuples()!=ids2->getNumberOfTuples())
6751       {
6752         std::ostringstream oss; oss << "DataArrayInt::FindPermutationFromFirstToSecond : first array has " << ids1->getNumberOfTuples() << " tuples and the second one " << ids2->getNumberOfTuples() << " tuples ! No chance to find a permutation between the 2 arrays !";
6753         throw INTERP_KERNEL::Exception(oss.str().c_str());
6754       }
6755     MCAuto<DataArrayType> c1(ids1->deepCopy());
6756     MCAuto<DataArrayType> c2(ids2->deepCopy());
6757     c1->sort(true); c2->sort(true);
6758     if(!c1->isEqualWithoutConsideringStr(*c2))
6759       throw INTERP_KERNEL::Exception("DataArrayInt::FindPermutationFromFirstToSecond : the two arrays are not lying on same ids ! Impossible to find a permutation between the 2 arrays !");
6760     MCAuto<DataArrayIdType> p1=ids1->checkAndPreparePermutation();
6761     MCAuto<DataArrayIdType> p2=ids2->checkAndPreparePermutation();
6762     p2=p2->invertArrayO2N2N2O(p2->getNumberOfTuples());
6763     p2=p2->selectByTupleIdSafe(p1->begin(),p1->end());
6764     return p2.retn();
6765   }
6766
6767   /*!
6768    * This method tries to find the permutation to apply to the first input \a ids1 to obtain the same array (without considering strings information) the second
6769    * input array \a ids2.
6770    * \a ids1 and \a ids2 are expected to be both a list of ids (both with number of components equal to one) not sorted and with values that can be negative.
6771    * This method will throw an exception is no such permutation array can be obtained. It is typically the case if there is some ids in \a ids1 not in \a ids2 or
6772    * inversely.
6773    * The difference with DataArrayInt::FindPermutationFromFirstToSecond is that this method supports multiple same values in \a ids1 and \a ids2 whereas 
6774    * DataArrayInt::FindPermutationFromFirstToSecond doesn't. It implies that this method my be slower than the DataArrayInt::FindPermutationFromFirstToSecond one.
6775    * 
6776    * In case of success both assertion will be true (no throw) :
6777    * \c ids1->renumber(ret)->isEqual(ids2) where \a ret is the return of this method.
6778    * \c ret->transformWithIndArr(ids2)->isEqual(ids1)
6779    *
6780    * \b Example:
6781    * - \a ids1 : [5, 3, 2, 1, 4, 5, 2, 1, 0, 11, 5, 4]
6782    * - \a ids2 : [0, 1, 1, 2, 2, 3, 4, 4, 5, 5, 5, 11]
6783    * - \a return is : [8, 5, 3, 1, 6, 9, 4, 2, 0, 11, 10, 7] because ids2[8]==ids1[0], ids2[5]==ids1[1], ids2[3]==ids1[2], ids2[1]==ids1[3]...
6784    *
6785    * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
6786    *          array using decrRef() as it is no more needed.
6787    * \throw If either ids1 or ids2 is null not allocated or not with one components.
6788    *
6789    * \sa DataArrayInt::findIdForEach, DataArrayInt::FindPermutationFromFirstToSecond, DataArrayInt::occurenceRankInThis
6790    */
6791   template<class T>
6792   DataArrayIdType *DataArrayDiscrete<T>::FindPermutationFromFirstToSecondDuplicate(const DataArrayType *ids1, const DataArrayType *ids2)
6793   {
6794     if(!ids1 || !ids2)
6795       throw INTERP_KERNEL::Exception("DataArrayInt::FindPermutationFromFirstToSecondDuplicate : the two input arrays must be not null !");
6796     constexpr char MSG0[] = "DataArrayInt::FindPermutationFromFirstToSecondDuplicate :";
6797     ids1->checkAllocated(); ids2->checkAllocated();
6798     ids1->checkNbOfComps(1,MSG0); ids2->checkNbOfComps(1,MSG0);
6799     mcIdType nbTuples(ids1->getNumberOfTuples());
6800     if(nbTuples != ids2->getNumberOfTuples())
6801       {
6802         std::ostringstream oss; oss << "DataArrayInt::FindPermutationFromFirstToSecondDuplicate : first array has " << ids1->getNumberOfTuples() << " tuples and the second one " << ids2->getNumberOfTuples() << " tuples ! No chance to find a permutation between the 2 arrays !";
6803         throw INTERP_KERNEL::Exception(oss.str().c_str());
6804       }
6805     MCAuto<DataArrayIdType> ret(DataArrayIdType::New()); ret->alloc(nbTuples,1);
6806     MCAuto<DataArrayIdType> oids2(ids2->occurenceRankInThis());
6807     std::map< std::pair<T,mcIdType>, mcIdType> m;
6808     mcIdType pos(0);
6809     const mcIdType *oids2Ptr(oids2->begin());
6810     for(const T * it2 = ids2->begin() ; it2 != ids2->end() ; ++it2, ++oids2Ptr, ++pos)
6811       m[{*it2,*oids2Ptr}] = pos;
6812     mcIdType *retPtr(ret->getPointer());
6813     //
6814     std::map<T,mcIdType> mOccurence1; // see DataArrayInt::occurenceRankInThis : avoid to compute additionnal temporary array
6815     //
6816     for(const T * it1 = ids1->begin() ; it1 != ids1->end() ; ++it1, ++retPtr)
6817     {
6818       auto it = mOccurence1.find(*it1);
6819       mcIdType occRk1;
6820       if( it == mOccurence1.end() )
6821       {
6822         occRk1 = 0;
6823         mOccurence1[*it1] = 1;
6824       }
6825       else
6826       {
6827         occRk1 = (*it).second++;
6828       }
6829       //
6830       auto it2 = m.find({*it1,occRk1});
6831       if(it2 != m.end())
6832       {
6833         *retPtr = (*it2).second;
6834       }
6835       else
6836       {
6837         std::ostringstream oss; oss << MSG0 << "At pos " << std::distance(ids1->begin(),it1) << " value is " << *it1 << " and occurence rank is " << occRk1 << ". No such item into second array !"; 
6838         throw INTERP_KERNEL::Exception(oss.str());
6839       }
6840       
6841     }
6842     return ret.retn();
6843   }
6844
6845   /*!
6846    * Returns a C array which is a renumbering map in "Old to New" mode for the input array.
6847    * This map, if applied to \a start array, would make it sorted. For example, if
6848    * \a start array contents are [9,10,0,6,4,11,3,7] then the contents of the result array is
6849    * [5,6,0,3,2,7,1,4].
6850    *  \param [in] start - pointer to the first element of the array for which the
6851    *         permutation map is computed.
6852    *  \param [in] end - pointer specifying the end of the array \a start, so that
6853    *         the last value of \a start is \a end[ -1 ].
6854    *  \return mcIdType * - the result permutation array that the caller is to delete as it is no
6855    *         more needed.
6856    *  \throw If there are equal values in the input array.
6857    */
6858   template<class T>
6859   mcIdType *DataArrayDiscrete<T>::CheckAndPreparePermutation(const T *start, const T *end)
6860   {
6861     std::size_t sz=std::distance(start,end);
6862     mcIdType *ret=(mcIdType *)malloc(sz*sizeof(mcIdType));
6863     T *work=new T[sz];
6864     std::copy(start,end,work);
6865     std::sort(work,work+sz);
6866     if(std::unique(work,work+sz)!=work+sz)
6867       {
6868         delete [] work;
6869         free(ret);
6870         throw INTERP_KERNEL::Exception("Some elements are equals in the specified array !");
6871       }
6872     std::map<T,mcIdType> m;
6873     for(T *workPt=work;workPt!=work+sz;workPt++)
6874       m[*workPt]=ToIdType(std::distance(work,workPt));
6875     mcIdType *iter2=ret;
6876     for(const T *iter=start;iter!=end;iter++,iter2++)
6877       *iter2=m[*iter];
6878     delete [] work;
6879     return ret;
6880   }
6881
6882   /*!
6883    * Returns a new DataArrayInt by concatenating two given arrays, so that (1) the number
6884    * of tuples in the result array is <em> a1->getNumberOfTuples() + a2->getNumberOfTuples() -
6885    * offsetA2</em> and (2)
6886    * the number of component in the result array is same as that of each of given arrays.
6887    * First \a offsetA2 tuples of \a a2 are skipped and thus are missing from the result array.
6888    * Info on components is copied from the first of the given arrays. Number of components
6889    * in the given arrays must be the same.
6890    *  \param [in] a1 - an array to include in the result array.
6891    *  \param [in] a2 - another array to include in the result array.
6892    *  \param [in] offsetA2 - number of tuples of \a a2 to skip.
6893    *  \return DataArrayInt * - the new instance of DataArrayInt.
6894    *          The caller is to delete this result array using decrRef() as it is no more
6895    *          needed.
6896    *  \throw If either \a a1 or \a a2 is NULL.
6897    *  \throw If \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents().
6898    */
6899   template <class T>
6900   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::Aggregate(const DataArrayType *a1, const DataArrayType *a2, T offsetA2)
6901   {
6902     if(!a1 || !a2)
6903       throw INTERP_KERNEL::Exception("DataArrayInt::Aggregate : input DataArrayInt instance is NULL !");
6904     std::size_t nbOfComp(a1->getNumberOfComponents());
6905     if(nbOfComp!=a2->getNumberOfComponents())
6906       throw INTERP_KERNEL::Exception("Nb of components mismatch for array Aggregation !");
6907     mcIdType nbOfTuple1(a1->getNumberOfTuples()),nbOfTuple2(a2->getNumberOfTuples());
6908     MCAuto<DataArrayType> ret(DataArrayType::New());
6909     ret->alloc(nbOfTuple1+nbOfTuple2-offsetA2,nbOfComp);
6910     T *pt=std::copy(a1->begin(),a1->end(),ret->getPointer());
6911     std::copy(a2->getConstPointer()+offsetA2*nbOfComp,a2->getConstPointer()+nbOfTuple2*nbOfComp,pt);
6912     ret->copyStringInfoFrom(*a1);
6913     return ret.retn();
6914   }
6915
6916   /*!
6917    * Returns a new DataArrayInt by concatenating all given arrays, so that (1) the number
6918    * of tuples in the result array is a sum of the number of tuples of given arrays and (2)
6919    * the number of component in the result array is same as that of each of given arrays.
6920    * Info on components is copied from the first of the given arrays. Number of components
6921    * in the given arrays must be  the same.
6922    * If the number of non null of elements in \a arr is equal to one the returned object is a copy of it
6923    * not the object itself.
6924    *  \param [in] arr - a sequence of arrays to include in the result array.
6925    *  \return DataArrayInt * - the new instance of DataArrayInt.
6926    *          The caller is to delete this result array using decrRef() as it is no more
6927    *          needed.
6928    *  \throw If all arrays within \a arr are NULL.
6929    *  \throw If getNumberOfComponents() of arrays within \a arr.
6930    */
6931   template <class T>
6932   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::Aggregate(const std::vector<const DataArrayType *>& arr)
6933   {
6934     std::vector<const DataArrayType *> a;
6935     for(typename std::vector<const DataArrayType *>::const_iterator it4=arr.begin();it4!=arr.end();it4++)
6936       if(*it4)
6937         a.push_back(*it4);
6938     if(a.empty())
6939       throw INTERP_KERNEL::Exception("DataArrayInt::Aggregate : input list must be NON EMPTY !");
6940     typename std::vector<const DataArrayType *>::const_iterator it=a.begin();
6941     std::size_t nbOfComp((*it)->getNumberOfComponents());
6942     mcIdType nbt((*it++)->getNumberOfTuples());
6943     for(;it!=a.end();it++)
6944       {
6945         if((*it)->getNumberOfComponents()!=nbOfComp)
6946           throw INTERP_KERNEL::Exception("DataArrayInt::Aggregate : Nb of components mismatch for array aggregation !");
6947         nbt+=(*it)->getNumberOfTuples();
6948       }
6949     MCAuto<DataArrayType> ret=DataArrayType::New();
6950     ret->alloc(nbt,nbOfComp);
6951     T *pt=ret->getPointer();
6952     for(it=a.begin();it!=a.end();it++)
6953       pt=std::copy((*it)->getConstPointer(),(*it)->getConstPointer()+(*it)->getNbOfElems(),pt);
6954     ret->copyStringInfoFrom(*(a[0]));
6955     return ret.retn();
6956   }
6957
6958   /*!
6959    * This method takes as input a list of DataArrayInt instances \a arrs that represent each a packed index arrays.
6960    * A packed index array is an allocated array with one component, and at least one tuple. The first element
6961    * of each array in \a arrs must be 0. Each array in \a arrs is expected to be increasingly monotonic.
6962    * This method is useful for users that want to aggregate a pair of DataArrayInt representing an indexed data (typically nodal connectivity index in unstructured meshes.
6963    *
6964    * \return DataArrayInt * - a new object to be managed by the caller.
6965    */
6966   template <class T>
6967   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::AggregateIndexes(const std::vector<const DataArrayType *>& arrs)
6968   {
6969     mcIdType retSz=1;
6970     for(typename std::vector<const DataArrayType *>::const_iterator it4=arrs.begin();it4!=arrs.end();it4++)
6971       {
6972         if(*it4)
6973           {
6974             (*it4)->checkAllocated();
6975             if((*it4)->getNumberOfComponents()!=1)
6976               {
6977                 std::ostringstream oss; oss << "DataArrayInt::AggregateIndexes : presence of a DataArrayInt instance with nb of compo != 1 at pos " << std::distance(arrs.begin(),it4) << " !";
6978                 throw INTERP_KERNEL::Exception(oss.str().c_str());
6979               }
6980             mcIdType nbTupl((*it4)->getNumberOfTuples());
6981             if(nbTupl<1)
6982               {
6983                 std::ostringstream oss; oss << "DataArrayInt::AggregateIndexes : presence of a DataArrayInt instance with nb of tuples < 1 at pos " << std::distance(arrs.begin(),it4) << " !";
6984                 throw INTERP_KERNEL::Exception(oss.str().c_str());
6985               }
6986             if((*it4)->front()!=0)
6987               {
6988                 std::ostringstream oss; oss << "DataArrayInt::AggregateIndexes : presence of a DataArrayInt instance with front value != 0 at pos " << std::distance(arrs.begin(),it4) << " !";
6989                 throw INTERP_KERNEL::Exception(oss.str().c_str());
6990               }
6991             retSz+=nbTupl-1;
6992           }
6993         else
6994           {
6995             std::ostringstream oss; oss << "DataArrayInt::AggregateIndexes : presence of a null instance at pos " << std::distance(arrs.begin(),it4) << " !";
6996             throw INTERP_KERNEL::Exception(oss.str().c_str());
6997           }
6998       }
6999     if(arrs.empty())
7000       throw INTERP_KERNEL::Exception("DataArrayInt::AggregateIndexes : input list must be NON EMPTY !");
7001     MCAuto<DataArrayType> ret=DataArrayType::New();
7002     ret->alloc(retSz,1);
7003     T *pt=ret->getPointer(); *pt++=0;
7004     for(typename std::vector<const DataArrayType *>::const_iterator it=arrs.begin();it!=arrs.end();it++)
7005       pt=std::transform((*it)->begin()+1,(*it)->end(),pt,std::bind2nd(std::plus<T>(),pt[-1]));
7006     ret->copyStringInfoFrom(*(arrs[0]));
7007     return ret.retn();
7008   }
7009
7010   /*!
7011    * Returns a new DataArrayInt which contains all elements of given one-dimensional
7012    * arrays. The result array does not contain any duplicates and its values
7013    * are sorted in ascending order.
7014    *  \param [in] arr - sequence of DataArrayInt's to unite.
7015    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
7016    *         array using decrRef() as it is no more needed.
7017    *  \throw If any \a arr[i] is not allocated.
7018    *  \throw If \a arr[i]->getNumberOfComponents() != 1.
7019    */
7020   template <class T>
7021   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::BuildUnion(const std::vector<const DataArrayType *>& arr)
7022   {
7023     std::vector<const DataArrayType *> a;
7024     for(typename std::vector<const DataArrayType *>::const_iterator it4=arr.begin();it4!=arr.end();it4++)
7025       if(*it4)
7026         a.push_back(*it4);
7027     for(typename std::vector<const DataArrayType *>::const_iterator it=a.begin();it!=a.end();it++)
7028       {
7029         (*it)->checkAllocated();
7030         if((*it)->getNumberOfComponents()!=1)
7031           throw INTERP_KERNEL::Exception("DataArrayInt::BuildUnion : only single component allowed !");
7032       }
7033     //
7034     std::set<T> r;
7035     for(typename std::vector<const DataArrayType *>::const_iterator it=a.begin();it!=a.end();it++)
7036       {
7037         const T *pt=(*it)->getConstPointer();
7038         mcIdType nbOfTuples((*it)->getNumberOfTuples());
7039         r.insert(pt,pt+nbOfTuples);
7040       }
7041     DataArrayType *ret=DataArrayType::New();
7042     ret->alloc(r.size(),1);
7043     std::copy(r.begin(),r.end(),ret->getPointer());
7044     return ret;
7045   }
7046
7047   /*!
7048    * Returns a new DataArrayInt which contains elements present in each of given one-dimensional
7049    * arrays. The result array does not contain any duplicates and its values
7050    * are sorted in ascending order.
7051    *  \param [in] arr - sequence of DataArrayInt's to intersect.
7052    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
7053    *         array using decrRef() as it is no more needed.
7054    *  \throw If any \a arr[i] is not allocated.
7055    *  \throw If \a arr[i]->getNumberOfComponents() != 1.
7056    */
7057   template <class T>
7058   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::BuildIntersection(const std::vector<const DataArrayType *>& arr)
7059   {
7060     std::vector<const DataArrayType *> a;
7061     for(typename std::vector<const DataArrayType *>::const_iterator it4=arr.begin();it4!=arr.end();it4++)
7062       if(*it4)
7063         a.push_back(*it4);
7064     for(typename std::vector<const DataArrayType *>::const_iterator it=a.begin();it!=a.end();it++)
7065       {
7066         (*it)->checkAllocated();
7067         if((*it)->getNumberOfComponents()!=1)
7068           throw INTERP_KERNEL::Exception("DataArrayInt::BuildIntersection : only single component allowed !");
7069       }
7070     //
7071     std::set<T> r;
7072     for(typename std::vector<const DataArrayType *>::const_iterator it=a.begin();it!=a.end();it++)
7073       {
7074         const T *pt=(*it)->getConstPointer();
7075         mcIdType nbOfTuples((*it)->getNumberOfTuples());
7076         std::set<T> s1(pt,pt+nbOfTuples);
7077         if(it!=a.begin())
7078           {
7079             std::set<T> r2;
7080             std::set_intersection(r.begin(),r.end(),s1.begin(),s1.end(),inserter(r2,r2.end()));
7081             r=r2;
7082           }
7083         else
7084           r=s1;
7085       }
7086     DataArrayType *ret(DataArrayType::New());
7087     ret->alloc(r.size(),1);
7088     std::copy(r.begin(),r.end(),ret->getPointer());
7089     return ret;
7090   }
7091
7092   /*!
7093    * This method allows to put a vector of vector of integer into a more compact data structure (skyline).
7094    * This method is not available into python because no available optimized data structure available to map std::vector< std::vector<mcIdType> >.
7095    *
7096    * \param [in] v the input data structure to be translate into skyline format.
7097    * \param [out] data the first element of the skyline format. The user is expected to deal with newly allocated array.
7098    * \param [out] dataIndex the second element of the skyline format.
7099    */
7100   template <class T>
7101   void DataArrayDiscrete<T>::PutIntoToSkylineFrmt(const std::vector< std::vector<T> >& v, DataArrayType *& data, DataArrayIdType *& dataIndex)
7102   {
7103     std::size_t sz(v.size());
7104     MCAuto<DataArrayType> retDat(DataArrayType::New());
7105     MCAuto<DataArrayIdType> retIdx(DataArrayIdType::New());
7106     retIdx->alloc(sz+1,1);
7107     mcIdType *ptid(retIdx->getPointer()); *ptid=0;
7108     for(std::size_t i=0;i<sz;i++,ptid++)
7109       ptid[1]=ptid[0]+ToIdType(v[i].size());
7110     retDat->alloc(retIdx->back(),1);
7111     T *pt=retDat->getPointer();
7112     for(std::size_t i=0;i<sz;i++)
7113       pt=std::copy(v[i].begin(),v[i].end(),pt);
7114     data=retDat.retn(); dataIndex=retIdx.retn();
7115   }
7116
7117   /*!
7118    * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
7119    * (\ref numbering-indirect).
7120    * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
7121    * The selection of extraction is done standardly in new2old format.
7122    * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
7123    *
7124    * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7125    * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7126    * \param [in] arrIn arr origin array from which the extraction will be done.
7127    * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7128    * \param [out] arrOut the resulting array
7129    * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7130    * \sa DataArrayInt::ExtractFromIndexedArraysSlice
7131    */
7132   template <class T>
7133   void DataArrayDiscrete<T>::ExtractFromIndexedArrays(const mcIdType *idsOfSelectBg, const mcIdType *idsOfSelectEnd,
7134                                                       const DataArrayType *arrIn, const DataArrayIdType *arrIndxIn,
7135                                                       DataArrayType* &arrOut, DataArrayIdType* &arrIndexOut)
7136   {
7137     if(!arrIn || !arrIndxIn)
7138       throw INTERP_KERNEL::Exception("DataArrayInt::ExtractFromIndexedArrays : input pointer is NULL !");
7139     arrIn->checkAllocated(); arrIndxIn->checkAllocated();
7140     if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
7141       throw INTERP_KERNEL::Exception("DataArrayInt::ExtractFromIndexedArrays : input arrays must have exactly one component !");
7142     std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
7143     const T *arrInPtr=arrIn->begin();
7144     const mcIdType *arrIndxPtr=arrIndxIn->begin();
7145     mcIdType nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
7146     if(nbOfGrps<0)
7147       throw INTERP_KERNEL::Exception("DataArrayInt::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
7148     mcIdType maxSizeOfArr(arrIn->getNumberOfTuples());
7149     MCAuto<DataArrayType> arro=DataArrayType::New();
7150     MCAuto<DataArrayIdType> arrIo=DataArrayIdType::New();
7151     arrIo->alloc(sz+1,1);
7152     const mcIdType *idsIt=idsOfSelectBg;
7153     mcIdType *work=arrIo->getPointer();
7154     *work++=0;
7155     mcIdType lgth=0;
7156     for(std::size_t i=0;i<sz;i++,work++,idsIt++)
7157       {
7158         if(*idsIt>=0 && *idsIt<nbOfGrps)
7159           lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
7160         else
7161           {
7162             std::ostringstream oss; oss << "DataArrayInt::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
7163             throw INTERP_KERNEL::Exception(oss.str());
7164           }
7165         if(lgth>=work[-1])
7166           *work=lgth;
7167         else
7168           {
7169             std::ostringstream oss; oss << "DataArrayInt::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
7170             oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
7171             throw INTERP_KERNEL::Exception(oss.str());
7172           }
7173       }
7174     arro->alloc(lgth,1);
7175     T *data=arro->getPointer();
7176     idsIt=idsOfSelectBg;
7177     for(std::size_t i=0;i<sz;i++,idsIt++)
7178       {
7179         if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
7180           data=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],data);
7181         else
7182           {
7183             std::ostringstream oss; oss << "DataArrayInt::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
7184             oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
7185             throw INTERP_KERNEL::Exception(oss.str());
7186           }
7187       }
7188     arrOut=arro.retn();
7189     arrIndexOut=arrIo.retn();
7190   }
7191
7192   /*!
7193    * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
7194    * (\ref numbering-indirect).
7195    * This method returns the result of the extraction ( specified by a set of ids with a slice given by \a idsOfSelectStart, \a idsOfSelectStop and \a idsOfSelectStep ).
7196    * The selection of extraction is done standardly in new2old format.
7197    * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
7198    *
7199    * \param [in] idsOfSelectStart begin of set of ids of the input extraction (included)
7200    * \param [in] idsOfSelectStop end of set of ids of the input extraction (excluded)
7201    * \param [in] idsOfSelectStep
7202    * \param [in] arrIn arr origin array from which the extraction will be done.
7203    * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7204    * \param [out] arrOut the resulting array
7205    * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7206    * \sa DataArrayInt::ExtractFromIndexedArrays
7207    */
7208   template <class T>
7209   void DataArrayDiscrete<T>::ExtractFromIndexedArraysSlice(mcIdType idsOfSelectStart, mcIdType idsOfSelectStop, mcIdType idsOfSelectStep,
7210                                                            const DataArrayType *arrIn, const DataArrayIdType *arrIndxIn,
7211                                                            DataArrayType* &arrOut, DataArrayIdType* &arrIndexOut)
7212   {
7213     if(!arrIn || !arrIndxIn)
7214       throw INTERP_KERNEL::Exception("DataArrayInt::ExtractFromIndexedArraysSlice : input pointer is NULL !");
7215     arrIn->checkAllocated(); arrIndxIn->checkAllocated();
7216     if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
7217       throw INTERP_KERNEL::Exception("DataArrayInt::ExtractFromIndexedArraysSlice : input arrays must have exactly one component !");
7218     mcIdType sz=DataArray::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArraysSlice : Input slice ");
7219     const T *arrInPtr=arrIn->begin();
7220     const mcIdType *arrIndxPtr=arrIndxIn->begin();
7221     mcIdType nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
7222     if(nbOfGrps<0)
7223       throw INTERP_KERNEL::Exception("DataArrayInt::ExtractFromIndexedArraysSlice : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
7224     mcIdType maxSizeOfArr(arrIn->getNumberOfTuples());
7225     MCAuto<DataArrayType> arro=DataArrayType::New();
7226     MCAuto<DataArrayIdType> arrIo=DataArrayIdType::New();
7227     arrIo->alloc(sz+1,1);
7228     mcIdType idsIt=idsOfSelectStart;
7229     mcIdType *work=arrIo->getPointer();
7230     *work++=0;
7231     mcIdType lgth=0;
7232     for(mcIdType i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
7233       {
7234         if(idsIt>=0 && idsIt<nbOfGrps)
7235           lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
7236         else
7237           {
7238             std::ostringstream oss; oss << "DataArrayInt::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
7239             throw INTERP_KERNEL::Exception(oss.str());
7240           }
7241         if(lgth>=work[-1])
7242           *work=lgth;
7243         else
7244           {
7245             std::ostringstream oss; oss << "DataArrayInt::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
7246             oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
7247             throw INTERP_KERNEL::Exception(oss.str());
7248           }
7249       }
7250     arro->alloc(lgth,1);
7251     T *data=arro->getPointer();
7252     idsIt=idsOfSelectStart;
7253     for(mcIdType i=0;i<sz;i++,idsIt+=idsOfSelectStep)
7254       {
7255         if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
7256           data=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],data);
7257         else
7258           {
7259             std::ostringstream oss; oss << "DataArrayInt::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
7260             oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
7261             throw INTERP_KERNEL::Exception(oss.str());
7262           }
7263       }
7264     arrOut=arro.retn();
7265     arrIndexOut=arrIo.retn();
7266   }
7267
7268   /*!
7269    * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7270    * This method builds an output pair (\b arrOut,\b arrIndexOut) that is a copy from \b arrIn for all cell ids \b not \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) and for
7271    * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
7272    * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitly a result output arrays.
7273    *
7274    * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7275    * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7276    * \param [in] arrIn arr origin array from which the extraction will be done.
7277    * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7278    * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
7279    * \param [in] srcArrIndex index array of \b srcArr
7280    * \param [out] arrOut the resulting array
7281    * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7282    *
7283    * \sa DataArrayInt::SetPartOfIndexedArraysSameIdx
7284    */
7285   template <class T>
7286   void DataArrayDiscrete<T>::SetPartOfIndexedArrays(const mcIdType *idsOfSelectBg, const mcIdType *idsOfSelectEnd,
7287                                                     const DataArrayType *arrIn, const DataArrayIdType *arrIndxIn,
7288                                                     const DataArrayType *srcArr, const DataArrayIdType *srcArrIndex,
7289                                                     DataArrayType* &arrOut, DataArrayIdType* &arrIndexOut)
7290   {
7291     if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7292       throw INTERP_KERNEL::Exception("DataArrayInt::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
7293     MCAuto<DataArrayType> arro=DataArrayType::New();
7294     MCAuto<DataArrayIdType> arrIo=DataArrayIdType::New();
7295     mcIdType nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7296     std::vector<bool> v(nbOfTuples,true);
7297     mcIdType offset=0;
7298     const mcIdType *arrIndxInPtr=arrIndxIn->begin();
7299     const mcIdType *srcArrIndexPtr=srcArrIndex->begin();
7300     for(const mcIdType *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
7301       {
7302         if(*it>=0 && *it<nbOfTuples)
7303           {
7304             v[*it]=false;
7305             offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
7306           }
7307         else
7308           {
7309             std::ostringstream oss; oss << "DataArrayInt::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
7310             throw INTERP_KERNEL::Exception(oss.str());
7311           }
7312       }
7313     srcArrIndexPtr=srcArrIndex->begin();
7314     arrIo->alloc(nbOfTuples+1,1);
7315     arro->alloc(arrIn->getNumberOfTuples()+offset,1);
7316     const T *arrInPtr=arrIn->begin();
7317     const T *srcArrPtr=srcArr->begin();
7318     mcIdType *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
7319     T *arroPtr=arro->getPointer();
7320     for(mcIdType ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
7321       {
7322         if(v[ii])
7323           {
7324             arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
7325             *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
7326           }
7327         else
7328           {
7329             std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
7330             arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
7331             *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
7332           }
7333       }
7334     arrOut=arro.retn();
7335     arrIndexOut=arrIo.retn();
7336   }
7337
7338   /*!
7339    * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7340    * This method builds an output pair (\b arrOut,\b arrIndexOut) that is a copy from \b arrIn for all cell ids \b not \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) and for
7341    * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
7342    * This method is an generalization of DataArrayInt::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitly a result output arrays.
7343    *
7344    * \param [in] start begin of set of ids of the input extraction (included)
7345    * \param [in] end end of set of ids of the input extraction (excluded)
7346    * \param [in] step step of the set of ids in range mode.
7347    * \param [in] arrIn arr origin array from which the extraction will be done.
7348    * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7349    * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
7350    * \param [in] srcArrIndex index array of \b srcArr
7351    * \param [out] arrOut the resulting array
7352    * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7353    *
7354    * \sa DataArrayInt::SetPartOfIndexedArraysSameIdx DataArrayInt::SetPartOfIndexedArrays
7355    */
7356   template <class T>
7357   void DataArrayDiscrete<T>::SetPartOfIndexedArraysSlice(mcIdType start, mcIdType end, mcIdType step,
7358                                                          const DataArrayType *arrIn, const DataArrayIdType *arrIndxIn,
7359                                                          const DataArrayType *srcArr, const DataArrayIdType *srcArrIndex,
7360                                                          DataArrayType* &arrOut, DataArrayIdType* &arrIndexOut)
7361   {
7362     if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7363       throw INTERP_KERNEL::Exception("DataArrayInt::SetPartOfIndexedArraysSlice : presence of null pointer in input parameter !");
7364     MCAuto<DataArrayType> arro=DataArrayType::New();
7365     MCAuto<DataArrayIdType> arrIo=DataArrayIdType::New();
7366     mcIdType nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7367     mcIdType offset=0;
7368     const mcIdType *arrIndxInPtr=arrIndxIn->begin();
7369     const mcIdType *srcArrIndexPtr=srcArrIndex->begin();
7370     mcIdType nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"DataArrayInt::SetPartOfIndexedArraysSlice : ");
7371     mcIdType it=start;
7372     for(mcIdType i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
7373       {
7374         if(it>=0 && it<nbOfTuples)
7375           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
7376         else
7377           {
7378             std::ostringstream oss; oss << "DataArrayInt::SetPartOfIndexedArraysSlice : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
7379             throw INTERP_KERNEL::Exception(oss.str());
7380           }
7381       }
7382     srcArrIndexPtr=srcArrIndex->begin();
7383     arrIo->alloc(nbOfTuples+1,1);
7384     arro->alloc(arrIn->getNumberOfTuples()+offset,1);
7385     const T *arrInPtr=arrIn->begin();
7386     const T *srcArrPtr=srcArr->begin();
7387     mcIdType *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
7388     T *arroPtr=arro->getPointer();
7389     for(mcIdType ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
7390       {
7391         mcIdType pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
7392         if(pos<0)
7393           {
7394             arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
7395             *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
7396           }
7397         else
7398           {
7399             arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
7400             *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
7401           }
7402       }
7403     arrOut=arro.retn();
7404     arrIndexOut=arrIo.retn();
7405   }
7406
7407   /*!
7408    * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7409    * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignment do not modify the index in \b arrIndxIn.
7410    *
7411    * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7412    * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7413    * \param [in,out] arrInOut arr origin array from which the extraction will be done.
7414    * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7415    * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
7416    * \param [in] srcArrIndex index array of \b srcArr
7417    *
7418    * \sa DataArrayInt::SetPartOfIndexedArrays
7419    */
7420   template <class T>
7421   void DataArrayDiscrete<T>::SetPartOfIndexedArraysSameIdx(const mcIdType *idsOfSelectBg, const mcIdType *idsOfSelectEnd,
7422                                                            DataArrayType *arrInOut, const DataArrayIdType *arrIndxIn,
7423                                                            const DataArrayType *srcArr, const DataArrayIdType *srcArrIndex)
7424   {
7425     if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7426       throw INTERP_KERNEL::Exception("DataArrayInt::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
7427     mcIdType nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7428     const mcIdType *arrIndxInPtr=arrIndxIn->begin();
7429     const mcIdType *srcArrIndexPtr=srcArrIndex->begin();
7430     T *arrInOutPtr=arrInOut->getPointer();
7431     const T *srcArrPtr=srcArr->begin();
7432     for(const mcIdType *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
7433       {
7434         if(*it>=0 && *it<nbOfTuples)
7435           {
7436             if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
7437               std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
7438             else
7439               {
7440                 std::ostringstream oss; oss << "DataArrayInt::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " id (idsOfSelectBg[" << std::distance(idsOfSelectBg,it)<< "]) is " << *it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
7441                 throw INTERP_KERNEL::Exception(oss.str());
7442               }
7443           }
7444         else
7445           {
7446             std::ostringstream oss; oss << "DataArrayInt::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
7447             throw INTERP_KERNEL::Exception(oss.str());
7448           }
7449       }
7450   }
7451
7452   /*!
7453    * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7454    * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignment do not modify the index in \b arrIndxIn.
7455    *
7456    * \param [in] start begin of set of ids of the input extraction (included)
7457    * \param [in] end end of set of ids of the input extraction (excluded)
7458    * \param [in] step step of the set of ids in range mode.
7459    * \param [in,out] arrInOut arr origin array from which the extraction will be done.
7460    * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7461    * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
7462    * \param [in] srcArrIndex index array of \b srcArr
7463    *
7464    * \sa DataArrayInt::SetPartOfIndexedArraysSlice DataArrayInt::SetPartOfIndexedArraysSameIdx
7465    */
7466   template <class T>
7467   void DataArrayDiscrete<T>::SetPartOfIndexedArraysSameIdxSlice(mcIdType start, mcIdType end, mcIdType step,
7468                                                                 DataArrayType *arrInOut, const DataArrayIdType *arrIndxIn,
7469                                                                 const DataArrayType *srcArr, const DataArrayIdType *srcArrIndex)
7470   {
7471     if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7472       throw INTERP_KERNEL::Exception("DataArrayInt::SetPartOfIndexedArraysSameIdxSlice : presence of null pointer in input parameter !");
7473     mcIdType nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7474     const mcIdType *arrIndxInPtr=arrIndxIn->begin();
7475     const mcIdType *srcArrIndexPtr=srcArrIndex->begin();
7476     T *arrInOutPtr=arrInOut->getPointer();
7477     const T *srcArrPtr=srcArr->begin();
7478     mcIdType nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"DataArrayInt::SetPartOfIndexedArraysSameIdxSlice : ");
7479     mcIdType it=start;
7480     for(mcIdType i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
7481       {
7482         if(it>=0 && it<nbOfTuples)
7483           {
7484             if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
7485               std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
7486             else
7487               {
7488                 std::ostringstream oss; oss << "DataArrayInt::SetPartOfIndexedArraysSameIdxSlice : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
7489                 throw INTERP_KERNEL::Exception(oss.str());
7490               }
7491           }
7492         else
7493           {
7494             std::ostringstream oss; oss << "DataArrayInt::SetPartOfIndexedArraysSameIdxSlice : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
7495             throw INTERP_KERNEL::Exception(oss.str());
7496           }
7497       }
7498   }
7499
7500   /*!
7501    * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
7502    * This method will not impact the size of inout parameter \b arrIndx but the size of \b arr will be modified in case of suppression.
7503    *
7504    * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
7505    * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
7506    * \param [in,out] arr array in which the remove operation will be done.
7507    * \param [in,out] arrIndx array in the remove operation will modify
7508    * \param [in] offsetForRemoval (by default 0) offset so that for each i in [0,arrIndx->getNumberOfTuples()-1) removal process will be performed in the following range [arr+arrIndx[i]+offsetForRemoval,arr+arr[i+1])
7509    * \return true if \b arr and \b arrIndx have been modified, false if not.
7510    */
7511   template <class T>
7512   bool DataArrayDiscrete<T>::RemoveIdsFromIndexedArrays(const T *idsToRemoveBg, const T *idsToRemoveEnd,
7513                                                         DataArrayType *arr, DataArrayIdType *arrIndx, mcIdType offsetForRemoval)
7514   {
7515     if(!arrIndx || !arr)
7516       throw INTERP_KERNEL::Exception("DataArrayInt::RemoveIdsFromIndexedArrays : some input arrays are empty !");
7517     if(offsetForRemoval<0)
7518       throw INTERP_KERNEL::Exception("DataArrayInt::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
7519     std::set<T> s(idsToRemoveBg,idsToRemoveEnd);
7520     mcIdType nbOfGrps=arrIndx->getNumberOfTuples()-1;
7521     mcIdType *arrIPtr=arrIndx->getPointer();
7522     *arrIPtr++=0;
7523     mcIdType previousArrI=0;
7524     const T *arrPtr=arr->begin();
7525     std::vector<T> arrOut;//no utility to switch to DataArrayInt because copy always needed
7526     for(mcIdType i=0;i<nbOfGrps;i++,arrIPtr++)
7527       {
7528         if(*arrIPtr-previousArrI>offsetForRemoval)
7529           {
7530             for(const T *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
7531               {
7532                 if(s.find(*work)==s.end())
7533                   arrOut.push_back(*work);
7534               }
7535           }
7536         previousArrI=*arrIPtr;
7537         *arrIPtr=ToIdType(arrOut.size());
7538       }
7539     if(arr->getNumberOfTuples()==ToIdType(arrOut.size()))
7540       return false;
7541     arr->alloc(arrOut.size(),1);
7542     std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
7543     return true;
7544   }
7545
7546   /*!
7547    * Returns a new DataArrayInt containing an arithmetic progression
7548    * that is equal to the sequence returned by Python \c range(\a begin,\a  end,\a  step )
7549    * function.
7550    *  \param [in] begin - the start value of the result sequence.
7551    *  \param [in] end - limiting value, so that every value of the result array is less than
7552    *              \a end.
7553    *  \param [in] step - specifies the increment or decrement.
7554    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
7555    *          array using decrRef() as it is no more needed.
7556    *  \throw If \a step == 0.
7557    *  \throw If \a end < \a begin && \a step > 0.
7558    *  \throw If \a end > \a begin && \a step < 0.
7559    */
7560   template <class T>
7561   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::Range(T begin, T end, T step)
7562   {
7563     mcIdType nbOfTuples=DataArrayTools<T>::GetNumberOfItemGivenBESRelative(begin,end,step,"DataArrayInt::Range");
7564     MCAuto<DataArrayType> ret=DataArrayType::New();
7565     ret->alloc(nbOfTuples,1);
7566     T *ptr=ret->getPointer();
7567     if(step>0)
7568       {
7569         for(T i=begin;i<end;i+=step,ptr++)
7570           *ptr=i;
7571       }
7572     else
7573       {
7574         for(T i=begin;i>end;i+=step,ptr++)
7575           *ptr=i;
7576       }
7577     return ret.retn();
7578   }
7579
7580   /*!
7581    * Returns a new DataArrayInt containing a renumbering map in "Old to New" mode computed
7582    * from a zip representation of a surjective format (returned e.g. by
7583    * \ref MEDCoupling::DataArrayDouble::findCommonTuples() "DataArrayDouble::findCommonTuples()"
7584    * for example). The result array minimizes the permutation. <br>
7585    * For more info on renumbering see \ref numbering. <br>
7586    * \b Example: <br>
7587    * - \a nbOfOldTuples: 10
7588    * - \a arr          : [0,3, 5,7,9]
7589    * - \a arrIBg       : [0,2,5]
7590    * - \a newNbOfTuples: 7
7591    * - result array    : [0,1,2,0,3,4,5,4,6,4]
7592    *
7593    *  \param [in] nbOfOldTuples - number of tuples in the initial array \a arr.
7594    *  \param [in] arr - the array of tuple indices grouped by \a arrIBg array.
7595    *  \param [in] arrIBg - the array dividing all indices stored in \a arr into groups of
7596    *         (indices of) equal values. Its every element (except the last one) points to
7597    *         the first element of a group of equal values.
7598    *  \param [in] arrIEnd - specifies the end of \a arrIBg, so that the last element of \a
7599    *          arrIBg is \a arrIEnd[ -1 ].
7600    *  \param [out] newNbOfTuples - number of tuples after surjection application.
7601    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
7602    *          array using decrRef() as it is no more needed.
7603    *  \throw If any value of \a arr breaks condition ( 0 <= \a arr[ i ] < \a nbOfOldTuples ).
7604    */
7605   template <class T>
7606   DataArrayIdType *DataArrayDiscrete<T>::ConvertIndexArrayToO2N(mcIdType nbOfOldTuples, const mcIdType *arr, const mcIdType *arrIBg, const mcIdType *arrIEnd, mcIdType &newNbOfTuples)
7607   {
7608     MCAuto<DataArrayIdType> ret=DataArrayIdType::New();
7609     ret->alloc(nbOfOldTuples,1);
7610     mcIdType *pt=ret->getPointer();
7611     std::fill(pt,pt+nbOfOldTuples,-1);
7612     mcIdType nbOfGrps=ToIdType(std::distance(arrIBg,arrIEnd))-1;
7613     const mcIdType *cIPtr=arrIBg;
7614     for(mcIdType i=0;i<nbOfGrps;i++)
7615       pt[arr[cIPtr[i]]]=-(i+2);
7616     mcIdType newNb=0;
7617     for(mcIdType iNode=0;iNode<nbOfOldTuples;iNode++)
7618       {
7619         if(pt[iNode]<0)
7620           {
7621             if(pt[iNode]==-1)
7622               pt[iNode]=newNb++;
7623             else
7624               {
7625                 mcIdType grpId=-(pt[iNode]+2);
7626                 for(mcIdType j=cIPtr[grpId];j<cIPtr[grpId+1];j++)
7627                   {
7628                     if(arr[j]>=0 && arr[j]<nbOfOldTuples)
7629                       pt[arr[j]]=newNb;
7630                     else
7631                       {
7632                         std::ostringstream oss; oss << "DataArrayInt::ConvertIndexArrayToO2N : With element #" << j << " value is " << arr[j] << " should be in [0," << nbOfOldTuples << ") !";
7633                         throw INTERP_KERNEL::Exception(oss.str().c_str());
7634                       }
7635                   }
7636                 newNb++;
7637               }
7638           }
7639       }
7640     newNbOfTuples=newNb;
7641     return ret.retn();
7642   }
7643
7644   /*!
7645    * Returns a new DataArrayInt which is a minimal partition of elements of \a groups.
7646    * The i-th item of the result array is an ID of a set of elements belonging to a
7647    * unique set of groups, which the i-th element is a part of. This set of elements
7648    * belonging to a unique set of groups is called \a family, so the result array contains
7649    * IDs of families each element belongs to.
7650    *
7651    * \b Example: if we have two groups of elements: \a group1 [0,4] and \a group2 [ 0,1,2 ],
7652    * then there are 3 families:
7653    * - \a family1 (with ID 1) contains element [0] belonging to ( \a group1 + \a group2 ),
7654    * - \a family2 (with ID 2) contains elements [4] belonging to ( \a group1 ),
7655    * - \a family3 (with ID 3) contains element [1,2] belonging to ( \a group2 ), <br>
7656    * and the result array contains IDs of families [ 1,3,3,0,2 ]. <br> Note a family ID 0 which
7657    * stands for the element #3 which is in none of groups.
7658    *
7659    *  \param [in] groups - sequence of groups of element IDs.
7660    *  \param [in] newNb - total number of elements; it must be more than max ID of element
7661    *         in \a groups.
7662    *  \param [out] fidsOfGroups - IDs of families the elements of each group belong to.
7663    *  \return DataArrayInt * - a new instance of DataArrayInt containing IDs of families
7664    *         each element with ID from range [0, \a newNb ) belongs to. The caller is to
7665    *         delete this array using decrRef() as it is no more needed.
7666    *  \throw If any element ID in \a groups violates condition ( 0 <= ID < \a newNb ).
7667    */
7668   template <class T>
7669   DataArrayIdType *DataArrayDiscrete<T>::MakePartition(const std::vector<const DataArrayType *>& groups, mcIdType newNb, std::vector< std::vector<mcIdType> >& fidsOfGroups)
7670   {
7671     std::vector<const DataArrayType *> groups2;
7672     for(typename std::vector<const DataArrayType *>::const_iterator it4=groups.begin();it4!=groups.end();it4++)
7673       if(*it4)
7674         groups2.push_back(*it4);
7675     MCAuto<DataArrayIdType> ret=DataArrayIdType::New();
7676     ret->alloc(newNb,1);
7677     mcIdType *retPtr=ret->getPointer();
7678     std::fill(retPtr,retPtr+newNb,0);
7679     mcIdType fid=1;
7680     for(typename std::vector<const DataArrayType *>::const_iterator iter=groups2.begin();iter!=groups2.end();iter++)
7681       {
7682         const T *ptr=(*iter)->getConstPointer();
7683         std::size_t nbOfElem=(*iter)->getNbOfElems();
7684         mcIdType sfid=fid;
7685         for(mcIdType j=0;j<sfid;j++)
7686           {
7687             bool found=false;
7688             for(std::size_t i=0;i<nbOfElem;i++)
7689               {
7690                 if(ptr[i]>=0 && ptr[i]<newNb)
7691                   {
7692                     if(retPtr[ptr[i]]==j)
7693                       {
7694                         retPtr[ptr[i]]=fid;
7695                         found=true;
7696                       }
7697                   }
7698                 else
7699                   {
7700                     std::ostringstream oss; oss << "DataArrayInt::MakePartition : In group \"" << (*iter)->getName() << "\" in tuple #" << i << " value = " << ptr[i] << " ! Should be in [0," << newNb;
7701                     oss << ") !";
7702                     throw INTERP_KERNEL::Exception(oss.str().c_str());
7703                   }
7704               }
7705             if(found)
7706               fid++;
7707           }
7708       }
7709     fidsOfGroups.clear();
7710     fidsOfGroups.resize(groups2.size());
7711     mcIdType grId=0;
7712     for(typename std::vector<const DataArrayType *>::const_iterator iter=groups2.begin();iter!=groups2.end();iter++,grId++)
7713       {
7714         std::set<mcIdType> tmp;
7715         const T *ptr=(*iter)->getConstPointer();
7716         std::size_t nbOfElem=(*iter)->getNbOfElems();
7717         for(const T *p=ptr;p!=ptr+nbOfElem;p++)
7718           tmp.insert(retPtr[*p]);
7719         fidsOfGroups[grId].insert(fidsOfGroups[grId].end(),tmp.begin(),tmp.end());
7720       }
7721     return ret.retn();
7722   }
7723
7724 }
7725
7726 /// @cond INTERNAL
7727 namespace MEDCouplingImpl
7728 {
7729   template <class T>
7730   class OpSwitchedOn
7731   {
7732   public:
7733     OpSwitchedOn(T *pt):_pt(pt),_cnt(0) { }
7734     void operator()(const bool& b) { if(b) *_pt++=FromIdType<T>(_cnt); _cnt++; }
7735   private:
7736     T *_pt;
7737     MEDCoupling::mcIdType _cnt;
7738   };
7739
7740   template <class T>
7741   class OpSwitchedOff
7742   {
7743   public:
7744     OpSwitchedOff(T *pt):_pt(pt),_cnt(0) { }
7745     void operator()(const bool& b) { if(!b) *_pt++=FromIdType<T>(_cnt); _cnt++; }
7746   private:
7747     T *_pt;
7748     MEDCoupling::mcIdType _cnt;
7749   };
7750 }
7751 /// @endcond
7752
7753 namespace MEDCoupling
7754 {
7755   /*!
7756    * This method returns the list of ids in ascending mode so that v[id]==true.
7757    */
7758   template <class T>
7759   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::BuildListOfSwitchedOn(const std::vector<bool>& v)
7760   {
7761     std::size_t sz(std::count(v.begin(),v.end(),true));
7762     MCAuto<DataArrayType> ret(DataArrayType::New()); ret->alloc(sz,1);
7763     std::for_each(v.begin(),v.end(),MEDCouplingImpl::OpSwitchedOn<T>(ret->getPointer()));
7764     return ret.retn();
7765   }
7766
7767   /*!
7768    * This method returns the list of ids in ascending mode so that v[id]==false.
7769    */
7770   template <class T>
7771   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::BuildListOfSwitchedOff(const std::vector<bool>& v)
7772   {
7773     std::size_t sz(std::count(v.begin(),v.end(),false));
7774     MCAuto<DataArrayType> ret(DataArrayType::New()); ret->alloc(sz,1);
7775     std::for_each(v.begin(),v.end(),MEDCouplingImpl::OpSwitchedOff<T>(ret->getPointer()));
7776     return ret.retn();
7777   }
7778 }
7779
7780 namespace MEDCoupling
7781 {
7782   /*!
7783    * This method compares content of input vector \a v and \a this.
7784    * 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.
7785    * For performance reasons \a this is expected to be sorted ascendingly. If not an exception will be thrown.
7786    *
7787    * \param [in] v - the vector of 'flags' to be compared with \a this.
7788    *
7789    * \throw If \a this is not sorted ascendingly.
7790    * \throw If \a this has not exactly one component.
7791    * \throw If \a this is not allocated.
7792    */
7793   template<class T>
7794   bool DataArrayDiscreteSigned<T>::isFittingWith(const std::vector<bool>& v) const
7795   {
7796     this->checkAllocated();
7797     if(this->getNumberOfComponents()!=1)
7798       throw INTERP_KERNEL::Exception("DataArrayInt::isFittingWith : number of components of this should be equal to one !");
7799     const T *w(this->begin()),*end2(this->end());
7800     T refVal=-std::numeric_limits<T>::max();
7801     T i=0;
7802     std::vector<bool>::const_iterator it(v.begin());
7803     for(;it!=v.end();it++,i++)
7804       {
7805         if(*it)
7806           {
7807             if(w!=end2)
7808               {
7809                 if(*w++==i)
7810                   {
7811                     if(i>refVal)
7812                       refVal=i;
7813                     else
7814                       {
7815                         std::ostringstream oss; oss << "DataArrayInt::isFittingWith : At pos #" << std::distance(this->begin(),w-1) << " this is not sorted ascendingly !";
7816                         throw INTERP_KERNEL::Exception(oss.str().c_str());
7817                       }
7818                   }
7819                 else
7820                   return false;
7821               }
7822             else
7823               return false;
7824           }
7825       }
7826     return w==end2;
7827   }
7828 }
7829
7830 #endif