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