Salome HOME
[EDF27988] : Implementation of MEDCouplingUMesh.explodeMeshTo for MEDFileUMesh.reduce...
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingMemArray.txx
1 // Copyright (C) 2007-2023  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
33 #include <sstream>
34 #include <cstdlib>
35 #include <numeric>
36 #include <algorithm>
37
38 namespace MEDCoupling
39 {
40   template<class T>
41   void MEDCouplingPointer<T>::setInternal(T *pointer)
42   {
43     _internal=pointer;
44     _external=0;
45   }
46
47   template<class T>
48   void MEDCouplingPointer<T>::setExternal(const T *pointer)
49   {
50     _external=pointer;
51     _internal=0;
52   }
53
54   template<class T>
55   MemArray<T>::MemArray(const MemArray<T>& other):_nb_of_elem(0),_nb_of_elem_alloc(0),_ownership(false),_dealloc(0),_param_for_deallocator(0)
56   {
57     if(!other._pointer.isNull())
58       {
59         _nb_of_elem_alloc=other._nb_of_elem;
60         T *pointer=(T*)malloc(_nb_of_elem_alloc*sizeof(T));
61         std::copy(other._pointer.getConstPointer(),other._pointer.getConstPointer()+other._nb_of_elem,pointer);
62         useArray(pointer,true,DeallocType::C_DEALLOC,other._nb_of_elem);
63       }
64   }
65
66   template<class T>
67   void MemArray<T>::useArray(const T *array, bool ownership, DeallocType type, std::size_t nbOfElem)
68   {
69     destroy();
70     _nb_of_elem=nbOfElem;
71     _nb_of_elem_alloc=nbOfElem;
72     if(ownership)
73       _pointer.setInternal(const_cast<T *>(array));
74     else
75       _pointer.setExternal(array);
76     _ownership=ownership;
77     _dealloc=BuildFromType(type);
78   }
79
80   template<class T>
81   void MemArray<T>::useExternalArrayWithRWAccess(const T *array, std::size_t nbOfElem)
82   {
83     destroy();
84     _nb_of_elem=nbOfElem;
85     _nb_of_elem_alloc=nbOfElem;
86     _pointer.setInternal(const_cast<T *>(array));
87     _ownership=false;
88     _dealloc=CPPDeallocator;
89   }
90
91   template<class T>
92   void MemArray<T>::writeOnPlace(std::size_t id, T element0, const T *others, std::size_t sizeOfOthers)
93   {
94     if(id+sizeOfOthers>=_nb_of_elem_alloc)
95       reserve(2*_nb_of_elem+sizeOfOthers+1);
96     T *pointer=_pointer.getPointer();
97     pointer[id]=element0;
98     std::copy(others,others+sizeOfOthers,pointer+id+1);
99     _nb_of_elem=std::max<std::size_t>(_nb_of_elem,id+sizeOfOthers+1);
100   }
101
102   template<class T>
103   void MemArray<T>::pushBack(T elem)
104   {
105     if(_nb_of_elem>=_nb_of_elem_alloc)
106       reserve(_nb_of_elem_alloc>0?2*_nb_of_elem_alloc:1);
107     T *pt=getPointer();
108     pt[_nb_of_elem++]=elem;
109   }
110
111   template<class T>
112   T MemArray<T>::popBack()
113   {
114     if(_nb_of_elem>0)
115       {
116         const T *pt=getConstPointer();
117         return pt[--_nb_of_elem];
118       }
119     throw INTERP_KERNEL::Exception("MemArray::popBack : nothing to pop in array !");
120   }
121
122   template<class T>
123   void MemArray<T>::pack() const
124   {
125     (const_cast<MemArray<T> * >(this))->reserve(_nb_of_elem);
126   }
127
128   template<class T>
129   bool MemArray<T>::isEqual(const MemArray<T>& other, T prec, std::string& reason) const
130   {
131     std::ostringstream oss; oss.precision(15);
132     if(_nb_of_elem!=other._nb_of_elem)
133       {
134         oss << "Number of elements in coarse data of DataArray mismatch : this=" << _nb_of_elem << " other=" << other._nb_of_elem;
135         reason=oss.str();
136         return false;
137       }
138     const T *pt1=_pointer.getConstPointer();
139     const T *pt2=other._pointer.getConstPointer();
140     if(pt1==0 && pt2==0)
141       return true;
142     if(pt1==0 || pt2==0)
143       {
144         oss << "coarse data pointer is defined for only one DataArray instance !";
145         reason=oss.str();
146         return false;
147       }
148     if(pt1==pt2)
149       return true;
150     for(std::size_t i=0;i<_nb_of_elem;i++)
151       if(pt1[i]-pt2[i]<-prec || (pt1[i]-pt2[i])>prec)
152         {
153           oss << "The content of data differs at pos #" << i << " of coarse data ! this[i]=" << pt1[i] << " other[i]=" << pt2[i];
154           reason=oss.str();
155           return false;
156         }
157     return true;
158   }
159
160   /*!
161    * \param [in] sl is typically the number of components
162    * \return True if a not null pointer is present, False if not.
163    */
164   template<class T>
165   bool MemArray<T>::reprHeader(mcIdType sl, std::ostream& stream) const
166   {
167     stream << "Number of tuples : ";
168     if(!_pointer.isNull())
169       {
170         if(sl!=0)
171           stream << _nb_of_elem/sl << std::endl << "Internal memory facts : " << _nb_of_elem << "/" << _nb_of_elem_alloc;
172         else
173           stream << "Empty Data";
174       }
175     else
176       stream << "No data";
177     stream << "\n";
178     stream << "Data content :\n";
179     bool ret=!_pointer.isNull();
180     if(!ret)
181       stream << "No data !\n";
182     return ret;
183   }
184
185   /*!
186    * \param [in] sl is typically the number of components
187    */
188   template<class T>
189   void MemArray<T>::repr(mcIdType sl, std::ostream& stream) const
190   {
191     if(reprHeader(sl,stream))
192       {
193         const T *data=getConstPointer();
194         if(_nb_of_elem!=0 && sl!=0)
195           {
196             std::size_t nbOfTuples=_nb_of_elem/std::abs(sl);
197             for(std::size_t i=0;i<nbOfTuples;i++)
198               {
199                 stream << "Tuple #" << i << " : ";
200                 std::copy(data,data+sl,std::ostream_iterator<T>(stream," "));
201                 stream << "\n";
202                 data+=sl;
203               }
204           }
205         else
206           stream << "Empty Data\n";
207       }
208   }
209
210   /*!
211    * \param [in] sl is typically the number of components
212    */
213   template<class T>
214   void MemArray<T>::reprZip(mcIdType sl, std::ostream& stream) const
215   {
216     stream << "Number of tuples : ";
217     if(!_pointer.isNull())
218       {
219         if(sl!=0)
220           stream << _nb_of_elem/sl;
221         else
222           stream << "Empty Data";
223       }
224     else
225       stream << "No data";
226     stream << "\n";
227     stream << "Data content : ";
228     const T *data=getConstPointer();
229     if(!_pointer.isNull())
230       {
231         if(_nb_of_elem!=0 && sl!=0)
232           {
233             std::size_t nbOfTuples=_nb_of_elem/std::abs(sl);
234             for(std::size_t i=0;i<nbOfTuples;i++)
235               {
236                 stream << "|";
237                 std::copy(data,data+sl,std::ostream_iterator<T>(stream," "));
238                 stream << "| ";
239                 data+=sl;
240               }
241             stream << "\n";
242           }
243         else
244           stream << "Empty Data\n";
245       }
246     else
247       stream << "No data !\n";
248   }
249
250   /*!
251    * \param [in] sl is typically the number of components
252    */
253   template<class T>
254   void MemArray<T>::reprNotTooLong(mcIdType sl, std::ostream& stream) const
255   {
256     if(reprHeader(sl,stream))
257       {
258         const T *data=getConstPointer();
259         if(_nb_of_elem!=0 && sl!=0)
260           {
261             std::size_t nbOfTuples=_nb_of_elem/std::abs(sl);
262             if(nbOfTuples<=1000)
263               {
264                 for(std::size_t i=0;i<nbOfTuples;i++)
265                   {
266                     stream << "Tuple #" << i << " : ";
267                     std::copy(data,data+sl,std::ostream_iterator<T>(stream," "));
268                     stream << "\n";
269                     data+=sl;
270                   }
271               }
272             else
273               {// too much tuples -> print the 3 first tuples and 3 last.
274                 stream << "Tuple #0 : ";
275                 std::copy(data,data+sl,std::ostream_iterator<T>(stream," ")); stream << "\n";
276                 stream << "Tuple #1 : ";
277                 std::copy(data+sl,data+2*sl,std::ostream_iterator<T>(stream," ")); stream << "\n";
278                 stream << "Tuple #2 : ";
279                 std::copy(data+2*sl,data+3*sl,std::ostream_iterator<T>(stream," ")); stream << "\n";
280                 stream << "...\n";
281                 stream << "Tuple #" << nbOfTuples-3 << " : ";
282                 std::copy(data+(nbOfTuples-3)*sl,data+(nbOfTuples-2)*sl,std::ostream_iterator<T>(stream," ")); stream << "\n";
283                 stream << "Tuple #" << nbOfTuples-2 << " : ";
284                 std::copy(data+(nbOfTuples-2)*sl,data+(nbOfTuples-1)*sl,std::ostream_iterator<T>(stream," ")); stream << "\n";
285                 stream << "Tuple #" << nbOfTuples-1 << " : ";
286                 std::copy(data+(nbOfTuples-1)*sl,data+nbOfTuples*sl,std::ostream_iterator<T>(stream," ")); stream << "\n";
287               }
288           }
289         else
290           stream << "Empty Data\n";
291       }
292   }
293
294   template<class T>
295   void MemArray<T>::fillWithValue(const T& val)
296   {
297     T *pt=_pointer.getPointer();
298     std::fill(pt,pt+_nb_of_elem,val);
299   }
300
301   template<class T>
302   T *MemArray<T>::fromNoInterlace(std::size_t nbOfComp) const
303   {
304     if(nbOfComp<1)
305       throw INTERP_KERNEL::Exception("MemArray<T>::fromNoInterlace : number of components must be > 0 !");
306     const T *pt=_pointer.getConstPointer();
307     std::size_t nbOfTuples=_nb_of_elem/nbOfComp;
308     T *ret=(T*)malloc(_nb_of_elem*sizeof(T));
309     T *w=ret;
310     for(std::size_t i=0;i<nbOfTuples;i++)
311       for(std::size_t j=0;j<nbOfComp;j++,w++)
312         *w=pt[j*nbOfTuples+i];
313     return ret;
314   }
315
316   template<class T>
317   T *MemArray<T>::toNoInterlace(std::size_t nbOfComp) const
318   {
319     if(nbOfComp<1)
320       throw INTERP_KERNEL::Exception("MemArray<T>::toNoInterlace : number of components must be > 0 !");
321     const T *pt=_pointer.getConstPointer();
322     std::size_t nbOfTuples=_nb_of_elem/nbOfComp;
323     T *ret=(T*)malloc(_nb_of_elem*sizeof(T));
324     T *w=ret;
325     for(std::size_t i=0;i<nbOfComp;i++)
326       for(std::size_t j=0;j<nbOfTuples;j++,w++)
327         *w=pt[j*nbOfComp+i];
328     return ret;
329   }
330
331   template<class T>
332   void MemArray<T>::sort(bool asc)
333   {
334     T *pt=_pointer.getPointer();
335     if(asc)
336       std::sort(pt,pt+_nb_of_elem);
337     else
338       {
339         typename std::reverse_iterator<T *> it1(pt+_nb_of_elem);
340         typename std::reverse_iterator<T *> it2(pt);
341         std::sort(it1,it2);
342       }
343   }
344
345   template<class T>
346   void MemArray<T>::reverse(std::size_t nbOfComp)
347   {
348     if(nbOfComp<1)
349       throw INTERP_KERNEL::Exception("MemArray<T>::reverse : only supported with 'this' array with ONE or more than ONE component !");
350     T *pt=_pointer.getPointer();
351     if(nbOfComp==1)
352       {
353         std::reverse(pt,pt+_nb_of_elem);
354         return ;
355       }
356     else
357       {
358         T *pt2=pt+_nb_of_elem-nbOfComp;
359         std::size_t nbOfTuples=_nb_of_elem/nbOfComp;
360         for(std::size_t i=0;i<nbOfTuples/2;i++,pt+=nbOfComp,pt2-=nbOfComp)
361           {
362             for(std::size_t j=0;j<nbOfComp;j++)
363               std::swap(pt[j],pt2[j]);
364           }
365       }
366   }
367
368   template<class T>
369   void MemArray<T>::alloc(std::size_t nbOfElements)
370   {
371     destroy();
372     _nb_of_elem=nbOfElements;
373     _nb_of_elem_alloc=nbOfElements;
374     _pointer.setInternal((T*)malloc(_nb_of_elem_alloc*sizeof(T)));
375     _ownership=true;
376     _dealloc=CDeallocator;
377   }
378
379   /*!
380    * This method performs systematically an allocation of \a newNbOfElements elements in \a this.
381    * \a _nb_of_elem and \a _nb_of_elem_alloc will \b NOT be systematically equal (contrary to MemArray<T>::reAlloc method.
382    * So after the call of this method \a _nb_of_elem will be equal tostd::min<std::size_t>(_nb_of_elem,newNbOfElements) and \a _nb_of_elem_alloc equal to
383    * \a newNbOfElements. This method is typically used to perform a pushBack to avoid systematic allocations-copy-deallocation.
384    * So after the call of this method the accessible content is perfectly set.
385    *
386    * So this method should not be confused with MemArray<T>::reserve that is close to MemArray<T>::reAlloc but not same.
387    */
388   template<class T>
389   void MemArray<T>::reserve(std::size_t newNbOfElements)
390   {
391     if(_nb_of_elem_alloc==newNbOfElements)
392       return ;
393     T *pointer=(T*)malloc(newNbOfElements*sizeof(T));
394     std::copy(_pointer.getConstPointer(),_pointer.getConstPointer()+std::min<std::size_t>(_nb_of_elem,newNbOfElements),pointer);
395     if(_ownership)
396       DestroyPointer(const_cast<T *>(_pointer.getConstPointer()),_dealloc,_param_for_deallocator);//Do not use getPointer because in case of _external
397     _pointer.setInternal(pointer);
398     _nb_of_elem=std::min<std::size_t>(_nb_of_elem,newNbOfElements);
399     _nb_of_elem_alloc=newNbOfElements;
400     _ownership=true;
401     _dealloc=CDeallocator;
402     _param_for_deallocator=0;
403   }
404
405   /*!
406    * This method performs systematically an allocation of \a newNbOfElements elements in \a this.
407    * \a _nb_of_elem and \a _nb_of_elem_alloc will be equal even if only std::min<std::size_t>(_nb_of_elem,newNbOfElements) come from the .
408    * The remaining part of the new allocated chunk are available but not set previously !
409    *
410    * So this method should not be confused with MemArray<T>::reserve that is close to MemArray<T>::reAlloc but not same.
411    */
412   template<class T>
413   void MemArray<T>::reAlloc(std::size_t newNbOfElements)
414   {
415     if(_nb_of_elem==newNbOfElements)
416       return ;
417     T *pointer=(T*)malloc(newNbOfElements*sizeof(T));
418     std::copy(_pointer.getConstPointer(),_pointer.getConstPointer()+std::min<std::size_t>(_nb_of_elem,newNbOfElements),pointer);
419     if(_ownership)
420       DestroyPointer(const_cast<T *>(_pointer.getConstPointer()),_dealloc,_param_for_deallocator);//Do not use getPointer because in case of _external
421     _pointer.setInternal(pointer);
422     _nb_of_elem=newNbOfElements;
423     _nb_of_elem_alloc=newNbOfElements;
424     _ownership=true;
425     _dealloc=CDeallocator;
426     _param_for_deallocator=0;
427   }
428
429   template<class T>
430   void MemArray<T>::CPPDeallocator(void *pt, void *param)
431   {
432     delete [] reinterpret_cast<T*>(pt);
433   }
434
435   template<class T>
436   void MemArray<T>::CDeallocator(void *pt, void *param)
437   {
438     free(pt);
439   }
440
441   template<class T>
442   void MemArray<T>::COffsetDeallocator(void *pt, void *param)
443   {
444     int64_t *offset(reinterpret_cast<int64_t *>(param));
445     char *ptcast(reinterpret_cast<char *>(pt));
446     free(ptcast+*offset);
447   }
448
449   template<class T>
450   typename MemArray<T>::Deallocator MemArray<T>::BuildFromType(DeallocType type)
451   {
452     switch(type)
453     {
454       case DeallocType::CPP_DEALLOC:
455         return CPPDeallocator;
456       case DeallocType::C_DEALLOC:
457         return CDeallocator;
458       case DeallocType::C_DEALLOC_WITH_OFFSET:
459         return COffsetDeallocator;
460       default:
461         throw INTERP_KERNEL::Exception("Invalid deallocation requested ! Unrecognized enum DeallocType !");
462     }
463   }
464
465   template<class T>
466   void MemArray<T>::DestroyPointer(T *pt, typename MemArray<T>::Deallocator dealloc, void *param)
467   {
468     if(dealloc)
469       dealloc(pt,param);
470   }
471
472   template<class T>
473   void MemArray<T>::destroy()
474   {
475     if(_ownership)
476       DestroyPointer(const_cast<T *>(_pointer.getConstPointer()),_dealloc,_param_for_deallocator);//Do not use getPointer because in case of _external
477     _pointer.null();
478     _ownership=false;
479     _dealloc=NULL;
480     _param_for_deallocator=NULL;
481     _nb_of_elem=0;
482     _nb_of_elem_alloc=0;
483   }
484
485   template<class T>
486   MemArray<T> &MemArray<T>::operator=(const MemArray<T>& other)
487   {
488     alloc(other._nb_of_elem);
489     std::copy(other._pointer.getConstPointer(),other._pointer.getConstPointer()+_nb_of_elem,_pointer.getPointer());
490     return *this;
491   }
492
493   //////////////////////////////////
494
495   template<class T>
496   DataArrayIterator<T>::DataArrayIterator(typename Traits<T>::ArrayType *da):_da(da),_tuple_id(0),_nb_comp(0),_nb_tuple(0)
497   {
498     if(_da)
499       {
500         _da->incrRef();
501         if(_da->isAllocated())
502           {
503             _nb_comp=da->getNumberOfComponents();
504             _nb_tuple=da->getNumberOfTuples();
505             _pt=da->getPointer();
506           }
507       }
508   }
509
510   template<class T>
511   DataArrayIterator<T>::~DataArrayIterator()
512   {
513     if(_da)
514       _da->decrRef();
515   }
516
517   template<class T>
518   typename Traits<T>::ArrayTuple *DataArrayIterator<T>::nextt()
519   {
520     if(_tuple_id<_nb_tuple)
521       {
522         _tuple_id++;
523         typename Traits<T>::ArrayTuple *ret=new typename Traits<T>::ArrayTuple(_pt,_nb_comp);
524         _pt+=_nb_comp;
525         return ret;
526       }
527     else
528       return 0;
529   }
530
531   //////////////////////////////////
532
533   template<class T>
534   DataArrayTuple<T>::DataArrayTuple(T *pt, std::size_t nbOfComp):_pt(pt),_nb_of_compo(nbOfComp)
535   {
536   }
537
538   template<class T>
539   T DataArrayTuple<T>::zeValue() const
540   {
541     if(_nb_of_compo==1)
542       return *_pt;
543     throw INTERP_KERNEL::Exception("DataArrayTuple<T>::zeValue : DataArrayTuple instance has not exactly 1 component -> Not possible to convert it into a single value !");
544   }
545
546   template<class T>
547   typename Traits<T>::ArrayType *DataArrayTuple<T>::buildDA(std::size_t nbOfTuples, std::size_t nbOfCompo) const
548   {
549     if((_nb_of_compo==nbOfCompo && nbOfTuples==1) || (_nb_of_compo==nbOfTuples && nbOfCompo==1))
550     {
551       typename Traits<T>::ArrayType *ret=Traits<T>::ArrayType::New();
552       ret->useExternalArrayWithRWAccess(_pt,nbOfTuples,nbOfCompo);
553       return ret;
554     }
555   else
556     {
557       std::ostringstream oss; oss << "DataArrayTuple<T>::buildDA : unable to build a requested DataArrayDouble instance with nbofTuple=" << nbOfTuples << " and nbOfCompo=" << nbOfCompo;
558       oss << ".\nBecause the number of elements in this is " << _nb_of_compo << " !";
559       throw INTERP_KERNEL::Exception(oss.str().c_str());
560     }
561   }
562
563   //////////////////////////////////
564
565   /*!
566    * This method is useful to slice work among a pool of threads or processes. \a begin, \a end \a step is the input whole slice of work to perform,
567    * typically it is a whole slice of tuples of DataArray or cells, nodes of a mesh...
568    *
569    * The input \a sliceId should be an id in [0, \a nbOfSlices) that specifies the slice of work.
570    *
571    * \param [in] start - the start of the input slice of the whole work to perform split into slices.
572    * \param [in] stop - the stop of the input slice of the whole work to perform split into slices.
573    * \param [in] step - the step (that can be <0) of the input slice of the whole work to perform split into slices.
574    * \param [in] sliceId - the slice id considered
575    * \param [in] nbOfSlices - the number of slices (typically the number of cores on which the work is expected to be sliced)
576    * \param [out] startSlice - the start of the slice considered
577    * \param [out] stopSlice - the stop of the slice consided
578    *
579    * \throw If \a step == 0
580    * \throw If \a nbOfSlices not > 0
581    * \throw If \a sliceId not in [0,nbOfSlices)
582    */
583   template <class T>
584   void DataArrayTools<T>::GetSlice(T start, T stop, T step, mcIdType sliceId, mcIdType nbOfSlices, T& startSlice, T& stopSlice)
585   {
586     if(nbOfSlices<=0)
587       {
588         std::ostringstream oss; oss << "DataArray::GetSlice : nbOfSlices (" << nbOfSlices << ") must be > 0 !";
589         throw INTERP_KERNEL::Exception(oss.str().c_str());
590       }
591     if(sliceId<0 || sliceId>=nbOfSlices)
592       {
593         std::ostringstream oss; oss << "DataArray::GetSlice : sliceId (" << nbOfSlices << ") must be in [0 , nbOfSlices (" << nbOfSlices << ") ) !";
594         throw INTERP_KERNEL::Exception(oss.str().c_str());
595       }
596     mcIdType nbElems=DataArrayTools<T>::GetNumberOfItemGivenBESRelative(start,stop,step,"DataArray::GetSlice");
597     mcIdType minNbOfElemsPerSlice=nbElems/nbOfSlices;
598     startSlice=start+minNbOfElemsPerSlice*step*sliceId;
599     if(sliceId<nbOfSlices-1)
600       stopSlice=start+minNbOfElemsPerSlice*step*(sliceId+1);
601     else
602       stopSlice=stop;
603   }
604
605   template <class T>
606   mcIdType DataArrayTools<T>::GetNumberOfItemGivenBES(T begin, T end, T step, const std::string& msg)
607   {
608     if(end<begin)
609       {
610         std::ostringstream oss; oss << msg << " : end before begin !";
611         throw INTERP_KERNEL::Exception(oss.str().c_str());
612       }
613     if(end==begin)
614       return 0;
615     if(step<=0)
616       {
617         std::ostringstream oss; oss << msg << " : invalid step should be > 0 !";
618         throw INTERP_KERNEL::Exception(oss.str().c_str());
619       }
620     return ToIdType((end-1-begin)/step+1);
621   }
622
623   template <class T>
624   mcIdType DataArrayTools<T>::GetNumberOfItemGivenBESRelative(T begin, T end, T step, const std::string& msg)
625   {
626     if(step==0)
627       throw INTERP_KERNEL::Exception("DataArray::GetNumberOfItemGivenBES : step=0 is not allowed !");
628     if(end<begin && step>0)
629       {
630         std::ostringstream oss; oss << msg << " : end before begin whereas step is positive !";
631         throw INTERP_KERNEL::Exception(oss.str().c_str());
632       }
633     if(begin<end && step<0)
634       {
635         std::ostringstream oss; oss << msg << " : invalid step should be > 0 !";
636         throw INTERP_KERNEL::Exception(oss.str().c_str());
637       }
638     if(begin!=end)
639       return ToIdType((std::max(begin,end)-1-std::min(begin,end))/std::abs(step)+1);
640     else
641       return 0;
642   }
643
644   template <class T>
645   mcIdType DataArrayTools<T>::GetPosOfItemGivenBESRelativeNoThrow(T value, T begin, T end, T step)
646   {
647     if (step == 0)
648       return -1;
649
650     if((step>0 && begin<=value && value<end) ||
651        (step<0 && begin>=value && value>end))
652     {
653       mcIdType id = ToIdType((value-begin)/step);
654       if (begin + step * id == value)
655         return id;
656       else
657         return -1;
658     }
659     else
660       return -1;
661   }
662
663   //////////////////////////////////
664
665   template<class T>
666   MCAuto< typename Traits<T>::ArrayTypeCh > DataArrayTemplate<T>::NewFromStdVector(const typename std::vector<T>& v)
667   {
668     std::size_t sz(v.size());
669     MCAuto< typename Traits<T>::ArrayTypeCh > ret(Traits<T>::ArrayTypeCh::New());
670     ret->alloc(sz,1);
671     T *pt(ret->getPointer());
672     std::copy(v.begin(),v.end(),pt);
673     return ret;
674   }
675
676   /*!
677    * Returns a newly created array containing a copy of the input array defined by [ \a arrBegin, \a arrEnd )
678    */
679   template<class T>
680   MCAuto< typename Traits<T>::ArrayTypeCh > DataArrayTemplate<T>::NewFromArray(const T *arrBegin, const T *arrEnd)
681   {
682     using DataArrayT = typename Traits<T>::ArrayTypeCh;
683     MCAuto< DataArrayT > ret(DataArrayT::New());
684     std::size_t nbElts(std::distance(arrBegin,arrEnd));
685     ret->alloc(nbElts,1);
686     std::copy(arrBegin,arrEnd,ret->getPointer());
687     return ret;
688   }
689
690   template<class T>
691   std::vector< MCAuto< typename Traits<T>::ArrayTypeCh > > DataArrayTemplate<T>::explodeComponents() const
692   {
693     checkAllocated();
694     std::size_t sz(getNumberOfComponents());
695     mcIdType nbTuples(getNumberOfTuples());
696     std::string name(getName());
697     std::vector<std::string> compNames(getInfoOnComponents());
698     std::vector< MCAuto< typename Traits<T>::ArrayTypeCh > > ret(sz);
699     const T *thisPt(begin());
700     for(std::size_t i=0;i<sz;i++)
701       {
702         MCAuto< typename Traits<T>::ArrayTypeCh > part(Traits<T>::ArrayTypeCh::New());
703         part->alloc(nbTuples,1);
704         part->setName(name);
705         part->setInfoOnComponent(0,compNames[i]);
706         T *otherPt(part->getPointer());
707         for(mcIdType j=0;j<nbTuples;j++)
708           otherPt[j]=thisPt[sz*j+i];
709         ret[i]=part;
710       }
711     return ret;
712   }
713
714   template<class T>
715   std::size_t DataArrayTemplate<T>::getHeapMemorySizeWithoutChildren() const
716   {
717     std::size_t sz(_mem.getNbOfElemAllocated());
718     sz*=sizeof(T);
719     return DataArray::getHeapMemorySizeWithoutChildren()+sz;
720   }
721
722   /*!
723    * Allocates the raw data in memory. If the memory was already allocated, then it is
724    * freed and re-allocated. See an example of this method use
725    * \ref MEDCouplingArraySteps1WC "here".
726    *  \param [in] nbOfTuple - number of tuples of data to allocate.
727    *  \param [in] nbOfCompo - number of components of data to allocate.
728    *  \throw If \a nbOfTuple < 0 or \a nbOfCompo < 0.
729    */
730   template<class T>
731   void DataArrayTemplate<T>::alloc(std::size_t nbOfTuple, std::size_t nbOfCompo)
732   {
733     _info_on_compo.resize(nbOfCompo);
734     _mem.alloc(nbOfCompo*nbOfTuple);
735     declareAsNew();
736   }
737
738   /*!
739    * Sets a C array to be used as raw data of \a this. The previously set info
740    *  of components is retained and re-sized.
741    * For more info see \ref MEDCouplingArraySteps1.
742    *  \param [in] array - the C array to be used as raw data of \a this.
743    *  \param [in] ownership - if \a true, \a array will be deallocated at destruction of \a this.
744    *  \param [in] type - specifies how to deallocate \a array. If \a type == MEDCoupling::CPP_DEALLOC,
745    *                     \c delete [] \c array; will be called. If \a type == MEDCoupling::C_DEALLOC,
746    *                     \c free(\c array ) will be called.
747    *  \param [in] nbOfTuple - new number of tuples in \a this.
748    *  \param [in] nbOfCompo - new number of components in \a this.
749    */
750   template<class T>
751   void DataArrayTemplate<T>::useArray(const T *array, bool ownership, DeallocType type, std::size_t nbOfTuple, std::size_t nbOfCompo)
752   {
753     _info_on_compo.resize(nbOfCompo);
754     _mem.useArray(array,ownership,type,nbOfTuple*nbOfCompo);
755     declareAsNew();
756   }
757
758   template<class T>
759   void DataArrayTemplate<T>::useExternalArrayWithRWAccess(const T *array, std::size_t nbOfTuple, std::size_t nbOfCompo)
760   {
761     _info_on_compo.resize(nbOfCompo);
762     _mem.useExternalArrayWithRWAccess(array,nbOfTuple*nbOfCompo);
763     declareAsNew();
764   }
765
766   /*!
767    * Returns a value located at specified tuple and component.
768    * This method is equivalent to DataArrayTemplate<T>::getIJ() except that validity of
769    * parameters is checked. So this method is safe but expensive if used to go through
770    * all values of \a this.
771    *  \param [in] tupleId - index of tuple of interest.
772    *  \param [in] compoId - index of component of interest.
773    *  \return double - value located by \a tupleId and \a compoId.
774    *  \throw If \a this is not allocated.
775    *  \throw If condition <em>( 0 <= tupleId < this->getNumberOfTuples() )</em> is violated.
776    *  \throw If condition <em>( 0 <= compoId < this->getNumberOfComponents() )</em> is violated.
777    */
778   template<class T>
779   T DataArrayTemplate<T>::getIJSafe(std::size_t tupleId, std::size_t compoId) const
780   {
781     checkAllocated();
782     if(ToIdType(tupleId)>=getNumberOfTuples())
783       {
784         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::getIJSafe : request for tupleId " << tupleId << " should be in [0," << getNumberOfTuples() << ") !";
785         throw INTERP_KERNEL::Exception(oss.str().c_str());
786       }
787     if(compoId>=getNumberOfComponents())
788       {
789         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::getIJSafe : request for compoId " << compoId << " should be in [0," << getNumberOfComponents() << ") !";
790         throw INTERP_KERNEL::Exception(oss.str().c_str());
791       }
792     return _mem[tupleId*_info_on_compo.size()+compoId];
793   }
794
795   /*!
796    * 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.
797    *
798    * \sa DataArray::getHeapMemorySizeWithoutChildren, DataArrayTemplate<T>::reserve
799    */
800   template<class T>
801   void DataArrayTemplate<T>::pack() const
802   {
803     _mem.pack();
804   }
805
806   /*!
807    * Checks if raw data is allocated. Read more on the raw data
808    * in \ref MEDCouplingArrayBasicsTuplesAndCompo "DataArrays infos" for more information.
809    *  \return bool - \a true if the raw data is allocated, \a false else.
810    */
811   template<class T>
812   bool DataArrayTemplate<T>::isAllocated() const
813   {
814     return getConstPointer()!=0;
815   }
816
817   /*!
818    * Checks if raw data is allocated and throws an exception if it is not the case.
819    *  \throw If the raw data is not allocated.
820    */
821   template<class T>
822   void DataArrayTemplate<T>::checkAllocated() const
823   {
824     if(!isAllocated())
825       {
826         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::checkAllocated : Array is defined but not allocated ! Call alloc or setValues method first !";
827         throw INTERP_KERNEL::Exception(oss.str().c_str());
828       }
829   }
830
831   /*!
832    * This method deallocated \a this without modification of information relative to the components.
833    * After call of this method, DataArrayDouble::isAllocated will return false.
834    * If \a this is already not allocated, \a this is let unchanged.
835    */
836   template<class T>
837   void DataArrayTemplate<T>::desallocate()
838   {
839     _mem.destroy();
840   }
841
842   /*!
843    * This method reserve nbOfElems elements in memory ( nbOfElems*sizeof(T) ) \b without impacting the number of tuples in \a this.
844    * 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.
845    * If \a this has not already been allocated, number of components is set to one.
846    * This method allows to reduce number of reallocations on invocation of DataArrayDouble::pushBackSilent and DataArrayDouble::pushBackValsSilent on \a this.
847    *
848    * \sa DataArrayDouble::pack, DataArrayDouble::pushBackSilent, DataArrayDouble::pushBackValsSilent
849    */
850   template<class T>
851   void DataArrayTemplate<T>::reserve(std::size_t nbOfElems)
852   {
853     std::size_t nbCompo(getNumberOfComponents());
854     if(nbCompo==1)
855       {
856         _mem.reserve(nbOfElems);
857       }
858     else if(nbCompo==0)
859       {
860         _mem.reserve(nbOfElems);
861         _info_on_compo.resize(1);
862       }
863     else
864       {
865         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::reserve : not available for DataArrayDouble with number of components different than 1 !";
866         throw INTERP_KERNEL::Exception(oss.str().c_str());
867       }
868   }
869
870   /*!
871    * 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
872    * of counter. So the caller is expected to call TimeLabel::declareAsNew on \a this at the end of the push session.
873    *
874    * \param [in] val the value to be added in \a this
875    * \throw If \a this has already been allocated with number of components different from one.
876    * \sa DataArrayDouble::pushBackValsSilent
877    */
878   template<class T>
879   void DataArrayTemplate<T>::pushBackSilent(T val)
880   {
881     std::size_t nbCompo(getNumberOfComponents());
882     if(nbCompo==1)
883       _mem.pushBack(val);
884     else if(nbCompo==0)
885       {
886         _info_on_compo.resize(1);
887         _mem.pushBack(val);
888       }
889     else
890       {
891         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::pushBackSilent : not available for DataArrayDouble with number of components different than 1 !";
892         throw INTERP_KERNEL::Exception(oss.str().c_str());
893       }
894   }
895
896   /*!
897    * This method adds at the end of \a this a series of values [\c valsBg,\c valsEnd). This method do \b not update its time label to avoid useless incrementation
898    * of counter. So the caller is expected to call TimeLabel::declareAsNew on \a this at the end of the push session.
899    *
900    *  \param [in] valsBg - an array of values to push at the end of \c this.
901    *  \param [in] valsEnd - specifies the end of the array \a valsBg, so that
902    *              the last value of \a valsBg is \a valsEnd[ -1 ].
903    * \throw If \a this has already been allocated with number of components different from one.
904    * \sa DataArrayDouble::pushBackSilent
905    */
906   template<class T>
907   void DataArrayTemplate<T>::pushBackValsSilent(const T *valsBg, const T *valsEnd)
908   {
909     std::size_t nbCompo(getNumberOfComponents());
910     if(nbCompo==1)
911       _mem.insertAtTheEnd(valsBg,valsEnd);
912     else if(nbCompo==0)
913       {
914         _info_on_compo.resize(1);
915         _mem.insertAtTheEnd(valsBg,valsEnd);
916       }
917     else
918       {
919         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::pushBackValsSilent : not available for DataArrayDouble with number of components different than 1 !";
920         throw INTERP_KERNEL::Exception(oss.str().c_str());
921       }
922   }
923
924   /*!
925    * This method returns silently ( without updating time label in \a this ) the last value, if any and suppress it.
926    * \throw If \a this is already empty.
927    * \throw If \a this has number of components different from one.
928    */
929   template<class T>
930   T DataArrayTemplate<T>::popBackSilent()
931   {
932     if(getNumberOfComponents()==1)
933       return _mem.popBack();
934     else
935       {
936         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::popBackSilent : not available for DataArrayDouble with number of components different than 1 !";
937         throw INTERP_KERNEL::Exception(oss.str().c_str());
938       }
939   }
940
941   /*!
942    * Allocates the raw data in memory. If exactly same memory as needed already
943    * allocated, it is not re-allocated.
944    *  \param [in] nbOfTuple - number of tuples of data to allocate.
945    *  \param [in] nbOfCompo - number of components of data to allocate.
946    *  \throw If \a nbOfTuple < 0 or \a nbOfCompo < 0.
947    */
948   template<class T>
949   void DataArrayTemplate<T>::allocIfNecessary(std::size_t nbOfTuple, std::size_t nbOfCompo)
950   {
951     if(isAllocated())
952       {
953         if(ToIdType(nbOfTuple)!=getNumberOfTuples() || nbOfCompo!=getNumberOfComponents())
954           alloc(nbOfTuple,nbOfCompo);
955       }
956     else
957       alloc(nbOfTuple,nbOfCompo);
958   }
959
960   /*!
961    * Checks the number of tuples.
962    *  \return bool - \a true if getNumberOfTuples() == 0, \a false else.
963    *  \throw If \a this is not allocated.
964    */
965   template<class T>
966   bool DataArrayTemplate<T>::empty() const
967   {
968     checkAllocated();
969     return getNumberOfTuples()==0;
970   }
971
972   /*!
973    * Copies all the data from another DataArrayDouble. For more info see
974    * \ref MEDCouplingArrayBasicsCopyDeepAssign.
975    *  \param [in] other - another instance of DataArrayDouble to copy data from.
976    *  \throw If the \a other is not allocated.
977    */
978   template<class T>
979   void DataArrayTemplate<T>::deepCopyFrom(const DataArrayTemplate<T>& other)
980   {
981     other.checkAllocated();
982     mcIdType nbOfTuples(other.getNumberOfTuples());
983     std::size_t nbOfComp(other.getNumberOfComponents());
984     allocIfNecessary(nbOfTuples,nbOfComp);
985     std::size_t nbOfElems(nbOfTuples*nbOfComp);
986     T *pt(getPointer());
987     const T *ptI(other.begin());
988     for(std::size_t i=0;i<nbOfElems;i++)
989       pt[i]=ptI[i];
990     copyStringInfoFrom(other);
991   }
992
993   /*!
994    * Reverse the array values.
995    *  \throw If \a this->getNumberOfComponents() < 1.
996    *  \throw If \a this is not allocated.
997    */
998   template<class T>
999   void DataArrayTemplate<T>::reverse()
1000   {
1001     checkAllocated();
1002     _mem.reverse(getNumberOfComponents());
1003     declareAsNew();
1004   }
1005
1006   /*!
1007    * Assign \a val to all values in \a this array. To know more on filling arrays see
1008    * \ref MEDCouplingArrayFill.
1009    *  \param [in] val - the value to fill with.
1010    *  \throw If \a this is not allocated.
1011    */
1012   template<class T>
1013   void DataArrayTemplate<T>::fillWithValue(T val)
1014   {
1015     checkAllocated();
1016     _mem.fillWithValue(val);
1017     declareAsNew();
1018   }
1019
1020   /*!
1021    * Changes number of tuples in the array. If the new number of tuples is smaller
1022    * than the current number the array is truncated, otherwise the array is extended.
1023    *  \param [in] nbOfTuples - new number of tuples.
1024    *  \throw If \a this is not allocated.
1025    *  \throw If \a nbOfTuples is negative.
1026    */
1027   template<class T>
1028   void DataArrayTemplate<T>::reAlloc(std::size_t nbOfTuples)
1029   {
1030     checkAllocated();
1031     _mem.reAlloc(getNumberOfComponents()*nbOfTuples);
1032     declareAsNew();
1033   }
1034
1035   /*!
1036    * Permutes values of \a this array as required by \a old2New array. The values are
1037    * permuted so that \c new[ \a old2New[ i ]] = \c old[ i ]. Number of tuples remains
1038    * the same as in \c this one.
1039    * If a permutation reduction is needed, subArray() or selectByTupleId() should be used.
1040    * For more info on renumbering see \ref numbering.
1041    *  \param [in] old2New - C array of length equal to \a this->getNumberOfTuples()
1042    *     giving a new position for i-th old value.
1043    */
1044   template<class T>
1045   void DataArrayTemplate<T>::renumberInPlace(const mcIdType *old2New)
1046   {
1047     checkAllocated();
1048     mcIdType nbTuples(getNumberOfTuples());
1049     std::size_t nbOfCompo(getNumberOfComponents());
1050     T *tmp(new T[nbTuples*nbOfCompo]);
1051     const T *iptr(begin());
1052     for(mcIdType i=0;i<nbTuples;i++)
1053       {
1054         mcIdType v=old2New[i];
1055         if(v>=0 && v<nbTuples)
1056           std::copy(iptr+nbOfCompo*i,iptr+nbOfCompo*(i+1),tmp+nbOfCompo*v);
1057         else
1058           {
1059             std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::renumberInPlace : At place #" << i << " value is " << v << " ! Should be in [0," << nbTuples << ") !";
1060             throw INTERP_KERNEL::Exception(oss.str().c_str());
1061           }
1062       }
1063     std::copy(tmp,tmp+nbTuples*nbOfCompo,getPointer());
1064     delete [] tmp;
1065     declareAsNew();
1066   }
1067
1068
1069   /*!
1070    * Permutes values of \a this array as required by \a new2Old array. The values are
1071    * permuted so that \c new[ i ] = \c old[ \a new2Old[ i ]]. Number of tuples remains
1072    * the same as in \c this one.
1073    * For more info on renumbering see \ref numbering.
1074    *  \param [in] new2Old - C array of length equal to \a this->getNumberOfTuples()
1075    *     giving a previous position of i-th new value.
1076    */
1077   template<class T>
1078   void DataArrayTemplate<T>::renumberInPlaceR(const mcIdType *new2Old)
1079   {
1080     checkAllocated();
1081     mcIdType nbTuples(getNumberOfTuples());
1082     std::size_t nbOfCompo(getNumberOfComponents());
1083     T *tmp(new T[nbTuples*nbOfCompo]);
1084     const T *iptr(begin());
1085     for(mcIdType i=0;i<nbTuples;i++)
1086       {
1087         mcIdType v=new2Old[i];
1088         if(v>=0 && v<nbTuples)
1089           std::copy(iptr+nbOfCompo*v,iptr+nbOfCompo*(v+1),tmp+nbOfCompo*i);
1090         else
1091           {
1092             std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::renumberInPlaceR : At place #" << i << " value is " << v << " ! Should be in [0," << nbTuples << ") !";
1093             throw INTERP_KERNEL::Exception(oss.str().c_str());
1094           }
1095       }
1096     std::copy(tmp,tmp+nbTuples*nbOfCompo,getPointer());
1097     delete [] tmp;
1098     declareAsNew();
1099   }
1100
1101   /*!
1102    * Sorts values of the array. \b Warning, this method is not const, it alterates \a this content.
1103    *
1104    *  \param [in] asc - \a true means ascending order, \a false, descending.
1105    *  \throw If \a this is not allocated.
1106    *  \throw If \a this->getNumberOfComponents() != 1.
1107    *  \sa copySorted
1108    */
1109   template<class T>
1110   void DataArrayTemplate<T>::sort(bool asc)
1111   {
1112     checkAllocated();
1113     if(getNumberOfComponents()!=1)
1114       {
1115         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::sort : only supported with 'this' array with ONE component !";
1116         throw INTERP_KERNEL::Exception(oss.str().c_str());
1117       }
1118     _mem.sort(asc);
1119     declareAsNew();
1120   }
1121
1122   /*!
1123    * Sorts values of the array and put the result in a newly allocated returned array.
1124    * This method does not alterate \a this content.
1125    *
1126    *  \param [in] asc - \a true means ascending order, \a false, descending.
1127    *  \throw If \a this is not allocated.
1128    *  \throw If \a this->getNumberOfComponents() != 1.
1129    *  \sa sort
1130    */
1131   template<class T>
1132   typename Traits<T>::ArrayTypeCh *DataArrayTemplate<T>::copySortedImpl(bool asc) const
1133   {
1134     MCAuto<typename Traits<T>::ArrayTypeCh> ret(static_cast<typename Traits<T>::ArrayTypeCh *>(this->deepCopy()));
1135     ret->sort(asc);
1136     return ret.retn();
1137   }
1138
1139   /*!
1140    * Returns a copy of \a this array with values permuted as required by \a old2New array.
1141    * The values are permuted so that  \c new[ \a old2New[ i ]] = \c old[ i ].
1142    * Number of tuples in the result array remains the same as in \c this one.
1143    * If a permutation reduction is needed, renumberAndReduce() should be used.
1144    * For more info on renumbering see \ref numbering.
1145    *  \param [in] old2New - C array of length equal to \a this->getNumberOfTuples()
1146    *          giving a new position for i-th old value.
1147    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1148    *          is to delete using decrRef() as it is no more needed.
1149    *  \throw If \a this is not allocated.
1150    */
1151   template<class T>
1152   typename Traits<T>::ArrayType *DataArrayTemplate<T>::renumber(const mcIdType *old2New) const
1153   {
1154     checkAllocated();
1155     mcIdType nbTuples(getNumberOfTuples());
1156     std::size_t nbOfCompo(getNumberOfComponents());
1157     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1158     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1159     ret->alloc(nbTuples,nbOfCompo);
1160     ret->copyStringInfoFrom(*this);
1161     const T *iptr(begin());
1162     T *optr(ret->getPointer());
1163     for(mcIdType i=0;i<nbTuples;i++)
1164       std::copy(iptr+nbOfCompo*i,iptr+nbOfCompo*(i+1),optr+nbOfCompo*old2New[i]);
1165     ret->copyStringInfoFrom(*this);
1166     return ret.retn();
1167   }
1168
1169   /*!
1170    * Returns a copy of \a this array with values permuted as required by \a new2Old array.
1171    * The values are permuted so that  \c new[ i ] = \c old[ \a new2Old[ i ]]. Number of
1172    * tuples in the result array remains the same as in \c this one.
1173    * If a permutation reduction is needed, subArray() or selectByTupleId() should be used.
1174    * For more info on renumbering see \ref numbering.
1175    *  \param [in] new2Old - C array of length equal to \a this->getNumberOfTuples()
1176    *     giving a previous position of i-th new value.
1177    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1178    *          is to delete using decrRef() as it is no more needed.
1179    */
1180   template<class T>
1181   typename Traits<T>::ArrayType *DataArrayTemplate<T>::renumberR(const mcIdType *new2Old) const
1182   {
1183     checkAllocated();
1184     mcIdType nbTuples(getNumberOfTuples());
1185     std::size_t nbOfCompo(getNumberOfComponents());
1186     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1187     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1188     ret->alloc(nbTuples,nbOfCompo);
1189     ret->copyStringInfoFrom(*this);
1190     const T *iptr(getConstPointer());
1191     T *optr(ret->getPointer());
1192     for(mcIdType i=0;i<nbTuples;i++)
1193       std::copy(iptr+nbOfCompo*new2Old[i],iptr+nbOfCompo*(new2Old[i]+1),optr+i*nbOfCompo);
1194     ret->copyStringInfoFrom(*this);
1195     return ret.retn();
1196   }
1197
1198   /*!
1199    * Returns a shorten and permuted copy of \a this array. The new DataArrayDouble is
1200    * of size \a newNbOfTuple and it's values are permuted as required by \a old2New array.
1201    * The values are permuted so that  \c new[ \a old2New[ i ]] = \c old[ i ] for all
1202    * \a old2New[ i ] >= 0. In other words every i-th tuple in \a this array, for which
1203    * \a old2New[ i ] is negative, is missing from the result array.
1204    * For more info on renumbering see \ref numbering.
1205    *  \param [in] old2New - C array of length equal to \a this->getNumberOfTuples()
1206    *     giving a new position for i-th old tuple and giving negative position for
1207    *     for i-th old tuple that should be omitted.
1208    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1209    *          is to delete using decrRef() as it is no more needed.
1210    */
1211   template<class T>
1212   typename Traits<T>::ArrayType *DataArrayTemplate<T>::renumberAndReduce(const mcIdType *old2New, mcIdType newNbOfTuple) const
1213   {
1214     checkAllocated();
1215     mcIdType nbTuples(getNumberOfTuples());
1216     std::size_t nbOfCompo(getNumberOfComponents());
1217     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1218     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1219     ret->alloc(newNbOfTuple,nbOfCompo);
1220     const T *iptr=getConstPointer();
1221     T *optr=ret->getPointer();
1222     for(mcIdType i=0;i<nbTuples;i++)
1223       {
1224         mcIdType w=old2New[i];
1225         if(w>=0)
1226           std::copy(iptr+i*nbOfCompo,iptr+(i+1)*nbOfCompo,optr+w*nbOfCompo);
1227       }
1228     ret->copyStringInfoFrom(*this);
1229     return ret.retn();
1230   }
1231
1232   /*!
1233    * Returns a shorten and permuted copy of \a this array. The new DataArrayDouble is
1234    * of size \a new2OldEnd - \a new2OldBg and it's values are permuted as required by
1235    * \a new2OldBg array.
1236    * The values are permuted so that  \c new[ i ] = \c old[ \a new2OldBg[ i ]].
1237    * This method is equivalent to renumberAndReduce() except that convention in input is
1238    * \c new2old and \b not \c old2new.
1239    * For more info on renumbering see \ref numbering.
1240    *  \param [in] new2OldBg - pointer to the beginning of a permutation array that gives a
1241    *              tuple index in \a this array to fill the i-th tuple in the new array.
1242    *  \param [in] new2OldEnd - specifies the end of the permutation array that starts at
1243    *              \a new2OldBg, so that pointer to a tuple index (\a pi) varies as this:
1244    *              \a new2OldBg <= \a pi < \a new2OldEnd.
1245    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1246    *          is to delete using decrRef() as it is no more needed.
1247    */
1248   template<class T>
1249   typename Traits<T>::ArrayType *DataArrayTemplate<T>::mySelectByTupleId(const mcIdType *new2OldBg, const mcIdType *new2OldEnd) const
1250   {
1251     checkAllocated();
1252     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1253     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1254     std::size_t nbComp(getNumberOfComponents());
1255     ret->alloc(std::distance(new2OldBg,new2OldEnd),nbComp);
1256     ret->copyStringInfoFrom(*this);
1257     T *pt(ret->getPointer());
1258     const T *srcPt(getConstPointer());
1259     std::size_t i(0);
1260     for(const mcIdType *w=new2OldBg;w!=new2OldEnd;w++,i++)
1261       std::copy(srcPt+(*w)*nbComp,srcPt+((*w)+1)*nbComp,pt+i*nbComp);
1262     ret->copyStringInfoFrom(*this);
1263     return ret.retn();
1264   }
1265
1266   template<class T>
1267   typename Traits<T>::ArrayType *DataArrayTemplate<T>::mySelectByTupleId(const DataArrayIdType& di) const
1268   {
1269     return this->mySelectByTupleId(di.begin(),di.end());
1270   }
1271
1272   template<class T>
1273   MCAuto<typename Traits<T>::ArrayTypeCh> DataArrayTemplate<T>::selectPartDef(const PartDefinition *pd) const
1274   {
1275     if(!pd)
1276       throw INTERP_KERNEL::Exception("DataArrayTemplate<T>::selectPartDef : null input pointer !");
1277     MCAuto<typename Traits<T>::ArrayTypeCh> ret(Traits<T>::ArrayTypeCh::New());
1278     const SlicePartDefinition *spd(dynamic_cast<const SlicePartDefinition *>(pd));
1279     if(spd)
1280       {
1281         mcIdType a,b,c;
1282         spd->getSlice(a,b,c);
1283         if(a==0 && b==getNumberOfTuples() && c==1)
1284           {
1285             DataArrayTemplate<T> *directRet(const_cast<DataArrayTemplate<T> *>(this));
1286             directRet->incrRef();
1287             MCAuto<DataArrayTemplate<T> > ret2(directRet);
1288             return DynamicCastSafe<DataArrayTemplate<T>,typename Traits<T>::ArrayTypeCh>(ret2);
1289           }
1290         else
1291           {
1292             MCAuto<DataArray> ret2(selectByTupleIdSafeSlice(a,b,c));
1293             return DynamicCastSafe<DataArray,typename Traits<T>::ArrayTypeCh>(ret2);
1294           }
1295       }
1296     const DataArrayPartDefinition *dpd(dynamic_cast<const DataArrayPartDefinition *>(pd));
1297     if(dpd)
1298       {
1299         MCAuto<DataArrayIdType> arr(dpd->toDAI());
1300         MCAuto<DataArray> ret2(selectByTupleIdSafe(arr->begin(),arr->end()));
1301         return DynamicCastSafe<DataArray,typename Traits<T>::ArrayTypeCh>(ret2);
1302
1303       }
1304     throw INTERP_KERNEL::Exception("DataArrayTemplate<T>::selectPartDef : unrecognized part def !");
1305   }
1306
1307   /*!
1308    * Returns a shorten and permuted copy of \a this array. The new DataArrayDouble is
1309    * of size \a new2OldEnd - \a new2OldBg and it's values are permuted as required by
1310    * \a new2OldBg array.
1311    * The values are permuted so that  \c new[ i ] = \c old[ \a new2OldBg[ i ]].
1312    * This method is equivalent to renumberAndReduce() except that convention in input is
1313    * \c new2old and \b not \c old2new.
1314    * This method is equivalent to selectByTupleId() except that it prevents coping data
1315    * from behind the end of \a this array.
1316    * For more info on renumbering see \ref numbering.
1317    *  \param [in] new2OldBg - pointer to the beginning of a permutation array that gives a
1318    *              tuple index in \a this array to fill the i-th tuple in the new array.
1319    *  \param [in] new2OldEnd - specifies the end of the permutation array that starts at
1320    *              \a new2OldBg, so that pointer to a tuple index (\a pi) varies as this:
1321    *              \a new2OldBg <= \a pi < \a new2OldEnd.
1322    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1323    *          is to delete using decrRef() as it is no more needed.
1324    *  \throw If \a new2OldEnd - \a new2OldBg > \a this->getNumberOfTuples().
1325    */
1326   template<class T>
1327   typename Traits<T>::ArrayType *DataArrayTemplate<T>::mySelectByTupleIdSafe(const mcIdType *new2OldBg, const mcIdType *new2OldEnd) const
1328   {
1329     checkAllocated();
1330     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1331     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1332     std::size_t nbComp(getNumberOfComponents());
1333     mcIdType oldNbOfTuples(getNumberOfTuples());
1334     ret->alloc(std::distance(new2OldBg,new2OldEnd),nbComp);
1335     ret->copyStringInfoFrom(*this);
1336     T *pt(ret->getPointer());
1337     const T *srcPt(getConstPointer());
1338     mcIdType i(0);
1339     for(const mcIdType *w=new2OldBg;w!=new2OldEnd;w++,i++)
1340       if(*w>=0 && *w<oldNbOfTuples)
1341         std::copy(srcPt+(*w)*nbComp,srcPt+((*w)+1)*nbComp,pt+i*nbComp);
1342       else
1343         {
1344           std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::selectByTupleIdSafe : some ids has been detected to be out of [0,this->getNumberOfTuples) !";
1345           throw INTERP_KERNEL::Exception(oss.str().c_str());
1346         }
1347     ret->copyStringInfoFrom(*this);
1348     return ret.retn();
1349   }
1350
1351   /*!
1352    * Changes the number of components within \a this array so that its raw data **does
1353    * not** change, instead splitting this data into tuples changes.
1354    *  \warning This method erases all (name and unit) component info set before!
1355    *  \param [in] newNbOfCompo - number of components for \a this array to have.
1356    *  \throw If \a this is not allocated
1357    *  \throw If getNbOfElems() % \a newNbOfCompo != 0.
1358    *  \throw If \a newNbOfCompo is lower than 1.
1359    *  \throw If the rearrange method would lead to a number of tuples higher than 2147483647 (maximal capacity of int32 !).
1360    *  \warning This method erases all (name and unit) component info set before!
1361    */
1362   template<class T>
1363   void DataArrayTemplate<T>::rearrange(std::size_t newNbOfCompo)
1364   {
1365     checkAllocated();
1366     if(newNbOfCompo<1)
1367       {
1368         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::rearrange : input newNbOfCompo must be > 0 !";
1369         throw INTERP_KERNEL::Exception(oss.str().c_str());
1370       }
1371     std::size_t nbOfElems=getNbOfElems();
1372     if(nbOfElems%newNbOfCompo!=0)
1373       {
1374         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::rearrange : nbOfElems%newNbOfCompo!=0 !";
1375         throw INTERP_KERNEL::Exception(oss.str().c_str());
1376       }
1377     if(nbOfElems/newNbOfCompo>(std::size_t)std::numeric_limits<mcIdType>::max())
1378       {
1379         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::rearrange : the rearrangement leads to too high number of tuples (> 2147483647) !";
1380         throw INTERP_KERNEL::Exception(oss.str().c_str());
1381       }
1382     _info_on_compo.clear();
1383     _info_on_compo.resize(newNbOfCompo);
1384     declareAsNew();
1385   }
1386
1387   /*!
1388    * Changes the number of components within \a this array to be equal to its number
1389    * of tuples, and inversely its number of tuples to become equal to its number of
1390    * components. So that its raw data **does not** change, instead splitting this
1391    * data into tuples changes.
1392    *  \warning This method erases all (name and unit) component info set before!
1393    *  \warning Do not confuse this method with fromNoInterlace() and toNoInterlace()!
1394    *  \throw If \a this is not allocated.
1395    *  \sa rearrange()
1396    */
1397   template<class T>
1398   void DataArrayTemplate<T>::transpose()
1399   {
1400     checkAllocated();
1401     rearrange(getNumberOfTuples());
1402   }
1403
1404   /*!
1405    * Returns a shorten or extended copy of \a this array. If \a newNbOfComp is less
1406    * than \a this->getNumberOfComponents() then the result array is shorten as each tuple
1407    * is truncated to have \a newNbOfComp components, keeping first components. If \a
1408    * newNbOfComp is more than \a this->getNumberOfComponents() then the result array is
1409    * expanded as each tuple is populated with \a dftValue to have \a newNbOfComp
1410    * components.
1411    *  \param [in] newNbOfComp - number of components for the new array to have.
1412    *  \param [in] dftValue - value assigned to new values added to the new array.
1413    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1414    *          is to delete using decrRef() as it is no more needed.
1415    *  \throw If \a this is not allocated.
1416    */
1417   template<class T>
1418   typename Traits<T>::ArrayType *DataArrayTemplate<T>::changeNbOfComponents(std::size_t newNbOfComp, T dftValue) const
1419   {
1420     checkAllocated();
1421     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1422     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1423     ret->alloc(getNumberOfTuples(),newNbOfComp);
1424     const T *oldc(getConstPointer());
1425     T *nc(ret->getPointer());
1426     mcIdType nbOfTuples=getNumberOfTuples();
1427     std::size_t oldNbOfComp=getNumberOfComponents();
1428     std::size_t dim(std::min(oldNbOfComp,newNbOfComp));
1429     for(mcIdType i=0;i<nbOfTuples;i++)
1430       {
1431         std::size_t j=0;
1432         for(;j<dim;j++)
1433           nc[newNbOfComp*i+j]=oldc[i*oldNbOfComp+j];
1434         for(;j<newNbOfComp;j++)
1435           nc[newNbOfComp*i+j]=dftValue;
1436       }
1437     ret->setName(getName());
1438     for(std::size_t i=0;i<dim;i++)
1439       ret->setInfoOnComponent(i,getInfoOnComponent(i));
1440     ret->setName(getName());
1441     return ret.retn();
1442   }
1443
1444   /*!
1445    * Returns a copy of \a this array composed of selected components.
1446    * The new DataArrayDouble has the same number of tuples but includes components
1447    * specified by \a compoIds parameter. So that getNbOfElems() of the result array
1448    * can be either less, same or more than \a this->getNbOfElems().
1449    *  \param [in] compoIds - sequence of zero based indices of components to include
1450    *              into the new array.
1451    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1452    *          is to delete using decrRef() as it is no more needed.
1453    *  \throw If \a this is not allocated.
1454    *  \throw If a component index (\a i) is not valid:
1455    *         \a i < 0 || \a i >= \a this->getNumberOfComponents().
1456    *
1457    *  \if ENABLE_EXAMPLES
1458    *  \ref py_mcdataarraydouble_KeepSelectedComponents "Here is a Python example".
1459    *  \endif
1460    */
1461   template<class T>
1462   typename Traits<T>::ArrayType *DataArrayTemplate<T>::myKeepSelectedComponents(const std::vector<std::size_t>& compoIds) const
1463   {
1464     checkAllocated();
1465     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1466     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1467     std::size_t newNbOfCompo=compoIds.size();
1468     std::size_t oldNbOfCompo=getNumberOfComponents();
1469     for(std::vector<std::size_t>::const_iterator it=compoIds.begin();it!=compoIds.end();it++)
1470       if((*it)>=oldNbOfCompo)  // (*it) >= 0 (it is a size_t)
1471         {
1472           std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::keepSelectedComponents : invalid requested component : " << *it << " whereas it should be in [0," << oldNbOfCompo << ") !";
1473           throw INTERP_KERNEL::Exception(oss.str().c_str());
1474         }
1475     mcIdType nbOfTuples(getNumberOfTuples());
1476     ret->alloc(nbOfTuples,newNbOfCompo);
1477     ret->copyPartOfStringInfoFrom(*this,compoIds);
1478     const T *oldc(getConstPointer());
1479     T *nc(ret->getPointer());
1480     for(mcIdType i=0;i<nbOfTuples;i++)
1481       for(std::size_t j=0;j<newNbOfCompo;j++,nc++)
1482         *nc=oldc[i*oldNbOfCompo+compoIds[j]];
1483     return ret.retn();
1484   }
1485
1486   /*!
1487    * Returns a shorten copy of \a this array. The new DataArrayDouble contains all
1488    * tuples starting from the \a tupleIdBg-th tuple and including all tuples located before
1489    * the \a tupleIdEnd-th one. This methods has a similar behavior as std::string::substr().
1490    * This method is a specialization of selectByTupleIdSafeSlice().
1491    *  \param [in] tupleIdBg - index of the first tuple to copy from \a this array.
1492    *  \param [in] tupleIdEnd - index of the tuple before which the tuples to copy are located.
1493    *          If \a tupleIdEnd == -1, all the tuples till the end of \a this array are copied.
1494    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1495    *          is to delete using decrRef() as it is no more needed.
1496    *  \throw If \a tupleIdBg < 0.
1497    *  \throw If \a tupleIdBg > \a this->getNumberOfTuples().
1498    *  \throw If \a tupleIdEnd != -1 && \a tupleIdEnd < \a this->getNumberOfTuples().
1499    *  \sa DataArrayDouble::selectByTupleIdSafeSlice
1500    */
1501   template<class T>
1502   typename Traits<T>::ArrayType *DataArrayTemplate<T>::subArray(mcIdType tupleIdBg, mcIdType tupleIdEnd) const
1503   {
1504     checkAllocated();
1505     mcIdType nbt=getNumberOfTuples();
1506     if(tupleIdBg<0)
1507       {
1508         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::subArray : The tupleIdBg parameter must be greater than 0 !";
1509         throw INTERP_KERNEL::Exception(oss.str().c_str());
1510       }
1511     if(tupleIdBg>nbt)
1512       {
1513         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << ":subArray : The tupleIdBg parameter is greater than number of tuples !";
1514         throw INTERP_KERNEL::Exception(oss.str().c_str());
1515       }
1516     mcIdType trueEnd=tupleIdEnd;
1517     if(tupleIdEnd!=-1)
1518       {
1519         if(tupleIdEnd>nbt)
1520           {
1521             std::ostringstream oss; oss << Traits<T>::ArrayTypeName << ":subArray : The tupleIdBg parameter is greater than number of tuples !";
1522             throw INTERP_KERNEL::Exception(oss.str().c_str());
1523           }
1524       }
1525     else
1526       trueEnd=nbt;
1527     std::size_t nbComp=getNumberOfComponents();
1528     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1529     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1530     ret->alloc(trueEnd-tupleIdBg,nbComp);
1531     ret->copyStringInfoFrom(*this);
1532     std::copy(getConstPointer()+tupleIdBg*nbComp,getConstPointer()+trueEnd*nbComp,ret->getPointer());
1533     return ret.retn();
1534   }
1535
1536   /*!
1537    * Returns a shorten copy of \a this array. The new DataArrayDouble contains every
1538    * (\a bg + \c i * \a step)-th tuple of \a this array located before the \a end2-th
1539    * tuple. Indices of the selected tuples are the same as ones returned by the Python
1540    * command \c range( \a bg, \a end2, \a step ).
1541    * This method is equivalent to selectByTupleIdSafe() except that the input array is
1542    * not constructed explicitly.
1543    * For more info on renumbering see \ref numbering.
1544    *  \param [in] bg - index of the first tuple to copy from \a this array.
1545    *  \param [in] end2 - index of the tuple before which the tuples to copy are located.
1546    *  \param [in] step - index increment to get index of the next tuple to copy.
1547    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1548    *          is to delete using decrRef() as it is no more needed.
1549    *  \sa DataArrayDouble::subArray.
1550    */
1551   template<class T>
1552   typename Traits<T>::ArrayType *DataArrayTemplate<T>::mySelectByTupleIdSafeSlice(mcIdType bg, mcIdType end2, mcIdType step) const
1553   {
1554     checkAllocated();
1555     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1556     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1557     std::size_t nbComp(getNumberOfComponents());
1558     std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::selectByTupleIdSafeSlice : ";
1559     mcIdType newNbOfTuples(GetNumberOfItemGivenBESRelative(bg,end2,step,oss.str()));
1560     ret->alloc(newNbOfTuples,nbComp);
1561     T *pt(ret->getPointer());
1562     const T *srcPt(getConstPointer()+bg*nbComp);
1563     for(mcIdType i=0;i<newNbOfTuples;i++,srcPt+=step*nbComp)
1564       std::copy(srcPt,srcPt+nbComp,pt+i*nbComp);
1565     ret->copyStringInfoFrom(*this);
1566     return ret.retn();
1567   }
1568
1569   /*!
1570    * Copy all values from another DataArrayDouble into specified tuples and components
1571    * of \a this array. Textual data is not copied.
1572    * The tree parameters defining set of indices of tuples and components are similar to
1573    * the tree parameters of the Python function \c range(\c start,\c stop,\c step).
1574    *  \param [in] a - the array to copy values from.
1575    *  \param [in] bgTuples - index of the first tuple of \a this array to assign values to.
1576    *  \param [in] endTuples - index of the tuple before which the tuples to assign to
1577    *              are located.
1578    *  \param [in] stepTuples - index increment to get index of the next tuple to assign to.
1579    *  \param [in] bgComp - index of the first component of \a this array to assign values to.
1580    *  \param [in] endComp - index of the component before which the components to assign
1581    *              to are located.
1582    *  \param [in] stepComp - index increment to get index of the next component to assign to.
1583    *  \param [in] strictCompoCompare - if \a true (by default), then \a a->getNumberOfComponents()
1584    *              must be equal to the number of columns to assign to, else an
1585    *              exception is thrown; if \a false, then it is only required that \a
1586    *              a->getNbOfElems() equals to number of values to assign to (this condition
1587    *              must be respected even if \a strictCompoCompare is \a true). The number of
1588    *              values to assign to is given by following Python expression:
1589    *              \a nbTargetValues =
1590    *              \c len(\c range(\a bgTuples,\a endTuples,\a stepTuples)) *
1591    *              \c len(\c range(\a bgComp,\a endComp,\a stepComp)).
1592    *  \throw If \a a is NULL.
1593    *  \throw If \a a is not allocated.
1594    *  \throw If \a this is not allocated.
1595    *  \throw If parameters specifying tuples and components to assign to do not give a
1596    *            non-empty range of increasing indices.
1597    *  \throw If \a a->getNbOfElems() != \a nbTargetValues.
1598    *  \throw If \a strictCompoCompare == \a true && \a a->getNumberOfComponents() !=
1599    *            \c len(\c range(\a bgComp,\a endComp,\a stepComp)).
1600    *
1601    *  \if ENABLE_EXAMPLES
1602    *  \ref py_mcdataarraydouble_setpartofvalues1 "Here is a Python example".
1603    *  \endif
1604    */
1605   template<class T>
1606   void DataArrayTemplate<T>::setPartOfValues1(const typename Traits<T>::ArrayType *a, mcIdType bgTuples, mcIdType endTuples, mcIdType stepTuples, mcIdType bgComp, mcIdType endComp, mcIdType stepComp, bool strictCompoCompare)
1607   {
1608     if(!a)
1609       {
1610         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::setPartOfValues1 : input DataArrayDouble is NULL !";
1611         throw INTERP_KERNEL::Exception(oss.str().c_str());
1612       }
1613     const char msg[]="DataArrayTemplate::setPartOfValues1";
1614     checkAllocated();
1615     a->checkAllocated();
1616     mcIdType newNbOfTuples(DataArray::GetNumberOfItemGivenBES(bgTuples,endTuples,stepTuples,msg));
1617     mcIdType newNbOfComp(DataArray::GetNumberOfItemGivenBES(bgComp,endComp,stepComp,msg));
1618     std::size_t nbComp(getNumberOfComponents());
1619     mcIdType nbOfTuples(getNumberOfTuples());
1620     DataArray::CheckValueInRangeEx(nbOfTuples,bgTuples,endTuples,"invalid tuple value");
1621     DataArray::CheckValueInRangeEx(ToIdType(nbComp),bgComp,endComp,"invalid component value");
1622     bool assignTech(true);
1623     if(a->getNbOfElems()==newNbOfTuples*newNbOfComp)
1624       {
1625         if(strictCompoCompare)
1626           a->checkNbOfTuplesAndComp(newNbOfTuples,newNbOfComp,msg);
1627       }
1628     else
1629       {
1630         a->checkNbOfTuplesAndComp(1,newNbOfComp,msg);
1631         assignTech=false;
1632       }
1633     const T *srcPt(a->getConstPointer());
1634     T *pt(getPointer()+bgTuples*nbComp+bgComp);
1635     if(assignTech)
1636       {
1637         for(mcIdType i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
1638           for(mcIdType j=0;j<newNbOfComp;j++,srcPt++)
1639             pt[j*stepComp]=*srcPt;
1640       }
1641     else
1642       {
1643         for(mcIdType i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
1644           {
1645             const T*srcPt2=srcPt;
1646             for(mcIdType j=0;j<newNbOfComp;j++,srcPt2++)
1647               pt[j*stepComp]=*srcPt2;
1648           }
1649       }
1650   }
1651
1652   /*!
1653  * Assign a given value to values at specified tuples and components of \a this array.
1654  * The tree parameters defining set of indices of tuples and components are similar to
1655  * the tree parameters of the Python function \c range(\c start,\c stop,\c step)..
1656  *  \param [in] a - the value to assign.
1657  *  \param [in] bgTuples - index of the first tuple of \a this array to assign to.
1658  *  \param [in] endTuples - index of the tuple before which the tuples to assign to
1659  *              are located.
1660  *  \param [in] stepTuples - index increment to get index of the next tuple to assign to.
1661  *  \param [in] bgComp - index of the first component of \a this array to assign to.
1662  *  \param [in] endComp - index of the component before which the components to assign
1663  *              to are located.
1664  *  \param [in] stepComp - index increment to get index of the next component to assign to.
1665  *  \throw If \a this is not allocated.
1666  *  \throw If parameters specifying tuples and components to assign to, do not give a
1667  *            non-empty range of increasing indices or indices are out of a valid range
1668  *            for \c this array.
1669  *
1670  *  \if ENABLE_EXAMPLES
1671  *  \ref py_mcdataarraydouble_setpartofvaluessimple1 "Here is a Python example".
1672  *  \endif
1673  */
1674   template<class T>
1675   void DataArrayTemplate<T>::setPartOfValuesSimple1(T a, mcIdType bgTuples, mcIdType endTuples, mcIdType stepTuples, mcIdType bgComp, mcIdType endComp, mcIdType stepComp)
1676   {
1677     const char msg[]="DataArrayTemplate::setPartOfValuesSimple1";
1678     checkAllocated();
1679     mcIdType newNbOfTuples(DataArray::GetNumberOfItemGivenBES(bgTuples,endTuples,stepTuples,msg));
1680     mcIdType newNbOfComp(DataArray::GetNumberOfItemGivenBES(bgComp,endComp,stepComp,msg));
1681     std::size_t nbComp(getNumberOfComponents());
1682     mcIdType nbOfTuples(getNumberOfTuples());
1683     DataArray::CheckValueInRangeEx(nbOfTuples,bgTuples,endTuples,"invalid tuple value");
1684     DataArray::CheckValueInRangeEx(ToIdType(nbComp),bgComp,endComp,"invalid component value");
1685     T *pt=getPointer()+bgTuples*nbComp+bgComp;
1686     for(mcIdType i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
1687       for(mcIdType j=0;j<newNbOfComp;j++)
1688         pt[j*stepComp]=a;
1689   }
1690
1691   /*!
1692    * Copy all values from another DataArrayDouble (\a a) into specified tuples and
1693    * components of \a this array. Textual data is not copied.
1694    * The tuples and components to assign to are defined by C arrays of indices.
1695    * There are two *modes of usage*:
1696    * - If \a a->getNbOfElems() equals to number of values to assign to, then every value
1697    *   of \a a is assigned to its own location within \a this array.
1698    * - If \a a includes one tuple, then all values of \a a are assigned to the specified
1699    *   components of every specified tuple of \a this array. In this mode it is required
1700    *   that \a a->getNumberOfComponents() equals to the number of specified components.
1701    *
1702    *  \param [in] a - the array to copy values from.
1703    *  \param [in] bgTuples - pointer to an array of tuple indices of \a this array to
1704    *              assign values of \a a to.
1705    *  \param [in] endTuples - specifies the end of the array \a bgTuples, so that
1706    *              pointer to a tuple index <em>(pi)</em> varies as this:
1707    *              \a bgTuples <= \a pi < \a endTuples.
1708    *  \param [in] bgComp - pointer to an array of component indices of \a this array to
1709    *              assign values of \a a to.
1710    *  \param [in] endComp - specifies the end of the array \a bgTuples, so that
1711    *              pointer to a component index <em>(pi)</em> varies as this:
1712    *              \a bgComp <= \a pi < \a endComp.
1713    *  \param [in] strictCompoCompare - this parameter is checked only if the
1714    *               *mode of usage* is the first; if it is \a true (default),
1715    *               then \a a->getNumberOfComponents() must be equal
1716    *               to the number of specified columns, else this is not required.
1717    *  \throw If \a a is NULL.
1718    *  \throw If \a a is not allocated.
1719    *  \throw If \a this is not allocated.
1720    *  \throw If any index of tuple/component given by <em>bgTuples / bgComp</em> is
1721    *         out of a valid range for \a this array.
1722    *  \throw In the first *mode of usage*, if <em>strictCompoCompare == true </em> and
1723    *         if <em> a->getNumberOfComponents() != (endComp - bgComp) </em>.
1724    *  \throw In the second *mode of usage*, if \a a->getNumberOfTuples() != 1 or
1725    *         <em> a->getNumberOfComponents() != (endComp - bgComp)</em>.
1726    *
1727    *  \if ENABLE_EXAMPLES
1728    *  \ref py_mcdataarraydouble_setpartofvalues2 "Here is a Python example".
1729    *  \endif
1730    */
1731   template<class T>
1732   void DataArrayTemplate<T>::setPartOfValues2(const typename Traits<T>::ArrayType *a, const mcIdType *bgTuples, const mcIdType *endTuples, const mcIdType *bgComp, const mcIdType *endComp, bool strictCompoCompare)
1733   {
1734     if(!a)
1735       throw INTERP_KERNEL::Exception("DataArrayDouble::setPartOfValues2 : input DataArrayDouble is NULL !");
1736     const char msg[]="DataArrayTemplate::setPartOfValues2";
1737     checkAllocated();
1738     a->checkAllocated();
1739     std::size_t nbComp(getNumberOfComponents());
1740     mcIdType nbOfTuples(getNumberOfTuples());
1741     for(const mcIdType *z=bgComp;z!=endComp;z++)
1742       DataArray::CheckValueInRange(ToIdType(nbComp),*z,"invalid component id");
1743     mcIdType newNbOfTuples(ToIdType(std::distance(bgTuples,endTuples)));
1744     mcIdType newNbOfComp(ToIdType(std::distance(bgComp,endComp)));
1745     bool assignTech(true);
1746     if(a->getNbOfElems()==newNbOfTuples*newNbOfComp)
1747       {
1748         if(strictCompoCompare)
1749           a->checkNbOfTuplesAndComp(newNbOfTuples,newNbOfComp,msg);
1750       }
1751     else
1752       {
1753         a->checkNbOfTuplesAndComp(1,newNbOfComp,msg);
1754         assignTech=false;
1755       }
1756     T *pt(getPointer());
1757     const T *srcPt(a->getConstPointer());
1758     if(assignTech)
1759       {
1760         for(const mcIdType *w=bgTuples;w!=endTuples;w++)
1761           {
1762             DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1763             for(const mcIdType *z=bgComp;z!=endComp;z++,srcPt++)
1764               {
1765                 pt[(std::size_t)(*w)*nbComp+(*z)]=*srcPt;
1766               }
1767           }
1768       }
1769     else
1770       {
1771         for(const mcIdType *w=bgTuples;w!=endTuples;w++)
1772           {
1773             const T *srcPt2=srcPt;
1774             DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1775             for(const mcIdType *z=bgComp;z!=endComp;z++,srcPt2++)
1776               {
1777                 pt[(std::size_t)(*w)*nbComp+(*z)]=*srcPt2;
1778               }
1779           }
1780       }
1781   }
1782
1783   /*!
1784    * Assign a given value to values at specified tuples and components of \a this array.
1785    * The tuples and components to assign to are defined by C arrays of indices.
1786    *  \param [in] a - the value to assign.
1787    *  \param [in] bgTuples - pointer to an array of tuple indices of \a this array to
1788    *              assign \a a to.
1789    *  \param [in] endTuples - specifies the end of the array \a bgTuples, so that
1790    *              pointer to a tuple index (\a pi) varies as this:
1791    *              \a bgTuples <= \a pi < \a endTuples.
1792    *  \param [in] bgComp - pointer to an array of component indices of \a this array to
1793    *              assign \a a to.
1794    *  \param [in] endComp - specifies the end of the array \a bgTuples, so that
1795    *              pointer to a component index (\a pi) varies as this:
1796    *              \a bgComp <= \a pi < \a endComp.
1797    *  \throw If \a this is not allocated.
1798    *  \throw If any index of tuple/component given by <em>bgTuples / bgComp</em> is
1799    *         out of a valid range for \a this array.
1800    *
1801    *  \if ENABLE_EXAMPLES
1802    *  \ref py_mcdataarraydouble_setpartofvaluessimple2 "Here is a Python example".
1803    *  \endif
1804    */
1805   template<class T>
1806   void DataArrayTemplate<T>::setPartOfValuesSimple2(T a, const mcIdType *bgTuples, const mcIdType *endTuples, const mcIdType *bgComp, const mcIdType *endComp)
1807   {
1808     checkAllocated();
1809     std::size_t nbComp=getNumberOfComponents();
1810     mcIdType nbOfTuples=getNumberOfTuples();
1811     for(const mcIdType *z=bgComp;z!=endComp;z++)
1812       DataArray::CheckValueInRange(ToIdType(nbComp),*z,"invalid component id");
1813     T *pt(getPointer());
1814     for(const mcIdType *w=bgTuples;w!=endTuples;w++)
1815       for(const mcIdType *z=bgComp;z!=endComp;z++)
1816         {
1817           DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1818           pt[(std::size_t)(*w)*nbComp+(*z)]=a;
1819         }
1820   }
1821
1822   /*!
1823    * Copy all values from another DataArrayDouble (\a a) into specified tuples and
1824    * components of \a this array. Textual data is not copied.
1825    * The tuples to assign to are defined by a C array of indices.
1826    * The components to assign to are defined by three values similar to parameters of
1827    * the Python function \c range(\c start,\c stop,\c step).
1828    * There are two *modes of usage*:
1829    * - If \a a->getNbOfElems() equals to number of values to assign to, then every value
1830    *   of \a a is assigned to its own location within \a this array.
1831    * - If \a a includes one tuple, then all values of \a a are assigned to the specified
1832    *   components of every specified tuple of \a this array. In this mode it is required
1833    *   that \a a->getNumberOfComponents() equals to the number of specified components.
1834    *
1835    *  \param [in] a - the array to copy values from.
1836    *  \param [in] bgTuples - pointer to an array of tuple indices of \a this array to
1837    *              assign values of \a a to.
1838    *  \param [in] endTuples - specifies the end of the array \a bgTuples, so that
1839    *              pointer to a tuple index <em>(pi)</em> varies as this:
1840    *              \a bgTuples <= \a pi < \a endTuples.
1841    *  \param [in] bgComp - index of the first component of \a this array to assign to.
1842    *  \param [in] endComp - index of the component before which the components to assign
1843    *              to are located.
1844    *  \param [in] stepComp - index increment to get index of the next component to assign to.
1845    *  \param [in] strictCompoCompare - this parameter is checked only in the first
1846    *               *mode of usage*; if \a strictCompoCompare is \a true (default),
1847    *               then \a a->getNumberOfComponents() must be equal
1848    *               to the number of specified columns, else this is not required.
1849    *  \throw If \a a is NULL.
1850    *  \throw If \a a is not allocated.
1851    *  \throw If \a this is not allocated.
1852    *  \throw If any index of tuple given by \a bgTuples is out of a valid range for
1853    *         \a this array.
1854    *  \throw In the first *mode of usage*, if <em>strictCompoCompare == true </em> and
1855    *         if <em> a->getNumberOfComponents()</em> is unequal to the number of components
1856    *         defined by <em>(bgComp,endComp,stepComp)</em>.
1857    *  \throw In the second *mode of usage*, if \a a->getNumberOfTuples() != 1 or
1858    *         <em> a->getNumberOfComponents()</em> is unequal to the number of components
1859    *         defined by <em>(bgComp,endComp,stepComp)</em>.
1860    *  \throw If parameters specifying components to assign to, do not give a
1861    *            non-empty range of increasing indices or indices are out of a valid range
1862    *            for \c this array.
1863    *
1864    *  \if ENABLE_EXAMPLES
1865    *  \ref py_mcdataarraydouble_setpartofvalues3 "Here is a Python example".
1866    *  \endif
1867    */
1868   template<class T>
1869   void DataArrayTemplate<T>::setPartOfValues3(const typename Traits<T>::ArrayType *a, const mcIdType *bgTuples, const mcIdType *endTuples, mcIdType bgComp, mcIdType endComp, mcIdType stepComp, bool strictCompoCompare)
1870   {
1871     if(!a)
1872       throw INTERP_KERNEL::Exception("DataArrayTemplate::setPartOfValues3 : input DataArrayDouble is NULL !");
1873     const char msg[]="DataArrayTemplate::setPartOfValues3";
1874     checkAllocated();
1875     a->checkAllocated();
1876     mcIdType newNbOfComp=DataArray::GetNumberOfItemGivenBES(bgComp,endComp,stepComp,msg);
1877     std::size_t nbComp(getNumberOfComponents());
1878     mcIdType nbOfTuples(getNumberOfTuples());
1879     DataArray::CheckValueInRangeEx(ToIdType(nbComp),bgComp,endComp,"invalid component value");
1880     mcIdType newNbOfTuples=ToIdType(std::distance(bgTuples,endTuples));
1881     bool assignTech=true;
1882     if(a->getNbOfElems()==newNbOfTuples*newNbOfComp)
1883       {
1884         if(strictCompoCompare)
1885           a->checkNbOfTuplesAndComp(newNbOfTuples,newNbOfComp,msg);
1886       }
1887     else
1888       {
1889         a->checkNbOfTuplesAndComp(1,newNbOfComp,msg);
1890         assignTech=false;
1891       }
1892     T *pt(getPointer()+bgComp);
1893     const T *srcPt(a->getConstPointer());
1894     if(assignTech)
1895       {
1896         for(const mcIdType *w=bgTuples;w!=endTuples;w++)
1897           for(mcIdType j=0;j<newNbOfComp;j++,srcPt++)
1898             {
1899               DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1900               pt[(std::size_t)(*w)*nbComp+j*stepComp]=*srcPt;
1901             }
1902       }
1903     else
1904       {
1905         for(const mcIdType *w=bgTuples;w!=endTuples;w++)
1906           {
1907             const T *srcPt2=srcPt;
1908             for(mcIdType j=0;j<newNbOfComp;j++,srcPt2++)
1909               {
1910                 DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1911                 pt[(std::size_t)(*w)*nbComp+j*stepComp]=*srcPt2;
1912               }
1913           }
1914       }
1915   }
1916
1917   /*!
1918    * Assign a given value to values at specified tuples and components of \a this array.
1919    * The tuples to assign to are defined by a C array of indices.
1920    * The components to assign to are defined by three values similar to parameters of
1921    * the Python function \c range(\c start,\c stop,\c step).
1922    *  \param [in] a - the value to assign.
1923    *  \param [in] bgTuples - pointer to an array of tuple indices of \a this array to
1924    *              assign \a a to.
1925    *  \param [in] endTuples - specifies the end of the array \a bgTuples, so that
1926    *              pointer to a tuple index <em>(pi)</em> varies as this:
1927    *              \a bgTuples <= \a pi < \a endTuples.
1928    *  \param [in] bgComp - index of the first component of \a this array to assign to.
1929    *  \param [in] endComp - index of the component before which the components to assign
1930    *              to are located.
1931    *  \param [in] stepComp - index increment to get index of the next component to assign to.
1932    *  \throw If \a this is not allocated.
1933    *  \throw If any index of tuple given by \a bgTuples is out of a valid range for
1934    *         \a this array.
1935    *  \throw If parameters specifying components to assign to, do not give a
1936    *            non-empty range of increasing indices or indices are out of a valid range
1937    *            for \c this array.
1938    *
1939    *  \if ENABLE_EXAMPLES
1940    *  \ref py_mcdataarraydouble_setpartofvaluessimple3 "Here is a Python example".
1941    *  \endif
1942    */
1943   template<class T>
1944   void DataArrayTemplate<T>::setPartOfValuesSimple3(T a, const mcIdType *bgTuples, const mcIdType *endTuples, mcIdType bgComp, mcIdType endComp, mcIdType stepComp)
1945   {
1946     const char msg[]="DataArrayTemplate::setPartOfValuesSimple3";
1947     checkAllocated();
1948     std::size_t newNbOfComp(DataArray::GetNumberOfItemGivenBES(bgComp,endComp,stepComp,msg));
1949     std::size_t nbComp(getNumberOfComponents());
1950     mcIdType nbOfTuples(getNumberOfTuples());
1951     DataArray::CheckValueInRangeEx(ToIdType(nbComp),bgComp,endComp,"invalid component value");
1952     T *pt(getPointer()+bgComp);
1953     for(const mcIdType *w=bgTuples;w!=endTuples;w++)
1954       for(std::size_t j=0;j<newNbOfComp;j++)
1955         {
1956           DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1957           pt[(std::size_t)(*w)*nbComp+j*stepComp]=a;
1958         }
1959   }
1960
1961   /*!
1962    * Copy all values from another DataArrayDouble into specified tuples and components
1963    * of \a this array. Textual data is not copied.
1964    * The tree parameters defining set of indices of tuples and components are similar to
1965    * the tree parameters of the Python function \c range(\c start,\c stop,\c step).
1966    *  \param [in] a - the array to copy values from.
1967    *  \param [in] bgTuples - index of the first tuple of \a this array to assign values to.
1968    *  \param [in] endTuples - index of the tuple before which the tuples to assign to
1969    *              are located.
1970    *  \param [in] stepTuples - index increment to get index of the next tuple to assign to.
1971    *  \param [in] bgComp - pointer to an array of component indices of \a this array to
1972    *              assign \a a to.
1973    *  \param [in] endComp - specifies the end of the array \a bgTuples, so that
1974    *              pointer to a component index (\a pi) varies as this:
1975    *              \a bgComp <= \a pi < \a endComp.
1976    *  \param [in] strictCompoCompare - if \a true (by default), then \a a->getNumberOfComponents()
1977    *              must be equal to the number of columns to assign to, else an
1978    *              exception is thrown; if \a false, then it is only required that \a
1979    *              a->getNbOfElems() equals to number of values to assign to (this condition
1980    *              must be respected even if \a strictCompoCompare is \a true). The number of
1981    *              values to assign to is given by following Python expression:
1982    *              \a nbTargetValues =
1983    *              \c len(\c range(\a bgTuples,\a endTuples,\a stepTuples)) *
1984    *              \c len(\c range(\a bgComp,\a endComp,\a stepComp)).
1985    *  \throw If \a a is NULL.
1986    *  \throw If \a a is not allocated.
1987    *  \throw If \a this is not allocated.
1988    *  \throw If parameters specifying tuples and components to assign to do not give a
1989    *            non-empty range of increasing indices.
1990    *  \throw If \a a->getNbOfElems() != \a nbTargetValues.
1991    *  \throw If \a strictCompoCompare == \a true && \a a->getNumberOfComponents() !=
1992    *            \c len(\c range(\a bgComp,\a endComp,\a stepComp)).
1993    *
1994    */
1995   template<class T>
1996   void DataArrayTemplate<T>::setPartOfValues4(const typename Traits<T>::ArrayType *a, mcIdType bgTuples, mcIdType endTuples, mcIdType stepTuples, const mcIdType *bgComp, const mcIdType *endComp, bool strictCompoCompare)
1997   {if(!a)
1998       throw INTERP_KERNEL::Exception("DataArrayTemplate::setPartOfValues4 : input DataArrayTemplate is NULL !");
1999     const char msg[]="DataArrayTemplate::setPartOfValues4";
2000     checkAllocated();
2001     a->checkAllocated();
2002     mcIdType newNbOfTuples(DataArray::GetNumberOfItemGivenBES(bgTuples,endTuples,stepTuples,msg));
2003     std::size_t newNbOfComp(std::distance(bgComp,endComp));
2004     std::size_t nbComp(getNumberOfComponents());
2005     for(const mcIdType *z=bgComp;z!=endComp;z++)
2006       DataArray::CheckValueInRange(ToIdType(nbComp),*z,"invalid component id");
2007     mcIdType nbOfTuples(getNumberOfTuples());
2008     DataArray::CheckValueInRangeEx(nbOfTuples,bgTuples,endTuples,"invalid tuple value");
2009     bool assignTech(true);
2010     if(a->getNbOfElems()==ToIdType(newNbOfTuples*newNbOfComp))
2011       {
2012         if(strictCompoCompare)
2013           a->checkNbOfTuplesAndComp(newNbOfTuples,newNbOfComp,msg);
2014       }
2015     else
2016       {
2017         a->checkNbOfTuplesAndComp(1,newNbOfComp,msg);
2018         assignTech=false;
2019       }
2020     const T *srcPt(a->getConstPointer());
2021     T *pt(getPointer()+bgTuples*nbComp);
2022     if(assignTech)
2023       {
2024         for(mcIdType i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
2025           for(const mcIdType *z=bgComp;z!=endComp;z++,srcPt++)
2026             pt[*z]=*srcPt;
2027       }
2028     else
2029       {
2030       for(mcIdType i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
2031         {
2032           const T *srcPt2(srcPt);
2033           for(const mcIdType *z=bgComp;z!=endComp;z++,srcPt2++)
2034             pt[*z]=*srcPt2;
2035         }
2036       }
2037   }
2038
2039   template<class T>
2040   void DataArrayTemplate<T>::setPartOfValuesSimple4(T a, mcIdType bgTuples, mcIdType endTuples, mcIdType stepTuples, const mcIdType *bgComp, const mcIdType *endComp)
2041   {
2042     const char msg[]="DataArrayTemplate::setPartOfValuesSimple4";
2043     checkAllocated();
2044     mcIdType newNbOfTuples(DataArray::GetNumberOfItemGivenBES(bgTuples,endTuples,stepTuples,msg));
2045     std::size_t nbComp(getNumberOfComponents());
2046     for(const mcIdType *z=bgComp;z!=endComp;z++)
2047       DataArray::CheckValueInRange(ToIdType(nbComp),*z,"invalid component id");
2048     mcIdType nbOfTuples(getNumberOfTuples());
2049     DataArray::CheckValueInRangeEx(nbOfTuples,bgTuples,endTuples,"invalid tuple value");
2050     T *pt=getPointer()+bgTuples*nbComp;
2051     for(mcIdType i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
2052       for(const mcIdType *z=bgComp;z!=endComp;z++)
2053         pt[*z]=a;
2054   }
2055
2056   /*!
2057    * Copy some tuples from another DataArrayDouble into specified tuples
2058    * of \a this array. Textual data is not copied. Both arrays must have equal number of
2059    * components.
2060    * Both the tuples to assign and the tuples to assign to are defined by a DataArrayInt.
2061    * All components of selected tuples are copied.
2062    *  \param [in] a - the array to copy values from.
2063    *  \param [in] tuplesSelec - the array specifying both source tuples of \a a and
2064    *              target tuples of \a this. \a tuplesSelec has two components, and the
2065    *              first component specifies index of the source tuple and the second
2066    *              one specifies index of the target tuple.
2067    *  \throw If \a this is not allocated.
2068    *  \throw If \a a is NULL.
2069    *  \throw If \a a is not allocated.
2070    *  \throw If \a tuplesSelec is NULL.
2071    *  \throw If \a tuplesSelec is not allocated.
2072    *  \throw If <em>this->getNumberOfComponents() != a->getNumberOfComponents()</em>.
2073    *  \throw If \a tuplesSelec->getNumberOfComponents() != 2.
2074    *  \throw If any tuple index given by \a tuplesSelec is out of a valid range for
2075    *         the corresponding (\a this or \a a) array.
2076    */
2077   template<class T>
2078   void DataArrayTemplate<T>::setPartOfValuesAdv(const typename Traits<T>::ArrayType *a, const DataArrayIdType *tuplesSelec)
2079   {
2080     if(!a || !tuplesSelec)
2081       throw INTERP_KERNEL::Exception("DataArrayTemplate::setPartOfValuesAdv : input DataArrayTemplate is NULL !");
2082     checkAllocated();
2083     a->checkAllocated();
2084     tuplesSelec->checkAllocated();
2085     std::size_t nbOfComp(getNumberOfComponents());
2086     if(nbOfComp!=a->getNumberOfComponents())
2087       throw INTERP_KERNEL::Exception("DataArrayTemplate::setPartOfValuesAdv : This and a do not have the same number of components !");
2088     if(tuplesSelec->getNumberOfComponents()!=2)
2089       throw INTERP_KERNEL::Exception("DataArrayTemplate::setPartOfValuesAdv : Expecting to have a tuple selector DataArrayInt instance with exactly 2 components !");
2090     mcIdType thisNt(getNumberOfTuples());
2091     mcIdType aNt(a->getNumberOfTuples());
2092     T *valsToSet(getPointer());
2093     const T *valsSrc(a->getConstPointer());
2094     for(const mcIdType *tuple=tuplesSelec->begin();tuple!=tuplesSelec->end();tuple+=2)
2095     {
2096       if(tuple[1]>=0 && tuple[1]<aNt)
2097         {
2098           if(tuple[0]>=0 && tuple[0]<thisNt)
2099             std::copy(valsSrc+nbOfComp*tuple[1],valsSrc+nbOfComp*(tuple[1]+1),valsToSet+nbOfComp*tuple[0]);
2100           else
2101             {
2102               std::ostringstream oss; oss << "DataArrayTemplate::setPartOfValuesAdv : Tuple #" << std::distance(tuplesSelec->begin(),tuple)/2;
2103               oss << " of 'tuplesSelec' request of tuple id #" << tuple[0] << " in 'this' ! It should be in [0," << thisNt << ") !";
2104               throw INTERP_KERNEL::Exception(oss.str().c_str());
2105             }
2106         }
2107       else
2108         {
2109           std::ostringstream oss; oss << "DataArrayTemplate::setPartOfValuesAdv : Tuple #" << std::distance(tuplesSelec->begin(),tuple)/2;
2110           oss << " of 'tuplesSelec' request of tuple id #" << tuple[1] << " in 'a' ! It should be in [0," << aNt << ") !";
2111           throw INTERP_KERNEL::Exception(oss.str().c_str());
2112         }
2113     }
2114   }
2115
2116   /*!
2117    * Copy some tuples from another DataArrayDouble (\a aBase) into contiguous tuples
2118    * of \a this array. Textual data is not copied. Both arrays must have equal number of
2119    * components.
2120    * The tuples to assign to are defined by index of the first tuple, and
2121    * their number is defined by \a tuplesSelec->getNumberOfTuples().
2122    * The tuples to copy are defined by values of a DataArrayInt.
2123    * All components of selected tuples are copied.
2124    *  \param [in] tupleIdStart - index of the first tuple of \a this array to assign
2125    *              values to.
2126    *  \param [in] aBase - the array to copy values from.
2127    *  \param [in] tuplesSelec - the array specifying tuples of \a a to copy.
2128    *  \throw If \a this is not allocated.
2129    *  \throw If \a aBase is NULL.
2130    *  \throw If \a aBase is not allocated.
2131    *  \throw If \a tuplesSelec is NULL.
2132    *  \throw If \a tuplesSelec is not allocated.
2133    *  \throw If <em>this->getNumberOfComponents() != aBase->getNumberOfComponents()</em>.
2134    *  \throw If \a tuplesSelec->getNumberOfComponents() != 1.
2135    *  \throw If <em>tupleIdStart + tuplesSelec->getNumberOfTuples() > this->getNumberOfTuples().</em>
2136    *  \throw If any tuple index given by \a tuplesSelec is out of a valid range for
2137    *         \a aBase array.
2138  */
2139   template<class T>
2140   void DataArrayTemplate<T>::setContigPartOfSelectedValues(mcIdType tupleIdStart, const DataArray *aBase, const DataArrayIdType *tuplesSelec)
2141   {
2142     if(!aBase || !tuplesSelec)
2143       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValues : input DataArray is NULL !");
2144     const typename Traits<T>::ArrayType *a(dynamic_cast<const typename Traits<T>::ArrayType *>(aBase));
2145     if(!a)
2146       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValues : input DataArray aBase is not a DataArrayDouble !");
2147     checkAllocated();
2148     a->checkAllocated();
2149     tuplesSelec->checkAllocated();
2150     std::size_t nbOfComp(getNumberOfComponents());
2151     if(nbOfComp!=a->getNumberOfComponents())
2152       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValues : This and a do not have the same number of components !");
2153     if(tuplesSelec->getNumberOfComponents()!=1)
2154       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValues : Expecting to have a tuple selector DataArrayInt instance with exactly 1 component !");
2155     mcIdType thisNt(getNumberOfTuples());
2156     mcIdType aNt(a->getNumberOfTuples());
2157     mcIdType nbOfTupleToWrite(tuplesSelec->getNumberOfTuples());
2158     T *valsToSet(getPointer()+tupleIdStart*nbOfComp);
2159     if(tupleIdStart+nbOfTupleToWrite>thisNt)
2160       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValues : invalid number range of values to write !");
2161     const T *valsSrc=a->getConstPointer();
2162     for(const mcIdType *tuple=tuplesSelec->begin();tuple!=tuplesSelec->end();tuple++,valsToSet+=nbOfComp)
2163       {
2164         if(*tuple>=0 && *tuple<aNt)
2165           {
2166             std::copy(valsSrc+nbOfComp*(*tuple),valsSrc+nbOfComp*(*tuple+1),valsToSet);
2167           }
2168         else
2169           {
2170             std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::setContigPartOfSelectedValues : Tuple #" << std::distance(tuplesSelec->begin(),tuple);
2171             oss << " of 'tuplesSelec' request of tuple id #" << *tuple << " in 'a' ! It should be in [0," << aNt << ") !";
2172             throw INTERP_KERNEL::Exception(oss.str().c_str());
2173           }
2174       }
2175   }
2176
2177   /*!
2178    * Copy some tuples from another DataArrayDouble (\a aBase) into contiguous tuples
2179    * of \a this array. Textual data is not copied. Both arrays must have equal number of
2180    * components.
2181    * The tuples to copy are defined by three values similar to parameters of
2182    * the Python function \c range(\c start,\c stop,\c step).
2183    * The tuples to assign to are defined by index of the first tuple, and
2184    * their number is defined by number of tuples to copy.
2185    * All components of selected tuples are copied.
2186    *  \param [in] tupleIdStart - index of the first tuple of \a this array to assign
2187    *              values to.
2188    *  \param [in] aBase - the array to copy values from.
2189    *  \param [in] bg - index of the first tuple to copy of the array \a aBase.
2190    *  \param [in] end2 - index of the tuple of \a aBase before which the tuples to copy
2191    *              are located.
2192    *  \param [in] step - index increment to get index of the next tuple to copy.
2193    *  \throw If \a this is not allocated.
2194    *  \throw If \a aBase is NULL.
2195    *  \throw If \a aBase is not allocated.
2196    *  \throw If <em>this->getNumberOfComponents() != aBase->getNumberOfComponents()</em>.
2197    *  \throw If <em>tupleIdStart + len(range(bg,end2,step)) > this->getNumberOfTuples().</em>
2198    *  \throw If parameters specifying tuples to copy, do not give a
2199    *            non-empty range of increasing indices or indices are out of a valid range
2200    *            for the array \a aBase.
2201    */
2202   template<class T>
2203   void DataArrayTemplate<T>::setContigPartOfSelectedValuesSlice(mcIdType tupleIdStart, const DataArray *aBase, mcIdType bg, mcIdType end2, mcIdType step)
2204   {
2205     if(!aBase)
2206       {
2207         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::setContigPartOfSelectedValuesSlice : input DataArray is NULL !";
2208         throw INTERP_KERNEL::Exception(oss.str().c_str());
2209       }
2210     const typename Traits<T>::ArrayType *a(dynamic_cast<const typename Traits<T>::ArrayType *>(aBase));
2211     if(!a)
2212       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValuesSlice : input DataArray aBase is not a DataArrayDouble !");
2213     checkAllocated();
2214     a->checkAllocated();
2215     std::size_t nbOfComp(getNumberOfComponents());
2216     const char msg[]="DataArrayDouble::setContigPartOfSelectedValuesSlice";
2217     mcIdType nbOfTupleToWrite(DataArray::GetNumberOfItemGivenBES(bg,end2,step,msg));
2218     if(nbOfComp!=a->getNumberOfComponents())
2219       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValuesSlice : This and a do not have the same number of components !");
2220     mcIdType thisNt(getNumberOfTuples());
2221     mcIdType aNt(a->getNumberOfTuples());
2222     T *valsToSet(getPointer()+tupleIdStart*nbOfComp);
2223     if(tupleIdStart+nbOfTupleToWrite>thisNt)
2224       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValuesSlice : invalid number range of values to write !");
2225     if(end2>aNt)
2226       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValuesSlice : invalid range of values to read !");
2227     const T *valsSrc(a->getConstPointer()+bg*nbOfComp);
2228     for(mcIdType i=0;i<nbOfTupleToWrite;i++,valsToSet+=nbOfComp,valsSrc+=step*nbOfComp)
2229       {
2230         std::copy(valsSrc,valsSrc+nbOfComp,valsToSet);
2231       }
2232   }
2233
2234   /*!
2235    * Returns a shorten copy of \a this array. The new DataArrayDouble contains ranges
2236    * of tuples specified by \a ranges parameter.
2237    * For more info on renumbering see \ref numbering.
2238    *  \param [in] ranges - std::vector of std::pair's each of which defines a range
2239    *              of tuples in [\c begin,\c end) format.
2240    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
2241    *          is to delete using decrRef() as it is no more needed.
2242    *  \throw If \a end < \a begin.
2243    *  \throw If \a end > \a this->getNumberOfTuples().
2244    *  \throw If \a this is not allocated.
2245    */
2246   template<class T>
2247   typename Traits<T>::ArrayType *DataArrayTemplate<T>::mySelectByTupleRanges(const std::vector<std::pair<mcIdType,mcIdType> >& ranges) const
2248   {
2249     checkAllocated();
2250     std::size_t nbOfComp(getNumberOfComponents());
2251     mcIdType nbOfTuplesThis(getNumberOfTuples());
2252     if(ranges.empty())
2253       {
2254         MCAuto<DataArray> ret0(buildNewEmptyInstance());
2255         MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
2256         ret->alloc(0,nbOfComp);
2257         ret->copyStringInfoFrom(*this);
2258         return ret.retn();
2259       }
2260     mcIdType ref(ranges.front().first),nbOfTuples(0);
2261     bool isIncreasing(true);
2262     for(std::vector<std::pair<mcIdType,mcIdType> >::const_iterator it=ranges.begin();it!=ranges.end();it++)
2263       {
2264         if((*it).first<=(*it).second)
2265           {
2266             if((*it).first>=0 && (*it).second<=nbOfTuplesThis)
2267               {
2268                 nbOfTuples+=(*it).second-(*it).first;
2269                 if(isIncreasing)
2270                   isIncreasing=ref<=(*it).first;
2271                 ref=(*it).second;
2272               }
2273             else
2274               {
2275                 std::ostringstream oss; oss << "DataArrayTemplate::selectByTupleRanges : on range #" << std::distance(ranges.begin(),it);
2276                 oss << " (" << (*it).first << "," << (*it).second << ") is greater than number of tuples of this :" << nbOfTuples << " !";
2277                 throw INTERP_KERNEL::Exception(oss.str().c_str());
2278               }
2279           }
2280         else
2281           {
2282             std::ostringstream oss; oss << "DataArrayTemplate::selectByTupleRanges : on range #" << std::distance(ranges.begin(),it);
2283             oss << " (" << (*it).first << "," << (*it).second << ") end is before begin !";
2284             throw INTERP_KERNEL::Exception(oss.str().c_str());
2285           }
2286       }
2287     if(isIncreasing && nbOfTuplesThis==nbOfTuples)
2288       return static_cast<typename Traits<T>::ArrayType *>(deepCopy());
2289     MCAuto<DataArray> ret0(buildNewEmptyInstance());
2290     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
2291     ret->alloc(nbOfTuples,nbOfComp);
2292     ret->copyStringInfoFrom(*this);
2293     const T *src(getConstPointer());
2294     T *work(ret->getPointer());
2295     for(std::vector<std::pair<mcIdType,mcIdType> >::const_iterator it=ranges.begin();it!=ranges.end();it++)
2296       work=std::copy(src+(*it).first*nbOfComp,src+(*it).second*nbOfComp,work);
2297     return ret.retn();
2298   }
2299
2300   /*!
2301    * Returns the first value of \a this.
2302    *  \return double - the last value of \a this array.
2303    *  \throw If \a this is not allocated.
2304    *  \throw If \a this->getNumberOfComponents() != 1.
2305    *  \throw If \a this->getNumberOfTuples() < 1.
2306    */
2307   template<class T>
2308   T DataArrayTemplate<T>::front() const
2309   {
2310     checkAllocated();
2311     if(getNumberOfComponents()!=1)
2312       throw INTERP_KERNEL::Exception("DataArrayTemplate::front : number of components not equal to one !");
2313     mcIdType nbOfTuples=getNumberOfTuples();
2314     if(nbOfTuples<1)
2315       throw INTERP_KERNEL::Exception("DataArrayTemplate::front : number of tuples must be >= 1 !");
2316     return *(getConstPointer());
2317   }
2318
2319   /*!
2320    * Returns the last value of \a this.
2321    *  \return double - the last value of \a this array.
2322    *  \throw If \a this is not allocated.
2323    *  \throw If \a this->getNumberOfComponents() != 1.
2324    *  \throw If \a this->getNumberOfTuples() < 1.
2325    */
2326   template<class T>
2327   T DataArrayTemplate<T>::back() const
2328   {
2329     checkAllocated();
2330     if(getNumberOfComponents()!=1)
2331       throw INTERP_KERNEL::Exception("DataArrayTemplate::back : number of components not equal to one !");
2332     mcIdType nbOfTuples=getNumberOfTuples();
2333     if(nbOfTuples<1)
2334       throw INTERP_KERNEL::Exception("DataArrayTemplate::back : number of tuples must be >= 1 !");
2335     return *(getConstPointer()+nbOfTuples-1);
2336   }
2337
2338   /*!
2339    * Returns the maximal value and its location within \a this one-dimensional array.
2340    *  \param [out] tupleId - index of the tuple holding the maximal value.
2341    *  \return double - the maximal value among all values of \a this array.
2342    *  \throw If \a this->getNumberOfComponents() != 1
2343    *  \throw If \a this->getNumberOfTuples() < 1
2344    *  \sa getMaxAbsValue, getMinValue
2345    */
2346   template<class T>
2347   T DataArrayTemplate<T>::getMaxValue(mcIdType& tupleId) const
2348   {
2349     checkAllocated();
2350     if(getNumberOfComponents()!=1)
2351       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 !");
2352     mcIdType nbOfTuples=getNumberOfTuples();
2353     if(nbOfTuples<=0)
2354       throw INTERP_KERNEL::Exception("DataArrayDouble::getMaxValue : array exists but number of tuples must be > 0 !");
2355     const T *vals(getConstPointer());
2356     const T *loc(std::max_element(vals,vals+nbOfTuples));
2357     tupleId=ToIdType(std::distance(vals,loc));
2358     return *loc;
2359   }
2360
2361   /*!
2362    * Returns the maximal value within \a this array that is allowed to have more than
2363    *  one component.
2364    *  \return double - the maximal value among all values of \a this array.
2365    *  \throw If \a this is not allocated.
2366    *  \sa getMaxAbsValueInArray, getMinValueInArray
2367    */
2368   template<class T>
2369   T DataArrayTemplate<T>::getMaxValueInArray() const
2370   {
2371     checkAllocated();
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   /*!
4206    * Creates a new DataArrayInt containing IDs (indices) of tuples holding value equal to a
4207    * given one. The ids are sorted in the ascending order.
4208    *  \param [in] val - the value to find within \a this.
4209    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
4210    *          array using decrRef() as it is no more needed.
4211    *  \throw If \a this is not allocated.
4212    *  \throw If \a this->getNumberOfComponents() != 1.
4213    *  \sa DataArrayInt::findIdsEqualTuple
4214    */
4215   template<class T>
4216   DataArrayIdType *DataArrayDiscrete<T>::findIdsEqual(T val) const
4217   {
4218     this->checkAllocated();
4219     if(this->getNumberOfComponents()!=1)
4220       throw INTERP_KERNEL::Exception("DataArrayInt::findIdsEqual : the array must have only one component, you can call 'rearrange' method before !");
4221     const T *cptr(this->getConstPointer());
4222     MCAuto<DataArrayIdType> ret(DataArrayIdType::New()); ret->alloc(0,1);
4223     mcIdType nbOfTuples(this->getNumberOfTuples());
4224     for(mcIdType i=0;i<nbOfTuples;i++,cptr++)
4225       if(*cptr==val)
4226         ret->pushBackSilent(ToIdType(i));
4227     return ret.retn();
4228   }
4229
4230   /*!
4231    * Creates a one-dimensional DataArrayInt (\a res) whose contents are computed from
4232    * values of \a this (\a a) and the given (\a indArr) arrays as follows:
4233    * \a res[ \a indArr[ \a a[ i ]]] = i. I.e. for each value in place i \a v = \a a[ i ],
4234    * new value in place \a indArr[ \a v ] is i.
4235    *  \param [in] indArrBg - the array holding indices within the result array to assign
4236    *         indices of values of \a this array pointing to values of \a indArrBg.
4237    *  \param [in] indArrEnd - specifies the end of the array \a indArrBg, so that
4238    *              the last value of \a indArrBg is \a indArrEnd[ -1 ].
4239    *  \return DataArrayInt * - the new instance of DataArrayInt.
4240    *          The caller is to delete this result array using decrRef() as it is no more
4241    *          needed.
4242    *  \throw If \a this->getNumberOfComponents() != 1.
4243    *  \throw If any value of \a this array is not a valid index for \a indArrBg array.
4244    *  \throw If any value of \a indArrBg is not a valid index for \a this array.
4245    */
4246   template<class T>
4247   DataArrayIdType *DataArrayDiscrete<T>::transformWithIndArrR(const T *indArrBg, const T *indArrEnd) const
4248   {
4249     this->checkAllocated();
4250     if(this->getNumberOfComponents()!=1)
4251       throw INTERP_KERNEL::Exception("Call transformWithIndArrR method on DataArrayInt with only one component, you can call 'rearrange' method before !");
4252     mcIdType nbElemsIn=ToIdType(std::distance(indArrBg,indArrEnd));
4253     mcIdType nbOfTuples(this->getNumberOfTuples());
4254     const T *pt=this->getConstPointer();
4255     MCAuto<DataArrayIdType> ret=DataArrayIdType::New();
4256     ret->alloc(nbOfTuples,1);
4257     ret->fillWithValue(-1);
4258     mcIdType *tmp=ret->getPointer();
4259     for(mcIdType i=0;i<nbOfTuples;i++,pt++)
4260       {
4261         if(*pt>=0 && *pt<nbElemsIn)
4262           {
4263             T pos=indArrBg[*pt];
4264             if(pos>=0 && pos<nbOfTuples)
4265               tmp[ToIdType(pos)]=i;
4266             else
4267               {
4268                 std::ostringstream oss; oss << "DataArrayInt::transformWithIndArrR : error on tuple #" << i << " value of new pos is " << pos << " ( indArrBg[" << *pt << "]) ! Should be in [0," << nbOfTuples << ") !";
4269                 throw INTERP_KERNEL::Exception(oss.str().c_str());
4270               }
4271           }
4272         else
4273           {
4274             std::ostringstream oss; oss << "DataArrayInt::transformWithIndArrR : error on tuple #" << i << " value is " << *pt << " and indirectionnal array as a size equal to " << nbElemsIn << " !";
4275             throw INTERP_KERNEL::Exception(oss.str().c_str());
4276           }
4277       }
4278     return ret.retn();
4279   }
4280
4281   /*!
4282    * Computes distribution of values of \a this one-dimensional array between given value
4283    * ranges (casts). This method is typically useful for entity number splitting by types,
4284    * for example.
4285    *  \warning The values contained in \a arrBg should be sorted ascendently. No
4286    *           check of this is be done. If not, the result is not warranted.
4287    *  \param [in] arrBg - the array of ascending values defining the value ranges. The i-th
4288    *         value of \a arrBg (\a arrBg[ i ]) gives the lowest value of the i-th range,
4289    *         and the greatest value of the i-th range equals to \a arrBg[ i+1 ] - 1. \a
4290    *         arrBg containing \a n values defines \a n-1 ranges. The last value of \a arrBg
4291    *         should be more than every value in \a this array.
4292    *  \param [in] arrEnd - specifies the end of the array \a arrBg, so that
4293    *              the last value of \a arrBg is \a arrEnd[ -1 ].
4294    *  \param [out] castArr - a new instance of DataArrayInt, of same size as \a this array
4295    *         (same number of tuples and components), the caller is to delete
4296    *         using decrRef() as it is no more needed.
4297    *         This array contains indices of ranges for every value of \a this array. I.e.
4298    *         the i-th value of \a castArr gives the index of range the i-th value of \a this
4299    *         belongs to. Or, in other words, this parameter contains for each tuple in \a
4300    *         this in which cast it holds.
4301    *  \param [out] rankInsideCast - a new instance of DataArrayInt, of same size as \a this
4302    *         array, the caller is to delete using decrRef() as it is no more needed.
4303    *         This array contains ranks of values of \a this array within ranges
4304    *         they belongs to. I.e. the i-th value of \a rankInsideCast gives the rank of
4305    *         the i-th value of \a this array within the \a castArr[ i ]-th range, to which
4306    *         the i-th value of \a this belongs to. Or, in other words, this param contains
4307    *         for each tuple its rank inside its cast. The rank is computed as difference
4308    *         between the value and the lowest value of range.
4309    *  \param [out] castsPresent - a new instance of DataArrayInt, containing indices of
4310    *         ranges (casts) to which at least one value of \a this array belongs.
4311    *         Or, in other words, this param contains the casts that \a this contains.
4312    *         The caller is to delete this array using decrRef() as it is no more needed.
4313    *
4314    * \b Example: If \a this contains [6,5,0,3,2,7,8,1,4] and \a arrBg contains [0,4,9] then
4315    *            the output of this method will be :
4316    * - \a castArr       : [1,1,0,0,0,1,1,0,1]
4317    * - \a rankInsideCast: [2,1,0,3,2,3,4,1,0]
4318    * - \a castsPresent  : [0,1]
4319    *
4320    * I.e. values of \a this array belong to 2 ranges: #0 and #1. Value 6 belongs to the
4321    * range #1 and its rank within this range is 2; etc.
4322    *
4323    *  \throw If \a this->getNumberOfComponents() != 1.
4324    *  \throw If \a arrEnd - arrBg < 2.
4325    *  \throw If any value of \a this is not less than \a arrEnd[-1].
4326    */
4327   template<class T>
4328   void DataArrayDiscrete<T>::splitByValueRange(const T *arrBg, const T *arrEnd,
4329                                                DataArrayType *& castArr, DataArrayType *& rankInsideCast, DataArrayType *& castsPresent) const
4330   {
4331     this->checkAllocated();
4332     if(this->getNumberOfComponents()!=1)
4333       throw INTERP_KERNEL::Exception("Call splitByValueRange  method on DataArrayInt with only one component, you can call 'rearrange' method before !");
4334     mcIdType nbOfTuples=this->getNumberOfTuples();
4335     std::size_t nbOfCast=std::distance(arrBg,arrEnd);
4336     if(nbOfCast<2)
4337       throw INTERP_KERNEL::Exception("DataArrayInt::splitByValueRange : The input array giving the cast range values should be of size >=2 !");
4338     nbOfCast--;
4339     const T *work=this->getConstPointer();
4340     typedef std::reverse_iterator<const T *> rintstart;
4341     rintstart bg(arrEnd);//OK no problem because size of 'arr' is greater or equal 2
4342     rintstart end2(arrBg);
4343     MCAuto<DataArrayType> ret1=DataArrayType::New();
4344     MCAuto<DataArrayType> ret2=DataArrayType::New();
4345     MCAuto<DataArrayType> ret3=DataArrayType::New();
4346     ret1->alloc(nbOfTuples,1);
4347     ret2->alloc(nbOfTuples,1);
4348     T *ret1Ptr=ret1->getPointer();
4349     T *ret2Ptr=ret2->getPointer();
4350     std::set<T> castsDetected;
4351     for(mcIdType i=0;i<nbOfTuples;i++)
4352       {
4353         rintstart res=std::find_if(bg,end2,std::bind(std::less_equal<T>(),std::placeholders::_1,work[i]));
4354         std::size_t pos=std::distance(bg,res);
4355         std::size_t pos2=nbOfCast-pos;
4356         if(pos2<nbOfCast)
4357           {
4358             ret1Ptr[i]=static_cast<T>(pos2);
4359             ret2Ptr[i]=work[i]-arrBg[pos2];
4360             castsDetected.insert(ret1Ptr[i]);
4361           }
4362         else
4363           {
4364             std::ostringstream oss; oss << "DataArrayInt::splitByValueRange : At rank #" << i << " the value is " << work[i] << " should be in [0," << *bg << ") !";
4365             throw INTERP_KERNEL::Exception(oss.str().c_str());
4366           }
4367       }
4368     ret3->alloc(castsDetected.size(),1);
4369     std::copy(castsDetected.begin(),castsDetected.end(),ret3->getPointer());
4370     castArr=ret1.retn();
4371     rankInsideCast=ret2.retn();
4372     castsPresent=ret3.retn();
4373   }
4374
4375   /*!
4376    * 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 ).
4377    * 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 ).
4378    * This method works only if \a this is allocated and single component. If not an exception will be thrown.
4379    *
4380    * \param [out] strt - the start of the range (included) if true is returned.
4381    * \param [out] sttoopp - the end of the range (not included) if true is returned.
4382    * \param [out] stteepp - the step of the range if true is returned.
4383    * \return the verdict of the check.
4384    *
4385    * \sa DataArray::GetNumberOfItemGivenBES
4386    */
4387   template<class T>
4388   bool DataArrayDiscrete<T>::isRange(T& strt, T& sttoopp, T& stteepp) const
4389   {
4390     this->checkAllocated();
4391     if(this->getNumberOfComponents()!=1)
4392       throw INTERP_KERNEL::Exception("DataArrayInt::isRange : this must be single component array !");
4393     mcIdType nbTuples(this->getNumberOfTuples());
4394     if(nbTuples==0)
4395       { strt=0; sttoopp=0; stteepp=1; return true; }
4396     const T *pt(this->begin());
4397     strt=*pt;
4398     if(nbTuples==1)
4399       { sttoopp=strt+1; stteepp=1; return true; }
4400     strt=*pt; sttoopp=pt[nbTuples-1];
4401     if(strt==sttoopp)
4402       return false;
4403     if(sttoopp>strt)
4404       {
4405         sttoopp++;
4406         T a(sttoopp-1-strt),tmp(strt);
4407         if(a%(nbTuples-1)!=0)
4408           return false;
4409         stteepp=a/(FromIdType<T>(nbTuples)-1);
4410         for(mcIdType i=0;i<nbTuples;i++,tmp+=stteepp)
4411           if(pt[i]!=tmp)
4412             return false;
4413         return true;
4414       }
4415     else
4416       {
4417         sttoopp--;
4418         T a(strt-sttoopp-1),tmp(strt);
4419         if(a%(nbTuples-1)!=0)
4420           return false;
4421         stteepp=-(a/(FromIdType<T>(nbTuples)-1));
4422         for(mcIdType i=0;i<nbTuples;i++,tmp+=stteepp)
4423           if(pt[i]!=tmp)
4424             return false;
4425         return true;
4426       }
4427   }
4428
4429   /*!
4430    * Creates a one-dimensional DataArrayInt of given length, whose contents are computed
4431    * from values of \a this array, which is supposed to contain a renumbering map in
4432    * "Old to New" mode. The result array contains a renumbering map in "New to Old" mode.
4433    * To know how to use the renumbering maps see \ref numbering.
4434    *  \param [in] newNbOfElem - the number of tuples in the result array.
4435    *  \return DataArrayInt * - the new instance of DataArrayInt.
4436    *          The caller is to delete this result array using decrRef() as it is no more
4437    *          needed.
4438    *
4439    *  \if ENABLE_EXAMPLES
4440    *  \ref cpp_mcdataarrayint_invertarrayo2n2n2o "Here is a C++ example".<br>
4441    *  \ref py_mcdataarrayint_invertarrayo2n2n2o  "Here is a Python example".
4442    *  \endif
4443    */
4444   template<class T>
4445   DataArrayIdType * DataArrayDiscrete<T>::invertArrayO2N2N2O(mcIdType newNbOfElem) const
4446   {
4447     MCAuto<DataArrayIdType> ret(DataArrayIdType::New());
4448     ret->alloc(newNbOfElem,1);
4449     mcIdType nbOfOldNodes(this->getNumberOfTuples());
4450     const T *old2New(this->begin());
4451     mcIdType *pt(ret->getPointer());
4452     for(mcIdType i=0;i!=nbOfOldNodes;i++)
4453       {
4454         T newp(old2New[i]);
4455         if(newp!=-1)
4456           {
4457             if(newp>=0 && newp<newNbOfElem)
4458               pt[newp]=i;
4459             else
4460               {
4461                 std::ostringstream oss; oss << "DataArrayInt::invertArrayO2N2N2O : At place #" << i << " the newplace is " << newp << " must be in [0," << newNbOfElem << ") !";
4462                 throw INTERP_KERNEL::Exception(oss.str().c_str());
4463               }
4464           }
4465       }
4466     return ret.retn();
4467   }
4468
4469   /*!
4470    * Creates a one-dimensional DataArrayInt of given length, whose contents are computed
4471    * from values of \a this array, which is supposed to contain a renumbering map in
4472    * "New to Old" mode. The result array contains a renumbering map in "Old to New" mode.
4473    * To know how to use the renumbering maps see \ref numbering.
4474    *  \param [in] oldNbOfElem - the number of tuples in the result array.
4475    *  \return DataArrayInt * - the new instance of DataArrayInt.
4476    *          The caller is to delete this result array using decrRef() as it is no more
4477    *          needed.
4478    *
4479    *  \if ENABLE_EXAMPLES
4480    *  \ref cpp_mcdataarrayint_invertarrayn2o2o2n "Here is a C++ example".
4481    *
4482    *  \ref py_mcdataarrayint_invertarrayn2o2o2n "Here is a Python example".
4483    *  \sa invertArrayN2O2O2NOptimized
4484    *  \endif
4485    */
4486   template <class T>
4487   DataArrayIdType *DataArrayDiscrete<T>::invertArrayN2O2O2N(mcIdType oldNbOfElem) const
4488   {
4489     this->checkAllocated();
4490     MCAuto<DataArrayIdType> ret=DataArrayIdType::New();
4491     ret->alloc(oldNbOfElem,1);
4492     const T *new2Old=this->getConstPointer();
4493     mcIdType *pt=ret->getPointer();
4494     std::fill(pt,pt+oldNbOfElem,-1);
4495     mcIdType nbOfNewElems(this->getNumberOfTuples());
4496     for(mcIdType i=0;i<nbOfNewElems;i++)
4497       {
4498         T v(new2Old[i]);
4499         if(v>=0 && v<oldNbOfElem)
4500           pt[v]=i;
4501         else
4502           {
4503             std::ostringstream oss; oss << "DataArrayInt::invertArrayN2O2O2N : in new id #" << i << " old value is " << v << " expected to be in [0," << oldNbOfElem << ") !";
4504             throw INTERP_KERNEL::Exception(oss.str().c_str());
4505           }
4506       }
4507     return ret.retn();
4508   }
4509
4510   /*!
4511    * This method is similar to DataArrayInt::invertArrayO2N2N2O except that
4512    * 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]
4513    */
4514   template <class T>
4515   DataArrayIdType *DataArrayDiscrete<T>::invertArrayO2N2N2OBis(mcIdType newNbOfElem) const
4516   {
4517     MCAuto<DataArrayIdType> ret=DataArrayIdType::New();
4518     ret->alloc(newNbOfElem,1);
4519     mcIdType nbOfOldNodes(this->getNumberOfTuples());
4520     const T *old2New=this->getConstPointer();
4521     mcIdType *pt=ret->getPointer();
4522     for(mcIdType i=nbOfOldNodes-1;i>=0;i--)
4523       {
4524         T newp(old2New[i]);
4525         if(newp!=-1)
4526           {
4527             if(newp>=0 && newp<newNbOfElem)
4528               pt[newp]=i;
4529             else
4530               {
4531                 std::ostringstream oss; oss << "DataArrayInt::invertArrayO2N2N2OBis : At place #" << i << " the newplace is " << newp << " must be in [0," << newNbOfElem << ") !";
4532                 throw INTERP_KERNEL::Exception(oss.str().c_str());
4533               }
4534           }
4535       }
4536     return ret.retn();
4537   }
4538
4539   /*!
4540    * Creates a map, whose contents are computed
4541    * from values of \a this array, which is supposed to contain a renumbering map in
4542    * "New to Old" mode. The result array contains a renumbering map in "Old to New" mode.
4543    * To know how to use the renumbering maps see \ref numbering.
4544    *  \return MapII  - the new instance of Map.
4545    *
4546    *  \if ENABLE_EXAMPLES
4547    *  \ref cpp_mcdataarrayint_invertarrayn2o2o2n "Here is a C++ example".
4548    *
4549    *  \ref py_mcdataarrayint_invertarrayn2o2o2n "Here is a Python example".
4550    *  \sa invertArrayN2O2O2N, giveN2OOptimized, MEDCouplingPointSet::renumberNodesInConn
4551    *  \endif
4552    */
4553   template <class T>
4554   MCAuto< MapKeyVal<T, mcIdType> > DataArrayDiscrete<T>::invertArrayN2O2O2NOptimized() const
4555   {
4556     this->checkAllocated();
4557     if(this->getNumberOfComponents()!=1)
4558       throw INTERP_KERNEL::Exception("DataArrayInt::invertArrayN2O2O2NOptimized : single component expected !");
4559     MCAuto< MapKeyVal<T, mcIdType> > ret(MapKeyVal<T, mcIdType>::New());
4560     std::map<T, mcIdType>& m(ret->data());
4561     const T *new2Old(this->begin());
4562     mcIdType nbOfNewElems(this->getNumberOfTuples());
4563     for(mcIdType i=0;i<nbOfNewElems;i++)
4564       {
4565         T v(new2Old[i]);
4566         m[v]=i;
4567       }
4568     return ret;
4569   }
4570
4571   /*!
4572    * Creates a map, whose contents are computed
4573    * from values of \a this array, which is supposed to contain a renumbering map in
4574    * "New to Old" mode. The result array contains a renumbering map in "New to Old" mode as C++ map for performance reasons.
4575    *
4576    * \sa invertArrayN2O2O2NOptimized, MEDCouplingPointSet::renumberNodesInConn
4577    */
4578   template <class T>
4579   MCAuto< MapKeyVal<mcIdType, T> > DataArrayDiscrete<T>::giveN2OOptimized() const
4580   {
4581     this->checkAllocated();
4582     if(this->getNumberOfComponents()!=1)
4583       throw INTERP_KERNEL::Exception("DataArrayInt::giveN2OOptimized : single component expected !");
4584     MCAuto< MapKeyVal<mcIdType, T> > ret(MapKeyVal<mcIdType, T>::New());
4585     std::map<mcIdType,T>& m(ret->data());
4586     const T *new2Old(this->begin());
4587     mcIdType nbOfNewElems(this->getNumberOfTuples());
4588     for(mcIdType i=0;i<nbOfNewElems;i++)
4589       {
4590         T v(new2Old[i]);
4591         m[i]=v;
4592       }
4593     return ret;
4594   }
4595
4596   /*!
4597    * This method finds for each element \a ELT in [valsBg,valsEnd) elements in \a this equal to it. Associated to ELT
4598    * this method will return the tuple id of last element found. If there is no element in \a this equal to ELT
4599    * an exception will be thrown.
4600    *
4601    * In case of success this[ret]==vals. Samely ret->transformWithIndArr(this->begin(),this->end())==vals.
4602    * Where \a vals is the [valsBg,valsEnd) array and \a ret the array returned by this method.
4603    * This method can be seen as an extension of FindPermutationFromFirstToSecond.
4604    * <br>
4605    * \b Example: <br>
4606    * - \a this: [17,27,2,10,-4,3,12,27,16]
4607    * - \a val : [3,16,-4,27,17]
4608    * - result: [5,8,4,7,0]
4609    *
4610    * \return - An array of size std::distance(valsBg,valsEnd)
4611    *
4612    * \sa DataArrayInt::FindPermutationFromFirstToSecond , DataArrayInt::FindPermutationFromFirstToSecondDuplicate
4613    */
4614   template <class T>
4615   MCAuto<DataArrayIdType> DataArrayDiscrete<T>::findIdForEach(const T *valsBg, const T *valsEnd) const
4616   {
4617     MCAuto<DataArrayIdType> ret(DataArrayIdType::New());
4618     std::size_t nbOfTuplesOut(std::distance(valsBg,valsEnd));
4619     ret->alloc(nbOfTuplesOut,1);
4620     MCAuto< MapKeyVal<T, mcIdType> > zeMap(this->invertArrayN2O2O2NOptimized());
4621     const std::map<T, mcIdType>& dat(zeMap->data());
4622     mcIdType *ptToFeed(ret->getPointer());
4623     for(const T *pt=valsBg;pt!=valsEnd;pt++)
4624       {
4625         typename std::map<T,mcIdType>::const_iterator it(dat.find(*pt));
4626         if(it!=dat.end())
4627           *ptToFeed++=(*it).second;
4628         else
4629           {
4630             std::ostringstream oss; oss << "DataArrayInt::findIdForEach : error for element at place " << std::distance(valsBg,pt);
4631             oss << " of input array value is " << *pt << " which is not in this !";
4632             throw INTERP_KERNEL::Exception(oss.str());
4633           }
4634       }
4635     return ret;
4636   }
4637
4638   /*!
4639    * Returns a new DataArrayInt containing a renumbering map in "Old to New" mode.
4640    * This map, if applied to \a this array, would make it sorted. For example, if
4641    * \a this array contents are [9,10,0,6,4,11,3,7] then the contents of the result array
4642    * are [5,6,0,3,2,7,1,4]; if this result array (\a res) is used as an argument in call
4643    * \a this->renumber(\a res) then the returned array contains [0,3,4,6,7,9,10,11].
4644    * This method is useful for renumbering (in MED file for example). For more info
4645    * on renumbering see \ref numbering.
4646    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
4647    *          array using decrRef() as it is no more needed.
4648    *  \throw If \a this is not allocated.
4649    *  \throw If \a this->getNumberOfComponents() != 1.
4650    *  \throw If there are equal values in \a this array.
4651    */
4652   template <class T>
4653   DataArrayIdType *DataArrayDiscrete<T>::checkAndPreparePermutation() const
4654   {
4655     this->checkAllocated();
4656     if(this->getNumberOfComponents()!=1)
4657       throw INTERP_KERNEL::Exception("DataArrayInt::checkAndPreparePermutation : number of components must == 1 !");
4658     mcIdType nbTuples(this->getNumberOfTuples());
4659     const T *pt=this->getConstPointer();
4660     mcIdType *pt2=this->CheckAndPreparePermutation(pt,pt+nbTuples);
4661     DataArrayIdType *ret=DataArrayIdType::New();
4662     ret->useArray(pt2,true,DeallocType::C_DEALLOC,nbTuples,1);
4663     return ret;
4664   }
4665
4666   /*!
4667    * Returns two arrays describing a surjective mapping from \a this set of values (\a A)
4668    * onto a set of values of size \a targetNb (\a B). The surjective function is
4669    * \a B[ \a A[ i ]] = i. That is to say that for each \a id in [0,\a targetNb), where \a
4670    * targetNb < \a this->getNumberOfTuples(), there exists at least one tupleId (\a tid) so
4671    * that <em> this->getIJ( tid, 0 ) == id</em>. <br>
4672    * The first of out arrays returns indices of elements of \a this array, grouped by their
4673    * place in the set \a B. The second out array is the index of the first one; it shows how
4674    * many elements of \a A are mapped into each element of \a B. <br>
4675    * For more info on
4676    * mapping and its usage in renumbering see \ref numbering. <br>
4677    * \b Example:
4678    * - \a this: [0,3,2,3,2,2,1,2]
4679    * - \a targetNb: 4
4680    * - \a arr:  [0,  6,  2,4,5,7,  1,3]
4681    * - \a arrI: [0,1,2,6,8]
4682    *
4683    * This result means: <br>
4684    * the element of \a B 0 encounters within \a A once (\a arrI[ 0+1 ] - \a arrI[ 0 ]) and
4685    * its index within \a A is 0 ( \a arr[ 0:1 ] == \a arr[ \a arrI[ 0 ] : \a arrI[ 0+1 ]]);<br>
4686    * the element of \a B 2 encounters within \a A 4 times (\a arrI[ 2+1 ] - \a arrI[ 2 ]) and
4687    * its indices within \a A are [2,4,5,7] ( \a arr[ 2:6 ] == \a arr[ \a arrI[ 2 ] :
4688    * \a arrI[ 2+1 ]]); <br> etc.
4689    *  \param [in] targetNb - the size of the set \a B. \a targetNb must be equal or more
4690    *         than the maximal value of \a A.
4691    *  \param [out] arr - a new instance of DataArrayInt returning indices of
4692    *         elements of \a this, grouped by their place in the set \a B. The caller is to delete
4693    *         this array using decrRef() as it is no more needed.
4694    *  \param [out] arrI - a new instance of DataArrayInt returning size of groups of equal
4695    *         elements of \a this. The caller is to delete this array using decrRef() as it
4696    *         is no more needed.
4697    *  \throw If \a this is not allocated.
4698    *  \throw If \a this->getNumberOfComponents() != 1.
4699    *  \throw If any value in \a this is more or equal to \a targetNb.
4700    */
4701   template <class T>
4702   void DataArrayDiscrete<T>::changeSurjectiveFormat(T targetNb, DataArrayIdType *&arr, DataArrayIdType *&arrI) const
4703   {
4704     this->checkAllocated();
4705     if(this->getNumberOfComponents()!=1)
4706       throw INTERP_KERNEL::Exception("DataArrayInt::changeSurjectiveFormat : number of components must == 1 !");
4707     mcIdType nbOfTuples(this->getNumberOfTuples());
4708     const T *input=this->getConstPointer();
4709     std::vector< std::vector<mcIdType> > tmp(targetNb);
4710     for(mcIdType i=0;i<nbOfTuples;i++)
4711       {
4712         T tmp2=input[i];
4713         if(tmp2>=0 && tmp2<targetNb)
4714           tmp[tmp2].push_back(i);
4715         else
4716           {
4717             std::ostringstream oss; oss << "DataArrayInt::changeSurjectiveFormat : At pos " << i << " presence of element " << tmp2 << " ! should be in [0," << targetNb << ") !";
4718             throw INTERP_KERNEL::Exception(oss.str().c_str());
4719           }
4720       }
4721
4722     MCAuto<DataArrayIdType> retI(DataArrayIdType::New());
4723     retI->alloc(targetNb+1,1);
4724     mcIdType *retIPtr=retI->getPointer();
4725     *retIPtr=0;
4726     for(std::vector< std::vector<mcIdType> >::const_iterator it1=tmp.begin();it1!=tmp.end();it1++,retIPtr++)
4727       retIPtr[1]=retIPtr[0]+ToIdType((*it1).size());
4728     if(nbOfTuples!=retI->getIJ(ToIdType(targetNb),0))
4729       throw INTERP_KERNEL::Exception("DataArrayInt::changeSurjectiveFormat : big problem should never happen !");
4730     MCAuto<DataArrayIdType> ret(DataArrayIdType::New());
4731     ret->alloc(nbOfTuples,1);
4732     mcIdType *retPtr=ret->getPointer();
4733     for(std::vector< std::vector<mcIdType> >::const_iterator it1=tmp.begin();it1!=tmp.end();it1++)
4734       retPtr=std::copy((*it1).begin(),(*it1).end(),retPtr);
4735     arr=ret.retn();
4736     arrI=retI.retn();
4737   }
4738
4739   /*!
4740    * Returns a new DataArrayInt containing a renumbering map in "New to Old" mode,
4741    * which if applied to \a this array would make it sorted ascendingly.
4742    * For more info on renumbering see \ref numbering. <br>
4743    * \b Example: <br>
4744    * - \a this: [2,0,1,1,0,1,2,0,1,1,0,0]
4745    * - result: [10,0,5,6,1,7,11,2,8,9,3,4]
4746    * - after applying result to \a this: [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2]
4747    *
4748    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
4749    *          array using decrRef() as it is no more needed.
4750    *  \throw If \a this is not allocated.
4751    *  \throw If \a this->getNumberOfComponents() != 1.
4752    */
4753   template <class T>
4754   DataArrayIdType *DataArrayDiscrete<T>::buildPermArrPerLevel() const
4755   {
4756     this->checkAllocated();
4757     if(this->getNumberOfComponents()!=1)
4758       throw INTERP_KERNEL::Exception("DataArrayInt::buildPermArrPerLevel : number of components must == 1 !");
4759     mcIdType nbOfTuples=this->getNumberOfTuples();
4760     const T *pt=this->getConstPointer();
4761     std::map<T,mcIdType> m;
4762     MCAuto<DataArrayIdType> ret=DataArrayIdType::New();
4763     ret->alloc(nbOfTuples,1);
4764     mcIdType *opt=ret->getPointer();
4765     for(mcIdType i=0;i<nbOfTuples;i++,pt++,opt++)
4766       {
4767         T val=*pt;
4768         typename std::map<T,mcIdType>::iterator it=m.find(val);
4769         if(it!=m.end())
4770           {
4771             *opt=(*it).second;
4772             (*it).second++;
4773           }
4774         else
4775           {
4776             *opt=0;
4777             m.insert(std::pair<T,mcIdType>(val,1));
4778           }
4779       }
4780     mcIdType sum=0;
4781     for(typename std::map<T,mcIdType>::iterator it=m.begin();it!=m.end();it++)
4782       {
4783         mcIdType vt=(*it).second;
4784         (*it).second=sum;
4785         sum+=vt;
4786       }
4787     pt=this->getConstPointer();
4788     opt=ret->getPointer();
4789     for(mcIdType i=0;i<nbOfTuples;i++,pt++,opt++)
4790       *opt+=m[*pt];
4791     //
4792     return ret.retn();
4793   }
4794
4795   /*!
4796    * Checks if \a this array has the given size, and if its contents is equal to an array filled with
4797    * iota(). This method is particularly useful for DataArrayInt instances that represent
4798    * a renumbering array, to check if there is a real need in renumbering.
4799    * This method checks than \a this can be considered as an identity mapping
4800    * of a set having \a sizeExpected elements into itself.
4801    *
4802    *  \param [in] sizeExpected - The number of elements expected.
4803    *  \return bool - \a true if \a this array contents == \a range( \a this->getNumberOfTuples())
4804    *  \throw If \a this is not allocated.
4805    *  \throw If \a this->getNumberOfComponents() != 1.
4806    */
4807   template <class T>
4808   bool DataArrayDiscrete<T>::isIota(mcIdType sizeExpected) const
4809   {
4810     this->checkAllocated();
4811     if(this->getNumberOfComponents()!=1)
4812       return false;
4813     mcIdType nbOfTuples(this->getNumberOfTuples());
4814     if(nbOfTuples!=sizeExpected)
4815       return false;
4816     const T *pt=this->getConstPointer();
4817     for(mcIdType i=0;i<nbOfTuples;i++,pt++)
4818       if(*pt!=i)
4819         return false;
4820     return true;
4821   }
4822
4823   /*!
4824    * Checks if all values in \a this array are equal to \a val.
4825    *  \param [in] val - value to check equality of array values to.
4826    *  \return bool - \a true if all values are \a val.
4827    *  \throw If \a this is not allocated.
4828    *  \throw If \a this->getNumberOfComponents() != 1
4829    *  \sa DataArrayInt::checkUniformAndGuess
4830    */
4831   template <class T>
4832   bool DataArrayDiscrete<T>::isUniform(T val) const
4833   {
4834     this->checkAllocated();
4835     if(this->getNumberOfComponents()!=1)
4836       throw INTERP_KERNEL::Exception("DataArrayInt::isUniform : must be applied on DataArrayInt with only one component, you can call 'rearrange' method before !");
4837     const T *w(this->begin()),*end2(this->end());
4838     for(;w!=end2;w++)
4839       if(*w!=val)
4840         return false;
4841     return true;
4842   }
4843
4844   /*!
4845    * This method checks that \a this is uniform. If not and exception will be thrown.
4846    * In case of uniformity the corresponding value is returned.
4847    *
4848    * \return mcIdType - the unique value contained in this
4849    * \throw If \a this is not allocated.
4850    * \throw If \a this->getNumberOfComponents() != 1
4851    * \throw If \a this is not uniform.
4852    * \sa DataArrayInt::isUniform
4853    */
4854   template <class T>
4855   T DataArrayDiscrete<T>::checkUniformAndGuess() const
4856   {
4857     this->checkAllocated();
4858     if(this->getNumberOfComponents()!=1)
4859       throw INTERP_KERNEL::Exception("DataArrayInt::checkUniformAndGuess : must be applied on DataArrayInt with only one component, you can call 'rearrange' method before !");
4860     if(this->empty())
4861       throw INTERP_KERNEL::Exception("DataArrayInt::checkUniformAndGuess : this is empty !");
4862     const T *w(this->begin()),*end2(this->end());
4863     T ret(*w);
4864     for(;w!=end2;w++)
4865       if(*w!=ret)
4866         throw INTERP_KERNEL::Exception("DataArrayInt::checkUniformAndGuess : this is not uniform !");
4867     return ret;
4868   }
4869
4870   /*!
4871    * Checks if all values in \a this array are unique.
4872    *  \return bool - \a true if condition above is true
4873    *  \throw If \a this is not allocated.
4874    *  \throw If \a this->getNumberOfComponents() != 1
4875    */
4876   template <class T>
4877   bool DataArrayDiscrete<T>::hasUniqueValues() const
4878   {
4879     this->checkAllocated();
4880     if(this->getNumberOfComponents()!=1)
4881       throw INTERP_KERNEL::Exception("DataArrayInt::hasOnlyUniqueValues: must be applied on DataArrayInt with only one component, you can call 'rearrange' method before !");
4882     std::size_t nbOfElements(this->getNumberOfTuples());
4883     std::set<T> s(this->begin(),this->end());  // in C++11, should use unordered_set (O(1) complexity)
4884     if (s.size() != nbOfElements)
4885       return false;
4886     return true;
4887   }
4888
4889   /*!
4890    * Copy all components in a specified order from another DataArrayInt.
4891    * The specified components become the first ones in \a this array.
4892    * Both numerical and textual data is copied. The number of tuples in \a this and
4893    * the other array can be different.
4894    *  \param [in] a - the array to copy data from.
4895    *  \param [in] compoIds - sequence of zero based indices of components, data of which is
4896    *              to be copied.
4897    *  \throw If \a a is NULL.
4898    *  \throw If \a compoIds.size() != \a a->getNumberOfComponents().
4899    *  \throw If \a compoIds[i] < 0 or \a compoIds[i] > \a this->getNumberOfComponents().
4900    *
4901    *  \if ENABLE_EXAMPLES
4902    *  \ref py_mcdataarrayint_setselectedcomponents "Here is a Python example".
4903    *  \endif
4904    */
4905   template <class T>
4906   void DataArrayDiscrete<T>::setSelectedComponents(const DataArrayType *a, const std::vector<std::size_t>& compoIds)
4907   {
4908     if(!a)
4909       throw INTERP_KERNEL::Exception("DataArrayInt::setSelectedComponents : input DataArrayInt is NULL !");
4910     this->checkAllocated();
4911     a->checkAllocated();
4912     this->copyPartOfStringInfoFrom2(compoIds,*a);
4913     std::size_t partOfCompoSz=compoIds.size();
4914     std::size_t nbOfCompo = this->getNumberOfComponents();
4915     mcIdType nbOfTuples=std::min(this->getNumberOfTuples(),a->getNumberOfTuples());
4916     const T *ac=a->getConstPointer();
4917     T *nc=this->getPointer();
4918     for(mcIdType i=0;i<nbOfTuples;i++)
4919       for(std::size_t j=0;j<partOfCompoSz;j++,ac++)
4920         nc[nbOfCompo*i+compoIds[j]]=*ac;
4921   }
4922
4923   /*!
4924    * This method searches each value in \a valToSearchIntoTuples among values in \a this given the corresponding tuple to find into.
4925    * If the value at the corresponding tuple is not found in the tuple an exception will be thrown.
4926    * If the value is found the corresponding component id is returned.
4927    * 
4928    *  \param [in] valToSearchIntoTuples - a one component array containing the values to find in \a this
4929    *  \param [in] tupleIdHint - a one component array having same size than \a valToSearchIntoTuples giving for each value the tuple to find into
4930    *  \return DataArrayInt * - A newly allocated array having same size than \a valToSearchIntoTuples with one component
4931    * 
4932    *   \b Example: <br>
4933    *          - \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)]
4934    *          - \a valToSearchIntoTuples: [1, 4, 6, 8, 10, 12, 14, 16, 17]
4935    *          - \a tupleIdHint: [0, 1, 2, 3, 4, 5, 6, 7, 7]
4936    *          - result array: [1, 1, 0, 1, 2, 1, 0, 1, 2] == <br>
4937    */
4938   template <class T>
4939   DataArrayIdType *DataArrayDiscrete<T>::locateComponentId(const DataArrayType *valToSearchIntoTuples, const DataArrayIdType *tupleIdHint) const
4940   {
4941     if(!valToSearchIntoTuples || !tupleIdHint)
4942       THROW_IK_EXCEPTION("DataArrayInt::locateComponentId : valToSearchIntoTuples and tupleIdHint must be not nullptr !");
4943     valToSearchIntoTuples->checkAllocated(); tupleIdHint->checkAllocated();
4944     this->checkAllocated();
4945     constexpr char MSG1[] = "DataArrayInt::locateComponentId : single component array expected";
4946     valToSearchIntoTuples->checkNbOfComps(1,MSG1); tupleIdHint->checkNbOfComps(1,MSG1);
4947     std::size_t nbOfCompo( this->getNumberOfComponents() );
4948     mcIdType thisNbTuples( this->getNumberOfTuples() );
4949     mcIdType nbOfTuples( valToSearchIntoTuples->getNumberOfTuples() );
4950     tupleIdHint->checkNbOfTuples(nbOfTuples,"Number of tuples of input arrays must be the same.");
4951     const T *cPtr(this->begin()),*valSearchPt(valToSearchIntoTuples->begin());
4952     const mcIdType *tHintPtr(tupleIdHint->begin());
4953     MCAuto<DataArrayIdType> ret = DataArrayIdType::New();
4954     ret->alloc(nbOfTuples,1);
4955     mcIdType *retPtr(ret->getPointer());
4956     for(auto i = 0 ; i < nbOfTuples ; ++i)
4957     {
4958       if( tHintPtr[i] >=0 && tHintPtr[i] < thisNbTuples )
4959       {
4960         auto strtSearch(cPtr+nbOfCompo*tHintPtr[i]),endSearch(cPtr+nbOfCompo*(tHintPtr[i]+1));
4961         auto pos = std::find(strtSearch,endSearch,valSearchPt[i]);
4962         if(pos != endSearch)
4963           *retPtr++ = ToIdType( std::distance(strtSearch,pos) );
4964         else
4965           THROW_IK_EXCEPTION("At pos " << i << " value " << valSearchPt[i] << " is not present at tuple " << tHintPtr[i]);
4966       }
4967       else
4968         THROW_IK_EXCEPTION("At pos " << i << " hint tuple is " << tHintPtr[i] << " not in [0," << thisNbTuples << ")");
4969     }
4970     return ret.retn();
4971   }
4972
4973   /*!
4974    * Creates a new DataArrayInt containing IDs (indices) of tuples holding value \b not
4975    * equal to a given one.
4976    *  \param [in] val - the value to ignore within \a this.
4977    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
4978    *          array using decrRef() as it is no more needed.
4979    *  \throw If \a this is not allocated.
4980    *  \throw If \a this->getNumberOfComponents() != 1.
4981    */
4982   template <class T>
4983   DataArrayIdType *DataArrayDiscrete<T>::findIdsNotEqual(T val) const
4984   {
4985     this->checkAllocated();
4986     if(this->getNumberOfComponents()!=1)
4987       throw INTERP_KERNEL::Exception("DataArrayInt::findIdsNotEqual : the array must have only one component, you can call 'rearrange' method before !");
4988     const T *cptr(this->getConstPointer());
4989     MCAuto<DataArrayIdType> ret(DataArrayIdType::New());
4990     ret->alloc(0,1);
4991     mcIdType nbOfTuples(this->getNumberOfTuples());
4992     for(mcIdType i=0;i<nbOfTuples;i++,cptr++)
4993       if(*cptr!=val)
4994         ret->pushBackSilent(i);
4995     return ret.retn();
4996   }
4997
4998   /*!
4999    * Creates a new DataArrayInt containing IDs (indices) of tuples holding tuple equal to those defined by [ \a tupleBg , \a tupleEnd )
5000    * This method is an extension of  DataArrayInt::findIdsEqual method.
5001    *
5002    *  \param [in] tupleBg - the begin (included) of the input tuple to find within \a this.
5003    *  \param [in] tupleEnd - the end (excluded) of the input tuple to find within \a this.
5004    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
5005    *          array using decrRef() as it is no more needed.
5006    *  \throw If \a this is not allocated.
5007    *  \throw If \a this->getNumberOfComponents() != std::distance(tupleBg,tupleEnd).
5008    * \throw If \a this->getNumberOfComponents() is equal to 0.
5009    * \sa DataArrayInt::findIdsEqual
5010    */
5011   template <class T>
5012   DataArrayIdType *DataArrayDiscrete<T>::findIdsEqualTuple(const T *tupleBg, const T *tupleEnd) const
5013   {
5014     std::size_t nbOfCompoExp=std::distance(tupleBg,tupleEnd);
5015     this->checkAllocated();
5016     if(this->getNumberOfComponents()!=nbOfCompoExp)
5017       {
5018         std::ostringstream oss; oss << "DataArrayInt::findIdsEqualTuple : mismatch of number of components. Input tuple has " << nbOfCompoExp << " whereas this array has " << this->getNumberOfComponents() << " components !";
5019         throw INTERP_KERNEL::Exception(oss.str().c_str());
5020       }
5021     if(nbOfCompoExp==0)
5022       throw INTERP_KERNEL::Exception("DataArrayInt::findIdsEqualTuple : number of components should be > 0 !");
5023     MCAuto<DataArrayIdType> ret(DataArrayIdType::New());
5024     ret->alloc(0,1);
5025     const T *bg(this->begin()),*end2(this->end()),*work(this->begin());
5026     while(work!=end2)
5027       {
5028         work=std::search(work,end2,tupleBg,tupleEnd);
5029         if(work!=end2)
5030           {
5031             std::ptrdiff_t pos=std::distance(bg,work);
5032             if(pos%nbOfCompoExp==0)
5033               ret->pushBackSilent(ToIdType(pos/nbOfCompoExp));
5034             work++;
5035           }
5036       }
5037     return ret.retn();
5038   }
5039
5040   /*!
5041    * Creates a new DataArrayInt containing IDs (indices) of tuples holding value equal to
5042    * one of given values.
5043    *  \param [in] valsBg - an array of values to find within \a this array.
5044    *  \param [in] valsEnd - specifies the end of the array \a valsBg, so that
5045    *              the last value of \a valsBg is \a valsEnd[ -1 ].
5046    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
5047    *          array using decrRef() as it is no more needed.
5048    *  \throw If \a this->getNumberOfComponents() != 1.
5049    */
5050   template <class T>
5051   DataArrayIdType *DataArrayDiscrete<T>::findIdsEqualList(const T *valsBg, const T *valsEnd) const
5052   {
5053     if(this->getNumberOfComponents()!=1)
5054       throw INTERP_KERNEL::Exception("DataArrayInt::findIdsEqualList : the array must have only one component, you can call 'rearrange' method before !");
5055     std::set<T> vals2(valsBg,valsEnd);
5056     const T *cptr(this->getConstPointer());
5057     mcIdType nbOfTuples(this->getNumberOfTuples());
5058     MCAuto<DataArrayIdType> ret(DataArrayIdType::New()); ret->alloc(0,1);
5059     for(mcIdType i=0;i<nbOfTuples;i++,cptr++)
5060       if(vals2.find(*cptr)!=vals2.end())
5061         ret->pushBackSilent(i);
5062     return ret.retn();
5063   }
5064
5065   /*!
5066    * Creates a new DataArrayInt containing IDs (indices) of tuples holding values \b not
5067    * equal to any of given values.
5068    *  \param [in] valsBg - an array of values to ignore within \a this array.
5069    *  \param [in] valsEnd - specifies the end of the array \a valsBg, so that
5070    *              the last value of \a valsBg is \a valsEnd[ -1 ].
5071    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
5072    *          array using decrRef() as it is no more needed.
5073    *  \throw If \a this->getNumberOfComponents() != 1.
5074    */
5075   template <class T>
5076   DataArrayIdType *DataArrayDiscrete<T>::findIdsNotEqualList(const T *valsBg, const T *valsEnd) const
5077   {
5078     if(this->getNumberOfComponents()!=1)
5079       throw INTERP_KERNEL::Exception("DataArrayInt::findIdsNotEqualList : the array must have only one component, you can call 'rearrange' method before !");
5080     std::set<T> vals2(valsBg,valsEnd);
5081     const T *cptr=this->getConstPointer();
5082     mcIdType nbOfTuples(this->getNumberOfTuples());
5083     MCAuto<DataArrayIdType> ret(DataArrayIdType::New()); ret->alloc(0,1);
5084     for(mcIdType i=0;i<nbOfTuples;i++,cptr++)
5085       if(vals2.find(*cptr)==vals2.end())
5086         ret->pushBackSilent(i);
5087     return ret.retn();
5088   }
5089
5090   /*!
5091    * This method expects to be called when number of components of this is equal to one.
5092    * This method returns the tuple id, if it exists, of the first tuple equal to \b value.
5093    * If not any tuple contains \b value -1 is returned.
5094    * \sa DataArrayInt::presenceOfValue
5095    */
5096   template <class T>
5097   mcIdType DataArrayDiscrete<T>::findIdFirstEqual(T value) const
5098   {
5099     this->checkAllocated();
5100     if(this->getNumberOfComponents()!=1)
5101       throw INTERP_KERNEL::Exception("DataArrayInt::presenceOfValue : the array must have only one component, you can call 'rearrange' method before !");
5102     const T *cptr=this->getConstPointer();
5103     mcIdType nbOfTuples(this->getNumberOfTuples());
5104     const T *ret=std::find(cptr,cptr+nbOfTuples,value);
5105     if(ret!=cptr+nbOfTuples)
5106       return ToIdType(std::distance(cptr,ret));
5107     return -1;
5108   }
5109
5110   /*!
5111    * This method expects to be called when number of components of this is equal to one.
5112    * This method returns the tuple id, if it exists, of the first tuple so that the value is contained in \b vals.
5113    * If not any tuple contains one of the values contained in 'vals' -1 is returned.
5114    * \sa DataArrayInt::presenceOfValue
5115    */
5116   template <class T>
5117   mcIdType DataArrayDiscrete<T>::findIdFirstEqual(const std::vector<T>& vals) const
5118   {
5119     this->checkAllocated();
5120     if(this->getNumberOfComponents()!=1)
5121       throw INTERP_KERNEL::Exception("DataArrayInt::presenceOfValue : the array must have only one component, you can call 'rearrange' method before !");
5122     std::set<T> vals2(vals.begin(),vals.end());
5123     const T *cptr=this->getConstPointer();
5124     mcIdType nbOfTuples(this->getNumberOfTuples());
5125     for(const T *w=cptr;w!=cptr+nbOfTuples;w++)
5126       if(vals2.find(*w)!=vals2.end())
5127         return ToIdType(std::distance(cptr,w));
5128     return -1;
5129   }
5130
5131   /*!
5132    * This method is an extension of DataArrayInt::findIdFirstEqual method because this method works for DataArrayInt with
5133    * any number of components excepted 0 (an INTERP_KERNEL::Exception is thrown in this case).
5134    * This method searches in \b this is there is a tuple that matched the input parameter \b tupl.
5135    * If any the tuple id is returned. If not -1 is returned.
5136    *
5137    * This method throws an INTERP_KERNEL::Exception if the number of components in \b this mismatches with the size of
5138    * the input vector. An INTERP_KERNEL::Exception is thrown too if \b this is not allocated.
5139    *
5140    * \return tuple id where \b tupl is. -1 if no such tuple exists in \b this.
5141    * \sa DataArrayInt::findIdSequence, DataArrayInt::presenceOfTuple.
5142    */
5143   template <class T>
5144   mcIdType DataArrayDiscrete<T>::findIdFirstEqualTuple(const std::vector<T>& tupl) const
5145   {
5146     this->checkAllocated();
5147     std::size_t nbOfCompo(this->getNumberOfComponents());
5148     if(nbOfCompo==0)
5149       throw INTERP_KERNEL::Exception("DataArrayInt::findIdFirstEqualTuple : 0 components in 'this' !");
5150     if(nbOfCompo!=tupl.size())
5151       {
5152         std::ostringstream oss; oss << "DataArrayInt::findIdFirstEqualTuple : 'this' contains " << nbOfCompo << " components and searching for a tuple of length " << tupl.size() << " !";
5153         throw INTERP_KERNEL::Exception(oss.str().c_str());
5154       }
5155     const T *cptr=this->getConstPointer();
5156     std::size_t nbOfVals=this->getNbOfElems();
5157     for(const T *work=cptr;work!=cptr+nbOfVals;)
5158       {
5159         work=std::search(work,cptr+nbOfVals,tupl.begin(),tupl.end());
5160         if(work!=cptr+nbOfVals)
5161           {
5162             if(std::distance(cptr,work)%nbOfCompo!=0)
5163               work++;
5164             else
5165               return ToIdType (std::distance(cptr,work)/nbOfCompo);
5166           }
5167       }
5168     return -1;
5169   }
5170
5171   /*!
5172    * This method searches the sequence specified in input parameter \b vals in \b this.
5173    * This works only for DataArrayInt having number of components equal to one (if not an INTERP_KERNEL::Exception will be thrown).
5174    * This method differs from DataArrayInt::findIdFirstEqualTuple in that the position is internal raw data is not considered here contrary to DataArrayInt::findIdFirstEqualTuple.
5175    * \sa DataArrayInt::findIdFirstEqualTuple
5176    */
5177   template <class T>
5178   mcIdType DataArrayDiscrete<T>::findIdSequence(const std::vector<T>& vals) const
5179   {
5180     this->checkAllocated();
5181     std::size_t nbOfCompo=this->getNumberOfComponents();
5182     if(nbOfCompo!=1)
5183       throw INTERP_KERNEL::Exception("DataArrayInt::findIdSequence : works only for DataArrayInt instance with one component !");
5184     const T *cptr=this->getConstPointer();
5185     std::size_t nbOfVals=this->getNbOfElems();
5186     const T *loc=std::search(cptr,cptr+nbOfVals,vals.begin(),vals.end());
5187     if(loc!=cptr+nbOfVals)
5188       return ToIdType(std::distance(cptr,loc));
5189     return -1;
5190   }
5191
5192   /*!
5193    * Assigns \a newValue to all elements holding \a oldValue within \a this
5194    * one-dimensional array.
5195    *  \param [in] oldValue - the value to replace.
5196    *  \param [in] newValue - the value to assign.
5197    *  \return mcIdType - number of replacements performed.
5198    *  \throw If \a this is not allocated.
5199    *  \throw If \a this->getNumberOfComponents() != 1.
5200    */
5201   template <class T>
5202   mcIdType DataArrayDiscrete<T>::changeValue(T oldValue, T newValue)
5203   {
5204     this->checkAllocated();
5205     if(this->getNumberOfComponents()!=1)
5206       throw INTERP_KERNEL::Exception("DataArrayInt::changeValue : the array must have only one component, you can call 'rearrange' method before !");
5207     if(oldValue==newValue)
5208       return 0;
5209     T *start(this->getPointer()),*end2(start+this->getNbOfElems());
5210     mcIdType ret(0);
5211     for(T *val=start;val!=end2;val++)
5212       {
5213         if(*val==oldValue)
5214           {
5215             *val=newValue;
5216             ret++;
5217           }
5218       }
5219     if(ret>0)
5220       this->declareAsNew();
5221     return ret;
5222   }
5223
5224   /*!
5225    * This method returns the number of values in \a this that are equals to input parameter \a value.
5226    * This method only works for single component array.
5227    *
5228    * \return a value in [ 0, \c this->getNumberOfTuples() )
5229    *
5230    * \throw If \a this is not allocated
5231    *
5232    */
5233   template <class T>
5234   mcIdType DataArrayDiscrete<T>::count(T value) const
5235   {
5236     mcIdType ret=0;
5237     this->checkAllocated();
5238     if(this->getNumberOfComponents()!=1)
5239       throw INTERP_KERNEL::Exception("DataArrayInt::count : must be applied on DataArrayInt with only one component, you can call 'rearrange' method before !");
5240     const T *vals=this->begin();
5241     std::size_t nbOfElements=this->getNumberOfTuples();
5242     for(std::size_t i=0;i<nbOfElements;i++,vals++)
5243       if(*vals==value)
5244         ret++;
5245     return ret;
5246   }
5247
5248   /*!
5249    * This method is an extension of DataArrayInt::presenceOfValue method because this method works for DataArrayInt with
5250    * any number of components excepted 0 (an INTERP_KERNEL::Exception is thrown in this case).
5251    * This method searches in \b this is there is a tuple that matched the input parameter \b tupl.
5252    * This method throws an INTERP_KERNEL::Exception if the number of components in \b this mismatches with the size of
5253    * the input vector. An INTERP_KERNEL::Exception is thrown too if \b this is not allocated.
5254    * \sa DataArrayInt::findIdFirstEqualTuple
5255    */
5256   template <class T>
5257   bool DataArrayDiscrete<T>::presenceOfTuple(const std::vector<T>& tupl) const
5258   {
5259     return this->findIdFirstEqualTuple(tupl)!=-1;
5260   }
5261
5262
5263   /*!
5264    * Returns \a true if a given value is present within \a this one-dimensional array.
5265    *  \param [in] value - the value to find within \a this array.
5266    *  \return bool - \a true in case if \a value is present within \a this array.
5267    *  \throw If \a this is not allocated.
5268    *  \throw If \a this->getNumberOfComponents() != 1.
5269    *  \sa findIdFirstEqual()
5270    */
5271   template <class T>
5272   bool DataArrayDiscrete<T>::presenceOfValue(T value) const
5273   {
5274     return this->findIdFirstEqual(value)!=-1;
5275   }
5276
5277   /*!
5278    * This method expects to be called when number of components of this is equal to one.
5279    * This method returns true if it exists a tuple so that the value is contained in \b vals.
5280    * If not any tuple contains one of the values contained in 'vals' false is returned.
5281    * \sa DataArrayInt::findIdFirstEqual
5282    */
5283   template <class T>
5284   bool DataArrayDiscrete<T>::presenceOfValue(const std::vector<T>& vals) const
5285   {
5286     return this->findIdFirstEqual(vals)!=-1;
5287   }
5288
5289   /*!
5290    * Accumulates values of each component of \a this array.
5291    *  \param [out] res - an array of length \a this->getNumberOfComponents(), allocated
5292    *         by the caller, that is filled by this method with sum value for each
5293    *         component.
5294    *  \throw If \a this is not allocated.
5295    */
5296   template <class T>
5297   void DataArrayDiscrete<T>::accumulate(T *res) const
5298   {
5299     this->checkAllocated();
5300     const T *ptr=this->getConstPointer();
5301     mcIdType nbTuple(this->getNumberOfTuples());
5302     std::size_t nbComps(this->getNumberOfComponents());
5303     std::fill(res,res+nbComps,0);
5304     for(mcIdType i=0;i<nbTuple;i++)
5305       std::transform(ptr+i*nbComps,ptr+(i+1)*nbComps,res,res,std::plus<T>());
5306   }
5307
5308   template <class T>
5309   T DataArrayDiscrete<T>::accumulate(std::size_t compId) const
5310   {
5311     this->checkAllocated();
5312     const T *ptr=this->getConstPointer();
5313     mcIdType nbTuple(this->getNumberOfTuples());
5314     std::size_t nbComps(this->getNumberOfComponents());
5315     if(compId>=nbComps) // compId >= 0 (it is a size_t)
5316       throw INTERP_KERNEL::Exception("DataArrayInt::accumulate : Invalid compId specified : No such nb of components !");
5317     T ret=0;
5318     for(mcIdType i=0;i<nbTuple;i++)
5319       ret+=ptr[i*nbComps+compId];
5320     return ret;
5321   }
5322
5323   /*!
5324    * This method accumulate using addition tuples in \a this using input index array [ \a bgOfIndex, \a endOfIndex ).
5325    * The returned array will have same number of components than \a this and number of tuples equal to
5326    * \c std::distance(bgOfIndex,endOfIndex) \b minus \b one.
5327    *
5328    * The input index array is expected to be ascendingly sorted in which the all referenced ids should be in [0, \c this->getNumberOfTuples).
5329    *
5330    * \param [in] bgOfIndex - begin (included) of the input index array.
5331    * \param [in] endOfIndex - end (excluded) of the input index array.
5332    * \return DataArrayInt * - the new instance having the same number of components than \a this.
5333    *
5334    * \throw If bgOfIndex or end is NULL.
5335    * \throw If input index array is not ascendingly sorted.
5336    * \throw If there is an id in [ \a bgOfIndex, \a endOfIndex ) not in [0, \c this->getNumberOfTuples).
5337    * \throw If std::distance(bgOfIndex,endOfIndex)==0.
5338    */
5339   template <class T>
5340   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::accumulatePerChunck(const mcIdType *bgOfIndex, const mcIdType *endOfIndex) const
5341   {
5342     if(!bgOfIndex || !endOfIndex)
5343       throw INTERP_KERNEL::Exception("DataArrayInt::accumulatePerChunck : input pointer NULL !");
5344     this->checkAllocated();
5345     std::size_t nbCompo(this->getNumberOfComponents());
5346     mcIdType nbOfTuples(this->getNumberOfTuples());
5347     mcIdType sz=ToIdType(std::distance(bgOfIndex,endOfIndex));
5348     if(sz<1)
5349       throw INTERP_KERNEL::Exception("DataArrayInt::accumulatePerChunck : invalid size of input index array !");
5350     sz--;
5351     MCAuto<DataArrayType> ret=DataArrayType::New(); ret->alloc(sz,nbCompo);
5352     const mcIdType *w=bgOfIndex;
5353     if(*w<0 || *w>=nbOfTuples)
5354       throw INTERP_KERNEL::Exception("DataArrayInt::accumulatePerChunck : The first element of the input index not in [0,nbOfTuples) !");
5355     const T *srcPt=this->begin()+(*w)*nbCompo;
5356     T *tmp=ret->getPointer();
5357     for(mcIdType i=0;i<sz;i++,tmp+=nbCompo,w++)
5358       {
5359         std::fill(tmp,tmp+nbCompo,0);
5360         if(w[1]>=w[0])
5361           {
5362             for(mcIdType j=w[0];j<w[1];j++,srcPt+=nbCompo)
5363               {
5364                 if(j>=0 && j<nbOfTuples)
5365                   std::transform(srcPt,srcPt+nbCompo,tmp,tmp,std::plus<T>());
5366                 else
5367                   {
5368                     std::ostringstream oss; oss << "DataArrayInt::accumulatePerChunck : At rank #" << i << " the input index array points to id " << j << " should be in [0," << nbOfTuples << ") !";
5369                     throw INTERP_KERNEL::Exception(oss.str().c_str());
5370                   }
5371               }
5372           }
5373         else
5374           {
5375             std::ostringstream oss; oss << "DataArrayInt::accumulatePerChunck : At rank #" << i << " the input index array is not in ascendingly sorted.";
5376             throw INTERP_KERNEL::Exception(oss.str().c_str());
5377           }
5378       }
5379     ret->copyStringInfoFrom(*this);
5380     return ret.retn();
5381   }
5382
5383   /*!
5384    * Returns in a single walk in \a this the min value and the max value in \a this.
5385    * \a this is expected to be single component array.
5386    *
5387    * \param [out] minValue - the min value in \a this.
5388    * \param [out] maxValue - the max value in \a this.
5389    *
5390    * \sa getMinValueInArray, getMinValue, getMaxValueInArray, getMaxValue
5391    */
5392   template <class T>
5393   void DataArrayDiscrete<T>::getMinMaxValues(T& minValue, T& maxValue) const
5394   {
5395     this->checkAllocated();
5396     if(this->getNumberOfComponents()!=1)
5397       throw INTERP_KERNEL::Exception("DataArrayInt::getMinMaxValues : must be applied on DataArrayInt with only one component !");
5398     std::size_t nbElements(this->getNumberOfTuples());
5399     const T *pt(this->begin());
5400     minValue=std::numeric_limits<T>::max(); maxValue=-std::numeric_limits<T>::max();
5401     for(std::size_t i=0;i<nbElements;i++,pt++)
5402       {
5403         if(*pt<minValue)
5404           minValue=*pt;
5405         if(*pt>maxValue)
5406           maxValue=*pt;
5407       }
5408   }
5409
5410   /*!
5411    * Modify all elements of \a this array, so that
5412    * an element _x_ becomes \f$ numerator / x \f$.
5413    *  \warning If an exception is thrown because of presence of 0 element in \a this
5414    *           array, all elements processed before detection of the zero element remain
5415    *           modified.
5416    *  \param [in] numerator - the numerator used to modify array elements.
5417    *  \throw If \a this is not allocated.
5418    *  \throw If there is an element equal to 0 in \a this array.
5419    */
5420   template <class T>
5421   void DataArrayDiscrete<T>::applyInv(T numerator)
5422   {
5423     this->checkAllocated();
5424     T *ptr=this->getPointer();
5425     std::size_t nbOfElems=this->getNbOfElems();
5426     for(std::size_t i=0;i<nbOfElems;i++,ptr++)
5427       {
5428         if(*ptr!=0)
5429           {
5430             *ptr=numerator/(*ptr);
5431           }
5432         else
5433           {
5434             std::ostringstream oss; oss << "DataArrayInt::applyInv : presence of null value in tuple #" << i/(this->getNumberOfComponents()) << " component #" << i%(this->getNumberOfComponents());
5435             oss << " !";
5436             throw INTERP_KERNEL::Exception(oss.str().c_str());
5437           }
5438       }
5439     this->declareAsNew();
5440   }
5441
5442   /*!
5443    * Modify all elements of \a this array, so that
5444    * an element _x_ becomes \f$ x / val \f$.
5445    *  \param [in] val - the denominator used to modify array elements.
5446    *  \throw If \a this is not allocated.
5447    *  \throw If \a val == 0.
5448    */
5449   template <class T>
5450   void DataArrayDiscrete<T>::applyDivideBy(T val)
5451   {
5452     if(val==0)
5453       throw INTERP_KERNEL::Exception("DataArrayInt::applyDivideBy : Trying to divide by 0 !");
5454     this->checkAllocated();
5455     T *ptr=this->getPointer();
5456     std::size_t nbOfElems=this->getNbOfElems();
5457     std::transform(ptr,ptr+nbOfElems,ptr,std::bind(std::divides<T>(),std::placeholders::_1,val));
5458     this->declareAsNew();
5459   }
5460
5461   /*!
5462    * Modify all elements of \a this array, so that
5463    * an element _x_ becomes  <em> x % val </em>.
5464    *  \param [in] val - the divisor used to modify array elements.
5465    *  \throw If \a this is not allocated.
5466    *  \throw If \a val <= 0.
5467    */
5468   template <class T>
5469   void DataArrayDiscrete<T>::applyModulus(T val)
5470   {
5471     if(val<=0)
5472       throw INTERP_KERNEL::Exception("DataArrayInt::applyDivideBy : Trying to operate modulus on value <= 0 !");
5473     this->checkAllocated();
5474     T *ptr=this->getPointer();
5475     std::size_t nbOfElems=this->getNbOfElems();
5476     std::transform(ptr,ptr+nbOfElems,ptr,std::bind(std::modulus<T>(),std::placeholders::_1,val));
5477     this->declareAsNew();
5478   }
5479
5480   /*!
5481    * Modify all elements of \a this array, so that
5482    * an element _x_ becomes <em> val % x </em>.
5483    *  \warning If an exception is thrown because of presence of an element <= 0 in \a this
5484    *           array, all elements processed before detection of the zero element remain
5485    *           modified.
5486    *  \param [in] val - the divident used to modify array elements.
5487    *  \throw If \a this is not allocated.
5488    *  \throw If there is an element equal to or less than 0 in \a this array.
5489    */
5490   template <class T>
5491   void DataArrayDiscrete<T>::applyRModulus(T val)
5492   {
5493     this->checkAllocated();
5494     T *ptr=this->getPointer();
5495     std::size_t nbOfElems=this->getNbOfElems();
5496     for(std::size_t i=0;i<nbOfElems;i++,ptr++)
5497       {
5498         if(*ptr>0)
5499           {
5500             *ptr=val%(*ptr);
5501           }
5502         else
5503           {
5504             std::ostringstream oss; oss << "DataArrayInt::applyRModulus : presence of value <=0 in tuple #" << i/(this->getNumberOfComponents()) << " component #" << i%(this->getNumberOfComponents());
5505             oss << " !";
5506             throw INTERP_KERNEL::Exception(oss.str().c_str());
5507           }
5508       }
5509     this->declareAsNew();
5510   }
5511
5512   /*!
5513    * Modify all elements of \a this array, so that
5514    * an element _x_ becomes <em> val ^ x </em>.
5515    *  \param [in] val - the value used to apply pow on all array elements.
5516    *  \throw If \a this is not allocated.
5517    *  \throw If \a val < 0.
5518    */
5519   template <class T>
5520   void DataArrayDiscrete<T>::applyPow(T val)
5521   {
5522     this->checkAllocated();
5523     if(val<0)
5524       throw INTERP_KERNEL::Exception("DataArrayInt::applyPow : input pow in < 0 !");
5525     T *ptr=this->getPointer();
5526     std::size_t nbOfElems=this->getNbOfElems();
5527     if(val==0)
5528       {
5529         std::fill(ptr,ptr+nbOfElems,1);
5530         return ;
5531       }
5532     for(std::size_t i=0;i<nbOfElems;i++,ptr++)
5533       {
5534         T tmp=1;
5535         for(T j=0;j<val;j++)
5536           tmp*=*ptr;
5537         *ptr=tmp;
5538       }
5539     this->declareAsNew();
5540   }
5541
5542   /*!
5543    * Modify all elements of \a this array, so that
5544    * an element _x_ becomes \f$ val ^ x \f$.
5545    *  \param [in] val - the value used to apply pow on all array elements.
5546    *  \throw If \a this is not allocated.
5547    *  \throw If there is an element < 0 in \a this array.
5548    *  \warning If an exception is thrown because of presence of 0 element in \a this
5549    *           array, all elements processed before detection of the zero element remain
5550    *           modified.
5551    */
5552   template <class T>
5553   void DataArrayDiscrete<T>::applyRPow(T val)
5554   {
5555     this->checkAllocated();
5556     T *ptr=this->getPointer();
5557     std::size_t nbOfElems=this->getNbOfElems();
5558     for(std::size_t i=0;i<nbOfElems;i++,ptr++)
5559       {
5560         if(*ptr>=0)
5561           {
5562             T tmp=1;
5563             for(T j=0;j<*ptr;j++)
5564               tmp*=val;
5565             *ptr=tmp;
5566           }
5567         else
5568           {
5569             std::ostringstream oss; oss << "DataArrayInt::applyRPow : presence of negative value in tuple #" << i/(this->getNumberOfComponents()) << " component #" << i%(this->getNumberOfComponents());
5570             oss << " !";
5571             throw INTERP_KERNEL::Exception(oss.str().c_str());
5572           }
5573       }
5574     this->declareAsNew();
5575   }
5576
5577   /*!
5578    * This method works only on data array with one component.
5579    * This method returns a newly allocated array storing stored ascendantly tuple ids in \b this so that
5580    * this[*id] in [\b vmin,\b vmax)
5581    *
5582    * \param [in] vmin begin of range. This value is included in range (included).
5583    * \param [in] vmax end of range. This value is \b not included in range (excluded).
5584    * \return a newly allocated data array that the caller should deal with.
5585    *
5586    * \sa DataArrayInt::findIdsNotInRange , DataArrayInt::findIdsStricltyNegative
5587    */
5588   template <class T>
5589   DataArrayIdType *DataArrayDiscrete<T>::findIdsInRange(T vmin, T vmax) const
5590   {
5591     InRange<T> ir(vmin,vmax);
5592     MCAuto<DataArrayIdType> ret(this->findIdsAdv(ir));
5593     return ret.retn();
5594   }
5595
5596   /*!
5597    * This method works only on data array with one component.
5598    * This method returns a newly allocated array storing stored ascendantly tuple ids in \b this so that
5599    * this[*id] \b not in [\b vmin,\b vmax)
5600    *
5601    * \param [in] vmin begin of range. This value is \b not included in range (excluded).
5602    * \param [in] vmax end of range. This value is included in range (included).
5603    * \return a newly allocated data array that the caller should deal with.
5604    *
5605    * \sa DataArrayInt::findIdsInRange , DataArrayInt::findIdsStricltyNegative
5606    */
5607   template <class T>
5608   DataArrayIdType *DataArrayDiscrete<T>::findIdsNotInRange(T vmin, T vmax) const
5609   {
5610     NotInRange<T> nir(vmin,vmax);
5611     MCAuto<DataArrayIdType> ret(this->findIdsAdv(nir));
5612     return ret.retn();
5613   }
5614
5615   /*!
5616    * This method works only on data array with one component.
5617    * 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.
5618    *
5619    * \param [in] vmin begin of range. This value is included in range (included).
5620    * \param [in] vmax end of range. This value is \b not included in range (excluded).
5621    * \return if all ids in \a this are so that (*this)[i]==i for all i in [ 0, \c this->getNumberOfTuples() ). */
5622   template <class T>
5623   bool DataArrayDiscrete<T>::checkAllIdsInRange(T vmin, T vmax) const
5624   {
5625     this->checkAllocated();
5626     if(this->getNumberOfComponents()!=1)
5627       throw INTERP_KERNEL::Exception("DataArrayInt::checkAllIdsInRange : this must have exactly one component !");
5628     mcIdType nbOfTuples(this->getNumberOfTuples());
5629     bool ret=true;
5630     const T *cptr=this->getConstPointer();
5631     for(mcIdType i=0;i<nbOfTuples;i++,cptr++)
5632       {
5633         if(*cptr>=vmin && *cptr<vmax)
5634           { ret=ret && *cptr==i; }
5635         else
5636           {
5637             std::ostringstream oss; oss << "DataArrayInt::checkAllIdsInRange : tuple #" << i << " has value " << *cptr << " should be in [" << vmin << "," << vmax << ") !";
5638             throw INTERP_KERNEL::Exception(oss.str().c_str());
5639           }
5640       }
5641     return ret;
5642   }
5643
5644   /*!
5645    * Returns a new DataArrayInt which contains a complement of elements of \a this
5646    * one-dimensional array. I.e. the result array contains all elements from the range [0,
5647    * \a nbOfElement) not present in \a this array.
5648    *  \param [in] nbOfElement - maximal size of the result array.
5649    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
5650    *         array using decrRef() as it is no more needed.
5651    *  \throw If \a this is not allocated.
5652    *  \throw If \a this->getNumberOfComponents() != 1.
5653    *  \throw If any element \a x of \a this array violates condition ( 0 <= \a x < \a
5654    *         nbOfElement ).
5655    */
5656   template <class T>
5657   DataArrayIdType *DataArrayDiscrete<T>::buildComplement(mcIdType nbOfElement) const
5658   {
5659     this->checkAllocated();
5660     if(this->getNumberOfComponents()!=1)
5661       throw INTERP_KERNEL::Exception("DataArrayInt::buildComplement : only single component allowed !");
5662     std::vector<bool> tmp(nbOfElement);
5663     const T *pt=this->getConstPointer();
5664     std::size_t nbOfElements=this->getNumberOfTuples();
5665     for(const T *w=pt;w!=pt+nbOfElements;w++)
5666       if(*w>=0 && *w<nbOfElement)
5667         tmp[*w]=true;
5668       else
5669         throw INTERP_KERNEL::Exception("DataArrayInt::buildComplement : an element is not in valid range : [0,nbOfElement) !");
5670     std::size_t nbOfRetVal=std::count(tmp.begin(),tmp.end(),false);
5671     DataArrayIdType *ret=DataArrayIdType::New();
5672     ret->alloc(nbOfRetVal,1);
5673     mcIdType j=0;
5674     mcIdType *retPtr=ret->getPointer();
5675     for(mcIdType i=0;i<nbOfElement;i++)
5676       if(!tmp[i])
5677         retPtr[j++]=i;
5678     return ret;
5679   }
5680
5681   /*!
5682    * Returns a new DataArrayInt containing elements of \a this one-dimensional missing
5683    * from an \a other one-dimensional array.
5684    *  \param [in] other - a DataArrayInt containing elements not to include in the result array.
5685    *  \return DataArrayInt * - a new instance of DataArrayInt with one component. The
5686    *         caller is to delete this array using decrRef() as it is no more needed.
5687    *  \throw If \a other is NULL.
5688    *  \throw If \a other is not allocated.
5689    *  \throw If \a other->getNumberOfComponents() != 1.
5690    *  \throw If \a this is not allocated.
5691    *  \throw If \a this->getNumberOfComponents() != 1.
5692    *  \sa DataArrayInt::buildSubstractionOptimized()
5693    */
5694   template <class T>
5695   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::buildSubstraction(const DataArrayType *other) const
5696   {
5697     if(!other)
5698       throw INTERP_KERNEL::Exception("DataArrayInt::buildSubstraction : DataArrayInt pointer in input is NULL !");
5699     this->checkAllocated();
5700     other->checkAllocated();
5701     if(this->getNumberOfComponents()!=1)
5702       throw INTERP_KERNEL::Exception("DataArrayInt::buildSubstraction : only single component allowed !");
5703     if(other->getNumberOfComponents()!=1)
5704       throw INTERP_KERNEL::Exception("DataArrayInt::buildSubstraction : only single component allowed for other type !");
5705     const T *pt=this->getConstPointer();
5706     std::size_t nbOfElements=this->getNumberOfTuples();
5707     std::set<T> s1(pt,pt+nbOfElements);
5708     pt=other->getConstPointer();
5709     nbOfElements=other->getNumberOfTuples();
5710     std::set<T> s2(pt,pt+nbOfElements);
5711     std::vector<T> r;
5712     std::set_difference(s1.begin(),s1.end(),s2.begin(),s2.end(),std::back_insert_iterator< std::vector<T> >(r));
5713     DataArrayType *ret=DataArrayType::New();
5714     ret->alloc(r.size(),1);
5715     std::copy(r.begin(),r.end(),ret->getPointer());
5716     return ret;
5717   }
5718
5719   /*!
5720    * \a this is expected to have one component and to be sorted ascendingly (as for \a other).
5721    * \a other is expected to be a part of \a this. If not DataArrayInt::buildSubstraction should be called instead.
5722    *
5723    * \param [in] other an array with one component and expected to be sorted ascendingly.
5724    * \ret list of ids in \a this but not in \a other.
5725    * \sa DataArrayInt::buildSubstraction
5726    */
5727   template <class T>
5728   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::buildSubstractionOptimized(const DataArrayType *other) const
5729   {
5730     static const char *MSG="DataArrayInt::buildSubstractionOptimized : only single component allowed !";
5731     if(!other) throw INTERP_KERNEL::Exception("DataArrayInt::buildSubstractionOptimized : NULL input array !");
5732     this->checkAllocated(); other->checkAllocated();
5733     if(this->getNumberOfComponents()!=1) throw INTERP_KERNEL::Exception(MSG);
5734     if(other->getNumberOfComponents()!=1) throw INTERP_KERNEL::Exception(MSG);
5735     const T *pt1Bg(this->begin()),*pt1End(this->end()),*pt2Bg(other->begin()),*pt2End(other->end());
5736     const T *work1(pt1Bg),*work2(pt2Bg);
5737     MCAuto<DataArrayType> ret(DataArrayType::New()); ret->alloc(0,1);
5738     for(;work1!=pt1End;work1++)
5739       {
5740         if(work2!=pt2End && *work1==*work2)
5741           work2++;
5742         else
5743           ret->pushBackSilent(*work1);
5744       }
5745     return ret.retn();
5746   }
5747
5748   /*!
5749    * Returns a new DataArrayInt which contains all elements of \a this and a given
5750    * one-dimensional arrays. The result array does not contain any duplicates
5751    * and its values are sorted in ascending order.
5752    *  \param [in] other - an array to unite with \a this one.
5753    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
5754    *         array using decrRef() as it is no more needed.
5755    *  \throw If \a this or \a other is not allocated.
5756    *  \throw If \a this->getNumberOfComponents() != 1.
5757    *  \throw If \a other->getNumberOfComponents() != 1.
5758    */
5759   template <class T>
5760   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::buildUnion(const DataArrayType *other) const
5761   {
5762     std::vector<const DataArrayType *>arrs(2);
5763     arrs[0]=dynamic_cast<const DataArrayType *>(this); arrs[1]=other;
5764     return DataArrayDiscrete<T>::BuildUnion(arrs);
5765   }
5766
5767   /*!
5768    * Returns a new DataArrayInt which contains elements present in both \a this and a given
5769    * one-dimensional arrays. The result array does not contain any duplicates
5770    * and its values are sorted in ascending order.
5771    *  \param [in] other - an array to intersect with \a this one.
5772    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
5773    *         array using decrRef() as it is no more needed.
5774    *  \throw If \a this or \a other is not allocated.
5775    *  \throw If \a this->getNumberOfComponents() != 1.
5776    *  \throw If \a other->getNumberOfComponents() != 1.
5777    */
5778   template <class T>
5779   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::buildIntersection(const DataArrayType *other) const
5780   {
5781     std::vector<const DataArrayType *>arrs(2);
5782     arrs[0]=dynamic_cast<const DataArrayType *>(this); arrs[1]=other;
5783     return DataArrayDiscrete<T>::BuildIntersection(arrs);
5784   }
5785   /*!
5786    * This method can be applied on allocated with one component DataArrayInt instance.
5787    * 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.
5788    * Number of tuples of returned array is equal to size of \a this->buildUnique() + 1.
5789    * Last value of returned array is equal to \a this->getNumberOfTuples()
5790    *
5791    * \b Example:
5792    * - \a this : [0, 1, 1, 2, 2, 3, 4, 4, 5, 5, 5, 11]
5793    * - \a return is : [0, 1, 3, 5, 6, 8, 11, 12]
5794    *
5795    * \return a newly allocated array containing the indexed array format of groups by same consecutive value.
5796    * \throw if \a this is not allocated or if \a this has not exactly one component.
5797    * \sa DataArrayInt::buildUnique, MEDCouplingSkyLineArray::groupPacks
5798    */
5799   template <class T>
5800   DataArrayIdType *DataArrayDiscrete<T>::indexOfSameConsecutiveValueGroups() const
5801   {
5802     this->checkAllocated();
5803     if(this->getNumberOfComponents()!=1)
5804       throw INTERP_KERNEL::Exception("DataArrayInt::indexOfSameConsecutiveValueGroups : only single component allowed !");
5805     const T *pt(this->begin());
5806     const T *const ptEnd(this->end()) , * const ptBg(this->begin());
5807     // first find nb of different values in this
5808     std::size_t nbOfTuplesOut(0);
5809     while( pt != ptEnd )
5810     {
5811       T val(*pt);
5812       const T *endOfPack(std::find_if(pt+1,ptEnd,[val](T elt){ return val!=elt; }));
5813       pt = endOfPack;
5814       ++nbOfTuplesOut;
5815     }
5816     MCAuto<DataArrayIdType> ret(DataArrayIdType::New()); ret->alloc(nbOfTuplesOut+1,1);
5817     mcIdType *retPtr(ret->getPointer()); *retPtr++ = 0;
5818     pt = this->begin();
5819     while( pt != ptEnd )
5820     {
5821       T val(*pt);
5822       const T *endOfPack(std::find_if(pt+1,ptEnd,[val](T elt){ return val!=elt; }));
5823       *retPtr++ = ToIdType( std::distance(ptBg,endOfPack) );
5824       pt = endOfPack;
5825       ++nbOfTuplesOut;
5826     }
5827     return ret.retn();
5828   }
5829
5830   /*!
5831    * This method can be applied on allocated with one component DataArrayInt instance.
5832    * This method is typically relevant for sorted arrays. All consecutive duplicated items in \a this will appear only once in returned DataArrayInt instance.
5833    * 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]
5834    *
5835    * \return a newly allocated array that contain the result of the unique operation applied on \a this.
5836    * \throw if \a this is not allocated or if \a this has not exactly one component.
5837    * \sa DataArrayInt::buildUniqueNotSorted, DataArrayInt::indexOfSameConsecutiveValueGroups
5838    */
5839   template <class T>
5840   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::buildUnique() const
5841   {
5842     this->checkAllocated();
5843     if(this->getNumberOfComponents()!=1)
5844       throw INTERP_KERNEL::Exception("DataArrayInt::buildUnique : only single component allowed !");
5845     std::size_t nbOfElements(this->getNumberOfTuples());
5846     MCAuto<DataArrayType> tmp(DataArrayType::New());
5847     tmp->deepCopyFrom(*this);
5848     T *data(tmp->getPointer());
5849     T *last(std::unique(data,data+nbOfElements));
5850     MCAuto<DataArrayType> ret(DataArrayType::New());
5851     ret->alloc(std::distance(data,last),1);
5852     std::copy(data,last,ret->getPointer());
5853     return ret.retn();
5854   }
5855
5856   /*!
5857    * This method can be applied on allocated with one component DataArrayInt instance.
5858    * This method keep elements only once by keeping the same order in \a this that is not expected to be sorted.
5859    *
5860    * \return a newly allocated array that contain the result of the unique operation applied on \a this.
5861    *
5862    * \throw if \a this is not allocated or if \a this has not exactly one component.
5863    *
5864    * \sa DataArrayInt::buildUnique
5865    */
5866   template <class T>
5867   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::buildUniqueNotSorted() const
5868   {
5869     this->checkAllocated();
5870     if(this->getNumberOfComponents()!=1)
5871       throw INTERP_KERNEL::Exception("DataArrayInt::buildUniqueNotSorted : only single component allowed !");
5872     T minVal,maxVal;
5873     this->getMinMaxValues(minVal,maxVal);
5874     std::vector<bool> b(maxVal-minVal+1,false);
5875     const T *ptBg(this->begin()),*endBg(this->end());
5876     MCAuto<DataArrayType> ret(DataArrayType::New()); ret->alloc(0,1);
5877     for(const T *pt=ptBg;pt!=endBg;pt++)
5878       {
5879         if(!b[*pt-minVal])
5880           {
5881             ret->pushBackSilent(*pt);
5882             b[*pt-minVal]=true;
5883           }
5884       }
5885     ret->copyStringInfoFrom(*this);
5886     return ret.retn();
5887   }
5888
5889   /*!
5890    * Returns a new DataArrayInt which contains size of every of groups described by \a this
5891    * "index" array. Such "index" array is returned for example by
5892    * \ref MEDCoupling::MEDCouplingUMesh::buildDescendingConnectivity
5893    * "MEDCouplingUMesh::buildDescendingConnectivity" and
5894    * \ref MEDCoupling::MEDCouplingUMesh::getNodalConnectivityIndex
5895    * "MEDCouplingUMesh::getNodalConnectivityIndex" etc.
5896    * This method performs the reverse operation of DataArrayInt::computeOffsetsFull.
5897    *  \return DataArrayInt * - a new instance of DataArrayInt, whose number of tuples
5898    *          equals to \a this->getNumberOfComponents() - 1, and number of components is 1.
5899    *          The caller is to delete this array using decrRef() as it is no more needed.
5900    *  \throw If \a this is not allocated.
5901    *  \throw If \a this->getNumberOfComponents() != 1.
5902    *  \throw If \a this->getNumberOfTuples() < 2.
5903    *
5904    *  \b Example: <br>
5905    *         - this contains [1,3,6,7,7,9,15]
5906    *         - result array contains [2,3,1,0,2,6],
5907    *          where 2 = 3 - 1, 3 = 6 - 3, 1 = 7 - 6 etc.
5908    *
5909    * \sa DataArrayInt::computeOffsetsFull
5910    */
5911   template <class T>
5912   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::deltaShiftIndex() const
5913   {
5914     this->checkAllocated();
5915     if(this->getNumberOfComponents()!=1)
5916       throw INTERP_KERNEL::Exception("DataArrayInt::deltaShiftIndex : only single component allowed !");
5917     std::size_t nbOfElements=this->getNumberOfTuples();
5918     if(nbOfElements<2)
5919       throw INTERP_KERNEL::Exception("DataArrayInt::deltaShiftIndex : 2 tuples at least must be present in 'this' !");
5920     const T *ptr=this->getConstPointer();
5921     DataArrayType *ret=DataArrayType::New();
5922     ret->alloc(nbOfElements-1,1);
5923     T *out=ret->getPointer();
5924     std::transform(ptr+1,ptr+nbOfElements,ptr,out,std::minus<T>());
5925     return ret;
5926   }
5927
5928   /*!
5929    * Modifies \a this one-dimensional array so that value of each element \a x
5930    * of \a this array (\a a) is computed as \f$ x_i = \sum_{j=0}^{i-1} a[ j ] \f$.
5931    * Or: for each i>0 new[i]=new[i-1]+old[i-1] for i==0 new[i]=0. Number of tuples
5932    * and components remains the same.<br>
5933    * This method is useful for allToAllV in MPI with contiguous policy. This method
5934    * differs from computeOffsetsFull() in that the number of tuples is \b not changed by
5935    * this one.
5936    *  \throw If \a this is not allocated.
5937    *  \throw If \a this->getNumberOfComponents() != 1.
5938    *
5939    *  \b Example: <br>
5940    *          - Before \a this contains [3,5,1,2,0,8]
5941    *          - After \a this contains  [0,3,8,9,11,11]<br>
5942    *          Note that the last element 19 = 11 + 8 is missing because size of \a this
5943    *          array is retained and thus there is no space to store the last element.
5944    */
5945   template <class T>
5946   void DataArrayDiscrete<T>::computeOffsets()
5947   {
5948     this->checkAllocated();
5949     if(this->getNumberOfComponents()!=1)
5950       throw INTERP_KERNEL::Exception("DataArrayInt::computeOffsets : only single component allowed !");
5951     std::size_t nbOfElements=this->getNumberOfTuples();
5952     if(nbOfElements==0)
5953       return ;
5954     T *work=this->getPointer();
5955     T tmp=work[0];
5956     work[0]=0;
5957     for(std::size_t i=1;i<nbOfElements;i++)
5958       {
5959         T tmp2=work[i];
5960         work[i]=work[i-1]+tmp;
5961         tmp=tmp2;
5962       }
5963     this->declareAsNew();
5964   }
5965
5966   /*!
5967    * Modifies \a this one-dimensional array so that value of each element \a x
5968    * of \a this array (\a a) is computed as \f$ x_i = \sum_{j=0}^{i-1} a[ j ] \f$.
5969    * Or: for each i>0 new[i]=new[i-1]+old[i-1] for i==0 new[i]=0. Number
5970    * components remains the same and number of tuples is inceamented by one.<br>
5971    * This method is useful for allToAllV in MPI with contiguous policy. This method
5972    * differs from computeOffsets() in that the number of tuples is changed by this one.
5973    * This method performs the reverse operation of DataArrayInt::deltaShiftIndex.
5974    *  \throw If \a this is not allocated.
5975    *  \throw If \a this->getNumberOfComponents() != 1.
5976    *
5977    *  \b Example: <br>
5978    *          - Before \a this contains [3,5,1,2,0,8]
5979    *          - After \a this contains  [0,3,8,9,11,11,19]<br>
5980    * \sa DataArrayInt::deltaShiftIndex
5981    */
5982   template <class T>
5983   void DataArrayDiscrete<T>::computeOffsetsFull()
5984   {
5985     this->checkAllocated();
5986     if(this->getNumberOfComponents()!=1)
5987       throw INTERP_KERNEL::Exception("DataArrayInt::computeOffsetsFull : only single component allowed !");
5988     std::size_t nbOfElements=this->getNumberOfTuples();
5989     T *ret=(T *)malloc((nbOfElements+1)*sizeof(T));
5990     const T *work=this->getConstPointer();
5991     ret[0]=0;
5992     for(std::size_t i=0;i<nbOfElements;i++)
5993       ret[i+1]=work[i]+ret[i];
5994     this->useArray(ret,true,DeallocType::C_DEALLOC,nbOfElements+1,1);
5995     this->declareAsNew();
5996   }
5997
5998   /*!
5999    * Returns two new DataArrayInt instances whose contents is computed from that of \a this and \a listOfIds arrays as follows.
6000    * \a this is expected to be an offset format ( as returned by DataArrayInt::computeOffsetsFull ) that is to say with one component
6001    * and ** sorted strictly increasingly **. \a listOfIds is expected to be sorted ascendingly (not strictly needed for \a listOfIds).
6002    * This methods searches in \a this, considered as a set of contiguous \c this->getNumberOfComponents() ranges, all ids in \a listOfIds
6003    * filling completely one of the ranges in \a this.
6004    *
6005    * \param [in] listOfIds a list of ids that has to be sorted ascendingly.
6006    * \param [out] rangeIdsFetched the range ids fetched
6007    * \param [out] idsInInputListThatFetch contains the list of ids in \a listOfIds that are \b fully included in a range in \a this. So
6008    *              \a idsInInputListThatFetch is a part of input \a listOfIds.
6009    *
6010    * \sa DataArrayInt::computeOffsetsFull
6011    *
6012    *  \b Example: <br>
6013    *          - \a this : [0,3,7,9,15,18]
6014    *          - \a listOfIds contains  [0,1,2,3,7,8,15,16,17]
6015    *          - \a rangeIdsFetched result array: [0,2,4]
6016    *          - \a idsInInputListThatFetch result array: [0,1,2,7,8,15,16,17]
6017    * In this example id 3 in input \a listOfIds is alone so it do not appear in output \a idsInInputListThatFetch.
6018    * <br>
6019    */
6020   template <class T>
6021   void DataArrayDiscrete<T>::findIdsRangesInListOfIds(const DataArrayType *listOfIds, DataArrayIdType *& rangeIdsFetched, DataArrayType *& idsInInputListThatFetch) const
6022   {
6023     if(!listOfIds)
6024       throw INTERP_KERNEL::Exception("DataArrayInt::findIdsRangesInListOfIds : input list of ids is null !");
6025     listOfIds->checkAllocated(); this->checkAllocated();
6026     if(listOfIds->getNumberOfComponents()!=1)
6027       throw INTERP_KERNEL::Exception("DataArrayInt::findIdsRangesInListOfIds : input list of ids must have exactly one component !");
6028     if(this->getNumberOfComponents()!=1)
6029       throw INTERP_KERNEL::Exception("DataArrayInt::findIdsRangesInListOfIds : this must have exactly one component !");
6030     MCAuto<DataArrayIdType> ret0=DataArrayIdType::New(); ret0->alloc(0,1);
6031     MCAuto<DataArrayType> ret1=DataArrayType::New(); ret1->alloc(0,1);
6032     const T *tupPtr(listOfIds->begin()), *tupEnd(listOfIds->end());
6033     const T *offBg(this->begin()),*offEnd(this->end()-1);
6034     const T *offPtr(offBg);
6035     while(tupPtr!=tupEnd && offPtr!=offEnd)
6036       {
6037         if(*tupPtr==*offPtr)
6038           {
6039             T i=offPtr[0];
6040             while(i<offPtr[1] && *tupPtr==i && tupPtr!=tupEnd) { i++; tupPtr++; }
6041             if(i==offPtr[1])
6042               {
6043                 ret0->pushBackSilent(ToIdType(std::distance(offBg,offPtr)));
6044                 ret1->pushBackValsSilent(tupPtr-(offPtr[1]-offPtr[0]),tupPtr);
6045                 offPtr++;
6046               }
6047           }
6048         else
6049           { if(*tupPtr<*offPtr) tupPtr++; else offPtr++; }
6050       }
6051     rangeIdsFetched=ret0.retn();
6052     idsInInputListThatFetch=ret1.retn();
6053   }
6054
6055   /*!
6056    * Returns a new DataArrayInt whose contents is computed from that of \a this and \a
6057    * offsets arrays as follows. \a offsets is a one-dimensional array considered as an
6058    * "index" array of a "iota" array, thus, whose each element gives an index of a group
6059    * beginning within the "iota" array. And \a this is a one-dimensional array
6060    * considered as a selector of groups described by \a offsets to include into the result array.
6061    *  \throw If \a offsets is NULL.
6062    *  \throw If \a offsets is not allocated.
6063    *  \throw If \a offsets->getNumberOfComponents() != 1.
6064    *  \throw If \a offsets is not monotonically increasing.
6065    *  \throw If \a this is not allocated.
6066    *  \throw If \a this->getNumberOfComponents() != 1.
6067    *  \throw If any element of \a this is not a valid index for \a offsets array.
6068    *
6069    *  \b Example: <br>
6070    *          - \a this: [0,2,3]
6071    *          - \a offsets: [0,3,6,10,14,20]
6072    *          - result array: [0,1,2,6,7,8,9,10,11,12,13] == <br>
6073    *            \c range(0,3) + \c range(6,10) + \c range(10,14) ==<br>
6074    *            \c range( \a offsets[ \a this[0] ], offsets[ \a this[0]+1 ]) +
6075    *            \c range( \a offsets[ \a this[1] ], offsets[ \a this[1]+1 ]) +
6076    *            \c range( \a offsets[ \a this[2] ], offsets[ \a this[2]+1 ])
6077    */
6078   template <class T>
6079   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::buildExplicitArrByRanges(const DataArrayType *offsets) const
6080   {
6081     if(!offsets)
6082       throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrByRanges : DataArrayInt pointer in input is NULL !");
6083     this->checkAllocated();
6084     if(this->getNumberOfComponents()!=1)
6085       throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrByRanges : only single component allowed !");
6086     offsets->checkAllocated();
6087     if(offsets->getNumberOfComponents()!=1)
6088       throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrByRanges : input array should have only single component !");
6089     mcIdType othNbTuples=offsets->getNumberOfTuples()-1;
6090     mcIdType nbOfTuples=this->getNumberOfTuples();
6091     T retNbOftuples=0;
6092     const T *work=this->getConstPointer();
6093     const T *offPtr=offsets->getConstPointer();
6094     for(mcIdType i=0;i<nbOfTuples;i++)
6095       {
6096         T val=work[i];
6097         if(val>=0 && val<othNbTuples)
6098           {
6099             T delta=offPtr[val+1]-offPtr[val];
6100             if(delta>=0)
6101               retNbOftuples+=delta;
6102             else
6103               {
6104                 std::ostringstream oss; oss << "DataArrayInt::buildExplicitArrByRanges : Tuple #" << val << " of offset array has a delta < 0 !";
6105                 throw INTERP_KERNEL::Exception(oss.str().c_str());
6106               }
6107           }
6108         else
6109           {
6110             std::ostringstream oss; oss << "DataArrayInt::buildExplicitArrByRanges : Tuple #" << i << " in this contains " << val;
6111             oss << " whereas offsets array is of size " << othNbTuples+1 << " !";
6112             throw INTERP_KERNEL::Exception(oss.str().c_str());
6113           }
6114       }
6115     MCAuto<DataArrayType> ret=DataArrayType::New();
6116     ret->alloc(retNbOftuples,1);
6117     T *retPtr=ret->getPointer();
6118     for(mcIdType i=0;i<nbOfTuples;i++)
6119       {
6120         T val=work[i];
6121         T start=offPtr[val];
6122         T off=offPtr[val+1]-start;
6123         for(T j=0;j<off;j++,retPtr++)
6124           *retPtr=start+j;
6125       }
6126     return ret.retn();
6127   }
6128
6129   /*!
6130    * Returns a new DataArrayInt whose contents is computed using \a this that must be a
6131    * scaled array (monotonically increasing).
6132   from that of \a this and \a
6133    * offsets arrays as follows. \a offsets is a one-dimensional array considered as an
6134    * "index" array of a "iota" array, thus, whose each element gives an index of a group
6135    * beginning within the "iota" array. And \a this is a one-dimensional array
6136    * considered as a selector of groups described by \a offsets to include into the result array.
6137    *  \throw If \a  is NULL.
6138    *  \throw If \a this is not allocated.
6139    *  \throw If \a this->getNumberOfComponents() != 1.
6140    *  \throw If \a this->getNumberOfTuples() == 0.
6141    *  \throw If \a this is not monotonically increasing.
6142    *  \throw If any element of ids in ( \a bg \a stop \a step ) points outside the scale in \a this.
6143    *
6144    *  \b Example: <br>
6145    *          - \a bg , \a stop and \a step : (0,5,2)
6146    *          - \a this: [0,3,6,10,14,20]
6147    *          - result array: [0,0,0, 2,2,2,2, 4,4,4,4,4,4] == <br>
6148    */
6149   template <class T>
6150   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::buildExplicitArrOfSliceOnScaledArr(T bg, T stop, T step) const
6151   {
6152     if(!this->isAllocated())
6153       throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrOfSliceOnScaledArr : not allocated array !");
6154     if(this->getNumberOfComponents()!=1)
6155       throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrOfSliceOnScaledArr : number of components is expected to be equal to one !");
6156     mcIdType nbOfTuples(this->getNumberOfTuples());
6157     if(nbOfTuples==0)
6158       throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrOfSliceOnScaledArr : number of tuples must be != 0 !");
6159     const T *ids(this->begin());
6160     mcIdType nbOfEltsInSlc=DataArrayTools<T>::GetNumberOfItemGivenBESRelative(bg,stop,step,"DataArrayInt::buildExplicitArrOfSliceOnScaledArr");
6161     T sz(0),pos(bg);
6162     for(mcIdType i=0;i<nbOfEltsInSlc;i++,pos+=step)
6163       {
6164         if(pos>=0 && pos<nbOfTuples-1)
6165           {
6166             T delta(ids[pos+1]-ids[pos]);
6167             sz+=delta;
6168             if(delta<0)
6169               {
6170                 std::ostringstream oss; oss << "DataArrayInt::buildExplicitArrOfSliceOnScaledArr : At pos #" << i << " of input slice, value is " << pos << " and at this pos this is not monotonically increasing !";
6171                 throw INTERP_KERNEL::Exception(oss.str().c_str());
6172               }
6173           }
6174         else
6175           {
6176             std::ostringstream oss; oss << "DataArrayInt::buildExplicitArrOfSliceOnScaledArr : At pos #" << i << " of input slice, value is " << pos << " should be in [0," << nbOfTuples-1 << ") !";
6177             throw INTERP_KERNEL::Exception(oss.str().c_str());
6178           }
6179       }
6180     MCAuto<DataArrayType> ret(DataArrayType::New()); ret->alloc(sz,1);
6181     T *retPtr(ret->getPointer());
6182     pos=bg;
6183     for(mcIdType i=0;i<nbOfEltsInSlc;i++,pos+=step)
6184       {
6185         T delta(ids[pos+1]-ids[pos]);
6186         for(T j=0;j<delta;j++,retPtr++)
6187           *retPtr=pos;
6188       }
6189     return ret.retn();
6190   }
6191
6192   /*!
6193    * 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.
6194    * 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
6195    * in tuple **i** of returned DataArrayInt.
6196    * If ranges overlapped (in theory it should not) this method do not detect it and always returns the first range.
6197    *
6198    * 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)]
6199    * The return DataArrayInt will contain : **[0,4,1,2,2,3]**
6200    *
6201    * \param [in] ranges typically come from output of MEDCouplingUMesh::ComputeRangesFromTypeDistribution. Each range is specified like this : 1st component is
6202    *             for lower value included and 2nd component is the upper value of corresponding range **excluded**.
6203    * \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
6204    *        is thrown if no ranges in \a ranges contains value in \a this.
6205    *
6206    * \sa DataArrayInt::findIdInRangeForEachTuple
6207    */
6208   template <class T>
6209   DataArrayIdType *DataArrayDiscrete<T>::findRangeIdForEachTuple(const DataArrayType *ranges) const
6210   {
6211     if(!ranges)
6212       throw INTERP_KERNEL::Exception("DataArrayInt::findRangeIdForEachTuple : null input pointer !");
6213     if(ranges->getNumberOfComponents()!=2)
6214       throw INTERP_KERNEL::Exception("DataArrayInt::findRangeIdForEachTuple : input DataArrayInt instance should have 2 components !");
6215     this->checkAllocated();
6216     if(this->getNumberOfComponents()!=1)
6217       throw INTERP_KERNEL::Exception("DataArrayInt::findRangeIdForEachTuple : this should have only one component !");
6218     mcIdType nbTuples(this->getNumberOfTuples());
6219     MCAuto<DataArrayIdType> ret=DataArrayIdType::New(); ret->alloc(nbTuples,1);
6220     mcIdType nbOfRanges(ranges->getNumberOfTuples());
6221     const T *rangesPtr=ranges->getConstPointer();
6222     mcIdType *retPtr=ret->getPointer();
6223     const T *inPtr=this->getConstPointer();
6224     for(mcIdType i=0;i<nbTuples;i++,retPtr++)
6225       {
6226         T val=inPtr[i];
6227         bool found=false;
6228         for(mcIdType j=0;j<nbOfRanges && !found;j++)
6229           if(val>=rangesPtr[2*j] && val<rangesPtr[2*j+1])
6230             { *retPtr=j; found=true; }
6231         if(found)
6232           continue;
6233         else
6234           {
6235             std::ostringstream oss; oss << "DataArrayInt::findRangeIdForEachTuple : tuple #" << i << " not found by any ranges !";
6236             throw INTERP_KERNEL::Exception(oss.str().c_str());
6237           }
6238       }
6239     return ret.retn();
6240   }
6241
6242   /*!
6243    * 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.
6244    * 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
6245    * in tuple **i** of returned DataArrayInt.
6246    * If ranges overlapped (in theory it should not) this method do not detect it and always returns the sub position of the first range.
6247    *
6248    * 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)]
6249    * The return DataArrayInt will contain : **[1,2,4,0,2,2]**
6250    * This method is often called in pair with DataArrayInt::findRangeIdForEachTuple method.
6251    *
6252    * \param [in] ranges typically come from output of MEDCouplingUMesh::ComputeRangesFromTypeDistribution. Each range is specified like this : 1st component is
6253    *             for lower value included and 2nd component is the upper value of corresponding range **excluded**.
6254    * \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
6255    *        is thrown if no ranges in \a ranges contains value in \a this.
6256    * \sa DataArrayInt::findRangeIdForEachTuple
6257    */
6258   template <class T>
6259   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::findIdInRangeForEachTuple(const DataArrayType *ranges) const
6260   {
6261     if(!ranges)
6262       throw INTERP_KERNEL::Exception("DataArrayInt::findIdInRangeForEachTuple : null input pointer !");
6263     if(ranges->getNumberOfComponents()!=2)
6264       throw INTERP_KERNEL::Exception("DataArrayInt::findIdInRangeForEachTuple : input DataArrayInt instance should have 2 components !");
6265     this->checkAllocated();
6266     if(this->getNumberOfComponents()!=1)
6267       throw INTERP_KERNEL::Exception("DataArrayInt::findIdInRangeForEachTuple : this should have only one component !");
6268     mcIdType nbTuples=this->getNumberOfTuples();
6269     MCAuto<DataArrayType> ret=DataArrayType::New(); ret->alloc(nbTuples,1);
6270     mcIdType nbOfRanges=ranges->getNumberOfTuples();
6271     const T *rangesPtr=ranges->getConstPointer();
6272     T *retPtr=ret->getPointer();
6273     const T *inPtr=this->getConstPointer();
6274     for(mcIdType i=0;i<nbTuples;i++,retPtr++)
6275       {
6276         T val=inPtr[i];
6277         bool found=false;
6278         for(mcIdType j=0;j<nbOfRanges && !found;j++)
6279           if(val>=rangesPtr[2*j] && val<rangesPtr[2*j+1])
6280             { *retPtr=val-rangesPtr[2*j]; found=true; }
6281         if(found)
6282           continue;
6283         else
6284           {
6285             std::ostringstream oss; oss << "DataArrayInt::findIdInRangeForEachTuple : tuple #" << i << " not found by any ranges !";
6286             throw INTERP_KERNEL::Exception(oss.str().c_str());
6287           }
6288       }
6289     return ret.retn();
6290   }
6291
6292   /*!
6293    * \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).
6294    * 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).
6295    * 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 !
6296    * If this method has correctly worked, \a this will be able to be considered as a linked list.
6297    * This method does nothing if number of tuples is lower of equal to 1.
6298    *
6299    * This method is useful for users having an unstructured mesh having only SEG2 to rearrange internally the connectivity without any coordinates consideration.
6300    *
6301    * \sa MEDCouplingUMesh::orderConsecutiveCells1D, DataArrayInt::sortToHaveConsecutivePairs(), DataArrayInt::fromLinkedListOfPairToList
6302    */
6303   template <class T>
6304   void DataArrayDiscrete<T>::sortEachPairToMakeALinkedList()
6305   {
6306     this->checkAllocated();
6307     if(this->getNumberOfComponents()!=2)
6308       throw INTERP_KERNEL::Exception("DataArrayInt::sortEachPairToMakeALinkedList : Only works on DataArrayInt instance with nb of components equal to 2 !");
6309     mcIdType nbOfTuples(this->getNumberOfTuples());
6310     if(nbOfTuples<=1)
6311       return ;
6312     T *conn(this->getPointer());
6313     for(mcIdType i=1;i<nbOfTuples;i++,conn+=2)
6314       {
6315         if(i>1)
6316           {
6317             if(conn[2]==conn[3])
6318               {
6319                 std::ostringstream oss; oss << "DataArrayInt::sortEachPairToMakeALinkedList : In the tuple #" << i << " presence of a pair filled with same ids !";
6320                 throw INTERP_KERNEL::Exception(oss.str().c_str());
6321               }
6322             if(conn[2]!=conn[1] && conn[3]!=conn[1])
6323               {
6324                 std::ostringstream oss; oss << "DataArrayInt::sortEachPairToMakeALinkedList : There is no common noeud between the tuple #" << i << " and the tuple #" << i + 1 << ". Need call DataArrayInt::sortToHaveConsecutivePairs() ";
6325                 throw INTERP_KERNEL::Exception(oss.str().c_str());
6326               }
6327             if(conn[2]!=conn[1] && conn[3]==conn[1] && conn[2]!=conn[0])
6328               std::swap(conn[2],conn[3]);
6329             //not(conn[2]==conn[1] && conn[3]!=conn[1] && conn[3]!=conn[0])
6330             if(conn[2]!=conn[1] || conn[3]==conn[1] || conn[3]==conn[0])
6331               {
6332                 std::ostringstream oss; oss << "DataArrayInt::sortEachPairToMakeALinkedList : In the tuple #" << i << " something is invalid !";
6333                 throw INTERP_KERNEL::Exception(oss.str().c_str());
6334               }
6335           }
6336         else
6337           {
6338             if(conn[0]==conn[1] || conn[2]==conn[3])
6339               throw INTERP_KERNEL::Exception("DataArrayInt::sortEachPairToMakeALinkedList : In the 2 first tuples presence of a pair filled with same ids !");
6340             T tmp[4];
6341             std::set<T> s;
6342             s.insert(conn,conn+4);
6343             if(s.size()!=3)
6344               throw INTERP_KERNEL::Exception("DataArrayInt::sortEachPairToMakeALinkedList : This can't be considered as a linked list regarding 2 first tuples !");
6345             if(std::count(conn,conn+4,conn[0])==2)
6346               {
6347                 tmp[0]=conn[1];
6348                 tmp[1]=conn[0];
6349                 tmp[2]=conn[0];
6350                 if(conn[2]==conn[0])
6351                   { tmp[3]=conn[3]; }
6352                 else
6353                   { tmp[3]=conn[2];}
6354                 std::copy(tmp,tmp+4,conn);
6355               }
6356             else
6357               {//here we are sure to have (std::count(conn,conn+4,conn[1])==2)
6358                 if(conn[1]==conn[3])
6359                   std::swap(conn[2],conn[3]);
6360               }
6361           }
6362       }
6363   }
6364
6365   /*!
6366    * This method is the improvement from the method sortEachPairToMakeALinkedList().
6367    *
6368    * \sa MEDCouplingUMesh::orderConsecutiveCells1D, DataArrayInt::sortEachPairToMakeALinkedList(), DataArrayInt::fromLinkedListOfPairToList
6369    */
6370   template <class T>
6371   void DataArrayDiscrete<T>::sortToHaveConsecutivePairs()
6372   {
6373     this->checkAllocated();
6374     if(this->getNumberOfComponents()!=2)
6375       throw INTERP_KERNEL::Exception("DataArrayInt::sortToHaveConsecutivePairs : Only works on DataArrayInt instance with nb of components equal to 2 !");
6376     mcIdType nbOfTuples(this->getNumberOfTuples());
6377     T *thisPtr(this->getPointer());
6378     mcIdType idOfLastTuple = 0;
6379     std::pair<T*,T*> tmp;
6380     if(thisPtr[0]==thisPtr[1])
6381       {
6382         THROW_IK_EXCEPTION("DataArrayInt::sortToHaveConsecutivePairs : In the first tuple presence of a pair filled with same ids !");
6383       }
6384     while(idOfLastTuple < nbOfTuples-1)
6385     {
6386       mcIdType i = idOfLastTuple+1;
6387       tmp.first = &thisPtr[2*i];
6388       tmp.second = &thisPtr[2*i+1];
6389       if(std::get<0>(tmp)[0] == std::get<1>(tmp)[0])
6390         {
6391           THROW_IK_EXCEPTION("DataArrayInt::sortToHaveConsecutivePairs : In the tuple #" << i << " presence of a pair filled with same ids !");
6392         }
6393       while((this->getIJ(idOfLastTuple,1) != std::get<0>(tmp)[0] &&
6394             this->getIJ(idOfLastTuple,1) != std::get<1>(tmp)[0]) &&
6395             i < nbOfTuples-1)
6396         {
6397           std::swap(std::get<0>(tmp)[0],thisPtr[2*(i+1)]);
6398           std::swap(std::get<1>(tmp)[0],thisPtr[2*(i+1)+1]);
6399           i++;
6400         }
6401       if(i < nbOfTuples-1 ||
6402          this->getIJ(idOfLastTuple,1) == std::get<0>(tmp)[0] ||
6403          this->getIJ(idOfLastTuple,1) == std::get<1>(tmp)[0])
6404       {
6405         if(this->getIJ(idOfLastTuple,1) != std::get<0>(tmp)[0])
6406           std::swap(std::get<0>(tmp)[0],std::get<1>(tmp)[0]);
6407         idOfLastTuple++;
6408       }
6409       else
6410       {
6411         THROW_IK_EXCEPTION("DataArrayInt::sortToHaveConsecutivePairs : not found the tuple which have the common noeud = " << this->getIJ(idOfLastTuple,1));
6412       }
6413     }
6414   }
6415
6416   /*!
6417    * \a this is expected to be a correctly linked list of pairs.
6418    *
6419    * \sa DataArrayInt::sortEachPairToMakeALinkedList
6420    */
6421   template <class T>
6422   MCAuto<typename Traits<T>::ArrayType> DataArrayDiscrete<T>::fromLinkedListOfPairToList() const
6423   {
6424     this->checkAllocated();
6425     this->checkNbOfComps(2,"DataArrayInt::fromLinkedListOfPairToList : this is expected to have 2 components");
6426     mcIdType nbTuples(this->getNumberOfTuples());
6427     if(nbTuples<1)
6428       throw INTERP_KERNEL::Exception("DataArrayInt::fromLinkedListOfPairToList : no tuples in this ! Not a linked list !");
6429     MCAuto<DataArrayType> ret(DataArrayType::New()); ret->alloc(nbTuples+1,1);
6430     const T *thisPtr(this->begin());
6431     T *retPtr(ret->getPointer());
6432     retPtr[0]=thisPtr[0];
6433     for(mcIdType i=0;i<nbTuples;i++)
6434       {
6435         retPtr[i+1]=thisPtr[2*i+1];
6436         if(i<nbTuples-1)
6437           if(thisPtr[2*i+1]!=thisPtr[2*(i+1)+0])
6438             {
6439               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 ?";
6440               throw INTERP_KERNEL::Exception(oss.str());
6441             }
6442       }
6443     return ret;
6444   }
6445
6446   /*!
6447    * This method returns all different values found in \a this. This method throws if \a this has not been allocated.
6448    * But the number of components can be different from one.
6449    * \return a newly allocated array (that should be dealt by the caller) containing different values in \a this.
6450    */
6451   template <class T>
6452   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::getDifferentValues() const
6453   {
6454     this->checkAllocated();
6455     std::set<T> ret;
6456     ret.insert(this->begin(),this->end());
6457     MCAuto<DataArrayType> ret2=DataArrayType::New();
6458     ret2->alloc(ret.size(),1);
6459     std::copy(ret.begin(),ret.end(),ret2->getPointer());
6460     return ret2.retn();
6461   }
6462
6463   /*!
6464    * This method is a refinement of DataArrayInt::getDifferentValues because it returns not only different values in \a this but also, for each of
6465    * them it tells which tuple id have this id.
6466    * This method works only on arrays with one component (if it is not the case call DataArrayInt::rearrange(1) ).
6467    * This method returns two arrays having same size.
6468    * 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.
6469    * 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]]
6470    */
6471   template <class T>
6472   std::vector<DataArrayIdType *> DataArrayDiscrete<T>::partitionByDifferentValues(std::vector<T>& differentIds) const
6473   {
6474     this->checkAllocated();
6475     if(this->getNumberOfComponents()!=1)
6476       throw INTERP_KERNEL::Exception("DataArrayInt::partitionByDifferentValues : this should have only one component !");
6477     mcIdType id=0;
6478     std::map<T,mcIdType> m,m2,m3;
6479     for(const T *w=this->begin();w!=this->end();w++)
6480       m[*w]++;
6481     differentIds.resize(m.size());
6482     std::vector<DataArrayIdType *> ret(m.size());
6483     std::vector<mcIdType *> retPtr(m.size());
6484     for(typename std::map<T,mcIdType>::const_iterator it=m.begin();it!=m.end();it++,id++)
6485       {
6486         m2[(*it).first]=id;
6487         ret[id]=DataArrayIdType::New();
6488         ret[id]->alloc((*it).second,1);
6489         retPtr[id]=ret[id]->getPointer();
6490         differentIds[id]=(*it).first;
6491       }
6492     id=0;
6493     for(const T *w=this->begin();w!=this->end();w++,id++)
6494       {
6495         retPtr[m2[*w]][m3[*w]++]=id;
6496       }
6497     return ret;
6498   }
6499
6500   /*!
6501    * This method split ids in [0, \c this->getNumberOfTuples() ) using \a this array as a field of weight (>=0 each).
6502    * The aim of this method is to return a set of \a nbOfSlices chunk of contiguous ids as balanced as possible.
6503    *
6504    * \param [in] nbOfSlices - number of slices expected.
6505    * \return - a vector having a size equal to \a nbOfSlices giving the start (included) and the stop (excluded) of each chunks.
6506    *
6507    * \sa DataArray::GetSlice
6508    * \throw If \a this is not allocated or not with exactly one component.
6509    * \throw If an element in \a this if < 0.
6510    */
6511   template <class T>
6512   std::vector< std::pair<mcIdType,mcIdType> > DataArrayDiscrete<T>::splitInBalancedSlices(mcIdType nbOfSlices) const
6513   {
6514     if(!this->isAllocated() || this->getNumberOfComponents()!=1)
6515       throw INTERP_KERNEL::Exception("DataArrayInt::splitInBalancedSlices : this array should have number of components equal to one and must be allocated !");
6516     if(nbOfSlices<=0)
6517       throw INTERP_KERNEL::Exception("DataArrayInt::splitInBalancedSlices : number of slices must be >= 1 !");
6518     T sum(this->accumulate((std::size_t)0));
6519     mcIdType nbOfTuples(this->getNumberOfTuples());
6520     T sumPerSlc(sum/FromIdType<T>(nbOfSlices));
6521     mcIdType pos(0);
6522     const T *w(this->begin());
6523     std::vector< std::pair<mcIdType,mcIdType> > ret(nbOfSlices);
6524     for(mcIdType i=0;i<nbOfSlices;i++)
6525       {
6526         std::pair<mcIdType, mcIdType> p(pos,-1);
6527         T locSum(0);
6528         while(locSum<sumPerSlc && pos<nbOfTuples) { pos++; locSum+=*w++; }
6529         if(i!=nbOfSlices-1)
6530           p.second=pos;
6531         else
6532           p.second=nbOfTuples;
6533         ret[i]=p;
6534       }
6535     return ret;
6536   }
6537
6538   /*!
6539    * Modify \a this array so that each value becomes a modulus of division of this value by
6540    * a value of another DataArrayInt. There are 3 valid cases.
6541    * 1.  The arrays have same number of tuples and components. Then each value of
6542    *    \a this array is divided by the corresponding value of \a other one, i.e.:
6543    *   _a_ [ i, j ] %= _other_ [ i, j ].
6544    * 2.  The arrays have same number of tuples and \a other array has one component. Then
6545    *   _a_ [ i, j ] %= _other_ [ i, 0 ].
6546    * 3.  The arrays have same number of components and \a other array has one tuple. Then
6547    *   _a_ [ i, j ] %= _a2_ [ 0, j ].
6548    *
6549    *  \warning No check of division by zero is performed!
6550    *  \param [in] other - a divisor array.
6551    *  \throw If \a other is NULL.
6552    *  \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples() and
6553    *         \a this->getNumberOfComponents() != \a other->getNumberOfComponents() and
6554    *         \a other has number of both tuples and components not equal to 1.
6555    */
6556   template <class T>
6557   void DataArrayDiscrete<T>::modulusEqual(const DataArrayType *other)
6558   {
6559     if(!other)
6560       throw INTERP_KERNEL::Exception("DataArrayInt::modulusEqual : input DataArrayInt instance is NULL !");
6561     const char *msg="Nb of tuples mismatch for DataArrayInt::modulusEqual !";
6562     this->checkAllocated(); other->checkAllocated();
6563     mcIdType nbOfTuple(this->getNumberOfTuples());
6564     mcIdType nbOfTuple2(other->getNumberOfTuples());
6565     std::size_t nbOfComp(this->getNumberOfComponents());
6566     std::size_t nbOfComp2(other->getNumberOfComponents());
6567     if(nbOfTuple==nbOfTuple2)
6568       {
6569         if(nbOfComp==nbOfComp2)
6570           {
6571             std::transform(this->begin(),this->end(),other->begin(),this->getPointer(),std::modulus<T>());
6572           }
6573         else if(nbOfComp2==1)
6574           {
6575             if(nbOfComp2==nbOfComp)
6576               {
6577                 T *ptr=this->getPointer();
6578                 const T *ptrc=other->getConstPointer();
6579                 for(mcIdType i=0;i<nbOfTuple;i++)
6580                   std::transform(ptr+i*nbOfComp,ptr+(i+1)*nbOfComp,ptr+i*nbOfComp,std::bind(std::modulus<T>(),std::placeholders::_1,*ptrc++));
6581               }
6582             else
6583               throw INTERP_KERNEL::Exception(msg);
6584           }
6585         else
6586           throw INTERP_KERNEL::Exception(msg);
6587       }
6588     else if(nbOfTuple2==1)
6589       {
6590         T *ptr=this->getPointer();
6591         const T *ptrc=other->getConstPointer();
6592         for(mcIdType i=0;i<nbOfTuple;i++)
6593           std::transform(ptr+i*nbOfComp,ptr+(i+1)*nbOfComp,ptrc,ptr+i*nbOfComp,std::modulus<T>());
6594       }
6595     else
6596       throw INTERP_KERNEL::Exception(msg);
6597     this->declareAsNew();
6598   }
6599
6600   /*!
6601    * Apply pow on values of another DataArrayInt to values of \a this one.
6602    *
6603    *  \param [in] other - an array to pow to \a this one.
6604    *  \throw If \a other is NULL.
6605    *  \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples()
6606    *  \throw If \a this->getNumberOfComponents() != 1 or \a other->getNumberOfComponents() != 1
6607    *  \throw If there is a negative value in \a other.
6608    */
6609   template <class T>
6610   void DataArrayDiscrete<T>::powEqual(const DataArrayType *other)
6611   {
6612     if(!other)
6613       throw INTERP_KERNEL::Exception("DataArrayInt::powEqual : input instance is null !");
6614     mcIdType nbOfTuple=this->getNumberOfTuples();
6615     mcIdType nbOfTuple2=other->getNumberOfTuples();
6616     std::size_t nbOfComp=this->getNumberOfComponents();
6617     std::size_t nbOfComp2=other->getNumberOfComponents();
6618     if(nbOfTuple!=nbOfTuple2)
6619       throw INTERP_KERNEL::Exception("DataArrayInt::powEqual : number of tuples mismatches !");
6620     if(nbOfComp!=1 || nbOfComp2!=1)
6621       throw INTERP_KERNEL::Exception("DataArrayInt::powEqual : number of components of both arrays must be equal to 1 !");
6622     T *ptr=this->getPointer();
6623     const T *ptrc=other->begin();
6624     for(mcIdType i=0;i<nbOfTuple;i++,ptrc++,ptr++)
6625       {
6626         if(*ptrc>=0)
6627           {
6628             T tmp=1;
6629             for(T j=0;j<*ptrc;j++)
6630               tmp*=*ptr;
6631             *ptr=tmp;
6632           }
6633         else
6634           {
6635             std::ostringstream oss; oss << "DataArrayInt::powEqual : on tuple #" << i << " of other value is < 0 (" << *ptrc << ") !";
6636             throw INTERP_KERNEL::Exception(oss.str().c_str());
6637           }
6638       }
6639     this->declareAsNew();
6640   }
6641
6642   ////////////////////////////////////
6643   /*!
6644    * Useless method for end user. Only for MPI/Corba/File serialsation for multi arrays class.
6645    * Server side.
6646    */
6647   template <class T>
6648   void DataArrayDiscrete<T>::getTinySerializationIntInformation(std::vector<mcIdType>& tinyInfo) const
6649   {
6650     tinyInfo.resize(2);
6651     if(this->isAllocated())
6652       {
6653         tinyInfo[0]=this->getNumberOfTuples();
6654         tinyInfo[1]=ToIdType(this->getNumberOfComponents());
6655       }
6656     else
6657       {
6658         tinyInfo[0]=-1;
6659         tinyInfo[1]=-1;
6660       }
6661   }
6662
6663   /*!
6664    * Useless method for end user. Only for MPI/Corba/File serialsation for multi arrays class.
6665    * Server side.
6666    */
6667   template <class T>
6668   void DataArrayDiscrete<T>::getTinySerializationStrInformation(std::vector<std::string>& tinyInfo) const
6669   {
6670     if(this->isAllocated())
6671       {
6672         std::size_t nbOfCompo(this->getNumberOfComponents());
6673         tinyInfo.resize(nbOfCompo+1);
6674         tinyInfo[0]=this->getName();
6675         for(std::size_t i=0;i<nbOfCompo;i++)
6676           tinyInfo[i+1]=this->getInfoOnComponent(i);
6677       }
6678     else
6679       {
6680         tinyInfo.resize(1);
6681         tinyInfo[0]=this->getName();
6682       }
6683   }
6684
6685   /*!
6686    * Useless method for end user. Only for MPI/Corba/File serialsation for multi arrays class.
6687    * This method returns if a feeding is needed.
6688    */
6689   template <class T>
6690   bool DataArrayDiscrete<T>::resizeForUnserialization(const std::vector<mcIdType>& tinyInfoI)
6691   {
6692     mcIdType nbOfTuple=tinyInfoI[0];
6693     mcIdType nbOfComp=tinyInfoI[1];
6694     if(nbOfTuple!=-1 || nbOfComp!=-1)
6695       {
6696         this->alloc(nbOfTuple,nbOfComp);
6697         return true;
6698       }
6699     return false;
6700   }
6701
6702   /*!
6703    * Useless method for end user. Only for MPI/Corba/File serialsation for multi arrays class.
6704    * This method returns if a feeding is needed.
6705    */
6706   template <class T>
6707   void DataArrayDiscrete<T>::finishUnserialization(const std::vector<mcIdType>& tinyInfoI, const std::vector<std::string>& tinyInfoS)
6708   {
6709     this->setName(tinyInfoS[0]);
6710     if(this->isAllocated())
6711       {
6712         mcIdType nbOfCompo=tinyInfoI[1];
6713         for(mcIdType i=0;i<nbOfCompo;i++)
6714           this->setInfoOnComponent(i,tinyInfoS[i+1]);
6715       }
6716   }
6717
6718   ////////////////////////////////////
6719
6720   /*!
6721    * Returns a new DataArrayInt that is the result of pow of two given arrays. There are 3
6722    * valid cases.
6723    *
6724    *  \param [in] a1 - an array to pow up.
6725    *  \param [in] a2 - another array to sum up.
6726    *  \return DataArrayInt * - the new instance of DataArrayInt.
6727    *          The caller is to delete this result array using decrRef() as it is no more
6728    *          needed.
6729    *  \throw If either \a a1 or \a a2 is NULL.
6730    *  \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples()
6731    *  \throw If \a a1->getNumberOfComponents() != 1 or \a a2->getNumberOfComponents() != 1.
6732    *  \throw If there is a negative value in \a a2.
6733    */
6734   template <class T>
6735   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::Pow(const DataArrayType *a1, const DataArrayType *a2)
6736   {
6737     if(!a1 || !a2)
6738       throw INTERP_KERNEL::Exception("DataArrayInt::Pow : at least one of input instances is null !");
6739     mcIdType nbOfTuple=a1->getNumberOfTuples();
6740     mcIdType nbOfTuple2=a2->getNumberOfTuples();
6741     std::size_t nbOfComp=a1->getNumberOfComponents();
6742     std::size_t nbOfComp2=a2->getNumberOfComponents();
6743     if(nbOfTuple!=nbOfTuple2)
6744       throw INTERP_KERNEL::Exception("DataArrayInt::Pow : number of tuples mismatches !");
6745     if(nbOfComp!=1 || nbOfComp2!=1)
6746       throw INTERP_KERNEL::Exception("DataArrayInt::Pow : number of components of both arrays must be equal to 1 !");
6747     MCAuto<DataArrayType> ret=DataArrayType::New(); ret->alloc(nbOfTuple,1);
6748     const T *ptr1(a1->begin()),*ptr2(a2->begin());
6749     T *ptr=ret->getPointer();
6750     for(mcIdType i=0;i<nbOfTuple;i++,ptr1++,ptr2++,ptr++)
6751       {
6752         if(*ptr2>=0)
6753           {
6754             T tmp=1;
6755             for(T j=0;j<*ptr2;j++)
6756               tmp*=*ptr1;
6757             *ptr=tmp;
6758           }
6759         else
6760           {
6761             std::ostringstream oss; oss << "DataArrayInt::Pow : on tuple #" << i << " of a2 value is < 0 (" << *ptr2 << ") !";
6762             throw INTERP_KERNEL::Exception(oss.str().c_str());
6763           }
6764       }
6765     return ret.retn();
6766   }
6767
6768   /*!
6769    * Returns a new DataArrayInt that is a modulus of two given arrays. There are 3
6770    * valid cases.
6771    * 1.  The arrays have same number of tuples and components. Then each value of
6772    *   the result array (_a_) is a division of the corresponding values of \a a1 and
6773    *   \a a2, i.e.: _a_ [ i, j ] = _a1_ [ i, j ] % _a2_ [ i, j ].
6774    * 2.  The arrays have same number of tuples and one array, say _a2_, has one
6775    *   component. Then
6776    *   _a_ [ i, j ] = _a1_ [ i, j ] % _a2_ [ i, 0 ].
6777    * 3.  The arrays have same number of components and one array, say _a2_, has one
6778    *   tuple. Then
6779    *   _a_ [ i, j ] = _a1_ [ i, j ] % _a2_ [ 0, j ].
6780    *
6781    * Info on components is copied either from the first array (in the first case) or from
6782    * the array with maximal number of elements (getNbOfElems()).
6783    *  \warning No check of division by zero is performed!
6784    *  \param [in] a1 - a dividend array.
6785    *  \param [in] a2 - a divisor array.
6786    *  \return DataArrayInt * - the new instance of DataArrayInt.
6787    *          The caller is to delete this result array using decrRef() as it is no more
6788    *          needed.
6789    *  \throw If either \a a1 or \a a2 is NULL.
6790    *  \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples() and
6791    *         \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents() and
6792    *         none of them has number of tuples or components equal to 1.
6793    */
6794   template <class T>
6795   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::Modulus(const DataArrayType *a1, const DataArrayType *a2)
6796   {
6797     if(!a1 || !a2)
6798       throw INTERP_KERNEL::Exception("DataArrayInt::Modulus : input DataArrayInt instance is NULL !");
6799     mcIdType nbOfTuple1(a1->getNumberOfTuples());
6800     mcIdType nbOfTuple2(a2->getNumberOfTuples());
6801     std::size_t nbOfComp1(a1->getNumberOfComponents());
6802     std::size_t nbOfComp2(a2->getNumberOfComponents());
6803     if(nbOfTuple2==nbOfTuple1)
6804       {
6805         if(nbOfComp1==nbOfComp2)
6806           {
6807             MCAuto<DataArrayType> ret=DataArrayType::New();
6808             ret->alloc(nbOfTuple2,nbOfComp1);
6809             std::transform(a1->begin(),a1->end(),a2->begin(),ret->getPointer(),std::modulus<T>());
6810             ret->copyStringInfoFrom(*a1);
6811             return ret.retn();
6812           }
6813         else if(nbOfComp2==1)
6814           {
6815             MCAuto<DataArrayType> ret=DataArrayType::New();
6816             ret->alloc(nbOfTuple1,nbOfComp1);
6817             const T *a2Ptr=a2->getConstPointer();
6818             const T *a1Ptr=a1->getConstPointer();
6819             T *res=ret->getPointer();
6820             for(mcIdType i=0;i<nbOfTuple1;i++)
6821               res=std::transform(a1Ptr+i*nbOfComp1,a1Ptr+(i+1)*nbOfComp1,res,std::bind(std::modulus<T>(),std::placeholders::_1,a2Ptr[i]));
6822             ret->copyStringInfoFrom(*a1);
6823             return ret.retn();
6824           }
6825         else
6826           {
6827             a1->checkNbOfComps(nbOfComp2,"Nb of components mismatch for array Modulus !");
6828             return 0;
6829           }
6830       }
6831     else if(nbOfTuple2==1)
6832       {
6833         a1->checkNbOfComps(nbOfComp2,"Nb of components mismatch for array Modulus !");
6834         MCAuto<DataArrayType> ret=DataArrayType::New();
6835         ret->alloc(nbOfTuple1,nbOfComp1);
6836         const T *a1ptr=a1->getConstPointer(),*a2ptr=a2->getConstPointer();
6837         T *pt=ret->getPointer();
6838         for(mcIdType i=0;i<nbOfTuple1;i++)
6839           pt=std::transform(a1ptr+i*nbOfComp1,a1ptr+(i+1)*nbOfComp1,a2ptr,pt,std::modulus<T>());
6840         ret->copyStringInfoFrom(*a1);
6841         return ret.retn();
6842       }
6843     else
6844       {
6845         a1->checkNbOfTuples(nbOfTuple2,"Nb of tuples mismatch for array Modulus !");//will always throw an exception
6846         return 0;
6847       }
6848   }
6849
6850   /*!
6851    * 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
6852    * input array \a ids2.
6853    * \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.
6854    * 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
6855    * inversely.
6856    * In case of success both assertion will be true (no throw) :
6857    * \c ids1->renumber(ret)->isEqual(ids2) where \a ret is the return of this method.
6858    * \c ret->transformWithIndArr(ids2)->isEqual(ids1)
6859    *
6860    * \b Example:
6861    * - \a ids1 : [3,1,103,4,6,10,-7,205]
6862    * - \a ids2 : [-7,1,205,10,6,3,103,4]
6863    * - \a return is : [5,1,6,7,4,3,0,2] because ids2[5]==ids1[0], ids2[1]==ids1[1], ids2[6]==ids1[2]...
6864    *
6865    * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
6866    *          array using decrRef() as it is no more needed.
6867    * \throw If either ids1 or ids2 is null not allocated or not with one components.
6868    *
6869    * \sa DataArrayInt::findIdForEach, DataArrayInt::FindPermutationFromFirstToSecondDuplicate, DataArrayInt::rankOfElementInThis
6870    */
6871   template<class T>
6872   DataArrayIdType *DataArrayDiscrete<T>::FindPermutationFromFirstToSecond(const DataArrayType *ids1, const DataArrayType *ids2)
6873   {
6874     if(!ids1 || !ids2)
6875       throw INTERP_KERNEL::Exception("DataArrayInt::FindPermutationFromFirstToSecond : the two input arrays must be not null !");
6876     if(!ids1->isAllocated() || !ids2->isAllocated())
6877       throw INTERP_KERNEL::Exception("DataArrayInt::FindPermutationFromFirstToSecond : the two input arrays must be allocated !");
6878     if(ids1->getNumberOfComponents()!=1 || ids2->getNumberOfComponents()!=1)
6879       throw INTERP_KERNEL::Exception("DataArrayInt::FindPermutationFromFirstToSecond : the two input arrays have exactly one component !");
6880     if(ids1->getNumberOfTuples()!=ids2->getNumberOfTuples())
6881       {
6882         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 !";
6883         throw INTERP_KERNEL::Exception(oss.str().c_str());
6884       }
6885     MCAuto<DataArrayType> c1(ids1->deepCopy());
6886     MCAuto<DataArrayType> c2(ids2->deepCopy());
6887     c1->sort(true); c2->sort(true);
6888     if(!c1->isEqualWithoutConsideringStr(*c2))
6889       throw INTERP_KERNEL::Exception("DataArrayInt::FindPermutationFromFirstToSecond : the two arrays are not lying on same ids ! Impossible to find a permutation between the 2 arrays !");
6890     MCAuto<DataArrayIdType> p1=ids1->checkAndPreparePermutation();
6891     MCAuto<DataArrayIdType> p2=ids2->checkAndPreparePermutation();
6892     p2=p2->invertArrayO2N2N2O(p2->getNumberOfTuples());
6893     p2=p2->selectByTupleIdSafe(p1->begin(),p1->end());
6894     return p2.retn();
6895   }
6896
6897   /*!
6898    * 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
6899    * input array \a ids2.
6900    * \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.
6901    * 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
6902    * inversely.
6903    * The difference with DataArrayInt::FindPermutationFromFirstToSecond is that this method supports multiple same values in \a ids1 and \a ids2 whereas
6904    * DataArrayInt::FindPermutationFromFirstToSecond doesn't. It implies that this method my be slower than the DataArrayInt::FindPermutationFromFirstToSecond one.
6905    *
6906    * In case of success both assertion will be true (no throw) :
6907    * \c ids1->renumber(ret)->isEqual(ids2) where \a ret is the return of this method.
6908    * \c ret->transformWithIndArr(ids2)->isEqual(ids1)
6909    *
6910    * \b Example:
6911    * - \a ids1 : [5, 3, 2, 1, 4, 5, 2, 1, 0, 11, 5, 4]
6912    * - \a ids2 : [0, 1, 1, 2, 2, 3, 4, 4, 5, 5, 5, 11]
6913    * - \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]...
6914    *
6915    * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
6916    *          array using decrRef() as it is no more needed.
6917    * \throw If either ids1 or ids2 is null not allocated or not with one components.
6918    *
6919    * \sa DataArrayInt::findIdForEach, DataArrayInt::FindPermutationFromFirstToSecond, DataArrayInt::occurenceRankInThis
6920    */
6921   template<class T>
6922   DataArrayIdType *DataArrayDiscrete<T>::FindPermutationFromFirstToSecondDuplicate(const DataArrayType *ids1, const DataArrayType *ids2)
6923   {
6924     if(!ids1 || !ids2)
6925       throw INTERP_KERNEL::Exception("DataArrayInt::FindPermutationFromFirstToSecondDuplicate : the two input arrays must be not null !");
6926     constexpr char MSG0[] = "DataArrayInt::FindPermutationFromFirstToSecondDuplicate :";
6927     ids1->checkAllocated(); ids2->checkAllocated();
6928     ids1->checkNbOfComps(1,MSG0); ids2->checkNbOfComps(1,MSG0);
6929     mcIdType nbTuples(ids1->getNumberOfTuples());
6930     if(nbTuples != ids2->getNumberOfTuples())
6931       {
6932         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 !";
6933         throw INTERP_KERNEL::Exception(oss.str().c_str());
6934       }
6935     MCAuto<DataArrayIdType> ret(DataArrayIdType::New()); ret->alloc(nbTuples,1);
6936     MCAuto<DataArrayIdType> oids2(ids2->occurenceRankInThis());
6937     std::map< std::pair<T,mcIdType>, mcIdType> m;
6938     mcIdType pos(0);
6939     const mcIdType *oids2Ptr(oids2->begin());
6940     for(const T * it2 = ids2->begin() ; it2 != ids2->end() ; ++it2, ++oids2Ptr, ++pos)
6941       m[{*it2,*oids2Ptr}] = pos;
6942     mcIdType *retPtr(ret->getPointer());
6943     //
6944     std::map<T,mcIdType> mOccurence1; // see DataArrayInt::occurenceRankInThis : avoid to compute additionnal temporary array
6945     //
6946     for(const T * it1 = ids1->begin() ; it1 != ids1->end() ; ++it1, ++retPtr)
6947     {
6948       auto it = mOccurence1.find(*it1);
6949       mcIdType occRk1;
6950       if( it == mOccurence1.end() )
6951       {
6952         occRk1 = 0;
6953         mOccurence1[*it1] = 1;
6954       }
6955       else
6956       {
6957         occRk1 = (*it).second++;
6958       }
6959       //
6960       auto it2 = m.find({*it1,occRk1});
6961       if(it2 != m.end())
6962       {
6963         *retPtr = (*it2).second;
6964       }
6965       else
6966       {
6967         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 !";
6968         throw INTERP_KERNEL::Exception(oss.str());
6969       }
6970
6971     }
6972     return ret.retn();
6973   }
6974
6975   /*!
6976    * Returns a C array which is a renumbering map in "Old to New" mode for the input array.
6977    * This map, if applied to \a start array, would make it sorted. For example, if
6978    * \a start array contents are [9,10,0,6,4,11,3,7] then the contents of the result array is
6979    * [5,6,0,3,2,7,1,4].
6980    *  \param [in] start - pointer to the first element of the array for which the
6981    *         permutation map is computed.
6982    *  \param [in] end - pointer specifying the end of the array \a start, so that
6983    *         the last value of \a start is \a end[ -1 ].
6984    *  \return mcIdType * - the result permutation array that the caller is to delete as it is no
6985    *         more needed.
6986    *  \throw If there are equal values in the input array.
6987    */
6988   template<class T>
6989   mcIdType *DataArrayDiscrete<T>::CheckAndPreparePermutation(const T *start, const T *end)
6990   {
6991     std::size_t sz=std::distance(start,end);
6992     mcIdType *ret=(mcIdType *)malloc(sz*sizeof(mcIdType));
6993     T *work=new T[sz];
6994     std::copy(start,end,work);
6995     std::sort(work,work+sz);
6996     if(std::unique(work,work+sz)!=work+sz)
6997       {
6998         delete [] work;
6999         free(ret);
7000         throw INTERP_KERNEL::Exception("Some elements are equals in the specified array !");
7001       }
7002     std::map<T,mcIdType> m;
7003     for(T *workPt=work;workPt!=work+sz;workPt++)
7004       m[*workPt]=ToIdType(std::distance(work,workPt));
7005     mcIdType *iter2=ret;
7006     for(const T *iter=start;iter!=end;iter++,iter2++)
7007       *iter2=m[*iter];
7008     delete [] work;
7009     return ret;
7010   }
7011
7012   /*!
7013    * Returns a new DataArrayInt by concatenating two given arrays, so that (1) the number
7014    * of tuples in the result array is <em> a1->getNumberOfTuples() + a2->getNumberOfTuples() -
7015    * offsetA2</em> and (2)
7016    * the number of component in the result array is same as that of each of given arrays.
7017    * First \a offsetA2 tuples of \a a2 are skipped and thus are missing from the result array.
7018    * Info on components is copied from the first of the given arrays. Number of components
7019    * in the given arrays must be the same.
7020    *  \param [in] a1 - an array to include in the result array.
7021    *  \param [in] a2 - another array to include in the result array.
7022    *  \param [in] offsetA2 - number of tuples of \a a2 to skip.
7023    *  \return DataArrayInt * - the new instance of DataArrayInt.
7024    *          The caller is to delete this result array using decrRef() as it is no more
7025    *          needed.
7026    *  \throw If either \a a1 or \a a2 is NULL.
7027    *  \throw If \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents().
7028    */
7029   template <class T>
7030   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::Aggregate(const DataArrayType *a1, const DataArrayType *a2, T offsetA2)
7031   {
7032     if(!a1 || !a2)
7033       throw INTERP_KERNEL::Exception("DataArrayInt::Aggregate : input DataArrayInt instance is NULL !");
7034     std::size_t nbOfComp(a1->getNumberOfComponents());
7035     if(nbOfComp!=a2->getNumberOfComponents())
7036       throw INTERP_KERNEL::Exception("Nb of components mismatch for array Aggregation !");
7037     mcIdType nbOfTuple1(a1->getNumberOfTuples()),nbOfTuple2(a2->getNumberOfTuples());
7038     MCAuto<DataArrayType> ret(DataArrayType::New());
7039     ret->alloc(nbOfTuple1+nbOfTuple2-offsetA2,nbOfComp);
7040     T *pt=std::copy(a1->begin(),a1->end(),ret->getPointer());
7041     std::copy(a2->getConstPointer()+offsetA2*nbOfComp,a2->getConstPointer()+nbOfTuple2*nbOfComp,pt);
7042     ret->copyStringInfoFrom(*a1);
7043     return ret.retn();
7044   }
7045
7046   /*!
7047    * Returns a new DataArrayInt by concatenating all given arrays, so that (1) the number
7048    * of tuples in the result array is a sum of the number of tuples of given arrays and (2)
7049    * the number of component in the result array is same as that of each of given arrays.
7050    * Info on components is copied from the first of the given arrays. Number of components
7051    * in the given arrays must be  the same.
7052    * If the number of non null of elements in \a arr is equal to one the returned object is a copy of it
7053    * not the object itself.
7054    *  \param [in] arr - a sequence of arrays to include in the result array.
7055    *  \return DataArrayInt * - the new instance of DataArrayInt.
7056    *          The caller is to delete this result array using decrRef() as it is no more
7057    *          needed.
7058    *  \throw If all arrays within \a arr are NULL.
7059    *  \throw If getNumberOfComponents() of arrays within \a arr.
7060    */
7061   template <class T>
7062   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::Aggregate(const std::vector<const DataArrayType *>& arr)
7063   {
7064     std::vector<const DataArrayType *> a;
7065     for(typename std::vector<const DataArrayType *>::const_iterator it4=arr.begin();it4!=arr.end();it4++)
7066       if(*it4)
7067         a.push_back(*it4);
7068     if(a.empty())
7069       throw INTERP_KERNEL::Exception("DataArrayInt::Aggregate : input list must be NON EMPTY !");
7070     typename std::vector<const DataArrayType *>::const_iterator it=a.begin();
7071     std::size_t nbOfComp((*it)->getNumberOfComponents());
7072     mcIdType nbt((*it++)->getNumberOfTuples());
7073     for(;it!=a.end();it++)
7074       {
7075         if((*it)->getNumberOfComponents()!=nbOfComp)
7076           throw INTERP_KERNEL::Exception("DataArrayInt::Aggregate : Nb of components mismatch for array aggregation !");
7077         nbt+=(*it)->getNumberOfTuples();
7078       }
7079     MCAuto<DataArrayType> ret=DataArrayType::New();
7080     ret->alloc(nbt,nbOfComp);
7081     T *pt=ret->getPointer();
7082     for(it=a.begin();it!=a.end();it++)
7083       pt=std::copy((*it)->getConstPointer(),(*it)->getConstPointer()+(*it)->getNbOfElems(),pt);
7084     ret->copyStringInfoFrom(*(a[0]));
7085     return ret.retn();
7086   }
7087
7088   /*!
7089    * This method takes as input a list of DataArrayInt instances \a arrs that represent each a packed index arrays.
7090    * A packed index array is an allocated array with one component, and at least one tuple. The first element
7091    * of each array in \a arrs must be 0. Each array in \a arrs is expected to be increasingly monotonic.
7092    * 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.
7093    *
7094    * \return DataArrayInt * - a new object to be managed by the caller.
7095    */
7096   template <class T>
7097   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::AggregateIndexes(const std::vector<const DataArrayType *>& arrs)
7098   {
7099     mcIdType retSz=1;
7100     for(typename std::vector<const DataArrayType *>::const_iterator it4=arrs.begin();it4!=arrs.end();it4++)
7101       {
7102         if(*it4)
7103           {
7104             (*it4)->checkAllocated();
7105             if((*it4)->getNumberOfComponents()!=1)
7106               {
7107                 std::ostringstream oss; oss << "DataArrayInt::AggregateIndexes : presence of a DataArrayInt instance with nb of compo != 1 at pos " << std::distance(arrs.begin(),it4) << " !";
7108                 throw INTERP_KERNEL::Exception(oss.str().c_str());
7109               }
7110             mcIdType nbTupl((*it4)->getNumberOfTuples());
7111             if(nbTupl<1)
7112               {
7113                 std::ostringstream oss; oss << "DataArrayInt::AggregateIndexes : presence of a DataArrayInt instance with nb of tuples < 1 at pos " << std::distance(arrs.begin(),it4) << " !";
7114                 throw INTERP_KERNEL::Exception(oss.str().c_str());
7115               }
7116             if((*it4)->front()!=0)
7117               {
7118                 std::ostringstream oss; oss << "DataArrayInt::AggregateIndexes : presence of a DataArrayInt instance with front value != 0 at pos " << std::distance(arrs.begin(),it4) << " !";
7119                 throw INTERP_KERNEL::Exception(oss.str().c_str());
7120               }
7121             retSz+=nbTupl-1;
7122           }
7123         else
7124           {
7125             std::ostringstream oss; oss << "DataArrayInt::AggregateIndexes : presence of a null instance at pos " << std::distance(arrs.begin(),it4) << " !";
7126             throw INTERP_KERNEL::Exception(oss.str().c_str());
7127           }
7128       }
7129     if(arrs.empty())
7130       throw INTERP_KERNEL::Exception("DataArrayInt::AggregateIndexes : input list must be NON EMPTY !");
7131     MCAuto<DataArrayType> ret=DataArrayType::New();
7132     ret->alloc(retSz,1);
7133     T *pt=ret->getPointer(); *pt++=0;
7134     for(typename std::vector<const DataArrayType *>::const_iterator it=arrs.begin();it!=arrs.end();it++)
7135       pt=std::transform((*it)->begin()+1,(*it)->end(),pt,std::bind(std::plus<T>(),std::placeholders::_1,pt[-1]));
7136     ret->copyStringInfoFrom(*(arrs[0]));
7137     return ret.retn();
7138   }
7139
7140   /*!
7141    * Returns a new DataArrayInt which contains all elements of given one-dimensional
7142    * arrays. The result array does not contain any duplicates and its values
7143    * are sorted in ascending order.
7144    *  \param [in] arr - sequence of DataArrayInt's to unite.
7145    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
7146    *         array using decrRef() as it is no more needed.
7147    *  \throw If any \a arr[i] is not allocated.
7148    *  \throw If \a arr[i]->getNumberOfComponents() != 1.
7149    */
7150   template <class T>
7151   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::BuildUnion(const std::vector<const DataArrayType *>& arr)
7152   {
7153     std::vector<const DataArrayType *> a;
7154     for(typename std::vector<const DataArrayType *>::const_iterator it4=arr.begin();it4!=arr.end();it4++)
7155       if(*it4)
7156         a.push_back(*it4);
7157     for(typename std::vector<const DataArrayType *>::const_iterator it=a.begin();it!=a.end();it++)
7158       {
7159         (*it)->checkAllocated();
7160         if((*it)->getNumberOfComponents()!=1)
7161           throw INTERP_KERNEL::Exception("DataArrayInt::BuildUnion : only single component allowed !");
7162       }
7163     //
7164     std::set<T> r;
7165     for(typename std::vector<const DataArrayType *>::const_iterator it=a.begin();it!=a.end();it++)
7166       {
7167         const T *pt=(*it)->getConstPointer();
7168         mcIdType nbOfTuples((*it)->getNumberOfTuples());
7169         r.insert(pt,pt+nbOfTuples);
7170       }
7171     DataArrayType *ret=DataArrayType::New();
7172     ret->alloc(r.size(),1);
7173     std::copy(r.begin(),r.end(),ret->getPointer());
7174     return ret;
7175   }
7176
7177   /*!
7178    * Returns a new DataArrayInt which contains elements present in each of given one-dimensional
7179    * arrays. The result array does not contain any duplicates and its values
7180    * are sorted in ascending order.
7181    *  \param [in] arr - sequence of DataArrayInt's to intersect.
7182    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
7183    *         array using decrRef() as it is no more needed.
7184    *  \throw If any \a arr[i] is not allocated.
7185    *  \throw If \a arr[i]->getNumberOfComponents() != 1.
7186    */
7187   template <class T>
7188   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::BuildIntersection(const std::vector<const DataArrayType *>& arr)
7189   {
7190     std::vector<const DataArrayType *> a;
7191     for(typename std::vector<const DataArrayType *>::const_iterator it4=arr.begin();it4!=arr.end();it4++)
7192       if(*it4)
7193         a.push_back(*it4);
7194     for(typename std::vector<const DataArrayType *>::const_iterator it=a.begin();it!=a.end();it++)
7195       {
7196         (*it)->checkAllocated();
7197         if((*it)->getNumberOfComponents()!=1)
7198           throw INTERP_KERNEL::Exception("DataArrayInt::BuildIntersection : only single component allowed !");
7199       }
7200     //
7201     if(a.size()==1)
7202       throw INTERP_KERNEL::Exception("DataArrayInt::BuildIntersection : only single not null element in array ! For safety reasons exception is raised !");
7203     //
7204     std::set<T> r;
7205     for(typename std::vector<const DataArrayType *>::const_iterator it=a.begin();it!=a.end();it++)
7206       {
7207         const T *pt=(*it)->getConstPointer();
7208         mcIdType nbOfTuples((*it)->getNumberOfTuples());
7209         std::set<T> s1(pt,pt+nbOfTuples);
7210         if(it!=a.begin())
7211           {
7212             std::set<T> r2;
7213             std::set_intersection(r.begin(),r.end(),s1.begin(),s1.end(),inserter(r2,r2.end()));
7214             r=r2;
7215           }
7216         else
7217           r=s1;
7218       }
7219     DataArrayType *ret(DataArrayType::New());
7220     ret->alloc(r.size(),1);
7221     std::copy(r.begin(),r.end(),ret->getPointer());
7222     return ret;
7223   }
7224
7225   /*!
7226    * This method allows to put a vector of vector of integer into a more compact data structure (skyline).
7227    * This method is not available into python because no available optimized data structure available to map std::vector< std::vector<mcIdType> >.
7228    *
7229    * \param [in] v the input data structure to be translate into skyline format.
7230    * \param [out] data the first element of the skyline format. The user is expected to deal with newly allocated array.
7231    * \param [out] dataIndex the second element of the skyline format.
7232    */
7233   template <class T>
7234   void DataArrayDiscrete<T>::PutIntoToSkylineFrmt(const std::vector< std::vector<T> >& v, DataArrayType *& data, DataArrayIdType *& dataIndex)
7235   {
7236     std::size_t sz(v.size());
7237     MCAuto<DataArrayType> retDat(DataArrayType::New());
7238     MCAuto<DataArrayIdType> retIdx(DataArrayIdType::New());
7239     retIdx->alloc(sz+1,1);
7240     mcIdType *ptid(retIdx->getPointer()); *ptid=0;
7241     for(std::size_t i=0;i<sz;i++,ptid++)
7242       ptid[1]=ptid[0]+ToIdType(v[i].size());
7243     retDat->alloc(retIdx->back(),1);
7244     T *pt=retDat->getPointer();
7245     for(std::size_t i=0;i<sz;i++)
7246       pt=std::copy(v[i].begin(),v[i].end(),pt);
7247     data=retDat.retn(); dataIndex=retIdx.retn();
7248   }
7249
7250   /*!
7251    * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
7252    * (\ref numbering-indirect).
7253    * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
7254    * The selection of extraction is done standardly in new2old format.
7255    * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
7256    *
7257    * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7258    * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7259    * \param [in] arrIn arr origin array from which the extraction will be done.
7260    * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7261    * \param [out] arrOut the resulting array
7262    * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7263    * \sa DataArrayInt::ExtractFromIndexedArraysSlice
7264    */
7265   template <class T>
7266   void DataArrayDiscrete<T>::ExtractFromIndexedArrays(const mcIdType *idsOfSelectBg, const mcIdType *idsOfSelectEnd,
7267                                                       const DataArrayType *arrIn, const DataArrayIdType *arrIndxIn,
7268                                                       DataArrayType* &arrOut, DataArrayIdType* &arrIndexOut)
7269   {
7270     if(!arrIn || !arrIndxIn)
7271       throw INTERP_KERNEL::Exception("DataArrayInt::ExtractFromIndexedArrays : input pointer is NULL !");
7272     arrIn->checkAllocated(); arrIndxIn->checkAllocated();
7273     if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
7274       throw INTERP_KERNEL::Exception("DataArrayInt::ExtractFromIndexedArrays : input arrays must have exactly one component !");
7275     std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
7276     const T *arrInPtr=arrIn->begin();
7277     const mcIdType *arrIndxPtr=arrIndxIn->begin();
7278     mcIdType nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
7279     if(nbOfGrps<0)
7280       throw INTERP_KERNEL::Exception("DataArrayInt::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
7281     mcIdType maxSizeOfArr(arrIn->getNumberOfTuples());
7282     MCAuto<DataArrayType> arro=DataArrayType::New();
7283     MCAuto<DataArrayIdType> arrIo=DataArrayIdType::New();
7284     arrIo->alloc(sz+1,1);
7285     const mcIdType *idsIt=idsOfSelectBg;
7286     mcIdType *work=arrIo->getPointer();
7287     *work++=0;
7288     mcIdType lgth=0;
7289     for(std::size_t i=0;i<sz;i++,work++,idsIt++)
7290       {
7291         if(*idsIt>=0 && *idsIt<nbOfGrps)
7292           lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
7293         else
7294           {
7295             std::ostringstream oss; oss << "DataArrayInt::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
7296             throw INTERP_KERNEL::Exception(oss.str());
7297           }
7298         if(lgth>=work[-1])
7299           *work=lgth;
7300         else
7301           {
7302             std::ostringstream oss; oss << "DataArrayInt::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
7303             oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
7304             throw INTERP_KERNEL::Exception(oss.str());
7305           }
7306       }
7307     arro->alloc(lgth,1);
7308     T *data=arro->getPointer();
7309     idsIt=idsOfSelectBg;
7310     for(std::size_t i=0;i<sz;i++,idsIt++)
7311       {
7312         if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
7313           data=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],data);
7314         else
7315           {
7316             std::ostringstream oss; oss << "DataArrayInt::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
7317             oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
7318             throw INTERP_KERNEL::Exception(oss.str());
7319           }
7320       }
7321     arrOut=arro.retn();
7322     arrIndexOut=arrIo.retn();
7323   }
7324
7325   /*!
7326    * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
7327    * (\ref numbering-indirect).
7328    * 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 ).
7329    * The selection of extraction is done standardly in new2old format.
7330    * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
7331    *
7332    * \param [in] idsOfSelectStart begin of set of ids of the input extraction (included)
7333    * \param [in] idsOfSelectStop end of set of ids of the input extraction (excluded)
7334    * \param [in] idsOfSelectStep step of set of ids of the input extraction
7335    * \param [in] arrIn arr origin array from which the extraction will be done.
7336    * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7337    * \param [out] arrOut the resulting array
7338    * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7339    * \sa DataArrayInt::ExtractFromIndexedArrays
7340    */
7341   template <class T>
7342   void DataArrayDiscrete<T>::ExtractFromIndexedArraysSlice(mcIdType idsOfSelectStart, mcIdType idsOfSelectStop, mcIdType idsOfSelectStep,
7343                                                            const DataArrayType *arrIn, const DataArrayIdType *arrIndxIn,
7344                                                            DataArrayType* &arrOut, DataArrayIdType* &arrIndexOut)
7345   {
7346     if(!arrIn || !arrIndxIn)
7347       throw INTERP_KERNEL::Exception("DataArrayInt::ExtractFromIndexedArraysSlice : input pointer is NULL !");
7348     arrIn->checkAllocated(); arrIndxIn->checkAllocated();
7349     if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
7350       throw INTERP_KERNEL::Exception("DataArrayInt::ExtractFromIndexedArraysSlice : input arrays must have exactly one component !");
7351     mcIdType sz=DataArray::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArraysSlice : Input slice ");
7352     const T *arrInPtr=arrIn->begin();
7353     const mcIdType *arrIndxPtr=arrIndxIn->begin();
7354     mcIdType nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
7355     if(nbOfGrps<0)
7356       throw INTERP_KERNEL::Exception("DataArrayInt::ExtractFromIndexedArraysSlice : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
7357     mcIdType maxSizeOfArr(arrIn->getNumberOfTuples());
7358     MCAuto<DataArrayType> arro=DataArrayType::New();
7359     MCAuto<DataArrayIdType> arrIo=DataArrayIdType::New();
7360     arrIo->alloc(sz+1,1);
7361     mcIdType idsIt=idsOfSelectStart;
7362     mcIdType *work=arrIo->getPointer();
7363     *work++=0;
7364     mcIdType lgth=0;
7365     for(mcIdType i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
7366       {
7367         if(idsIt>=0 && idsIt<nbOfGrps)
7368           lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
7369         else
7370           {
7371             std::ostringstream oss; oss << "DataArrayInt::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
7372             throw INTERP_KERNEL::Exception(oss.str());
7373           }
7374         if(lgth>=work[-1])
7375           *work=lgth;
7376         else
7377           {
7378             std::ostringstream oss; oss << "DataArrayInt::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
7379             oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
7380             throw INTERP_KERNEL::Exception(oss.str());
7381           }
7382       }
7383     arro->alloc(lgth,1);
7384     T *data=arro->getPointer();
7385     idsIt=idsOfSelectStart;
7386     for(mcIdType i=0;i<sz;i++,idsIt+=idsOfSelectStep)
7387       {
7388         if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
7389           data=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],data);
7390         else
7391           {
7392             std::ostringstream oss; oss << "DataArrayInt::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
7393             oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
7394             throw INTERP_KERNEL::Exception(oss.str());
7395           }
7396       }
7397     arrOut=arro.retn();
7398     arrIndexOut=arrIo.retn();
7399   }
7400
7401   /*!
7402    * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7403    * 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
7404    * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
7405    * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitly a result output arrays.
7406    *
7407    * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7408    * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7409    * \param [in] arrIn arr origin array from which the extraction will be done.
7410    * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7411    * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
7412    * \param [in] srcArrIndex index array of \b srcArr
7413    * \param [out] arrOut the resulting array
7414    * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7415    *
7416    * \sa DataArrayInt::SetPartOfIndexedArraysSameIdx
7417    */
7418   template <class T>
7419   void DataArrayDiscrete<T>::SetPartOfIndexedArrays(const mcIdType *idsOfSelectBg, const mcIdType *idsOfSelectEnd,
7420                                                     const DataArrayType *arrIn, const DataArrayIdType *arrIndxIn,
7421                                                     const DataArrayType *srcArr, const DataArrayIdType *srcArrIndex,
7422                                                     DataArrayType* &arrOut, DataArrayIdType* &arrIndexOut)
7423   {
7424     if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7425       throw INTERP_KERNEL::Exception("DataArrayInt::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
7426     MCAuto<DataArrayType> arro=DataArrayType::New();
7427     MCAuto<DataArrayIdType> arrIo=DataArrayIdType::New();
7428     mcIdType nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7429     std::vector<bool> v(nbOfTuples,true);
7430     mcIdType offset=0;
7431     const mcIdType *arrIndxInPtr=arrIndxIn->begin();
7432     const mcIdType *srcArrIndexPtr=srcArrIndex->begin();
7433     for(const mcIdType *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
7434       {
7435         if(*it>=0 && *it<nbOfTuples)
7436           {
7437             v[*it]=false;
7438             offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
7439           }
7440         else
7441           {
7442             std::ostringstream oss; oss << "DataArrayInt::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
7443             throw INTERP_KERNEL::Exception(oss.str());
7444           }
7445       }
7446     srcArrIndexPtr=srcArrIndex->begin();
7447     arrIo->alloc(nbOfTuples+1,1);
7448     arro->alloc(arrIn->getNumberOfTuples()+offset,1);
7449     const T *arrInPtr=arrIn->begin();
7450     const T *srcArrPtr=srcArr->begin();
7451     mcIdType *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
7452     T *arroPtr=arro->getPointer();
7453     for(mcIdType ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
7454       {
7455         if(v[ii])
7456           {
7457             arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
7458             *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
7459           }
7460         else
7461           {
7462             std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
7463             arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
7464             *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
7465           }
7466       }
7467     arrOut=arro.retn();
7468     arrIndexOut=arrIo.retn();
7469   }
7470
7471   /*!
7472    * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7473    * 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
7474    * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
7475    * This method is an generalization of DataArrayInt::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitly a result output arrays.
7476    *
7477    * \param [in] start begin of set of ids of the input extraction (included)
7478    * \param [in] end end of set of ids of the input extraction (excluded)
7479    * \param [in] step step of the set of ids in range mode.
7480    * \param [in] arrIn arr origin array from which the extraction will be done.
7481    * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7482    * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
7483    * \param [in] srcArrIndex index array of \b srcArr
7484    * \param [out] arrOut the resulting array
7485    * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7486    *
7487    * \sa DataArrayInt::SetPartOfIndexedArraysSameIdx DataArrayInt::SetPartOfIndexedArrays
7488    */
7489   template <class T>
7490   void DataArrayDiscrete<T>::SetPartOfIndexedArraysSlice(mcIdType start, mcIdType end, mcIdType step,
7491                                                          const DataArrayType *arrIn, const DataArrayIdType *arrIndxIn,
7492                                                          const DataArrayType *srcArr, const DataArrayIdType *srcArrIndex,
7493                                                          DataArrayType* &arrOut, DataArrayIdType* &arrIndexOut)
7494   {
7495     if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7496       throw INTERP_KERNEL::Exception("DataArrayInt::SetPartOfIndexedArraysSlice : presence of null pointer in input parameter !");
7497     MCAuto<DataArrayType> arro=DataArrayType::New();
7498     MCAuto<DataArrayIdType> arrIo=DataArrayIdType::New();
7499     mcIdType nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7500     mcIdType offset=0;
7501     const mcIdType *arrIndxInPtr=arrIndxIn->begin();
7502     const mcIdType *srcArrIndexPtr=srcArrIndex->begin();
7503     mcIdType nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"DataArrayInt::SetPartOfIndexedArraysSlice : ");
7504     mcIdType it=start;
7505     for(mcIdType i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
7506       {
7507         if(it>=0 && it<nbOfTuples)
7508           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
7509         else
7510           {
7511             std::ostringstream oss; oss << "DataArrayInt::SetPartOfIndexedArraysSlice : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
7512             throw INTERP_KERNEL::Exception(oss.str());
7513           }
7514       }
7515     srcArrIndexPtr=srcArrIndex->begin();
7516     arrIo->alloc(nbOfTuples+1,1);
7517     arro->alloc(arrIn->getNumberOfTuples()+offset,1);
7518     const T *arrInPtr=arrIn->begin();
7519     const T *srcArrPtr=srcArr->begin();
7520     mcIdType *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
7521     T *arroPtr=arro->getPointer();
7522     for(mcIdType ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
7523       {
7524         mcIdType pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
7525         if(pos<0)
7526           {
7527             arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
7528             *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
7529           }
7530         else
7531           {
7532             arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
7533             *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
7534           }
7535       }
7536     arrOut=arro.retn();
7537     arrIndexOut=arrIo.retn();
7538   }
7539
7540   /*!
7541    * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7542    * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignment do not modify the index in \b arrIndxIn.
7543    *
7544    * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7545    * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7546    * \param [in,out] arrInOut arr origin array from which the extraction will be done.
7547    * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7548    * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
7549    * \param [in] srcArrIndex index array of \b srcArr
7550    *
7551    * \sa DataArrayInt::SetPartOfIndexedArrays
7552    */
7553   template <class T>
7554   void DataArrayDiscrete<T>::SetPartOfIndexedArraysSameIdx(const mcIdType *idsOfSelectBg, const mcIdType *idsOfSelectEnd,
7555                                                            DataArrayType *arrInOut, const DataArrayIdType *arrIndxIn,
7556                                                            const DataArrayType *srcArr, const DataArrayIdType *srcArrIndex)
7557   {
7558     if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7559       throw INTERP_KERNEL::Exception("DataArrayInt::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
7560     mcIdType nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7561     const mcIdType *arrIndxInPtr=arrIndxIn->begin();
7562     const mcIdType *srcArrIndexPtr=srcArrIndex->begin();
7563     T *arrInOutPtr=arrInOut->getPointer();
7564     const T *srcArrPtr=srcArr->begin();
7565     for(const mcIdType *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
7566       {
7567         if(*it>=0 && *it<nbOfTuples)
7568           {
7569             if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
7570               std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
7571             else
7572               {
7573                 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] !";
7574                 throw INTERP_KERNEL::Exception(oss.str());
7575               }
7576           }
7577         else
7578           {
7579             std::ostringstream oss; oss << "DataArrayInt::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
7580             throw INTERP_KERNEL::Exception(oss.str());
7581           }
7582       }
7583   }
7584
7585   /*!
7586    * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7587    * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignment do not modify the index in \b arrIndxIn.
7588    *
7589    * \param [in] start begin of set of ids of the input extraction (included)
7590    * \param [in] end end of set of ids of the input extraction (excluded)
7591    * \param [in] step step of the set of ids in range mode.
7592    * \param [in,out] arrInOut arr origin array from which the extraction will be done.
7593    * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7594    * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
7595    * \param [in] srcArrIndex index array of \b srcArr
7596    *
7597    * \sa DataArrayInt::SetPartOfIndexedArraysSlice DataArrayInt::SetPartOfIndexedArraysSameIdx
7598    */
7599   template <class T>
7600   void DataArrayDiscrete<T>::SetPartOfIndexedArraysSameIdxSlice(mcIdType start, mcIdType end, mcIdType step,
7601                                                                 DataArrayType *arrInOut, const DataArrayIdType *arrIndxIn,
7602                                                                 const DataArrayType *srcArr, const DataArrayIdType *srcArrIndex)
7603   {
7604     if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7605       throw INTERP_KERNEL::Exception("DataArrayInt::SetPartOfIndexedArraysSameIdxSlice : presence of null pointer in input parameter !");
7606     mcIdType nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7607     const mcIdType *arrIndxInPtr=arrIndxIn->begin();
7608     const mcIdType *srcArrIndexPtr=srcArrIndex->begin();
7609     T *arrInOutPtr=arrInOut->getPointer();
7610     const T *srcArrPtr=srcArr->begin();
7611     mcIdType nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"DataArrayInt::SetPartOfIndexedArraysSameIdxSlice : ");
7612     mcIdType it=start;
7613     for(mcIdType i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
7614       {
7615         if(it>=0 && it<nbOfTuples)
7616           {
7617             if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
7618               std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
7619             else
7620               {
7621                 std::ostringstream oss; oss << "DataArrayInt::SetPartOfIndexedArraysSameIdxSlice : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
7622                 throw INTERP_KERNEL::Exception(oss.str());
7623               }
7624           }
7625         else
7626           {
7627             std::ostringstream oss; oss << "DataArrayInt::SetPartOfIndexedArraysSameIdxSlice : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
7628             throw INTERP_KERNEL::Exception(oss.str());
7629           }
7630       }
7631   }
7632
7633   /*!
7634    * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
7635    * 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.
7636    *
7637    * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
7638    * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
7639    * \param [in,out] arr array in which the remove operation will be done.
7640    * \param [in,out] arrIndx array in the remove operation will modify
7641    * \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])
7642    * \return true if \b arr and \b arrIndx have been modified, false if not.
7643    */
7644   template <class T>
7645   bool DataArrayDiscrete<T>::RemoveIdsFromIndexedArrays(const T *idsToRemoveBg, const T *idsToRemoveEnd,
7646                                                         DataArrayType *arr, DataArrayIdType *arrIndx, mcIdType offsetForRemoval)
7647   {
7648     if(!arrIndx || !arr)
7649       throw INTERP_KERNEL::Exception("DataArrayInt::RemoveIdsFromIndexedArrays : some input arrays are empty !");
7650     if(offsetForRemoval<0)
7651       throw INTERP_KERNEL::Exception("DataArrayInt::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
7652     std::set<T> s(idsToRemoveBg,idsToRemoveEnd);
7653     mcIdType nbOfGrps=arrIndx->getNumberOfTuples()-1;
7654     mcIdType *arrIPtr=arrIndx->getPointer();
7655     *arrIPtr++=0;
7656     mcIdType previousArrI=0;
7657     const T *arrPtr=arr->begin();
7658     std::vector<T> arrOut;//no utility to switch to DataArrayInt because copy always needed
7659     for(mcIdType i=0;i<nbOfGrps;i++,arrIPtr++)
7660       {
7661         if(*arrIPtr-previousArrI>offsetForRemoval)
7662           {
7663             for(const T *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
7664               {
7665                 if(s.find(*work)==s.end())
7666                   arrOut.push_back(*work);
7667               }
7668           }
7669         previousArrI=*arrIPtr;
7670         *arrIPtr=ToIdType(arrOut.size());
7671       }
7672     if(arr->getNumberOfTuples()==ToIdType(arrOut.size()))
7673       return false;
7674     arr->alloc(arrOut.size(),1);
7675     std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
7676     return true;
7677   }
7678
7679   /*!
7680    * Returns a new DataArrayInt containing an arithmetic progression
7681    * that is equal to the sequence returned by Python \c range(\a begin,\a  end,\a  step )
7682    * function.
7683    *  \param [in] begin - the start value of the result sequence.
7684    *  \param [in] end - limiting value, so that every value of the result array is less than
7685    *              \a end.
7686    *  \param [in] step - specifies the increment or decrement.
7687    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
7688    *          array using decrRef() as it is no more needed.
7689    *  \throw If \a step == 0.
7690    *  \throw If \a end < \a begin && \a step > 0.
7691    *  \throw If \a end > \a begin && \a step < 0.
7692    */
7693   template <class T>
7694   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::Range(T begin, T end, T step)
7695   {
7696     mcIdType nbOfTuples=DataArrayTools<T>::GetNumberOfItemGivenBESRelative(begin,end,step,"DataArrayInt::Range");
7697     MCAuto<DataArrayType> ret=DataArrayType::New();
7698     ret->alloc(nbOfTuples,1);
7699     T *ptr=ret->getPointer();
7700     if(step>0)
7701       {
7702         for(T i=begin;i<end;i+=step,ptr++)
7703           *ptr=i;
7704       }
7705     else
7706       {
7707         for(T i=begin;i>end;i+=step,ptr++)
7708           *ptr=i;
7709       }
7710     return ret.retn();
7711   }
7712
7713   /*!
7714    * Returns a new DataArrayInt containing a renumbering map in "Old to New" mode computed
7715    * from a zip representation of a surjective format (returned e.g. by
7716    * \ref MEDCoupling::DataArrayDouble::findCommonTuples() "DataArrayDouble::findCommonTuples()"
7717    * for example). The result array minimizes the permutation. <br>
7718    * For more info on renumbering see \ref numbering. <br>
7719    * \b Example: <br>
7720    * - \a nbOfOldTuples: 10
7721    * - \a arr          : [0,3, 5,7,9]
7722    * - \a arrIBg       : [0,2,5]
7723    * - \a newNbOfTuples: 7
7724    * - result array    : [0,1,2,0,3,4,5,4,6,4]
7725    *
7726    *  \param [in] nbOfOldTuples - number of tuples in the initial array \a arr.
7727    *  \param [in] arr - the array of tuple indices grouped by \a arrIBg array.
7728    *  \param [in] arrIBg - the array dividing all indices stored in \a arr into groups of
7729    *         (indices of) equal values. Its every element (except the last one) points to
7730    *         the first element of a group of equal values.
7731    *  \param [in] arrIEnd - specifies the end of \a arrIBg, so that the last element of \a
7732    *          arrIBg is \a arrIEnd[ -1 ].
7733    *  \param [out] newNbOfTuples - number of tuples after surjection application.
7734    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
7735    *          array using decrRef() as it is no more needed.
7736    *  \throw If any value of \a arr breaks condition ( 0 <= \a arr[ i ] < \a nbOfOldTuples ).
7737    */
7738   template <class T>
7739   DataArrayIdType *DataArrayDiscrete<T>::ConvertIndexArrayToO2N(mcIdType nbOfOldTuples, const mcIdType *arr, const mcIdType *arrIBg, const mcIdType *arrIEnd, mcIdType &newNbOfTuples)
7740   {
7741     MCAuto<DataArrayIdType> ret=DataArrayIdType::New();
7742     ret->alloc(nbOfOldTuples,1);
7743     mcIdType *pt=ret->getPointer();
7744     std::fill(pt,pt+nbOfOldTuples,-1);
7745     mcIdType nbOfGrps=ToIdType(std::distance(arrIBg,arrIEnd))-1;
7746     const mcIdType *cIPtr=arrIBg;
7747     for(mcIdType i=0;i<nbOfGrps;i++)
7748       pt[arr[cIPtr[i]]]=-(i+2);
7749     mcIdType newNb=0;
7750     for(mcIdType iNode=0;iNode<nbOfOldTuples;iNode++)
7751       {
7752         if(pt[iNode]<0)
7753           {
7754             if(pt[iNode]==-1)
7755               pt[iNode]=newNb++;
7756             else
7757               {
7758                 mcIdType grpId=-(pt[iNode]+2);
7759                 for(mcIdType j=cIPtr[grpId];j<cIPtr[grpId+1];j++)
7760                   {
7761                     if(arr[j]>=0 && arr[j]<nbOfOldTuples)
7762                       pt[arr[j]]=newNb;
7763                     else
7764                       {
7765                         std::ostringstream oss; oss << "DataArrayInt::ConvertIndexArrayToO2N : With element #" << j << " value is " << arr[j] << " should be in [0," << nbOfOldTuples << ") !";
7766                         throw INTERP_KERNEL::Exception(oss.str().c_str());
7767                       }
7768                   }
7769                 newNb++;
7770               }
7771           }
7772       }
7773     newNbOfTuples=newNb;
7774     return ret.retn();
7775   }
7776
7777   /*!
7778    * Returns a new DataArrayInt which is a minimal partition of elements of \a groups.
7779    * The i-th item of the result array is an ID of a set of elements belonging to a
7780    * unique set of groups, which the i-th element is a part of. This set of elements
7781    * belonging to a unique set of groups is called \a family, so the result array contains
7782    * IDs of families each element belongs to.
7783    *
7784    * \b Example: if we have two groups of elements: \a group1 [0,4] and \a group2 [ 0,1,2 ],
7785    * then there are 3 families:
7786    * - \a family1 (with ID 1) contains element [0] belonging to ( \a group1 + \a group2 ),
7787    * - \a family2 (with ID 2) contains elements [4] belonging to ( \a group1 ),
7788    * - \a family3 (with ID 3) contains element [1,2] belonging to ( \a group2 ), <br>
7789    * and the result array contains IDs of families [ 1,3,3,0,2 ]. <br> Note a family ID 0 which
7790    * stands for the element #3 which is in none of groups.
7791    *
7792    *  \param [in] groups - sequence of groups of element IDs.
7793    *  \param [in] newNb - total number of elements; it must be more than max ID of element
7794    *         in \a groups.
7795    *  \param [out] fidsOfGroups - IDs of families the elements of each group belong to.
7796    *  \return DataArrayInt * - a new instance of DataArrayInt containing IDs of families
7797    *         each element with ID from range [0, \a newNb ) belongs to. The caller is to
7798    *         delete this array using decrRef() as it is no more needed.
7799    *  \throw If any element ID in \a groups violates condition ( 0 <= ID < \a newNb ).
7800    */
7801   template <class T>
7802   DataArrayIdType *DataArrayDiscrete<T>::MakePartition(const std::vector<const DataArrayType *>& groups, mcIdType newNb, std::vector< std::vector<mcIdType> >& fidsOfGroups)
7803   {
7804     std::vector<const DataArrayType *> groups2;
7805     for(typename std::vector<const DataArrayType *>::const_iterator it4=groups.begin();it4!=groups.end();it4++)
7806       if(*it4)
7807         groups2.push_back(*it4);
7808     MCAuto<DataArrayIdType> ret=DataArrayIdType::New();
7809     ret->alloc(newNb,1);
7810     mcIdType *retPtr=ret->getPointer();
7811     std::fill(retPtr,retPtr+newNb,0);
7812     mcIdType fid=1;
7813     for(typename std::vector<const DataArrayType *>::const_iterator iter=groups2.begin();iter!=groups2.end();iter++)
7814       {
7815         const T *ptr=(*iter)->getConstPointer();
7816         std::size_t nbOfElem=(*iter)->getNbOfElems();
7817         mcIdType sfid=fid;
7818         for(mcIdType j=0;j<sfid;j++)
7819           {
7820             bool found=false;
7821             for(std::size_t i=0;i<nbOfElem;i++)
7822               {
7823                 if(ptr[i]>=0 && ptr[i]<newNb)
7824                   {
7825                     if(retPtr[ptr[i]]==j)
7826                       {
7827                         retPtr[ptr[i]]=fid;
7828                         found=true;
7829                       }
7830                   }
7831                 else
7832                   {
7833                     std::ostringstream oss; oss << "DataArrayInt::MakePartition : In group \"" << (*iter)->getName() << "\" in tuple #" << i << " value = " << ptr[i] << " ! Should be in [0," << newNb;
7834                     oss << ") !";
7835                     throw INTERP_KERNEL::Exception(oss.str().c_str());
7836                   }
7837               }
7838             if(found)
7839               fid++;
7840           }
7841       }
7842     fidsOfGroups.clear();
7843     fidsOfGroups.resize(groups2.size());
7844     mcIdType grId=0;
7845     for(typename std::vector<const DataArrayType *>::const_iterator iter=groups2.begin();iter!=groups2.end();iter++,grId++)
7846       {
7847         std::set<mcIdType> tmp;
7848         const T *ptr=(*iter)->getConstPointer();
7849         std::size_t nbOfElem=(*iter)->getNbOfElems();
7850         for(const T *p=ptr;p!=ptr+nbOfElem;p++)
7851           tmp.insert(retPtr[*p]);
7852         fidsOfGroups[grId].insert(fidsOfGroups[grId].end(),tmp.begin(),tmp.end());
7853       }
7854     return ret.retn();
7855   }
7856
7857 }
7858
7859 /// @cond INTERNAL
7860 namespace MEDCouplingImpl
7861 {
7862   template <class T>
7863   class OpSwitchedOn
7864   {
7865   public:
7866     OpSwitchedOn(T *pt):_pt(pt),_cnt(0) { }
7867     void operator()(const bool& b) { if(b) *_pt++=FromIdType<T>(_cnt); _cnt++; }
7868   private:
7869     T *_pt;
7870     MEDCoupling::mcIdType _cnt;
7871   };
7872
7873   template <class T>
7874   class OpSwitchedOff
7875   {
7876   public:
7877     OpSwitchedOff(T *pt):_pt(pt),_cnt(0) { }
7878     void operator()(const bool& b) { if(!b) *_pt++=FromIdType<T>(_cnt); _cnt++; }
7879   private:
7880     T *_pt;
7881     MEDCoupling::mcIdType _cnt;
7882   };
7883 }
7884 /// @endcond
7885
7886 namespace MEDCoupling
7887 {
7888   /*!
7889    * This method returns the list of ids in ascending mode so that v[id]==true.
7890    */
7891   template <class T>
7892   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::BuildListOfSwitchedOn(const std::vector<bool>& v)
7893   {
7894     std::size_t sz(std::count(v.begin(),v.end(),true));
7895     MCAuto<DataArrayType> ret(DataArrayType::New()); ret->alloc(sz,1);
7896     std::for_each(v.begin(),v.end(),MEDCouplingImpl::OpSwitchedOn<T>(ret->getPointer()));
7897     return ret.retn();
7898   }
7899
7900   /*!
7901    * This method returns the list of ids in ascending mode so that v[id]==false.
7902    */
7903   template <class T>
7904   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::BuildListOfSwitchedOff(const std::vector<bool>& v)
7905   {
7906     std::size_t sz(std::count(v.begin(),v.end(),false));
7907     MCAuto<DataArrayType> ret(DataArrayType::New()); ret->alloc(sz,1);
7908     std::for_each(v.begin(),v.end(),MEDCouplingImpl::OpSwitchedOff<T>(ret->getPointer()));
7909     return ret.retn();
7910   }
7911 }
7912
7913 namespace MEDCoupling
7914 {
7915   /*!
7916    * This method compares content of input vector \a v and \a this.
7917    * 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.
7918    * For performance reasons \a this is expected to be sorted ascendingly. If not an exception will be thrown.
7919    *
7920    * \param [in] v - the vector of 'flags' to be compared with \a this.
7921    *
7922    * \throw If \a this is not sorted ascendingly.
7923    * \throw If \a this has not exactly one component.
7924    * \throw If \a this is not allocated.
7925    */
7926   template<class T>
7927   bool DataArrayDiscreteSigned<T>::isFittingWith(const std::vector<bool>& v) const
7928   {
7929     this->checkAllocated();
7930     if(this->getNumberOfComponents()!=1)
7931       throw INTERP_KERNEL::Exception("DataArrayInt::isFittingWith : number of components of this should be equal to one !");
7932     const T *w(this->begin()),*end2(this->end());
7933     T refVal=-std::numeric_limits<T>::max();
7934     T i=0;
7935     std::vector<bool>::const_iterator it(v.begin());
7936     for(;it!=v.end();it++,i++)
7937       {
7938         if(*it)
7939           {
7940             if(w!=end2)
7941               {
7942                 if(*w++==i)
7943                   {
7944                     if(i>refVal)
7945                       refVal=i;
7946                     else
7947                       {
7948                         std::ostringstream oss; oss << "DataArrayInt::isFittingWith : At pos #" << std::distance(this->begin(),w-1) << " this is not sorted ascendingly !";
7949                         throw INTERP_KERNEL::Exception(oss.str().c_str());
7950                       }
7951                   }
7952                 else
7953                   return false;
7954               }
7955             else
7956               return false;
7957           }
7958       }
7959     return w==end2;
7960   }
7961 }
7962
7963 #endif