Salome HOME
Copyright update 2021
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingMemArray.txx
1 // Copyright (C) 2007-2021  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (EDF R&D)
20
21 #ifndef __PARAMEDMEM_MEDCOUPLINGMEMARRAY_TXX__
22 #define __PARAMEDMEM_MEDCOUPLINGMEMARRAY_TXX__
23
24 #include "MEDCouplingMemArray.hxx"
25 #include "NormalizedUnstructuredMesh.hxx"
26 #include "InterpKernelException.hxx"
27 #include "InterpolationUtils.hxx"
28 #include "MEDCouplingPartDefinition.hxx"
29 #include "InterpKernelAutoPtr.hxx"
30 #include "MCAuto.hxx"
31 #include "MEDCouplingMap.txx"
32
33 #include <sstream>
34 #include <cstdlib>
35 #include <numeric>
36 #include <algorithm>
37
38 namespace MEDCoupling
39 {
40   template<class T>
41   void MEDCouplingPointer<T>::setInternal(T *pointer)
42   {
43     _internal=pointer;
44     _external=0;
45   }
46
47   template<class T>
48   void MEDCouplingPointer<T>::setExternal(const T *pointer)
49   {
50     _external=pointer;
51     _internal=0;
52   }
53
54   template<class T>
55   MemArray<T>::MemArray(const MemArray<T>& other):_nb_of_elem(0),_nb_of_elem_alloc(0),_ownership(false),_dealloc(0),_param_for_deallocator(0)
56   {
57     if(!other._pointer.isNull())
58       {
59         _nb_of_elem_alloc=other._nb_of_elem;
60         T *pointer=(T*)malloc(_nb_of_elem_alloc*sizeof(T));
61         std::copy(other._pointer.getConstPointer(),other._pointer.getConstPointer()+other._nb_of_elem,pointer);
62         useArray(pointer,true,DeallocType::C_DEALLOC,other._nb_of_elem);
63       }
64   }
65
66   template<class T>
67   void MemArray<T>::useArray(const T *array, bool ownership, DeallocType type, std::size_t nbOfElem)
68   {
69     destroy();
70     _nb_of_elem=nbOfElem;
71     _nb_of_elem_alloc=nbOfElem;
72     if(ownership)
73       _pointer.setInternal(const_cast<T *>(array));
74     else
75       _pointer.setExternal(array);
76     _ownership=ownership;
77     _dealloc=BuildFromType(type);
78   }
79
80   template<class T>
81   void MemArray<T>::useExternalArrayWithRWAccess(const T *array, std::size_t nbOfElem)
82   {
83     destroy();
84     _nb_of_elem=nbOfElem;
85     _nb_of_elem_alloc=nbOfElem;
86     _pointer.setInternal(const_cast<T *>(array));
87     _ownership=false;
88     _dealloc=CPPDeallocator;
89   }
90
91   template<class T>
92   void MemArray<T>::writeOnPlace(std::size_t id, T element0, const T *others, std::size_t sizeOfOthers)
93   {
94     if(id+sizeOfOthers>=_nb_of_elem_alloc)
95       reserve(2*_nb_of_elem+sizeOfOthers+1);
96     T *pointer=_pointer.getPointer();
97     pointer[id]=element0;
98     std::copy(others,others+sizeOfOthers,pointer+id+1);
99     _nb_of_elem=std::max<std::size_t>(_nb_of_elem,id+sizeOfOthers+1);
100   }
101
102   template<class T>
103   void MemArray<T>::pushBack(T elem)
104   {
105     if(_nb_of_elem>=_nb_of_elem_alloc)
106       reserve(_nb_of_elem_alloc>0?2*_nb_of_elem_alloc:1);
107     T *pt=getPointer();
108     pt[_nb_of_elem++]=elem;
109   }
110
111   template<class T>
112   T MemArray<T>::popBack()
113   {
114     if(_nb_of_elem>0)
115       {
116         const T *pt=getConstPointer();
117         return pt[--_nb_of_elem];
118       }
119     throw INTERP_KERNEL::Exception("MemArray::popBack : nothing to pop in array !");
120   }
121
122   template<class T>
123   void MemArray<T>::pack() const
124   {
125     (const_cast<MemArray<T> * >(this))->reserve(_nb_of_elem);
126   }
127
128   template<class T>
129   bool MemArray<T>::isEqual(const MemArray<T>& other, T prec, std::string& reason) const
130   {
131     std::ostringstream oss; oss.precision(15);
132     if(_nb_of_elem!=other._nb_of_elem)
133       {
134         oss << "Number of elements in coarse data of DataArray mismatch : this=" << _nb_of_elem << " other=" << other._nb_of_elem;
135         reason=oss.str();
136         return false;
137       }
138     const T *pt1=_pointer.getConstPointer();
139     const T *pt2=other._pointer.getConstPointer();
140     if(pt1==0 && pt2==0)
141       return true;
142     if(pt1==0 || pt2==0)
143       {
144         oss << "coarse data pointer is defined for only one DataArray instance !";
145         reason=oss.str();
146         return false;
147       }
148     if(pt1==pt2)
149       return true;
150     for(std::size_t i=0;i<_nb_of_elem;i++)
151       if(pt1[i]-pt2[i]<-prec || (pt1[i]-pt2[i])>prec)
152         {
153           oss << "The content of data differs at pos #" << i << " of coarse data ! this[i]=" << pt1[i] << " other[i]=" << pt2[i];
154           reason=oss.str();
155           return false;
156         }
157     return true;
158   }
159
160   /*!
161    * \param [in] sl is typically the number of components
162    * \return True if a not null pointer is present, False if not.
163    */
164   template<class T>
165   bool MemArray<T>::reprHeader(mcIdType sl, std::ostream& stream) const
166   {
167     stream << "Number of tuples : ";
168     if(!_pointer.isNull())
169       {
170         if(sl!=0)
171           stream << _nb_of_elem/sl << std::endl << "Internal memory facts : " << _nb_of_elem << "/" << _nb_of_elem_alloc;
172         else
173           stream << "Empty Data";
174       }
175     else
176       stream << "No data";
177     stream << "\n";
178     stream << "Data content :\n";
179     bool ret=!_pointer.isNull();
180     if(!ret)
181       stream << "No data !\n";
182     return ret;
183   }
184
185   /*!
186    * \param [in] sl is typically the number of components
187    */
188   template<class T>
189   void MemArray<T>::repr(mcIdType sl, std::ostream& stream) const
190   {
191     if(reprHeader(sl,stream))
192       {
193         const T *data=getConstPointer();
194         if(_nb_of_elem!=0 && sl!=0)
195           {
196             std::size_t nbOfTuples=_nb_of_elem/std::abs(sl);
197             for(std::size_t i=0;i<nbOfTuples;i++)
198               {
199                 stream << "Tuple #" << i << " : ";
200                 std::copy(data,data+sl,std::ostream_iterator<T>(stream," "));
201                 stream << "\n";
202                 data+=sl;
203               }
204           }
205         else
206           stream << "Empty Data\n";
207       }
208   }
209
210   /*!
211    * \param [in] sl is typically the number of components
212    */
213   template<class T>
214   void MemArray<T>::reprZip(mcIdType sl, std::ostream& stream) const
215   {
216     stream << "Number of tuples : ";
217     if(!_pointer.isNull())
218       {
219         if(sl!=0)
220           stream << _nb_of_elem/sl;
221         else
222           stream << "Empty Data";
223       }
224     else
225       stream << "No data";
226     stream << "\n";
227     stream << "Data content : ";
228     const T *data=getConstPointer();
229     if(!_pointer.isNull())
230       {
231         if(_nb_of_elem!=0 && sl!=0)
232           {
233             std::size_t nbOfTuples=_nb_of_elem/std::abs(sl);
234             for(std::size_t i=0;i<nbOfTuples;i++)
235               {
236                 stream << "|";
237                 std::copy(data,data+sl,std::ostream_iterator<T>(stream," "));
238                 stream << "| ";
239                 data+=sl;
240               }
241             stream << "\n";
242           }
243         else
244           stream << "Empty Data\n";
245       }
246     else
247       stream << "No data !\n";
248   }
249
250   /*!
251    * \param [in] sl is typically the number of components
252    */
253   template<class T>
254   void MemArray<T>::reprNotTooLong(mcIdType sl, std::ostream& stream) const
255   {
256     if(reprHeader(sl,stream))
257       {
258         const T *data=getConstPointer();
259         if(_nb_of_elem!=0 && sl!=0)
260           {
261             std::size_t nbOfTuples=_nb_of_elem/std::abs(sl);
262             if(nbOfTuples<=1000)
263               {
264                 for(std::size_t i=0;i<nbOfTuples;i++)
265                   {
266                     stream << "Tuple #" << i << " : ";
267                     std::copy(data,data+sl,std::ostream_iterator<T>(stream," "));
268                     stream << "\n";
269                     data+=sl;
270                   }
271               }
272             else
273               {// too much tuples -> print the 3 first tuples and 3 last.
274                 stream << "Tuple #0 : ";
275                 std::copy(data,data+sl,std::ostream_iterator<T>(stream," ")); stream << "\n";
276                 stream << "Tuple #1 : ";
277                 std::copy(data+sl,data+2*sl,std::ostream_iterator<T>(stream," ")); stream << "\n";
278                 stream << "Tuple #2 : ";
279                 std::copy(data+2*sl,data+3*sl,std::ostream_iterator<T>(stream," ")); stream << "\n";
280                 stream << "...\n";
281                 stream << "Tuple #" << nbOfTuples-3 << " : ";
282                 std::copy(data+(nbOfTuples-3)*sl,data+(nbOfTuples-2)*sl,std::ostream_iterator<T>(stream," ")); stream << "\n";
283                 stream << "Tuple #" << nbOfTuples-2 << " : ";
284                 std::copy(data+(nbOfTuples-2)*sl,data+(nbOfTuples-1)*sl,std::ostream_iterator<T>(stream," ")); stream << "\n";
285                 stream << "Tuple #" << nbOfTuples-1 << " : ";
286                 std::copy(data+(nbOfTuples-1)*sl,data+nbOfTuples*sl,std::ostream_iterator<T>(stream," ")); stream << "\n";
287               }
288           }
289         else
290           stream << "Empty Data\n";
291       }
292   }
293
294   template<class T>
295   void MemArray<T>::fillWithValue(const T& val)
296   {
297     T *pt=_pointer.getPointer();
298     std::fill(pt,pt+_nb_of_elem,val);
299   }
300
301   template<class T>
302   T *MemArray<T>::fromNoInterlace(std::size_t nbOfComp) const
303   {
304     if(nbOfComp<1)
305       throw INTERP_KERNEL::Exception("MemArray<T>::fromNoInterlace : number of components must be > 0 !");
306     const T *pt=_pointer.getConstPointer();
307     std::size_t nbOfTuples=_nb_of_elem/nbOfComp;
308     T *ret=(T*)malloc(_nb_of_elem*sizeof(T));
309     T *w=ret;
310     for(std::size_t i=0;i<nbOfTuples;i++)
311       for(std::size_t j=0;j<nbOfComp;j++,w++)
312         *w=pt[j*nbOfTuples+i];
313     return ret;
314   }
315
316   template<class T>
317   T *MemArray<T>::toNoInterlace(std::size_t nbOfComp) const
318   {
319     if(nbOfComp<1)
320       throw INTERP_KERNEL::Exception("MemArray<T>::toNoInterlace : number of components must be > 0 !");
321     const T *pt=_pointer.getConstPointer();
322     std::size_t nbOfTuples=_nb_of_elem/nbOfComp;
323     T *ret=(T*)malloc(_nb_of_elem*sizeof(T));
324     T *w=ret;
325     for(std::size_t i=0;i<nbOfComp;i++)
326       for(std::size_t j=0;j<nbOfTuples;j++,w++)
327         *w=pt[j*nbOfComp+i];
328     return ret;
329   }
330
331   template<class T>
332   void MemArray<T>::sort(bool asc)
333   {
334     T *pt=_pointer.getPointer();
335     if(asc)
336       std::sort(pt,pt+_nb_of_elem);
337     else
338       {
339         typename std::reverse_iterator<T *> it1(pt+_nb_of_elem);
340         typename std::reverse_iterator<T *> it2(pt);
341         std::sort(it1,it2);
342       }
343   }
344
345   template<class T>
346   void MemArray<T>::reverse(std::size_t nbOfComp)
347   {
348     if(nbOfComp<1)
349       throw INTERP_KERNEL::Exception("MemArray<T>::reverse : only supported with 'this' array with ONE or more than ONE component !");
350     T *pt=_pointer.getPointer();
351     if(nbOfComp==1)
352       {
353         std::reverse(pt,pt+_nb_of_elem);
354         return ;
355       }
356     else
357       {
358         T *pt2=pt+_nb_of_elem-nbOfComp;
359         std::size_t nbOfTuples=_nb_of_elem/nbOfComp;
360         for(std::size_t i=0;i<nbOfTuples/2;i++,pt+=nbOfComp,pt2-=nbOfComp)
361           {
362             for(std::size_t j=0;j<nbOfComp;j++)
363               std::swap(pt[j],pt2[j]);
364           }
365       }
366   }
367
368   template<class T>
369   void MemArray<T>::alloc(std::size_t nbOfElements)
370   {
371     destroy();
372     _nb_of_elem=nbOfElements;
373     _nb_of_elem_alloc=nbOfElements;
374     _pointer.setInternal((T*)malloc(_nb_of_elem_alloc*sizeof(T)));
375     _ownership=true;
376     _dealloc=CDeallocator;
377   }
378
379   /*!
380    * This method performs systematically an allocation of \a newNbOfElements elements in \a this.
381    * \a _nb_of_elem and \a _nb_of_elem_alloc will \b NOT be systematically equal (contrary to MemArray<T>::reAlloc method.
382    * So after the call of this method \a _nb_of_elem will be equal tostd::min<std::size_t>(_nb_of_elem,newNbOfElements) and \a _nb_of_elem_alloc equal to 
383    * \a newNbOfElements. This method is typically used to perform a pushBack to avoid systematic allocations-copy-deallocation.
384    * So after the call of this method the accessible content is perfectly set.
385    * 
386    * So this method should not be confused with MemArray<T>::reserve that is close to MemArray<T>::reAlloc but not same.
387    */
388   template<class T>
389   void MemArray<T>::reserve(std::size_t newNbOfElements)
390   {
391     if(_nb_of_elem_alloc==newNbOfElements)
392       return ;
393     T *pointer=(T*)malloc(newNbOfElements*sizeof(T));
394     std::copy(_pointer.getConstPointer(),_pointer.getConstPointer()+std::min<std::size_t>(_nb_of_elem,newNbOfElements),pointer);
395     if(_ownership)
396       DestroyPointer(const_cast<T *>(_pointer.getConstPointer()),_dealloc,_param_for_deallocator);//Do not use getPointer because in case of _external
397     _pointer.setInternal(pointer);
398     _nb_of_elem=std::min<std::size_t>(_nb_of_elem,newNbOfElements);
399     _nb_of_elem_alloc=newNbOfElements;
400     _ownership=true;
401     _dealloc=CDeallocator;
402     _param_for_deallocator=0;
403   }
404
405   /*!
406    * This method performs systematically an allocation of \a newNbOfElements elements in \a this.
407    * \a _nb_of_elem and \a _nb_of_elem_alloc will be equal even if only std::min<std::size_t>(_nb_of_elem,newNbOfElements) come from the .
408    * The remaining part of the new allocated chunk are available but not set previously !
409    * 
410    * So this method should not be confused with MemArray<T>::reserve that is close to MemArray<T>::reAlloc but not same.
411    */
412   template<class T>
413   void MemArray<T>::reAlloc(std::size_t newNbOfElements)
414   {
415     if(_nb_of_elem==newNbOfElements)
416       return ;
417     T *pointer=(T*)malloc(newNbOfElements*sizeof(T));
418     std::copy(_pointer.getConstPointer(),_pointer.getConstPointer()+std::min<std::size_t>(_nb_of_elem,newNbOfElements),pointer);
419     if(_ownership)
420       DestroyPointer(const_cast<T *>(_pointer.getConstPointer()),_dealloc,_param_for_deallocator);//Do not use getPointer because in case of _external
421     _pointer.setInternal(pointer);
422     _nb_of_elem=newNbOfElements;
423     _nb_of_elem_alloc=newNbOfElements;
424     _ownership=true;
425     _dealloc=CDeallocator;
426     _param_for_deallocator=0;
427   }
428
429   template<class T>
430   void MemArray<T>::CPPDeallocator(void *pt, void *param)
431   {
432     delete [] reinterpret_cast<T*>(pt);
433   }
434
435   template<class T>
436   void MemArray<T>::CDeallocator(void *pt, void *param)
437   {
438     free(pt);
439   }
440
441   template<class T>
442   void MemArray<T>::COffsetDeallocator(void *pt, void *param)
443   {
444     int64_t *offset(reinterpret_cast<int64_t *>(param));
445     char *ptcast(reinterpret_cast<char *>(pt));
446     free(ptcast+*offset);
447   }
448
449   template<class T>
450   typename MemArray<T>::Deallocator MemArray<T>::BuildFromType(DeallocType type)
451   {
452     switch(type)
453     {
454       case DeallocType::CPP_DEALLOC:
455         return CPPDeallocator;
456       case DeallocType::C_DEALLOC:
457         return CDeallocator;
458       case DeallocType::C_DEALLOC_WITH_OFFSET:
459         return COffsetDeallocator;
460       default:
461         throw INTERP_KERNEL::Exception("Invalid deallocation requested ! Unrecognized enum DeallocType !");
462     }
463   }
464
465   template<class T>
466   void MemArray<T>::DestroyPointer(T *pt, typename MemArray<T>::Deallocator dealloc, void *param)
467   {
468     if(dealloc)
469       dealloc(pt,param);
470   }
471
472   template<class T>
473   void MemArray<T>::destroy()
474   {
475     if(_ownership)
476       DestroyPointer(const_cast<T *>(_pointer.getConstPointer()),_dealloc,_param_for_deallocator);//Do not use getPointer because in case of _external
477     _pointer.null();
478     _ownership=false;
479     _dealloc=NULL;
480     _param_for_deallocator=NULL;
481     _nb_of_elem=0;
482     _nb_of_elem_alloc=0;
483   }
484
485   template<class T>
486   MemArray<T> &MemArray<T>::operator=(const MemArray<T>& other)
487   {
488     alloc(other._nb_of_elem);
489     std::copy(other._pointer.getConstPointer(),other._pointer.getConstPointer()+_nb_of_elem,_pointer.getPointer());
490     return *this;
491   }
492
493   //////////////////////////////////
494
495   template<class T>
496   DataArrayIterator<T>::DataArrayIterator(typename Traits<T>::ArrayType *da):_da(da),_tuple_id(0),_nb_comp(0),_nb_tuple(0)
497   {
498     if(_da)
499       {
500         _da->incrRef();
501         if(_da->isAllocated())
502           {
503             _nb_comp=da->getNumberOfComponents();
504             _nb_tuple=da->getNumberOfTuples();
505             _pt=da->getPointer();
506           }
507       }
508   }
509   
510   template<class T>
511   DataArrayIterator<T>::~DataArrayIterator()
512   {
513     if(_da)
514       _da->decrRef();
515   }
516
517   template<class T>
518   typename Traits<T>::ArrayTuple *DataArrayIterator<T>::nextt()
519   {
520     if(_tuple_id<_nb_tuple)
521       {
522         _tuple_id++;
523         typename Traits<T>::ArrayTuple *ret=new typename Traits<T>::ArrayTuple(_pt,_nb_comp);
524         _pt+=_nb_comp;
525         return ret;
526       }
527     else
528       return 0;
529   }
530
531   //////////////////////////////////
532
533   template<class T>
534   DataArrayTuple<T>::DataArrayTuple(T *pt, std::size_t nbOfComp):_pt(pt),_nb_of_compo(nbOfComp)
535   {
536   }
537   
538   template<class T>
539   T DataArrayTuple<T>::zeValue() const
540   {
541     if(_nb_of_compo==1)
542       return *_pt;
543     throw INTERP_KERNEL::Exception("DataArrayTuple<T>::zeValue : DataArrayTuple instance has not exactly 1 component -> Not possible to convert it into a single value !");
544   }
545   
546   template<class T>
547   typename Traits<T>::ArrayType *DataArrayTuple<T>::buildDA(std::size_t nbOfTuples, std::size_t nbOfCompo) const
548   {
549     if((_nb_of_compo==nbOfCompo && nbOfTuples==1) || (_nb_of_compo==nbOfTuples && nbOfCompo==1))
550     {
551       typename Traits<T>::ArrayType *ret=Traits<T>::ArrayType::New();
552       ret->useExternalArrayWithRWAccess(_pt,nbOfTuples,nbOfCompo);
553       return ret;
554     }
555   else
556     {
557       std::ostringstream oss; oss << "DataArrayTuple<T>::buildDA : unable to build a requested DataArrayDouble instance with nbofTuple=" << nbOfTuples << " and nbOfCompo=" << nbOfCompo;
558       oss << ".\nBecause the number of elements in this is " << _nb_of_compo << " !";
559       throw INTERP_KERNEL::Exception(oss.str().c_str());
560     }
561   }
562   
563   //////////////////////////////////
564
565   /*!
566    * This method is useful to slice work among a pool of threads or processes. \a begin, \a end \a step is the input whole slice of work to perform,
567    * typically it is a whole slice of tuples of DataArray or cells, nodes of a mesh...
568    *
569    * The input \a sliceId should be an id in [0, \a nbOfSlices) that specifies the slice of work.
570    *
571    * \param [in] start - the start of the input slice of the whole work to perform split into slices.
572    * \param [in] stop - the stop of the input slice of the whole work to perform split into slices.
573    * \param [in] step - the step (that can be <0) of the input slice of the whole work to perform split into slices.
574    * \param [in] sliceId - the slice id considered
575    * \param [in] nbOfSlices - the number of slices (typically the number of cores on which the work is expected to be sliced)
576    * \param [out] startSlice - the start of the slice considered
577    * \param [out] stopSlice - the stop of the slice consided
578    *
579    * \throw If \a step == 0
580    * \throw If \a nbOfSlices not > 0
581    * \throw If \a sliceId not in [0,nbOfSlices)
582    */
583   template <class T>
584   void DataArrayTools<T>::GetSlice(T start, T stop, T step, mcIdType sliceId, mcIdType nbOfSlices, T& startSlice, T& stopSlice)
585   {
586     if(nbOfSlices<=0)
587       {
588         std::ostringstream oss; oss << "DataArray::GetSlice : nbOfSlices (" << nbOfSlices << ") must be > 0 !";
589         throw INTERP_KERNEL::Exception(oss.str().c_str());
590       }
591     if(sliceId<0 || sliceId>=nbOfSlices)
592       {
593         std::ostringstream oss; oss << "DataArray::GetSlice : sliceId (" << nbOfSlices << ") must be in [0 , nbOfSlices (" << nbOfSlices << ") ) !";
594         throw INTERP_KERNEL::Exception(oss.str().c_str());
595       }
596     mcIdType nbElems=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 DataArrayFloat and assigns all (textual and numerical) data of \a this
2616    * array to the new one.
2617    *  \return DataArrayFloat * - the new instance of DataArrayInt.
2618    */
2619   template<class T>
2620   MCAuto<DataArrayFloat> DataArrayTemplateClassic<T>::convertToFloatArr() const
2621   {
2622     return convertToOtherTypeOfArr<float>();
2623   }
2624
2625   /*!
2626    * Apply a linear function to a given component of \a this array, so that
2627    * an array element <em>(x)</em> becomes \f$ a * x + b \f$.
2628    *  \param [in] a - the first coefficient of the function.
2629    *  \param [in] b - the second coefficient of the function.
2630    *  \param [in] compoId - the index of component to modify.
2631    *  \throw If \a this is not allocated, or \a compoId is not in [0,\c this->getNumberOfComponents() ).
2632    */
2633   template<class T>
2634   void DataArrayTemplateClassic<T>::applyLin(T a, T b, std::size_t compoId)
2635   {
2636     this->checkAllocated();
2637     std::size_t nbOfComp=this->getNumberOfComponents();
2638     if(compoId>=nbOfComp)
2639       {
2640         std::ostringstream oss; oss << "DataArrayDouble::applyLin : The compoId requested (" << compoId << ") is not valid ! Must be in [0," << nbOfComp << ") !";
2641         throw INTERP_KERNEL::Exception(oss.str().c_str());
2642       }
2643     T *ptr(this->getPointer()+compoId);
2644     mcIdType nbOfTuple=this->getNumberOfTuples();
2645     for(mcIdType i=0;i<nbOfTuple;i++,ptr+=nbOfComp)
2646       *ptr=a*(*ptr)+b;
2647     this->declareAsNew();
2648   }
2649
2650   /*!
2651    * Apply a linear function to all elements of \a this array, so that
2652    * an element _x_ becomes \f$ a * x + b \f$.
2653    *  \param [in] a - the first coefficient of the function.
2654    *  \param [in] b - the second coefficient of the function.
2655    *  \throw If \a this is not allocated.
2656    */
2657   template<class T>
2658   void DataArrayTemplateClassic<T>::applyLin(T a, T b)
2659   {
2660     this->checkAllocated();
2661     T *ptr(this->getPointer());
2662     std::size_t nbOfElems(this->getNbOfElems());
2663     for(std::size_t i=0;i<nbOfElems;i++,ptr++)
2664       *ptr=a*(*ptr)+b;
2665     this->declareAsNew();
2666   }
2667   
2668   /*!
2669    * Returns a full copy of \a this array except that sign of all elements is reversed.
2670    *  \return DataArrayDouble * - the new instance of DataArrayDouble containing the
2671    *          same number of tuples and component as \a this array.
2672    *          The caller is to delete this result array using decrRef() as it is no more
2673    *          needed.
2674    *  \throw If \a this is not allocated.
2675    */
2676   template<class T>
2677   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::negate() const
2678   {
2679     this->checkAllocated();
2680     MCAuto<typename Traits<T>::ArrayType> newArr(Traits<T>::ArrayType::New());
2681     mcIdType nbOfTuples(this->getNumberOfTuples());
2682     std::size_t nbOfComp(this->getNumberOfComponents());
2683     newArr->alloc(nbOfTuples,nbOfComp);
2684     const T *cptr(this->begin());
2685     std::transform(cptr,cptr+nbOfTuples*nbOfComp,newArr->getPointer(),std::negate<T>());
2686     newArr->copyStringInfoFrom(*this);
2687     return newArr.retn();
2688   }
2689
2690   template<class T>
2691   template<class FCT>
2692   void DataArrayTemplateClassic<T>::somethingEqual(const typename Traits<T>::ArrayType *other)
2693   {
2694     if(!other)
2695       throw INTERP_KERNEL::Exception("DataArray<T>::SomethingEqual : input DataArray<T> instance is NULL !");
2696     const char *msg="Nb of tuples mismatch for DataArrayDouble::multiplyEqual !";
2697     this->checkAllocated();
2698     other->checkAllocated();
2699     mcIdType nbOfTuple(this->getNumberOfTuples());
2700     mcIdType nbOfTuple2(other->getNumberOfTuples());
2701     std::size_t nbOfComp(this->getNumberOfComponents());
2702     std::size_t nbOfComp2(other->getNumberOfComponents());
2703     if(nbOfTuple==nbOfTuple2)
2704       {
2705         if(nbOfComp==nbOfComp2)
2706           {
2707             std::transform(this->begin(),this->end(),other->begin(),this->getPointer(),FCT());
2708           }
2709         else if(nbOfComp2==1)
2710           {
2711             T *ptr(this->getPointer());
2712             const T *ptrc(other->begin());
2713             for(mcIdType i=0;i<nbOfTuple;i++)
2714               std::transform(ptr+i*nbOfComp,ptr+(i+1)*nbOfComp,ptr+i*nbOfComp,std::bind(FCT(),std::placeholders::_1,*ptrc++));
2715           }
2716         else
2717           throw INTERP_KERNEL::Exception(msg);
2718       }
2719     else if(nbOfTuple2==1)
2720       {
2721         if(nbOfComp2==nbOfComp)
2722           {
2723             T *ptr(this->getPointer());
2724             const T *ptrc(other->begin());
2725             for(mcIdType i=0;i<nbOfTuple;i++)
2726               std::transform(ptr+i*nbOfComp,ptr+(i+1)*nbOfComp,ptrc,ptr+i*nbOfComp,FCT());
2727           }
2728         else
2729           throw INTERP_KERNEL::Exception(msg);
2730       }
2731     else
2732       throw INTERP_KERNEL::Exception(msg);
2733     this->declareAsNew();
2734   }
2735   
2736   /*!
2737    * Adds values of another DataArrayDouble to values of \a this one. There are 3
2738    * valid cases.
2739    * 1.  The arrays have same number of tuples and components. Then each value of
2740    *   \a other array is added to the corresponding value of \a this array, i.e.:
2741    *   _a_ [ i, j ] += _other_ [ i, j ].
2742    * 2.  The arrays have same number of tuples and \a other array has one component. Then
2743    *   _a_ [ i, j ] += _other_ [ i, 0 ].
2744    * 3.  The arrays have same number of components and \a other array has one tuple. Then
2745    *   _a_ [ i, j ] += _a2_ [ 0, j ].
2746    *
2747    *  \param [in] other - an array to add to \a this one.
2748    *  \throw If \a other is NULL.
2749    *  \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples() and
2750    *         \a this->getNumberOfComponents() != \a other->getNumberOfComponents() and
2751    *         \a other has number of both tuples and components not equal to 1.
2752    */
2753   template<class T>
2754   void DataArrayTemplateClassic<T>::addEqual(const typename Traits<T>::ArrayType *other)
2755   {
2756     this->somethingEqual< std::plus<T> >(other);
2757   }
2758
2759   /*!
2760    * Subtract values of another DataArrayDouble from values of \a this one. There are 3
2761    * valid cases.
2762    * 1.  The arrays have same number of tuples and components. Then each value of
2763    *   \a other array is subtracted from the corresponding value of \a this array, i.e.:
2764    *   _a_ [ i, j ] -= _other_ [ i, j ].
2765    * 2.  The arrays have same number of tuples and \a other array has one component. Then
2766    *   _a_ [ i, j ] -= _other_ [ i, 0 ].
2767    * 3.  The arrays have same number of components and \a other array has one tuple. Then
2768    *   _a_ [ i, j ] -= _a2_ [ 0, j ].
2769    *
2770    *  \param [in] other - an array to subtract from \a this one.
2771    *  \throw If \a other is NULL.
2772    *  \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples() and
2773    *         \a this->getNumberOfComponents() != \a other->getNumberOfComponents() and
2774    *         \a other has number of both tuples and components not equal to 1.
2775    */
2776   template<class T>
2777   void DataArrayTemplateClassic<T>::substractEqual(const typename Traits<T>::ArrayType *other)
2778   {
2779     this->somethingEqual< std::minus<T> >(other);
2780   }
2781   
2782   /*!
2783    * Multiply values of another DataArrayDouble to values of \a this one. There are 3
2784    * valid cases.
2785    * 1.  The arrays have same number of tuples and components. Then each value of
2786    *   \a other array is multiplied to the corresponding value of \a this array, i.e.
2787    *   _this_ [ i, j ] *= _other_ [ i, j ].
2788    * 2.  The arrays have same number of tuples and \a other array has one component. Then
2789    *   _this_ [ i, j ] *= _other_ [ i, 0 ].
2790    * 3.  The arrays have same number of components and \a other array has one tuple. Then
2791    *   _this_ [ i, j ] *= _a2_ [ 0, j ].
2792    *
2793    *  \param [in] other - an array to multiply to \a this one.
2794    *  \throw If \a other is NULL.
2795    *  \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples() and
2796    *         \a this->getNumberOfComponents() != \a other->getNumberOfComponents() and
2797    *         \a other has number of both tuples and components not equal to 1.
2798    */
2799   template<class T>
2800   void DataArrayTemplateClassic<T>::multiplyEqual(const typename Traits<T>::ArrayType *other)
2801   {
2802     this->somethingEqual< std::multiplies<T> >(other);
2803   }
2804
2805   /*!
2806    * Divide values of \a this array by values of another DataArrayDouble. There are 3
2807    * valid cases.
2808    * 1.  The arrays have same number of tuples and components. Then each value of
2809    *    \a this array is divided by the corresponding value of \a other one, i.e.:
2810    *   _a_ [ i, j ] /= _other_ [ i, j ].
2811    * 2.  The arrays have same number of tuples and \a other array has one component. Then
2812    *   _a_ [ i, j ] /= _other_ [ i, 0 ].
2813    * 3.  The arrays have same number of components and \a other array has one tuple. Then
2814    *   _a_ [ i, j ] /= _a2_ [ 0, j ].
2815    *
2816    *  \warning No check of division by zero is performed!
2817    *  \param [in] other - an array to divide \a this one by.
2818    *  \throw If \a other is NULL.
2819    *  \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples() and
2820    *         \a this->getNumberOfComponents() != \a other->getNumberOfComponents() and
2821    *         \a other has number of both tuples and components not equal to 1.
2822    */
2823   template<class T>
2824   void DataArrayTemplateClassic<T>::divideEqual(const typename Traits<T>::ArrayType *other)
2825   {
2826     this->somethingEqual< std::divides<T> >(other);
2827   }
2828   
2829   template<class T, class FCT>
2830   typename Traits<T>::ArrayType *DivSub(const typename Traits<T>::ArrayType *a1, const typename Traits<T>::ArrayType *a2)
2831   {
2832     if(!a1 || !a2)
2833       throw INTERP_KERNEL::Exception("DivSub : input DataArrayDouble instance is NULL !");
2834     mcIdType nbOfTuple1(a1->getNumberOfTuples());
2835     mcIdType nbOfTuple2(a2->getNumberOfTuples());
2836     std::size_t nbOfComp1(a1->getNumberOfComponents());
2837     std::size_t nbOfComp2(a2->getNumberOfComponents());
2838     if(nbOfTuple2==nbOfTuple1)
2839       {
2840         if(nbOfComp1==nbOfComp2)
2841           {
2842             MCAuto<typename Traits<T>::ArrayType> ret(Traits<T>::ArrayType::New());
2843             ret->alloc(nbOfTuple2,nbOfComp1);
2844             std::transform(a1->begin(),a1->end(),a2->begin(),ret->getPointer(),FCT());
2845             ret->copyStringInfoFrom(*a1);
2846             return ret.retn();
2847           }
2848         else if(nbOfComp2==1)
2849           {
2850             MCAuto<typename Traits<T>::ArrayType> ret(Traits<T>::ArrayType::New());
2851             ret->alloc(nbOfTuple1,nbOfComp1);
2852             const T *a2Ptr(a2->begin()),*a1Ptr(a1->begin());
2853             T *res(ret->getPointer());
2854             for(mcIdType i=0;i<nbOfTuple1;i++)
2855               res=std::transform(a1Ptr+i*nbOfComp1,a1Ptr+(i+1)*nbOfComp1,res,std::bind(FCT(),std::placeholders::_1,a2Ptr[i]));
2856             ret->copyStringInfoFrom(*a1);
2857             return ret.retn();
2858           }
2859         else
2860           {
2861             a1->checkNbOfComps(nbOfComp2,"Nb of components mismatch for array Divide !");
2862             return 0;
2863           }
2864       }
2865     else if(nbOfTuple2==1)
2866       {
2867         a1->checkNbOfComps(nbOfComp2,"Nb of components mismatch for array Divide !");
2868         MCAuto<typename Traits<T>::ArrayType> ret(Traits<T>::ArrayType::New());
2869         ret->alloc(nbOfTuple1,nbOfComp1);
2870         const T *a1ptr=a1->begin(),*a2ptr(a2->begin());
2871         T *pt(ret->getPointer());
2872         for(mcIdType i=0;i<nbOfTuple1;i++)
2873           pt=std::transform(a1ptr+i*nbOfComp1,a1ptr+(i+1)*nbOfComp1,a2ptr,pt,FCT());
2874         ret->copyStringInfoFrom(*a1);
2875         return ret.retn();
2876       }
2877     else
2878       {
2879         a1->checkNbOfTuples(nbOfTuple2,"Nb of tuples mismatch for array Divide !");//will always throw an exception
2880         return 0;
2881       }
2882   }
2883   
2884   /*!
2885    * Returns a new DataArrayDouble that is a subtraction of two given arrays. There are 3
2886    * valid cases.
2887    * 1.  The arrays have same number of tuples and components. Then each value of
2888    *   the result array (_a_) is a subtraction of the corresponding values of \a a1 and
2889    *   \a a2, i.e.: _a_ [ i, j ] = _a1_ [ i, j ] - _a2_ [ i, j ].
2890    * 2.  The arrays have same number of tuples and one array, say _a2_, has one
2891    *   component. Then
2892    *   _a_ [ i, j ] = _a1_ [ i, j ] - _a2_ [ i, 0 ].
2893    * 3.  The arrays have same number of components and one array, say _a2_, has one
2894    *   tuple. Then
2895    *   _a_ [ i, j ] = _a1_ [ i, j ] - _a2_ [ 0, j ].
2896    *
2897    * Info on components is copied either from the first array (in the first case) or from
2898    * the array with maximal number of elements (getNbOfElems()).
2899    *  \param [in] a1 - an array to subtract from.
2900    *  \param [in] a2 - an array to subtract.
2901    *  \return DataArrayDouble * - the new instance of DataArrayDouble.
2902    *          The caller is to delete this result array using decrRef() as it is no more
2903    *          needed.
2904    *  \throw If either \a a1 or \a a2 is NULL.
2905    *  \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples() and
2906    *         \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents() and
2907    *         none of them has number of tuples or components equal to 1.
2908    */
2909   template<class T>
2910   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::Substract(const typename Traits<T>::ArrayType *a1, const typename Traits<T>::ArrayType *a2)
2911   {
2912     return DivSub< T,std::minus<T> >(a1,a2);
2913   }
2914   
2915   /*!
2916    * Returns a new DataArrayDouble that is a division of two given arrays. There are 3
2917    * valid cases.
2918    * 1.  The arrays have same number of tuples and components. Then each value of
2919    *   the result array (_a_) is a division of the corresponding values of \a a1 and
2920    *   \a a2, i.e.: _a_ [ i, j ] = _a1_ [ i, j ] / _a2_ [ i, j ].
2921    * 2.  The arrays have same number of tuples and one array, say _a2_, has one
2922    *   component. Then
2923    *   _a_ [ i, j ] = _a1_ [ i, j ] / _a2_ [ i, 0 ].
2924    * 3.  The arrays have same number of components and one array, say _a2_, has one
2925    *   tuple. Then
2926    *   _a_ [ i, j ] = _a1_ [ i, j ] / _a2_ [ 0, j ].
2927    *
2928    * Info on components is copied either from the first array (in the first case) or from
2929    * the array with maximal number of elements (getNbOfElems()).
2930    *  \warning No check of division by zero is performed!
2931    *  \param [in] a1 - a numerator array.
2932    *  \param [in] a2 - a denominator array.
2933    *  \return DataArrayDouble * - the new instance of DataArrayDouble.
2934    *          The caller is to delete this result array using decrRef() as it is no more
2935    *          needed.
2936    *  \throw If either \a a1 or \a a2 is NULL.
2937    *  \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples() and
2938    *         \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents() and
2939    *         none of them has number of tuples or components equal to 1.
2940    */
2941   template<class T>
2942   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::Divide(const typename Traits<T>::ArrayType *a1, const typename Traits<T>::ArrayType *a2)
2943   {
2944     return DivSub< T,std::divides<T> >(a1,a2);
2945   }
2946
2947   template<class T, class FCT>
2948   typename Traits<T>::ArrayType *MulAdd(const typename Traits<T>::ArrayType *a1, const typename Traits<T>::ArrayType *a2)
2949   {
2950     if(!a1 || !a2)
2951       throw INTERP_KERNEL::Exception("DataArrayDouble::MulAdd : input DataArrayDouble instance is NULL !");
2952     mcIdType nbOfTuple(a1->getNumberOfTuples());
2953     mcIdType nbOfTuple2(a2->getNumberOfTuples());
2954     std::size_t nbOfComp(a1->getNumberOfComponents());
2955     std::size_t nbOfComp2(a2->getNumberOfComponents());
2956     MCAuto<typename Traits<T>::ArrayType> ret=0;
2957     if(nbOfTuple==nbOfTuple2)
2958       {
2959         if(nbOfComp==nbOfComp2)
2960           {
2961             ret=Traits<T>::ArrayType::New();
2962             ret->alloc(nbOfTuple,nbOfComp);
2963             std::transform(a1->begin(),a1->end(),a2->begin(),ret->getPointer(),FCT());
2964             ret->copyStringInfoFrom(*a1);
2965           }
2966         else
2967           {
2968             std::size_t nbOfCompMin,nbOfCompMax;
2969             const typename Traits<T>::ArrayType *aMin, *aMax;
2970             if(nbOfComp>nbOfComp2)
2971               {
2972                 nbOfCompMin=nbOfComp2; nbOfCompMax=nbOfComp;
2973                 aMin=a2; aMax=a1;
2974               }
2975             else
2976               {
2977                 nbOfCompMin=nbOfComp; nbOfCompMax=nbOfComp2;
2978                 aMin=a1; aMax=a2;
2979               }
2980             if(nbOfCompMin==1)
2981               {
2982                 ret=Traits<T>::ArrayType::New();
2983                 ret->alloc(nbOfTuple,nbOfCompMax);
2984                 const T *aMinPtr(aMin->begin());
2985                 const T *aMaxPtr(aMax->begin());
2986                 T *res=ret->getPointer();
2987                 for(mcIdType i=0;i<nbOfTuple;i++)
2988                   res=std::transform(aMaxPtr+i*nbOfCompMax,aMaxPtr+(i+1)*nbOfCompMax,res,std::bind(FCT(),std::placeholders::_1,aMinPtr[i]));
2989                 ret->copyStringInfoFrom(*aMax);
2990               }
2991             else
2992               throw INTERP_KERNEL::Exception("Nb of components mismatch for array MulAdd !");
2993           }
2994       }
2995     else if((nbOfTuple==1 && nbOfTuple2>1) || (nbOfTuple>1 && nbOfTuple2==1))
2996       {
2997         if(nbOfComp==nbOfComp2)
2998           {
2999             mcIdType nbOfTupleMax=std::max(nbOfTuple,nbOfTuple2);
3000             const typename Traits<T>::ArrayType *aMin(nbOfTuple>nbOfTuple2?a2:a1);
3001             const typename Traits<T>::ArrayType *aMax(nbOfTuple>nbOfTuple2?a1:a2);
3002             const T *aMinPtr(aMin->begin()),*aMaxPtr(aMax->begin());
3003             ret=Traits<T>::ArrayType::New();
3004             ret->alloc(nbOfTupleMax,nbOfComp);
3005             T *res(ret->getPointer());
3006             for(mcIdType i=0;i<nbOfTupleMax;i++)
3007               res=std::transform(aMaxPtr+i*nbOfComp,aMaxPtr+(i+1)*nbOfComp,aMinPtr,res,FCT());
3008             ret->copyStringInfoFrom(*aMax);
3009           }
3010         else
3011           throw INTERP_KERNEL::Exception("Nb of components mismatch for array MulAdd !");
3012       }
3013     else
3014       throw INTERP_KERNEL::Exception("Nb of tuples mismatch for array MulAdd !");
3015     return ret.retn();
3016   }
3017   
3018   /*!
3019    * Returns a new DataArrayDouble that is a product of two given arrays. There are 3
3020    * valid cases.
3021    * 1.  The arrays have same number of tuples and components. Then each value of
3022    *   the result array (_a_) is a product of the corresponding values of \a a1 and
3023    *   \a a2, i.e. _a_ [ i, j ] = _a1_ [ i, j ] * _a2_ [ i, j ].
3024    * 2.  The arrays have same number of tuples and one array, say _a2_, has one
3025    *   component. Then
3026    *   _a_ [ i, j ] = _a1_ [ i, j ] * _a2_ [ i, 0 ].
3027    * 3.  The arrays have same number of components and one array, say _a2_, has one
3028    *   tuple. Then
3029    *   _a_ [ i, j ] = _a1_ [ i, j ] * _a2_ [ 0, j ].
3030    *
3031    * Info on components is copied either from the first array (in the first case) or from
3032    * the array with maximal number of elements (getNbOfElems()).
3033    *  \param [in] a1 - a factor array.
3034    *  \param [in] a2 - another factor array.
3035    *  \return DataArrayDouble * - the new instance of DataArrayDouble.
3036    *          The caller is to delete this result array using decrRef() as it is no more
3037    *          needed.
3038    *  \throw If either \a a1 or \a a2 is NULL.
3039    *  \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples() and
3040    *         \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents() and
3041    *         none of them has number of tuples or components equal to 1.
3042    */
3043   template<class T>
3044   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::Multiply(const typename Traits<T>::ArrayType *a1, const typename Traits<T>::ArrayType *a2)
3045   {
3046     return MulAdd< T , std::multiplies<T> >(a1,a2);
3047   }
3048   
3049   /*!
3050    * Returns a new DataArrayDouble that is a sum of two given arrays. There are 3
3051    * valid cases.
3052    * 1.  The arrays have same number of tuples and components. Then each value of
3053    *   the result array (_a_) is a sum of the corresponding values of \a a1 and \a a2,
3054    *   i.e.: _a_ [ i, j ] = _a1_ [ i, j ] + _a2_ [ i, j ].
3055    * 2.  The arrays have same number of tuples and one array, say _a2_, has one
3056    *   component. Then
3057    *   _a_ [ i, j ] = _a1_ [ i, j ] + _a2_ [ i, 0 ].
3058    * 3.  The arrays have same number of components and one array, say _a2_, has one
3059    *   tuple. Then
3060    *   _a_ [ i, j ] = _a1_ [ i, j ] + _a2_ [ 0, j ].
3061    *
3062    * Info on components is copied either from the first array (in the first case) or from
3063    * the array with maximal number of elements (getNbOfElems()).
3064    *  \param [in] a1 - an array to sum up.
3065    *  \param [in] a2 - another array to sum up.
3066    *  \return DataArrayDouble * - the new instance of DataArrayDouble.
3067    *          The caller is to delete this result array using decrRef() as it is no more
3068    *          needed.
3069    *  \throw If either \a a1 or \a a2 is NULL.
3070    *  \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples() and
3071    *         \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents() and
3072    *         none of them has number of tuples or components equal to 1.
3073    */
3074   template<class T>
3075   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::Add(const typename Traits<T>::ArrayType *a1, const typename Traits<T>::ArrayType *a2)
3076   {
3077     return MulAdd< T , std::plus<T> >(a1,a2);
3078   }
3079   
3080   /*!
3081    * Returns either a \a deep or \a shallow copy of this array. For more info see
3082    * \ref MEDCouplingArrayBasicsCopyDeep and \ref MEDCouplingArrayBasicsCopyShallow.
3083    *  \param [in] dCpy - if \a true, a deep copy is returned, else, a shallow one.
3084    *  \return DataArrayDouble * - either a new instance of DataArrayDouble (if \a dCpy
3085    *          == \a true) or \a this instance (if \a dCpy == \a false).
3086    */
3087   template<class T>
3088   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::PerformCopyOrIncrRef(bool dCpy, const typename Traits<T>::ArrayType& self)
3089   {
3090     if(dCpy)
3091       return self.deepCopy();
3092     else
3093       {
3094         self.incrRef();
3095         return const_cast<typename Traits<T>::ArrayType *>(&self);
3096       }
3097   }
3098
3099   template<class T>
3100   struct GreatEqual
3101   {
3102     GreatEqual(T v):_v(v) { }
3103     bool operator()(T v) const { return v>=_v; }
3104     T _v;
3105   };
3106   
3107   template<class T>
3108   struct GreaterThan
3109   {
3110     GreaterThan(T v):_v(v) { }
3111     bool operator()(T v) const { return v>_v; }
3112     T _v;
3113   };
3114   
3115   template<class T>
3116   struct LowerEqual
3117   {
3118     LowerEqual(T v):_v(v) { }
3119     bool operator()(T v) const { return v<=_v; }
3120     T _v;
3121   };
3122   
3123   template<class T>
3124   struct LowerThan
3125   {
3126     LowerThan(T v):_v(v) { }
3127     bool operator()(T v) const { return v<_v; }
3128     T _v;
3129   };
3130   
3131   template<class T>
3132   struct InRange
3133   {
3134     InRange(T a, T b):_a(a),_b(b) { }
3135     bool operator()(T v) const { return v>=_a && v<_b; }
3136     T _a,_b;
3137   };
3138
3139 template<class T>
3140 struct NotInRange
3141 {
3142   NotInRange(T a, T b):_a(a),_b(b) { }
3143   bool operator()(T v) const { return v<_a || v>=_b; }
3144   T _a,_b;
3145 };
3146
3147   /*!
3148    * 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.
3149    *
3150    * \return a newly allocated data array that the caller should deal with.
3151    * \sa DataArrayInt::findIdsInRange
3152    */
3153   template<class T>
3154   DataArrayIdType *DataArrayTemplateClassic<T>::findIdsStrictlyNegative() const
3155   {
3156     LowerThan<T> lt((T)0);
3157     MCAuto<DataArrayIdType> ret(findIdsAdv(lt));
3158     return ret.retn();
3159   }
3160   
3161   template<class T>
3162   MCAuto<DataArrayIdType> DataArrayTemplateClassic<T>::findIdsGreaterOrEqualTo(T val) const
3163   {
3164     GreatEqual<T> ge(val);
3165     return findIdsAdv(ge);
3166   }
3167   
3168   template<class T>
3169   MCAuto<DataArrayIdType> DataArrayTemplateClassic<T>::findIdsGreaterThan(T val) const
3170   {
3171     GreaterThan<T> gt(val);
3172     return findIdsAdv(gt);
3173   }
3174   
3175   template<class T>
3176   MCAuto<DataArrayIdType> DataArrayTemplateClassic<T>::findIdsLowerOrEqualTo(T val) const
3177   {
3178     LowerEqual<T> le(val);
3179     return findIdsAdv(le);
3180   }
3181   
3182   template<class T>
3183   MCAuto<DataArrayIdType> DataArrayTemplateClassic<T>::findIdsLowerThan(T val) const
3184   {
3185     LowerThan<T> lt(val);
3186     return findIdsAdv(lt);
3187   }
3188
3189   /*!
3190    * Returns a new DataArrayDouble by aggregating two given arrays, so that (1) the number
3191    * of components in the result array is a sum of the number of components of given arrays
3192    * and (2) the number of tuples in the result array is same as that of each of given
3193    * arrays. In other words the i-th tuple of result array includes all components of
3194    * i-th tuples of all given arrays.
3195    * Number of tuples in the given arrays must be  the same.
3196    *  \param [in] a1 - an array to include in the result array.
3197    *  \param [in] a2 - another array to include in the result array.
3198    *  \return DataArrayDouble * - the new instance of DataArrayDouble.
3199    *          The caller is to delete this result array using decrRef() as it is no more
3200    *          needed.
3201    *  \throw If both \a a1 and \a a2 are NULL.
3202    *  \throw If any given array is not allocated.
3203    *  \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples()
3204    */
3205   template<class T>
3206   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::Meld(const typename Traits<T>::ArrayType *a1, const typename Traits<T>::ArrayType *a2)
3207   {
3208     std::vector<const typename Traits<T>::ArrayType *> arr(2);
3209     arr[0]=a1; arr[1]=a2;
3210     return Meld(arr);
3211   }
3212
3213   /*!
3214    * Returns a new DataArrayDouble by aggregating all given arrays, so that (1) the number
3215    * of components in the result array is a sum of the number of components of given arrays
3216    * and (2) the number of tuples in the result array is same as that of each of given
3217    * arrays. In other words the i-th tuple of result array includes all components of
3218    * i-th tuples of all given arrays.
3219    * Number of tuples in the given arrays must be  the same.
3220    *  \param [in] arr - a sequence of arrays to include in the result array.
3221    *  \return DataArrayDouble * - the new instance of DataArrayDouble.
3222    *          The caller is to delete this result array using decrRef() as it is no more
3223    *          needed.
3224    *  \throw If all arrays within \a arr are NULL.
3225    *  \throw If any given array is not allocated.
3226    *  \throw If getNumberOfTuples() of arrays within \a arr is different.
3227    */
3228   template<class T>
3229   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::Meld(const std::vector<const typename Traits<T>::ArrayType *>& arr)
3230   {
3231     std::vector<const typename Traits<T>::ArrayType *> a;
3232     for(typename std::vector<const typename Traits<T>::ArrayType *>::const_iterator it4=arr.begin();it4!=arr.end();it4++)
3233       if(*it4)
3234         a.push_back(*it4);
3235     if(a.empty())
3236       throw INTERP_KERNEL::Exception("DataArrayDouble::Meld : input list must contain at least one NON EMPTY DataArrayDouble !");
3237     typename std::vector<const typename Traits<T>::ArrayType *>::const_iterator it;
3238     for(it=a.begin();it!=a.end();it++)
3239       (*it)->checkAllocated();
3240     it=a.begin();
3241     mcIdType nbOfTuples((*it)->getNumberOfTuples());
3242     std::vector<std::size_t> nbc(a.size());
3243     std::vector<const T *> pts(a.size());
3244     nbc[0]=(*it)->getNumberOfComponents();
3245     pts[0]=(*it++)->getConstPointer();
3246     for(mcIdType i=1;it!=a.end();it++,i++)
3247       {
3248         if(nbOfTuples!=(*it)->getNumberOfTuples())
3249           throw INTERP_KERNEL::Exception("DataArrayDouble::Meld : mismatch of number of tuples !");
3250         nbc[i]=(*it)->getNumberOfComponents();
3251         pts[i]=(*it)->getConstPointer();
3252       }
3253     std::size_t totalNbOfComp=std::accumulate(nbc.begin(),nbc.end(),(std::size_t)0);
3254     typename Traits<T>::ArrayType *ret(Traits<T>::ArrayType::New());
3255     ret->alloc(nbOfTuples,totalNbOfComp);
3256     T *retPtr(ret->getPointer());
3257     for(mcIdType i=0;i<nbOfTuples;i++)
3258       for(std::size_t j=0;j<a.size();j++)
3259         {
3260           retPtr=std::copy(pts[j],pts[j]+nbc[j],retPtr);
3261           pts[j]+=nbc[j];
3262         }
3263     std::size_t k=0;
3264     for(std::size_t i=0;i<a.size();i++)
3265       for(std::size_t j=0;j<nbc[i];j++,k++)
3266         ret->setInfoOnComponent(k,a[i]->getInfoOnComponent(j));
3267     return ret;
3268   }
3269
3270   /*!
3271    * Returns a new DataArrayDouble holding the same values as \a this array but differently
3272    * arranged in memory. If \a this array holds 2 components of 3 values:
3273    * \f$ x_0,x_1,x_2,y_0,y_1,y_2 \f$, then the result array holds these values arranged
3274    * as follows: \f$ x_0,y_0,x_1,y_1,x_2,y_2 \f$.
3275    *  \warning Do not confuse this method with transpose()!
3276    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
3277    *          is to delete using decrRef() as it is no more needed.
3278    *  \throw If \a this is not allocated.
3279    */
3280   template<class T>
3281   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::fromNoInterlace() const
3282   {
3283     if(this->_mem.isNull())
3284       throw INTERP_KERNEL::Exception("DataArrayDouble::fromNoInterlace : Not defined array !");
3285     T *tab(this->_mem.fromNoInterlace(this->getNumberOfComponents()));
3286     MCAuto<typename Traits<T>::ArrayType> ret(Traits<T>::ArrayType::New());
3287     ret->useArray(tab,true,DeallocType::C_DEALLOC,this->getNumberOfTuples(),this->getNumberOfComponents());
3288     return ret.retn();
3289   }
3290
3291   /*!
3292    * Returns a new DataArrayDouble holding the same values as \a this array but differently
3293    * arranged in memory. If \a this array holds 2 components of 3 values:
3294    * \f$ x_0,y_0,x_1,y_1,x_2,y_2 \f$, then the result array holds these values arranged
3295    * as follows: \f$ x_0,x_1,x_2,y_0,y_1,y_2 \f$.
3296    *  \warning Do not confuse this method with transpose()!
3297    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
3298    *          is to delete using decrRef() as it is no more needed.
3299    *  \throw If \a this is not allocated.
3300    */
3301   template<class T>
3302   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::toNoInterlace() const
3303   {
3304     if(this->_mem.isNull())
3305       throw INTERP_KERNEL::Exception("DataArrayDouble::toNoInterlace : Not defined array !");
3306     T *tab(this->_mem.toNoInterlace(this->getNumberOfComponents()));
3307     MCAuto<typename Traits<T>::ArrayType> ret(Traits<T>::ArrayType::New());
3308     ret->useArray(tab,true,DeallocType::C_DEALLOC,this->getNumberOfTuples(),this->getNumberOfComponents());
3309     return ret.retn();
3310   }
3311   
3312   /*!
3313    * Appends components of another array to components of \a this one, tuple by tuple.
3314    * So that the number of tuples of \a this array remains the same and the number of 
3315    * components increases.
3316    *  \param [in] other - the DataArrayDouble to append to \a this one.
3317    *  \throw If \a this is not allocated.
3318    *  \throw If \a this and \a other arrays have different number of tuples.
3319    *
3320    *  \if ENABLE_EXAMPLES
3321    *  \ref cpp_mcdataarraydouble_meldwith "Here is a C++ example".
3322    *
3323    *  \ref py_mcdataarraydouble_meldwith "Here is a Python example".
3324    *  \endif
3325    */
3326   template<class T>
3327   void DataArrayTemplateClassic<T>::meldWith(const typename Traits<T>::ArrayType *other)
3328   {
3329     this->checkAllocated();
3330     other->checkAllocated();
3331     mcIdType nbOfTuples(this->getNumberOfTuples());
3332     if(nbOfTuples!=other->getNumberOfTuples())
3333       throw INTERP_KERNEL::Exception("DataArrayDouble::meldWith : mismatch of number of tuples !");
3334     std::size_t nbOfComp1=this->getNumberOfComponents();
3335     std::size_t nbOfComp2=other->getNumberOfComponents();
3336     T *newArr=(T *)malloc((nbOfTuples*(nbOfComp1+nbOfComp2))*sizeof(T));
3337     T *w=newArr;
3338     const T *inp1(this->begin()),*inp2(other->begin());
3339     for(mcIdType i=0;i<nbOfTuples;i++,inp1+=nbOfComp1,inp2+=nbOfComp2)
3340       {
3341         w=std::copy(inp1,inp1+nbOfComp1,w);
3342         w=std::copy(inp2,inp2+nbOfComp2,w);
3343       }
3344     this->useArray(newArr,true,DeallocType::C_DEALLOC,nbOfTuples,nbOfComp1+nbOfComp2);
3345     std::vector<std::size_t> compIds(nbOfComp2);
3346     for(std::size_t i=0;i<nbOfComp2;i++)
3347       compIds[i]=nbOfComp1+i;
3348     this->copyPartOfStringInfoFrom2(compIds,*other);
3349   }
3350
3351   /*!
3352    * 
3353    * \param [in] nbTimes specifies the nb of times each tuples in \a this will be duplicated contiguouly in returned DataArrayDouble instance.
3354    *             \a nbTimes  should be at least equal to 1.
3355    * \return a newly allocated DataArrayDouble having one component and number of tuples equal to \a nbTimes * \c this->getNumberOfTuples.
3356    * \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.
3357    */
3358   template<class T>
3359   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::duplicateEachTupleNTimes(mcIdType nbTimes) const
3360   {
3361     this->checkAllocated();
3362     if(this->getNumberOfComponents()!=1)
3363       throw INTERP_KERNEL::Exception("DataArrayDouble::duplicateEachTupleNTimes : this should have only one component !");
3364     if(nbTimes<1)
3365       throw INTERP_KERNEL::Exception("DataArrayDouble::duplicateEachTupleNTimes : nb times should be >= 1 !");
3366     mcIdType nbTuples=this->getNumberOfTuples();
3367     const T *inPtr(this->begin());
3368     MCAuto<typename Traits<T>::ArrayType> ret(Traits<T>::ArrayType::New()); ret->alloc(nbTimes*nbTuples,1);
3369     T *retPtr(ret->getPointer());
3370     for(mcIdType i=0;i<nbTuples;i++,inPtr++)
3371       {
3372         T val(*inPtr);
3373         for(mcIdType j=0;j<nbTimes;j++,retPtr++)
3374           *retPtr=val;
3375       }
3376     ret->copyStringInfoFrom(*this);
3377     return ret.retn();
3378   }
3379   
3380   template<class T>
3381   void DataArrayTemplateClassic<T>::aggregate(const typename Traits<T>::ArrayType *other)
3382   {
3383     if(!other)
3384       throw INTERP_KERNEL::Exception("DataArrayDouble::aggregate : null pointer !");
3385     if(this->getNumberOfComponents()!=other->getNumberOfComponents())
3386       throw INTERP_KERNEL::Exception("DataArrayDouble::aggregate : mismatch number of components !");
3387     this->_mem.insertAtTheEnd(other->begin(),other->end());
3388   }
3389
3390   /*!
3391    * Converts every value of \a this array to its absolute value.
3392    * \b WARNING this method is non const. If a new DataArrayDouble instance should be built containing the result of abs DataArrayDouble::computeAbs
3393    * should be called instead.
3394    *
3395    * \throw If \a this is not allocated.
3396    * \sa DataArrayDouble::computeAbs
3397    */
3398   template<class T>
3399   void DataArrayTemplateClassic<T>::abs()
3400   {
3401     this->checkAllocated();
3402     T *ptr(this->getPointer());
3403     std::size_t nbOfElems(this->getNbOfElems());
3404     std::transform(ptr,ptr+nbOfElems,ptr,[](T c){return std::abs(c);});
3405     this->declareAsNew();
3406   }
3407
3408   /*!
3409    * This method builds a new instance of \a this object containing the result of std::abs applied of all elements in \a this.
3410    * This method is a const method (that do not change any values in \a this) contrary to  DataArrayDouble::abs method.
3411    *
3412    * \return DataArrayDouble * - the new instance of DataArrayDouble containing the
3413    *         same number of tuples and component as \a this array.
3414    *         The caller is to delete this result array using decrRef() as it is no more
3415    *         needed.
3416    * \throw If \a this is not allocated.
3417    * \sa DataArrayDouble::abs
3418    */
3419   template<class T>
3420   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::computeAbs() const
3421   {
3422     this->checkAllocated();
3423     MCAuto<typename Traits<T>::ArrayType> newArr(Traits<T>::ArrayType::New());
3424     mcIdType nbOfTuples(this->getNumberOfTuples());
3425     std::size_t nbOfComp(this->getNumberOfComponents());
3426     newArr->alloc(nbOfTuples,nbOfComp);
3427     std::transform(this->begin(),this->end(),newArr->getPointer(),[](T c){return std::abs(c);});
3428     newArr->copyStringInfoFrom(*this);
3429     return newArr.retn();
3430   }
3431
3432   /*!
3433    * Returns either a \a deep or \a shallow copy of this array. For more info see
3434    * \ref MEDCouplingArrayBasicsCopyDeep and \ref MEDCouplingArrayBasicsCopyShallow.
3435    *  \param [in] dCpy - if \a true, a deep copy is returned, else, a shallow one.
3436    *  \return DataArrayDouble * - either a new instance of DataArrayDouble (if \a dCpy
3437    *          == \a true) or \a this instance (if \a dCpy == \a false).
3438    */
3439   template<class T>
3440   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::performCopyOrIncrRef(bool dCpy) const
3441   {
3442     const typename Traits<T>::ArrayType *thisC(static_cast<const typename Traits<T>::ArrayType *>(this));
3443     return DataArrayTemplateClassic<T>::PerformCopyOrIncrRef(dCpy,*thisC);
3444   }
3445
3446   /*!
3447    * Computes for each tuple the sum of number of components values in the tuple and return it.
3448    * 
3449    * \return DataArrayDouble * - the new instance of DataArrayDouble containing the
3450    *          same number of tuples as \a this array and one component.
3451    *          The caller is to delete this result array using decrRef() as it is no more
3452    *          needed.
3453    *  \throw If \a this is not allocated.
3454    */
3455   template<class T>
3456   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::sumPerTuple() const
3457   {
3458     this->checkAllocated();
3459     std::size_t nbOfComp(this->getNumberOfComponents());
3460     mcIdType nbOfTuple(this->getNumberOfTuples());
3461     MCAuto<typename Traits<T>::ArrayType> ret(Traits<T>::ArrayType::New());
3462     ret->alloc(nbOfTuple,1);
3463     const T *src(this->begin());
3464     T *dest(ret->getPointer());
3465     for(mcIdType i=0;i<nbOfTuple;i++,dest++,src+=nbOfComp)
3466       *dest=std::accumulate(src,src+nbOfComp,(T)0);
3467     return ret.retn();
3468   }
3469
3470   /*!
3471    * Set all values in \a this array so that the i-th element equals to \a init + i
3472    * (i starts from zero). To know more on filling arrays see \ref MEDCouplingArrayFill.
3473    *  \param [in] init - value to assign to the first element of array.
3474    *  \throw If \a this->getNumberOfComponents() != 1
3475    *  \throw If \a this is not allocated.
3476    */
3477   template<class T>
3478   void DataArrayTemplateClassic<T>::iota(T init)
3479   {
3480     this->checkAllocated();
3481     if(this->getNumberOfComponents()!=1)
3482       throw INTERP_KERNEL::Exception("DataArrayDouble::iota : works only for arrays with only one component, you can call 'rearrange' method before !");
3483     T *ptr(this->getPointer());
3484     mcIdType ntuples(this->getNumberOfTuples());
3485     for(mcIdType i=0;i<ntuples;i++)
3486       ptr[i]=init+(T)i;
3487     this->declareAsNew();
3488   }
3489
3490   template<class T>
3491   struct ImplReprTraits { static void SetPrecision(std::ostream& oss) { } };
3492
3493   template<>
3494   struct ImplReprTraits<double> {  static void SetPrecision(std::ostream& oss) { oss.precision(17); } };
3495   
3496   template<>
3497   struct ImplReprTraits<float> {  static void SetPrecision(std::ostream& oss) { oss.precision(7); } };
3498   
3499   template<class T>
3500   void DataArrayTemplateClassic<T>::reprStream(std::ostream& stream) const
3501   {
3502     stream << "Name of " << Traits<T>::ReprStr << " array : \"" << this->_name << "\"\n";
3503     reprWithoutNameStream(stream);
3504   }
3505
3506   template<class T>
3507   void DataArrayTemplateClassic<T>::reprZipStream(std::ostream& stream) const
3508   {
3509     stream << "Name of " << Traits<T>::ReprStr << " array : \"" << this->_name << "\"\n";
3510     reprZipWithoutNameStream(stream);
3511   }
3512
3513   template<class T>
3514   void DataArrayTemplateClassic<T>::reprNotTooLongStream(std::ostream& stream) const
3515   {
3516     stream << "Name of "<< Traits<T>::ReprStr << " array : \"" << this->_name << "\"\n";
3517     reprNotTooLongWithoutNameStream(stream);
3518   }
3519
3520   template<class T>
3521   void DataArrayTemplateClassic<T>::reprWithoutNameStream(std::ostream& stream) const
3522   {
3523     DataArray::reprWithoutNameStream(stream);
3524     ImplReprTraits<T>::SetPrecision(stream);
3525     this->_mem.repr(ToIdType(this->getNumberOfComponents()),stream);
3526   }
3527
3528   template<class T>
3529   void DataArrayTemplateClassic<T>::reprZipWithoutNameStream(std::ostream& stream) const
3530   {
3531     DataArray::reprWithoutNameStream(stream);
3532     ImplReprTraits<T>::SetPrecision(stream);
3533     this->_mem.reprZip(ToIdType(this->getNumberOfComponents()),stream);
3534   }
3535
3536   template<class T>
3537   void DataArrayTemplateClassic<T>::reprNotTooLongWithoutNameStream(std::ostream& stream) const
3538   {
3539     DataArray::reprWithoutNameStream(stream);
3540     ImplReprTraits<T>::SetPrecision(stream);
3541     this->_mem.reprNotTooLong(ToIdType(this->getNumberOfComponents()),stream);
3542   }
3543
3544   /*!
3545    * This method is close to repr method except that when \a this has more than 1000 tuples, all tuples are not
3546    * printed out to avoid to consume too much space in interpretor.
3547    * \sa repr
3548    */
3549   template<class T>
3550   std::string DataArrayTemplateClassic<T>::reprNotTooLong() const
3551   {
3552     std::ostringstream ret;
3553     reprNotTooLongStream(ret);
3554     return ret.str();
3555   }
3556   
3557   /*!
3558    * Returns a textual and human readable representation of \a this instance of
3559    * DataArrayInt. This text is shown when a DataArrayInt is printed in Python.
3560    * \return std::string - text describing \a this DataArrayInt.
3561    *
3562    * \sa reprNotTooLong, reprZip
3563    */
3564   template<class T>
3565   std::string DataArrayTemplateClassic<T>::repr() const
3566   {
3567     std::ostringstream ret;
3568     DataArrayTemplateClassic<T>::reprStream(ret);
3569     return ret.str();
3570   }
3571   
3572   template<class T>
3573   std::string DataArrayTemplateClassic<T>::reprZip() const
3574   {
3575     std::ostringstream ret;
3576     DataArrayTemplateClassic<T>::reprZipStream(ret);
3577     return ret.str();
3578   }
3579   
3580   /////////////////////////////////
3581   
3582   /*!
3583    * Checks if all values in \a this array are equal to \a val at precision \a eps.
3584    *  \param [in] val - value to check equality of array values to.
3585    *  \param [in] eps - precision to check the equality.
3586    *  \return bool - \a true if all values are in range (_val_ - _eps_; _val_ + _eps_),
3587    *                 \a false else.
3588    *  \throw If \a this->getNumberOfComponents() != 1
3589    *  \throw If \a this is not allocated.
3590    */
3591   template<class T>
3592   bool DataArrayTemplateFP<T>::isUniform(T val, T eps) const
3593   {
3594     this->checkAllocated();
3595     if(this->getNumberOfComponents()!=1)
3596       throw INTERP_KERNEL::Exception("DataArrayDouble::isUniform : must be applied on DataArrayDouble with only one component, you can call 'rearrange' method before !");
3597     const T *w(this->begin()),*end2(this->end());
3598     const T vmin(val-eps),vmax(val+eps);
3599     for(;w!=end2;w++)
3600       if(*w<vmin || *w>vmax)
3601         return false;
3602     return true;
3603   }
3604
3605   /////////////////////////////////
3606
3607   /*!
3608    * Returns the only one value in \a this, if and only if number of elements
3609    * (nb of tuples * nb of components) is equal to 1, and that \a this is allocated.
3610    *  \return double - the sole value stored in \a this array.
3611    *  \throw If at least one of conditions stated above is not fulfilled.
3612    */
3613   template <class T>
3614   T DataArrayDiscrete<T>::intValue() const
3615   {
3616     if(this->isAllocated())
3617       {
3618         if(this->getNbOfElems()==1)
3619           {
3620             return *this->getConstPointer();
3621           }
3622         else
3623           throw INTERP_KERNEL::Exception("DataArrayInt::intValue : DataArrayInt instance is allocated but number of elements is not equal to 1 !");
3624       }
3625     else
3626       throw INTERP_KERNEL::Exception("DataArrayInt::intValue : DataArrayInt instance is not allocated !");
3627   }
3628
3629   /*!
3630    * Equivalent to DataArrayInt::isEqual except that if false the reason of
3631    * mismatch is given.
3632    * 
3633    * \param [in] other the instance to be compared with \a this
3634    * \param [out] reason In case of inequality returns the reason.
3635    * \sa DataArrayInt::isEqual
3636    */
3637   template<class T>
3638   bool DataArrayDiscrete<T>::isEqualIfNotWhy(const DataArrayDiscrete<T>& other, std::string& reason) const
3639   {
3640     if(!this->areInfoEqualsIfNotWhy(other,reason))
3641       return false;
3642     return this->_mem.isEqual(other._mem,0,reason);
3643   }
3644
3645   /*!
3646    * Checks if \a this and another DataArrayInt are fully equal. For more info see
3647    * \ref MEDCouplingArrayBasicsCompare.
3648    *  \param [in] other - an instance of DataArrayInt to compare with \a this one.
3649    *  \return bool - \a true if the two arrays are equal, \a false else.
3650    */
3651   template<class T>
3652   bool DataArrayDiscrete<T>::isEqual(const DataArrayDiscrete<T>& other) const
3653   {
3654     std::string tmp;
3655     return isEqualIfNotWhy(other,tmp);
3656   }
3657   
3658   /*!
3659    * Returns a new instance of DataArrayInt. The caller is to delete this array
3660    * using decrRef() as it is no more needed.
3661    */
3662   template<class T>
3663   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::New()
3664   {
3665     return new typename Traits<T>::ArrayType;
3666   }
3667   
3668   /*!
3669    * Checks if values of \a this and another DataArrayInt are equal. For more info see
3670    * \ref MEDCouplingArrayBasicsCompare.
3671    *  \param [in] other - an instance of DataArrayInt to compare with \a this one.
3672    *  \return bool - \a true if the values of two arrays are equal, \a false else.
3673    */
3674   template<class T>
3675   bool DataArrayDiscrete<T>::isEqualWithoutConsideringStr(const DataArrayDiscrete<T>& other) const
3676   {
3677     std::string tmp;
3678     return this->_mem.isEqual(other._mem,0,tmp);
3679   }
3680
3681   /*!
3682    * Checks if values of \a this and another DataArrayInt are equal. Comparison is
3683    * performed on sorted value sequences.
3684    * For more info see\ref MEDCouplingArrayBasicsCompare.
3685    *  \param [in] other - an instance of DataArrayInt to compare with \a this one.
3686    *  \return bool - \a true if the sorted values of two arrays are equal, \a false else.
3687    */
3688   template<class T>
3689   bool DataArrayDiscrete<T>::isEqualWithoutConsideringStrAndOrder(const typename Traits<T>::ArrayType& other) const
3690   {
3691     MCAuto<typename Traits<T>::ArrayType> a((static_cast<const typename Traits<T>::ArrayType *>(this))->deepCopy());
3692     MCAuto<typename Traits<T>::ArrayType> b((static_cast<const typename Traits<T>::ArrayType *>(&other))->deepCopy());
3693     a->sort();
3694     b->sort();
3695     return a->isEqualWithoutConsideringStr(*b);
3696   }
3697   
3698   template<class T>
3699   template<class ALG>
3700   void DataArrayDiscrete<T>::switchOnTupleAlg(T val, std::vector<bool>& vec, ALG algo) const
3701   {
3702     this->checkAllocated();
3703     if(this->getNumberOfComponents()!=1)
3704       throw INTERP_KERNEL::Exception("DataArrayInt::switchOnTupleEqualTo : number of components of this should be equal to one !");
3705     mcIdType nbOfTuples(this->getNumberOfTuples());
3706     if(nbOfTuples!=ToIdType(vec.size()))
3707       throw INTERP_KERNEL::Exception("DataArrayInt::switchOnTupleEqualTo : number of tuples of this should be equal to size of input vector of bool !");
3708     const T *pt(this->begin());
3709     for(mcIdType i=0;i<nbOfTuples;i++)
3710       if(algo(pt[i],val))
3711         vec[i]=true;
3712   }
3713   
3714   /*!
3715    * 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
3716    * put True to the corresponding entry in \a vec.
3717    * \a vec is expected to be with the same size than the number of tuples of \a this.
3718    *
3719    *  \sa DataArrayInt::switchOnTupleNotEqualTo.
3720    */
3721   template<class T>
3722   void DataArrayDiscrete<T>::switchOnTupleEqualTo(T val, std::vector<bool>& vec) const
3723   {
3724     switchOnTupleAlg(val,vec,std::equal_to<T>());
3725   }
3726
3727   /*!
3728    * 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
3729    * put True to the corresponding entry in \a vec.
3730    * \a vec is expected to be with the same size than the number of tuples of \a this.
3731    * 
3732    *  \sa DataArrayInt::switchOnTupleEqualTo.
3733    */
3734   template<class T>
3735   void DataArrayDiscrete<T>::switchOnTupleNotEqualTo(T val, std::vector<bool>& vec) const
3736   {
3737     switchOnTupleAlg(val,vec,std::not_equal_to<T>());
3738   }
3739
3740   /*!
3741    * 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
3742    * appearing several times. If each element in \a this appears once an 1 component array containing only 0 will be returned.
3743    *
3744    * \b Example:
3745    * - \a this : [5, 3, 2, 1, 4, 5, 2, 1, 0, 11, 5, 4]
3746    * - \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.
3747    *
3748    * \return DataArrayInt * - a new instance of DataArrayInt with same number of tuples than \a this. The caller is to delete this
3749    *          array using decrRef() as it is no more needed.
3750    * \throw If either this not allocated or not with one component.
3751    *
3752    * \sa DataArrayInt::FindPermutationFromFirstToSecond
3753    */
3754   template<class T>
3755   DataArrayIdType *DataArrayDiscrete<T>::occurenceRankInThis() const
3756   {
3757     constexpr char MSG0[] = "occurenceRankInThis :";
3758     this->checkAllocated();
3759     this->checkNbOfComps(1,MSG0);
3760     MCAuto<DataArrayIdType> ret(DataArrayIdType::New());
3761     ret->alloc(this->getNumberOfTuples(),1);
3762     mcIdType *retPtr(ret->getPointer());
3763     std::map<T,mcIdType> m;
3764     for(const T *pt = this->begin() ; pt != this->end() ; ++pt, ++retPtr )
3765     {
3766       auto it = m.find(*pt);
3767       if( it == m.end() )
3768       {
3769         *retPtr = 0;
3770         m[*pt] = 1;
3771       }
3772       else
3773       {
3774         *retPtr = (*it).second++;
3775       }
3776     }
3777     return ret.retn();
3778   }
3779
3780   /*!
3781    * Creates a new one-dimensional DataArrayInt of the same size as \a this and a given
3782    * one-dimensional arrays that must be of the same length. The result array describes
3783    * correspondence between \a this and \a other arrays, so that 
3784    * <em> other.getIJ(i,0) == this->getIJ(ret->getIJ(i),0)</em>. If such a permutation is
3785    * not possible because some element in \a other is not in \a this, an exception is thrown.
3786    *  \param [in] other - an array to compute permutation to.
3787    *  \return DataArrayInt * - a new instance of DataArrayInt, which is a permutation array
3788    * from \a this to \a other. The caller is to delete this array using decrRef() as it is
3789    * no more needed.
3790    *  \throw If \a this->getNumberOfComponents() != 1.
3791    *  \throw If \a other->getNumberOfComponents() != 1.
3792    *  \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples().
3793    *  \throw If \a other includes a value which is not in \a this array.
3794    * 
3795    *  \if ENABLE_EXAMPLES
3796    *  \ref cpp_mcdataarrayint_buildpermutationarr "Here is a C++ example".
3797    *
3798    *  \ref py_mcdataarrayint_buildpermutationarr "Here is a Python example".
3799    *  \endif
3800    */
3801   template<class T>
3802   DataArrayIdType *DataArrayDiscrete<T>::buildPermutationArr(const DataArrayDiscrete<T>& other) const
3803   {
3804     this->checkAllocated();
3805     if(this->getNumberOfComponents()!=1 || other.getNumberOfComponents()!=1)
3806       throw INTERP_KERNEL::Exception("DataArrayInt::buildPermutationArr : 'this' and 'other' have to have exactly ONE component !");
3807     mcIdType nbTuple(this->getNumberOfTuples());
3808     other.checkAllocated();
3809     if(nbTuple!=other.getNumberOfTuples())
3810       throw INTERP_KERNEL::Exception("DataArrayInt::buildPermutationArr : 'this' and 'other' must have the same number of tuple !");
3811     MCAuto<DataArrayIdType> ret(DataArrayIdType::New());
3812     ret->alloc(nbTuple,1);
3813     ret->fillWithValue(-1);
3814     const T *pt(this->begin());
3815     std::map<mcIdType,mcIdType> mm;
3816     for(mcIdType i=0;i<nbTuple;i++)
3817       mm[ToIdType(pt[i])]=i;
3818     pt=other.begin();
3819     mcIdType *retToFill(ret->getPointer());
3820     for(mcIdType i=0;i<nbTuple;i++)
3821       {
3822         std::map<mcIdType,mcIdType>::const_iterator it=mm.find(ToIdType(pt[i]));
3823         if(it==mm.end())
3824           {
3825             std::ostringstream oss; oss << "DataArrayInt::buildPermutationArr : Arrays mismatch : element (" << pt[i] << ") in 'other' not findable in 'this' !";
3826             throw INTERP_KERNEL::Exception(oss.str().c_str());
3827           }
3828         retToFill[i]=(*it).second;
3829       }
3830     return ret.retn();
3831   }
3832
3833   /*!
3834    * Elements of \a partOfThis are expected to be included in \a this.
3835    * The returned array \a ret is so that this[ret]==partOfThis
3836    *
3837    * 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]
3838    * the return array will contain [3,2,5,7].
3839    *
3840    * \a this is expected to be a 1 compo allocated array.
3841    * \param [in] partOfThis - A 1 compo allocated array
3842    * \return - A newly allocated array to be dealed by caller having the same number of tuples than \a partOfThis.
3843    * \throw if two same element is present twice in \a this
3844    * \throw if an element in \a partOfThis is \b NOT in \a this.
3845    */
3846   template<class T>
3847   DataArrayIdType *DataArrayDiscrete<T>::indicesOfSubPart(const DataArrayDiscrete<T>& partOfThis) const
3848   {
3849     if(this->getNumberOfComponents()!=1 || partOfThis.getNumberOfComponents()!=1)
3850       throw INTERP_KERNEL::Exception("DataArrayInt::indicesOfSubPart : this and input array must be one component array !");
3851     this->checkAllocated(); partOfThis.checkAllocated();
3852     mcIdType thisNbTuples(this->getNumberOfTuples()),nbTuples(partOfThis.getNumberOfTuples());
3853     const T *thisPt(this->begin()),*pt(partOfThis.begin());
3854     MCAuto<DataArrayIdType> ret(DataArrayIdType::New());
3855     ret->alloc(nbTuples,1);
3856     mcIdType *retPt(ret->getPointer());
3857     std::map<mcIdType,mcIdType> m;
3858     for(mcIdType i=0;i<thisNbTuples;i++,thisPt++)
3859       m[ToIdType(*thisPt)]=i;
3860     if(ToIdType(m.size())!=thisNbTuples)
3861       throw INTERP_KERNEL::Exception("DataArrayInt::indicesOfSubPart : some elements appears more than once !");
3862     for(mcIdType i=0;i<nbTuples;i++,retPt++,pt++)
3863       {
3864         std::map<mcIdType,mcIdType>::const_iterator it(m.find(ToIdType(*pt)));
3865         if(it!=m.end())
3866           *retPt=(*it).second;
3867         else
3868           {
3869             std::ostringstream oss; oss << "DataArrayInt::indicesOfSubPart : At pos #" << i << " of input array value is " << *pt << " not in this !";
3870             throw INTERP_KERNEL::Exception(oss.str());
3871           }
3872       }
3873     return ret.retn();
3874   }
3875
3876   /*!
3877    * Checks that \a this array is consistently **increasing** or **decreasing** in value.
3878    * If not an exception is thrown.
3879    *  \param [in] increasing - if \a true, the array values should be increasing.
3880    *  \throw If sequence of values is not strictly monotonic in agreement with \a
3881    *         increasing arg.
3882    *  \throw If \a this->getNumberOfComponents() != 1.
3883    *  \throw If \a this is not allocated.
3884    */
3885   template<class T>
3886   void DataArrayDiscrete<T>::checkMonotonic(bool increasing) const
3887   {
3888     if(!isMonotonic(increasing))
3889       {
3890         if (increasing)
3891           throw INTERP_KERNEL::Exception("DataArrayInt::checkMonotonic : 'this' is not INCREASING monotonic !");
3892         else
3893           throw INTERP_KERNEL::Exception("DataArrayInt::checkMonotonic : 'this' is not DECREASING monotonic !");
3894       }
3895   }
3896
3897   /*!
3898    * Checks that \a this array is consistently **increasing** or **decreasing** in value.
3899    *  \param [in] increasing - if \a true, array values should be increasing.
3900    *  \return bool - \a true if values change in accordance with \a increasing arg.
3901    *  \throw If \a this->getNumberOfComponents() != 1.
3902    *  \throw If \a this is not allocated.
3903    */
3904   template<class T>
3905   bool DataArrayDiscrete<T>::isMonotonic(bool increasing) const
3906   {
3907     this->checkAllocated();
3908     if(this->getNumberOfComponents()!=1)
3909       throw INTERP_KERNEL::Exception("DataArrayInt::isMonotonic : only supported with 'this' array with ONE component !");
3910     std::size_t nbOfElements(this->getNumberOfTuples());
3911     const T *ptr(this->begin());
3912     if(nbOfElements==0)
3913       return true;
3914     T ref(ptr[0]);
3915     if(increasing)
3916       {
3917         for(std::size_t i=1;i<nbOfElements;i++)
3918           {
3919             if(ptr[i]>=ref)
3920               ref=ptr[i];
3921             else
3922               return false;
3923           }
3924       }
3925     else
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     return true;
3936   }
3937
3938   /*!
3939    * This method check that array consistently INCREASING or DECREASING in value.
3940    */
3941   template<class T>
3942   bool DataArrayDiscrete<T>::isStrictlyMonotonic(bool increasing) const
3943   {
3944     this->checkAllocated();
3945     if(this->getNumberOfComponents()!=1)
3946       throw INTERP_KERNEL::Exception("DataArrayInt::isStrictlyMonotonic : only supported with 'this' array with ONE component !");
3947     std::size_t nbOfElements(this->getNumberOfTuples());
3948     const T *ptr(this->begin());
3949     if(nbOfElements==0)
3950       return true;
3951     T ref(ptr[0]);
3952     if(increasing)
3953       {
3954         for(std::size_t i=1;i<nbOfElements;i++)
3955           {
3956             if(ptr[i]>ref)
3957               ref=ptr[i];
3958             else
3959               return false;
3960           }
3961       }
3962     else
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     return true;
3973   }
3974
3975   /*!
3976    * This method check that array consistently INCREASING or DECREASING in value.
3977    */
3978   template<class T>
3979   void DataArrayDiscrete<T>::checkStrictlyMonotonic(bool increasing) const
3980   {
3981     if(!isStrictlyMonotonic(increasing))
3982       {
3983         if (increasing)
3984           throw INTERP_KERNEL::Exception("DataArrayInt::checkStrictlyMonotonic : 'this' is not strictly INCREASING monotonic !");
3985         else
3986           throw INTERP_KERNEL::Exception("DataArrayInt::checkStrictlyMonotonic : 'this' is not strictly DECREASING monotonic !");
3987       }
3988   }
3989
3990   /*!
3991    * Returns an integer value characterizing \a this array, which is useful for a quick
3992    * comparison of many instances of DataArrayInt.
3993    *  \return mcIdType - the hash value.
3994    *  \throw If \a this is not allocated.
3995    */
3996   template<class T>
3997   mcIdType DataArrayDiscrete<T>::getHashCode() const
3998   {
3999     this->checkAllocated();
4000     mcIdType nbOfElems=ToIdType(this->getNbOfElems());
4001     mcIdType ret=nbOfElems*65536;
4002     mcIdType delta=3;
4003     if(nbOfElems>48)
4004       delta=nbOfElems/8;
4005     T ret0(0);
4006     const T *pt(this->begin());
4007     for(mcIdType i=0;i<nbOfElems;i+=delta)
4008       ret0+=pt[i] & 0x1FFF;
4009     return ToIdType(ret+ret0);
4010   }
4011
4012   template<class T>
4013   void DataArrayDiscrete<T>::reprCppStream(const std::string& varName, std::ostream& stream) const
4014   {
4015     mcIdType nbTuples(this->getNumberOfTuples());
4016     std::size_t nbComp(this->getNumberOfComponents());
4017     const T *data(this->getConstPointer());
4018     stream << Traits<T>::ArrayTypeName << " *" << varName << "=" << Traits<T>::ArrayTypeName << "::New();" << std::endl;
4019     if(nbTuples*nbComp>=1)
4020       {
4021         stream << "const mcIdType " << varName << "Data[" << nbTuples*nbComp << "]={";
4022         std::copy(data,data+nbTuples*nbComp-1,std::ostream_iterator<T>(stream,","));
4023         stream << data[nbTuples*nbComp-1] << "};" << std::endl;
4024         stream << varName << "->useArray(" << varName << "Data,false,CPP_DEALLOC," << nbTuples << "," << nbComp << ");" << std::endl;
4025       }
4026     else
4027       stream << varName << "->alloc(" << nbTuples << "," << nbComp << ");" << std::endl;
4028     stream << varName << "->setName(\"" << this->getName() << "\");" << std::endl;
4029   }
4030
4031   /*!
4032    * Method that gives a quick overvien of \a this for python.
4033    */
4034   template<class T>
4035   void DataArrayDiscrete<T>::reprQuickOverview(std::ostream& stream) const
4036   {
4037     static const std::size_t MAX_NB_OF_BYTE_IN_REPR=300;
4038     stream << Traits<T>::ArrayTypeName << " C++ instance at " << this << ". ";
4039     if(this->isAllocated())
4040       {
4041         std::size_t nbOfCompo(this->getNumberOfComponents());
4042         if(nbOfCompo>=1)
4043           {
4044             mcIdType nbOfTuples(this->getNumberOfTuples());
4045             stream << "Number of tuples : " << nbOfTuples << ". Number of components : " << nbOfCompo << "." << std::endl;
4046             reprQuickOverviewData(stream,MAX_NB_OF_BYTE_IN_REPR);
4047           }
4048         else
4049           stream << "Number of components : 0.";
4050       }
4051     else
4052       stream << "*** No data allocated ****";
4053   }
4054
4055   template<class T>
4056   void DataArrayDiscrete<T>::reprQuickOverviewData(std::ostream& stream, std::size_t maxNbOfByteInRepr) const
4057   {
4058     const T *data(this->begin());
4059     mcIdType nbOfTuples(this->getNumberOfTuples());
4060     std::size_t nbOfCompo(this->getNumberOfComponents());
4061     std::ostringstream oss2; oss2 << "[";
4062     std::string oss2Str(oss2.str());
4063     bool isFinished=true;
4064     for(mcIdType i=0;i<nbOfTuples && isFinished;i++)
4065       {
4066         if(nbOfCompo>1)
4067           {
4068             oss2 << "(";
4069             for(std::size_t j=0;j<nbOfCompo;j++,data++)
4070               {
4071                 oss2 << *data;
4072                 if(j!=nbOfCompo-1) oss2 << ", ";
4073               }
4074             oss2 << ")";
4075           }
4076         else
4077           oss2 << *data++;
4078         if(i!=nbOfTuples-1) oss2 << ", ";
4079         std::string oss3Str(oss2.str());
4080         if(oss3Str.length()<maxNbOfByteInRepr)
4081           oss2Str=oss3Str;
4082         else
4083           isFinished=false;
4084       }
4085     stream << oss2Str;
4086     if(!isFinished)
4087       stream << "... ";
4088     stream << "]";
4089   }
4090
4091   template<class T>
4092   void DataArrayDiscrete<T>::writeVTK(std::ostream& ofs, mcIdType indent, const std::string& type, const std::string& nameInFile, DataArrayByte *byteArr) const
4093   {
4094     static const char SPACE[4]={' ',' ',' ',' '};
4095     this->checkAllocated();
4096     std::string idt(indent,' ');
4097     ofs << idt << "<DataArray type=\"" << type << "\" Name=\"" << nameInFile << "\" NumberOfComponents=\"" << this->getNumberOfComponents() << "\"";
4098     if(byteArr)
4099       {
4100         ofs << " format=\"appended\" offset=\"" << byteArr->getNumberOfTuples() << "\">";
4101         if(std::string(type)==Traits<T>::VTKReprStr)
4102           {
4103             const char *data(reinterpret_cast<const char *>(this->begin()));
4104             std::size_t sz(this->getNbOfElems()*sizeof(T));
4105             byteArr->insertAtTheEnd(data,data+sz);
4106             byteArr->insertAtTheEnd(SPACE,SPACE+4);
4107           }
4108         else if(std::string(type)=="Int8")
4109           {
4110             INTERP_KERNEL::AutoPtr<char> tmp(new char[this->getNbOfElems()]);
4111             copyCast(this->begin(),this->end(),(char *)tmp);
4112             byteArr->insertAtTheEnd((char *)tmp,(char *)tmp+this->getNbOfElems());
4113             byteArr->insertAtTheEnd(SPACE,SPACE+4);
4114           }
4115         else if(std::string(type)=="UInt8")
4116           {
4117             INTERP_KERNEL::AutoPtr<unsigned char> tmp(new unsigned char[this->getNbOfElems()]);
4118             copyCast(this->begin(),this->end(),(unsigned char *)tmp);
4119             byteArr->insertAtTheEnd((unsigned char *)tmp,(unsigned char *)tmp+this->getNbOfElems());
4120             byteArr->insertAtTheEnd(SPACE,SPACE+4);
4121           }
4122         else
4123           {
4124             std::ostringstream oss;
4125             oss << Traits<T>::ArrayTypeName << "::writeVTK : Only " << Traits<T>::VTKReprStr << ", Int8 and UInt8 supported !";
4126             throw INTERP_KERNEL::Exception(oss.str());
4127           }
4128       }
4129     else
4130       {
4131         ofs << " RangeMin=\"" << this->getMinValueInArray() << "\" RangeMax=\"" << this->getMaxValueInArray() << "\" format=\"ascii\">\n" << idt;
4132         std::copy(this->begin(),this->end(),std::ostream_iterator<T>(ofs," "));
4133       }
4134       ofs << std::endl << idt << "</DataArray>\n";
4135   }
4136
4137   /*!
4138    * Modifies in place \a this one-dimensional array so that each value \a v = \a indArrBg[ \a v ],
4139    * i.e. a current value is used as in index to get a new value from \a indArrBg.
4140    *  \param [in] indArrBg - pointer to the first element of array of new values to assign
4141    *         to \a this array.
4142    *  \param [in] indArrEnd - specifies the end of the array \a indArrBg, so that
4143    *              the last value of \a indArrBg is \a indArrEnd[ -1 ].
4144    *  \throw If \a this->getNumberOfComponents() != 1
4145    *  \throw If any value of \a this can't be used as a valid index for
4146    *         [\a indArrBg, \a indArrEnd).
4147    *
4148    *  \sa changeValue, findIdForEach
4149    */
4150   template<class T>
4151   void DataArrayDiscrete<T>::transformWithIndArr(const T *indArrBg, const T *indArrEnd)
4152   {
4153     this->checkAllocated();
4154     if(this->getNumberOfComponents()!=1)
4155       throw INTERP_KERNEL::Exception("Call transformWithIndArr method on DataArrayInt with only one component, you can call 'rearrange' method before !");
4156     mcIdType nbElemsIn=ToIdType(std::distance(indArrBg,indArrEnd));
4157     mcIdType nbOfTuples(this->getNumberOfTuples());
4158     T *pt(this->getPointer());
4159     for(mcIdType i=0;i<nbOfTuples;i++,pt++)
4160       {
4161         if(*pt>=0 && *pt<nbElemsIn)
4162           *pt=indArrBg[*pt];
4163         else
4164           {
4165             std::ostringstream oss; oss << "DataArrayInt::transformWithIndArr : error on tuple #" << i << " of this value is " << *pt << ", should be in [0," << nbElemsIn << ") !";
4166             throw INTERP_KERNEL::Exception(oss.str());
4167           }
4168       }
4169     this->declareAsNew();
4170   }
4171
4172   template<class T>
4173   void DataArrayDiscrete<T>::transformWithIndArr(const MapKeyVal<T, T>& m)
4174   {
4175     this->checkAllocated();
4176     if(this->getNumberOfComponents()!=1)
4177       throw INTERP_KERNEL::Exception("Call transformWithIndArr method on DataArrayInt with only one component, you can call 'rearrange' method before !");
4178     const typename std::map<T,T>& dat(m.data());
4179     mcIdType nbOfTuples(this->getNumberOfTuples());
4180     T *pt(this->getPointer());
4181     for(mcIdType i=0;i<nbOfTuples;i++,pt++)
4182       {
4183         typename std::map<T,T>::const_iterator it(dat.find(*pt));
4184         if(it!=dat.end())
4185           *pt=(*it).second;
4186         else
4187           {
4188             std::ostringstream oss; oss << "DataArrayInt::transformWithIndArr : error on tuple #" << i << " of this value is " << *pt << " not in map !";
4189             throw INTERP_KERNEL::Exception(oss.str());
4190           }
4191       }
4192     this->declareAsNew();
4193   }
4194
4195   /*!
4196    * Creates a new DataArrayInt containing IDs (indices) of tuples holding value equal to a
4197    * given one. The ids are sorted in the ascending order.
4198    *  \param [in] val - the value to find within \a this.
4199    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
4200    *          array using decrRef() as it is no more needed.
4201    *  \throw If \a this is not allocated.
4202    *  \throw If \a this->getNumberOfComponents() != 1.
4203    *  \sa DataArrayInt::findIdsEqualTuple
4204    */
4205   template<class T>
4206   DataArrayIdType *DataArrayDiscrete<T>::findIdsEqual(T val) const
4207   {
4208     this->checkAllocated();
4209     if(this->getNumberOfComponents()!=1)
4210       throw INTERP_KERNEL::Exception("DataArrayInt::findIdsEqual : the array must have only one component, you can call 'rearrange' method before !");
4211     const T *cptr(this->getConstPointer());
4212     MCAuto<DataArrayIdType> ret(DataArrayIdType::New()); ret->alloc(0,1);
4213     mcIdType nbOfTuples(this->getNumberOfTuples());
4214     for(mcIdType i=0;i<nbOfTuples;i++,cptr++)
4215       if(*cptr==val)
4216         ret->pushBackSilent(ToIdType(i));
4217     return ret.retn();
4218   }
4219
4220   /*!
4221    * Creates a one-dimensional DataArrayInt (\a res) whose contents are computed from
4222    * values of \a this (\a a) and the given (\a indArr) arrays as follows:
4223    * \a res[ \a indArr[ \a a[ i ]]] = i. I.e. for each value in place i \a v = \a a[ i ],
4224    * new value in place \a indArr[ \a v ] is i.
4225    *  \param [in] indArrBg - the array holding indices within the result array to assign
4226    *         indices of values of \a this array pointing to values of \a indArrBg.
4227    *  \param [in] indArrEnd - specifies the end of the array \a indArrBg, so that
4228    *              the last value of \a indArrBg is \a indArrEnd[ -1 ].
4229    *  \return DataArrayInt * - the new instance of DataArrayInt.
4230    *          The caller is to delete this result array using decrRef() as it is no more
4231    *          needed.
4232    *  \throw If \a this->getNumberOfComponents() != 1.
4233    *  \throw If any value of \a this array is not a valid index for \a indArrBg array.
4234    *  \throw If any value of \a indArrBg is not a valid index for \a this array.
4235    */
4236   template<class T>
4237   DataArrayIdType *DataArrayDiscrete<T>::transformWithIndArrR(const T *indArrBg, const T *indArrEnd) const
4238   {
4239     this->checkAllocated();
4240     if(this->getNumberOfComponents()!=1)
4241       throw INTERP_KERNEL::Exception("Call transformWithIndArrR method on DataArrayInt with only one component, you can call 'rearrange' method before !");
4242     mcIdType nbElemsIn=ToIdType(std::distance(indArrBg,indArrEnd));
4243     mcIdType nbOfTuples(this->getNumberOfTuples());
4244     const T *pt=this->getConstPointer();
4245     MCAuto<DataArrayIdType> ret=DataArrayIdType::New();
4246     ret->alloc(nbOfTuples,1);
4247     ret->fillWithValue(-1);
4248     mcIdType *tmp=ret->getPointer();
4249     for(mcIdType i=0;i<nbOfTuples;i++,pt++)
4250       {
4251         if(*pt>=0 && *pt<nbElemsIn)
4252           {
4253             T pos=indArrBg[*pt];
4254             if(pos>=0 && pos<nbOfTuples)
4255               tmp[ToIdType(pos)]=i;
4256             else
4257               {
4258                 std::ostringstream oss; oss << "DataArrayInt::transformWithIndArrR : error on tuple #" << i << " value of new pos is " << pos << " ( indArrBg[" << *pt << "]) ! Should be in [0," << nbOfTuples << ") !";
4259                 throw INTERP_KERNEL::Exception(oss.str().c_str());
4260               }
4261           }
4262         else
4263           {
4264             std::ostringstream oss; oss << "DataArrayInt::transformWithIndArrR : error on tuple #" << i << " value is " << *pt << " and indirectionnal array as a size equal to " << nbElemsIn << " !";
4265             throw INTERP_KERNEL::Exception(oss.str().c_str());
4266           }
4267       }
4268     return ret.retn();
4269   }
4270
4271   /*!
4272    * Computes distribution of values of \a this one-dimensional array between given value
4273    * ranges (casts). This method is typically useful for entity number splitting by types,
4274    * for example. 
4275    *  \warning The values contained in \a arrBg should be sorted ascendently. No
4276    *           check of this is be done. If not, the result is not warranted. 
4277    *  \param [in] arrBg - the array of ascending values defining the value ranges. The i-th
4278    *         value of \a arrBg (\a arrBg[ i ]) gives the lowest value of the i-th range,
4279    *         and the greatest value of the i-th range equals to \a arrBg[ i+1 ] - 1. \a
4280    *         arrBg containing \a n values defines \a n-1 ranges. The last value of \a arrBg
4281    *         should be more than every value in \a this array.
4282    *  \param [in] arrEnd - specifies the end of the array \a arrBg, so that
4283    *              the last value of \a arrBg is \a arrEnd[ -1 ].
4284    *  \param [out] castArr - a new instance of DataArrayInt, of same size as \a this array
4285    *         (same number of tuples and components), the caller is to delete
4286    *         using decrRef() as it is no more needed.
4287    *         This array contains indices of ranges for every value of \a this array. I.e.
4288    *         the i-th value of \a castArr gives the index of range the i-th value of \a this
4289    *         belongs to. Or, in other words, this parameter contains for each tuple in \a
4290    *         this in which cast it holds.
4291    *  \param [out] rankInsideCast - a new instance of DataArrayInt, of same size as \a this
4292    *         array, the caller is to delete using decrRef() as it is no more needed.
4293    *         This array contains ranks of values of \a this array within ranges
4294    *         they belongs to. I.e. the i-th value of \a rankInsideCast gives the rank of
4295    *         the i-th value of \a this array within the \a castArr[ i ]-th range, to which
4296    *         the i-th value of \a this belongs to. Or, in other words, this param contains
4297    *         for each tuple its rank inside its cast. The rank is computed as difference
4298    *         between the value and the lowest value of range.
4299    *  \param [out] castsPresent - a new instance of DataArrayInt, containing indices of
4300    *         ranges (casts) to which at least one value of \a this array belongs.
4301    *         Or, in other words, this param contains the casts that \a this contains.
4302    *         The caller is to delete this array using decrRef() as it is no more needed.
4303    *
4304    * \b Example: If \a this contains [6,5,0,3,2,7,8,1,4] and \a arrBg contains [0,4,9] then
4305    *            the output of this method will be :
4306    * - \a castArr       : [1,1,0,0,0,1,1,0,1]
4307    * - \a rankInsideCast: [2,1,0,3,2,3,4,1,0]
4308    * - \a castsPresent  : [0,1]
4309    *
4310    * I.e. values of \a this array belong to 2 ranges: #0 and #1. Value 6 belongs to the
4311    * range #1 and its rank within this range is 2; etc.
4312    *
4313    *  \throw If \a this->getNumberOfComponents() != 1.
4314    *  \throw If \a arrEnd - arrBg < 2.
4315    *  \throw If any value of \a this is not less than \a arrEnd[-1].
4316    */
4317   template<class T>
4318   void DataArrayDiscrete<T>::splitByValueRange(const T *arrBg, const T *arrEnd,
4319                                                DataArrayType *& castArr, DataArrayType *& rankInsideCast, DataArrayType *& castsPresent) const
4320   {
4321     this->checkAllocated();
4322     if(this->getNumberOfComponents()!=1)
4323       throw INTERP_KERNEL::Exception("Call splitByValueRange  method on DataArrayInt with only one component, you can call 'rearrange' method before !");
4324     mcIdType nbOfTuples=this->getNumberOfTuples();
4325     std::size_t nbOfCast=std::distance(arrBg,arrEnd);
4326     if(nbOfCast<2)
4327       throw INTERP_KERNEL::Exception("DataArrayInt::splitByValueRange : The input array giving the cast range values should be of size >=2 !");
4328     nbOfCast--;
4329     const T *work=this->getConstPointer();
4330     typedef std::reverse_iterator<const T *> rintstart;
4331     rintstart bg(arrEnd);//OK no problem because size of 'arr' is greater or equal 2
4332     rintstart end2(arrBg);
4333     MCAuto<DataArrayType> ret1=DataArrayType::New();
4334     MCAuto<DataArrayType> ret2=DataArrayType::New();
4335     MCAuto<DataArrayType> ret3=DataArrayType::New();
4336     ret1->alloc(nbOfTuples,1);
4337     ret2->alloc(nbOfTuples,1);
4338     T *ret1Ptr=ret1->getPointer();
4339     T *ret2Ptr=ret2->getPointer();
4340     std::set<T> castsDetected;
4341     for(mcIdType i=0;i<nbOfTuples;i++)
4342       {
4343         rintstart res=std::find_if(bg,end2,std::bind(std::less_equal<T>(),std::placeholders::_1,work[i]));
4344         std::size_t pos=std::distance(bg,res);
4345         std::size_t pos2=nbOfCast-pos;
4346         if(pos2<nbOfCast)
4347           {
4348             ret1Ptr[i]=static_cast<T>(pos2);
4349             ret2Ptr[i]=work[i]-arrBg[pos2];
4350             castsDetected.insert(ret1Ptr[i]);
4351           }
4352         else
4353           {
4354             std::ostringstream oss; oss << "DataArrayInt::splitByValueRange : At rank #" << i << " the value is " << work[i] << " should be in [0," << *bg << ") !";
4355             throw INTERP_KERNEL::Exception(oss.str().c_str());
4356           }
4357       }
4358     ret3->alloc(castsDetected.size(),1);
4359     std::copy(castsDetected.begin(),castsDetected.end(),ret3->getPointer());
4360     castArr=ret1.retn();
4361     rankInsideCast=ret2.retn();
4362     castsPresent=ret3.retn();
4363   }
4364
4365   /*!
4366    * 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 ).
4367    * 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 ).
4368    * This method works only if \a this is allocated and single component. If not an exception will be thrown.
4369    *
4370    * \param [out] strt - the start of the range (included) if true is returned.
4371    * \param [out] sttoopp - the end of the range (not included) if true is returned.
4372    * \param [out] stteepp - the step of the range if true is returned.
4373    * \return the verdict of the check.
4374    *
4375    * \sa DataArray::GetNumberOfItemGivenBES
4376    */
4377   template<class T>
4378   bool DataArrayDiscrete<T>::isRange(T& strt, T& sttoopp, T& stteepp) const
4379   {
4380     this->checkAllocated();
4381     if(this->getNumberOfComponents()!=1)
4382       throw INTERP_KERNEL::Exception("DataArrayInt::isRange : this must be single component array !");
4383     mcIdType nbTuples(this->getNumberOfTuples());
4384     if(nbTuples==0)
4385       { strt=0; sttoopp=0; stteepp=1; return true; }
4386     const T *pt(this->begin());
4387     strt=*pt;
4388     if(nbTuples==1)
4389       { sttoopp=strt+1; stteepp=1; return true; }
4390     strt=*pt; sttoopp=pt[nbTuples-1];
4391     if(strt==sttoopp)
4392       return false;
4393     if(sttoopp>strt)
4394       {
4395         sttoopp++;
4396         T a(sttoopp-1-strt),tmp(strt);
4397         if(a%(nbTuples-1)!=0)
4398           return false;
4399         stteepp=a/(FromIdType<T>(nbTuples)-1);
4400         for(mcIdType i=0;i<nbTuples;i++,tmp+=stteepp)
4401           if(pt[i]!=tmp)
4402             return false;
4403         return true;
4404       }
4405     else
4406       {
4407         sttoopp--;
4408         T a(strt-sttoopp-1),tmp(strt);
4409         if(a%(nbTuples-1)!=0)
4410           return false;
4411         stteepp=-(a/(FromIdType<T>(nbTuples)-1));
4412         for(mcIdType i=0;i<nbTuples;i++,tmp+=stteepp)
4413           if(pt[i]!=tmp)
4414             return false;
4415         return true;
4416       }
4417   }
4418
4419   /*!
4420    * Creates a one-dimensional DataArrayInt of given length, whose contents are computed
4421    * from values of \a this array, which is supposed to contain a renumbering map in
4422    * "Old to New" mode. The result array contains a renumbering map in "New to Old" mode.
4423    * To know how to use the renumbering maps see \ref numbering.
4424    *  \param [in] newNbOfElem - the number of tuples in the result array.
4425    *  \return DataArrayInt * - the new instance of DataArrayInt.
4426    *          The caller is to delete this result array using decrRef() as it is no more
4427    *          needed.
4428    *
4429    *  \if ENABLE_EXAMPLES
4430    *  \ref cpp_mcdataarrayint_invertarrayo2n2n2o "Here is a C++ example".<br>
4431    *  \ref py_mcdataarrayint_invertarrayo2n2n2o  "Here is a Python example".
4432    *  \endif
4433    */
4434   template<class T>
4435   DataArrayIdType * DataArrayDiscrete<T>::invertArrayO2N2N2O(mcIdType newNbOfElem) const
4436   {
4437     MCAuto<DataArrayIdType> ret(DataArrayIdType::New());
4438     ret->alloc(newNbOfElem,1);
4439     mcIdType nbOfOldNodes(this->getNumberOfTuples());
4440     const T *old2New(this->begin());
4441     mcIdType *pt(ret->getPointer());
4442     for(mcIdType i=0;i!=nbOfOldNodes;i++)
4443       {
4444         T newp(old2New[i]);
4445         if(newp!=-1)
4446           {
4447             if(newp>=0 && newp<newNbOfElem)
4448               pt[newp]=i;
4449             else
4450               {
4451                 std::ostringstream oss; oss << "DataArrayInt::invertArrayO2N2N2O : At place #" << i << " the newplace is " << newp << " must be in [0," << newNbOfElem << ") !";
4452                 throw INTERP_KERNEL::Exception(oss.str().c_str());
4453               }
4454           }
4455       }
4456     return ret.retn();
4457   }
4458
4459   /*!
4460    * Creates a one-dimensional DataArrayInt of given length, whose contents are computed
4461    * from values of \a this array, which is supposed to contain a renumbering map in
4462    * "New to Old" mode. The result array contains a renumbering map in "Old to New" mode.
4463    * To know how to use the renumbering maps see \ref numbering.
4464    *  \param [in] oldNbOfElem - the number of tuples in the result array.
4465    *  \return DataArrayInt * - the new instance of DataArrayInt.
4466    *          The caller is to delete this result array using decrRef() as it is no more
4467    *          needed.
4468    *
4469    *  \if ENABLE_EXAMPLES
4470    *  \ref cpp_mcdataarrayint_invertarrayn2o2o2n "Here is a C++ example".
4471    *
4472    *  \ref py_mcdataarrayint_invertarrayn2o2o2n "Here is a Python example".
4473    *  \sa invertArrayN2O2O2NOptimized
4474    *  \endif
4475    */
4476   template <class T>
4477   DataArrayIdType *DataArrayDiscrete<T>::invertArrayN2O2O2N(mcIdType oldNbOfElem) const
4478   {
4479     this->checkAllocated();
4480     MCAuto<DataArrayIdType> ret=DataArrayIdType::New();
4481     ret->alloc(oldNbOfElem,1);
4482     const T *new2Old=this->getConstPointer();
4483     mcIdType *pt=ret->getPointer();
4484     std::fill(pt,pt+oldNbOfElem,-1);
4485     mcIdType nbOfNewElems(this->getNumberOfTuples());
4486     for(mcIdType i=0;i<nbOfNewElems;i++)
4487       {
4488         T v(new2Old[i]);
4489         if(v>=0 && v<oldNbOfElem)
4490           pt[v]=i;
4491         else
4492           {
4493             std::ostringstream oss; oss << "DataArrayInt::invertArrayN2O2O2N : in new id #" << i << " old value is " << v << " expected to be in [0," << oldNbOfElem << ") !";
4494             throw INTERP_KERNEL::Exception(oss.str().c_str());
4495           }
4496       }
4497     return ret.retn();
4498   }
4499
4500   /*!
4501    * This method is similar to DataArrayInt::invertArrayO2N2N2O except that
4502    * 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]
4503    */
4504   template <class T>
4505   DataArrayIdType *DataArrayDiscrete<T>::invertArrayO2N2N2OBis(mcIdType newNbOfElem) const
4506   {
4507     MCAuto<DataArrayIdType> ret=DataArrayIdType::New();
4508     ret->alloc(newNbOfElem,1);
4509     mcIdType nbOfOldNodes(this->getNumberOfTuples());
4510     const T *old2New=this->getConstPointer();
4511     mcIdType *pt=ret->getPointer();
4512     for(mcIdType i=nbOfOldNodes-1;i>=0;i--)
4513       {
4514         T newp(old2New[i]);
4515         if(newp!=-1)
4516           {
4517             if(newp>=0 && newp<newNbOfElem)
4518               pt[newp]=i;
4519             else
4520               {
4521                 std::ostringstream oss; oss << "DataArrayInt::invertArrayO2N2N2OBis : At place #" << i << " the newplace is " << newp << " must be in [0," << newNbOfElem << ") !";
4522                 throw INTERP_KERNEL::Exception(oss.str().c_str());
4523               }
4524           }
4525       }
4526     return ret.retn();
4527   }
4528
4529   /*!
4530    * Creates a map, whose contents are computed
4531    * from values of \a this array, which is supposed to contain a renumbering map in
4532    * "New to Old" mode. The result array contains a renumbering map in "Old to New" mode.
4533    * To know how to use the renumbering maps see \ref numbering.
4534    *  \return MapII  - the new instance of Map.
4535    *
4536    *  \if ENABLE_EXAMPLES
4537    *  \ref cpp_mcdataarrayint_invertarrayn2o2o2n "Here is a C++ example".
4538    *
4539    *  \ref py_mcdataarrayint_invertarrayn2o2o2n "Here is a Python example".
4540    *  \sa invertArrayN2O2O2N, giveN2OOptimized, MEDCouplingPointSet::renumberNodesInConn
4541    *  \endif
4542    */
4543   template <class T>
4544   MCAuto< MapKeyVal<T, mcIdType> > DataArrayDiscrete<T>::invertArrayN2O2O2NOptimized() const
4545   {
4546     this->checkAllocated();
4547     if(this->getNumberOfComponents()!=1)
4548       throw INTERP_KERNEL::Exception("DataArrayInt::invertArrayN2O2O2NOptimized : single component expected !");
4549     MCAuto< MapKeyVal<T, mcIdType> > ret(MapKeyVal<T, mcIdType>::New());
4550     std::map<T, mcIdType>& m(ret->data());
4551     const T *new2Old(this->begin());
4552     mcIdType nbOfNewElems(this->getNumberOfTuples());
4553     for(mcIdType i=0;i<nbOfNewElems;i++)
4554       {
4555         T v(new2Old[i]);
4556         m[v]=i;
4557       }
4558     return ret;
4559   }
4560
4561   /*!
4562    * Creates a map, whose contents are computed
4563    * from values of \a this array, which is supposed to contain a renumbering map in 
4564    * "New to Old" mode. The result array contains a renumbering map in "New to Old" mode as C++ map for performance reasons.
4565    *
4566    * \sa invertArrayN2O2O2NOptimized, MEDCouplingPointSet::renumberNodesInConn
4567    */
4568   template <class T>
4569   MCAuto< MapKeyVal<mcIdType, T> > DataArrayDiscrete<T>::giveN2OOptimized() const
4570   {
4571     this->checkAllocated();
4572     if(this->getNumberOfComponents()!=1)
4573       throw INTERP_KERNEL::Exception("DataArrayInt::giveN2OOptimized : single component expected !");
4574     MCAuto< MapKeyVal<mcIdType, T> > ret(MapKeyVal<mcIdType, T>::New());
4575     std::map<mcIdType,T>& m(ret->data());
4576     const T *new2Old(this->begin());
4577     mcIdType nbOfNewElems(this->getNumberOfTuples());
4578     for(mcIdType i=0;i<nbOfNewElems;i++)
4579       {
4580         T v(new2Old[i]);
4581         m[i]=v;
4582       }
4583     return ret;
4584   }
4585
4586   /*!
4587    * This method finds for each element \a ELT in [valsBg,valsEnd) elements in \a this equal to it. Associated to ELT
4588    * this method will return the tuple id of last element found. If there is no element in \a this equal to ELT
4589    * an exception will be thrown.
4590    *
4591    * In case of success this[ret]==vals. Samely ret->transformWithIndArr(this->begin(),this->end())==vals.
4592    * Where \a vals is the [valsBg,valsEnd) array and \a ret the array returned by this method.
4593    * This method can be seen as an extension of FindPermutationFromFirstToSecond.
4594    * <br>
4595    * \b Example: <br>
4596    * - \a this: [17,27,2,10,-4,3,12,27,16]
4597    * - \a val : [3,16,-4,27,17]
4598    * - result: [5,8,4,7,0]
4599    *
4600    * \return - An array of size std::distance(valsBg,valsEnd)
4601    *
4602    * \sa DataArrayInt::FindPermutationFromFirstToSecond , DataArrayInt::FindPermutationFromFirstToSecondDuplicate
4603    */
4604   template <class T>
4605   MCAuto<DataArrayIdType> DataArrayDiscrete<T>::findIdForEach(const T *valsBg, const T *valsEnd) const
4606   {
4607     MCAuto<DataArrayIdType> ret(DataArrayIdType::New());
4608     std::size_t nbOfTuplesOut(std::distance(valsBg,valsEnd));
4609     ret->alloc(nbOfTuplesOut,1);
4610     MCAuto< MapKeyVal<T, mcIdType> > zeMap(this->invertArrayN2O2O2NOptimized());
4611     const std::map<T, mcIdType>& dat(zeMap->data());
4612     mcIdType *ptToFeed(ret->getPointer());
4613     for(const T *pt=valsBg;pt!=valsEnd;pt++)
4614       {
4615         typename std::map<T,mcIdType>::const_iterator it(dat.find(*pt));
4616         if(it!=dat.end())
4617           *ptToFeed++=(*it).second;
4618         else
4619           {
4620             std::ostringstream oss; oss << "DataArrayInt::findIdForEach : error for element at place " << std::distance(valsBg,pt);
4621             oss << " of input array value is " << *pt << " which is not in this !";
4622             throw INTERP_KERNEL::Exception(oss.str());
4623           }
4624       }
4625     return ret;
4626   }
4627
4628   /*!
4629    * Returns a new DataArrayInt containing a renumbering map in "Old to New" mode.
4630    * This map, if applied to \a this array, would make it sorted. For example, if
4631    * \a this array contents are [9,10,0,6,4,11,3,7] then the contents of the result array
4632    * are [5,6,0,3,2,7,1,4]; if this result array (\a res) is used as an argument in call
4633    * \a this->renumber(\a res) then the returned array contains [0,3,4,6,7,9,10,11].
4634    * This method is useful for renumbering (in MED file for example). For more info
4635    * on renumbering see \ref numbering.
4636    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
4637    *          array using decrRef() as it is no more needed.
4638    *  \throw If \a this is not allocated.
4639    *  \throw If \a this->getNumberOfComponents() != 1.
4640    *  \throw If there are equal values in \a this array.
4641    */
4642   template <class T>
4643   DataArrayIdType *DataArrayDiscrete<T>::checkAndPreparePermutation() const
4644   {
4645     this->checkAllocated();
4646     if(this->getNumberOfComponents()!=1)
4647       throw INTERP_KERNEL::Exception("DataArrayInt::checkAndPreparePermutation : number of components must == 1 !");
4648     mcIdType nbTuples(this->getNumberOfTuples());
4649     const T *pt=this->getConstPointer();
4650     mcIdType *pt2=this->CheckAndPreparePermutation(pt,pt+nbTuples);
4651     DataArrayIdType *ret=DataArrayIdType::New();
4652     ret->useArray(pt2,true,DeallocType::C_DEALLOC,nbTuples,1);
4653     return ret;
4654   }
4655
4656   /*!
4657    * Returns two arrays describing a surjective mapping from \a this set of values (\a A)
4658    * onto a set of values of size \a targetNb (\a B). The surjective function is
4659    * \a B[ \a A[ i ]] = i. That is to say that for each \a id in [0,\a targetNb), where \a
4660    * targetNb < \a this->getNumberOfTuples(), there exists at least one tupleId (\a tid) so
4661    * that <em> this->getIJ( tid, 0 ) == id</em>. <br>
4662    * The first of out arrays returns indices of elements of \a this array, grouped by their
4663    * place in the set \a B. The second out array is the index of the first one; it shows how
4664    * many elements of \a A are mapped into each element of \a B. <br>
4665    * For more info on
4666    * mapping and its usage in renumbering see \ref numbering. <br>
4667    * \b Example:
4668    * - \a this: [0,3,2,3,2,2,1,2]
4669    * - \a targetNb: 4
4670    * - \a arr:  [0,  6,  2,4,5,7,  1,3]
4671    * - \a arrI: [0,1,2,6,8]
4672    *
4673    * This result means: <br>
4674    * the element of \a B 0 encounters within \a A once (\a arrI[ 0+1 ] - \a arrI[ 0 ]) and
4675    * its index within \a A is 0 ( \a arr[ 0:1 ] == \a arr[ \a arrI[ 0 ] : \a arrI[ 0+1 ]]);<br>
4676    * the element of \a B 2 encounters within \a A 4 times (\a arrI[ 2+1 ] - \a arrI[ 2 ]) and
4677    * its indices within \a A are [2,4,5,7] ( \a arr[ 2:6 ] == \a arr[ \a arrI[ 2 ] :
4678    * \a arrI[ 2+1 ]]); <br> etc.
4679    *  \param [in] targetNb - the size of the set \a B. \a targetNb must be equal or more
4680    *         than the maximal value of \a A.
4681    *  \param [out] arr - a new instance of DataArrayInt returning indices of
4682    *         elements of \a this, grouped by their place in the set \a B. The caller is to delete
4683    *         this array using decrRef() as it is no more needed.
4684    *  \param [out] arrI - a new instance of DataArrayInt returning size of groups of equal
4685    *         elements of \a this. The caller is to delete this array using decrRef() as it
4686    *         is no more needed.
4687    *  \throw If \a this is not allocated.
4688    *  \throw If \a this->getNumberOfComponents() != 1.
4689    *  \throw If any value in \a this is more or equal to \a targetNb.
4690    */
4691   template <class T>
4692   void DataArrayDiscrete<T>::changeSurjectiveFormat(T targetNb, DataArrayIdType *&arr, DataArrayIdType *&arrI) const
4693   {
4694     this->checkAllocated();
4695     if(this->getNumberOfComponents()!=1)
4696       throw INTERP_KERNEL::Exception("DataArrayInt::changeSurjectiveFormat : number of components must == 1 !");
4697     mcIdType nbOfTuples(this->getNumberOfTuples());
4698     const T *input=this->getConstPointer();
4699     std::vector< std::vector<mcIdType> > tmp(targetNb);
4700     for(mcIdType i=0;i<nbOfTuples;i++)
4701       {
4702         T tmp2=input[i];
4703         if(tmp2>=0 && tmp2<targetNb)
4704           tmp[tmp2].push_back(i);
4705         else
4706           {
4707             std::ostringstream oss; oss << "DataArrayInt::changeSurjectiveFormat : At pos " << i << " presence of element " << tmp2 << " ! should be in [0," << targetNb << ") !";
4708             throw INTERP_KERNEL::Exception(oss.str().c_str());
4709           }
4710       }
4711
4712     MCAuto<DataArrayIdType> retI(DataArrayIdType::New());
4713     retI->alloc(targetNb+1,1);
4714     mcIdType *retIPtr=retI->getPointer();
4715     *retIPtr=0;
4716     for(std::vector< std::vector<mcIdType> >::const_iterator it1=tmp.begin();it1!=tmp.end();it1++,retIPtr++)
4717       retIPtr[1]=retIPtr[0]+ToIdType((*it1).size());
4718     if(nbOfTuples!=retI->getIJ(ToIdType(targetNb),0))
4719       throw INTERP_KERNEL::Exception("DataArrayInt::changeSurjectiveFormat : big problem should never happen !");
4720     MCAuto<DataArrayIdType> ret(DataArrayIdType::New());
4721     ret->alloc(nbOfTuples,1);
4722     mcIdType *retPtr=ret->getPointer();
4723     for(std::vector< std::vector<mcIdType> >::const_iterator it1=tmp.begin();it1!=tmp.end();it1++)
4724       retPtr=std::copy((*it1).begin(),(*it1).end(),retPtr);
4725     arr=ret.retn();
4726     arrI=retI.retn();
4727   }
4728
4729   /*!
4730    * Returns a new DataArrayInt containing a renumbering map in "New to Old" mode,
4731    * which if applied to \a this array would make it sorted ascendingly.
4732    * For more info on renumbering see \ref numbering. <br>
4733    * \b Example: <br>
4734    * - \a this: [2,0,1,1,0,1,2,0,1,1,0,0]
4735    * - result: [10,0,5,6,1,7,11,2,8,9,3,4]
4736    * - after applying result to \a this: [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2]
4737    *
4738    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
4739    *          array using decrRef() as it is no more needed.
4740    *  \throw If \a this is not allocated.
4741    *  \throw If \a this->getNumberOfComponents() != 1.
4742    */
4743   template <class T>
4744   DataArrayIdType *DataArrayDiscrete<T>::buildPermArrPerLevel() const
4745   {
4746     this->checkAllocated();
4747     if(this->getNumberOfComponents()!=1)
4748       throw INTERP_KERNEL::Exception("DataArrayInt::buildPermArrPerLevel : number of components must == 1 !");
4749     mcIdType nbOfTuples=this->getNumberOfTuples();
4750     const T *pt=this->getConstPointer();
4751     std::map<T,mcIdType> m;
4752     MCAuto<DataArrayIdType> ret=DataArrayIdType::New();
4753     ret->alloc(nbOfTuples,1);
4754     mcIdType *opt=ret->getPointer();
4755     for(mcIdType i=0;i<nbOfTuples;i++,pt++,opt++)
4756       {
4757         T val=*pt;
4758         typename std::map<T,mcIdType>::iterator it=m.find(val);
4759         if(it!=m.end())
4760           {
4761             *opt=(*it).second;
4762             (*it).second++;
4763           }
4764         else
4765           {
4766             *opt=0;
4767             m.insert(std::pair<T,mcIdType>(val,1));
4768           }
4769       }
4770     mcIdType sum=0;
4771     for(typename std::map<T,mcIdType>::iterator it=m.begin();it!=m.end();it++)
4772       {
4773         mcIdType vt=(*it).second;
4774         (*it).second=sum;
4775         sum+=vt;
4776       }
4777     pt=this->getConstPointer();
4778     opt=ret->getPointer();
4779     for(mcIdType i=0;i<nbOfTuples;i++,pt++,opt++)
4780       *opt+=m[*pt];
4781     //
4782     return ret.retn();
4783   }
4784
4785   /*!
4786    * Checks if \a this array has the given size, and if its contents is equal to an array filled with
4787    * iota(). This method is particularly useful for DataArrayInt instances that represent
4788    * a renumbering array, to check if there is a real need in renumbering.
4789    * This method checks than \a this can be considered as an identity mapping
4790    * of a set having \a sizeExpected elements into itself.
4791    *
4792    *  \param [in] sizeExpected - The number of elements expected.
4793    *  \return bool - \a true if \a this array contents == \a range( \a this->getNumberOfTuples())
4794    *  \throw If \a this is not allocated.
4795    *  \throw If \a this->getNumberOfComponents() != 1.
4796    */
4797   template <class T>
4798   bool DataArrayDiscrete<T>::isIota(mcIdType sizeExpected) const
4799   {
4800     this->checkAllocated();
4801     if(this->getNumberOfComponents()!=1)
4802       return false;
4803     mcIdType nbOfTuples(this->getNumberOfTuples());
4804     if(nbOfTuples!=sizeExpected)
4805       return false;
4806     const T *pt=this->getConstPointer();
4807     for(mcIdType i=0;i<nbOfTuples;i++,pt++)
4808       if(*pt!=i)
4809         return false;
4810     return true;
4811   }
4812
4813   /*!
4814    * Checks if all values in \a this array are equal to \a val.
4815    *  \param [in] val - value to check equality of array values to.
4816    *  \return bool - \a true if all values are \a val.
4817    *  \throw If \a this is not allocated.
4818    *  \throw If \a this->getNumberOfComponents() != 1
4819    *  \sa DataArrayInt::checkUniformAndGuess
4820    */
4821   template <class T>
4822   bool DataArrayDiscrete<T>::isUniform(T val) const
4823   {
4824     this->checkAllocated();
4825     if(this->getNumberOfComponents()!=1)
4826       throw INTERP_KERNEL::Exception("DataArrayInt::isUniform : must be applied on DataArrayInt with only one component, you can call 'rearrange' method before !");
4827     const T *w(this->begin()),*end2(this->end());
4828     for(;w!=end2;w++)
4829       if(*w!=val)
4830         return false;
4831     return true;
4832   }
4833
4834   /*!
4835    * This method checks that \a this is uniform. If not and exception will be thrown.
4836    * In case of uniformity the corresponding value is returned.
4837    *
4838    * \return mcIdType - the unique value contained in this
4839    * \throw If \a this is not allocated.
4840    * \throw If \a this->getNumberOfComponents() != 1
4841    * \throw If \a this is not uniform.
4842    * \sa DataArrayInt::isUniform
4843    */
4844   template <class T>
4845   T DataArrayDiscrete<T>::checkUniformAndGuess() const
4846   {
4847     this->checkAllocated();
4848     if(this->getNumberOfComponents()!=1)
4849       throw INTERP_KERNEL::Exception("DataArrayInt::checkUniformAndGuess : must be applied on DataArrayInt with only one component, you can call 'rearrange' method before !");
4850     if(this->empty())
4851       throw INTERP_KERNEL::Exception("DataArrayInt::checkUniformAndGuess : this is empty !");
4852     const T *w(this->begin()),*end2(this->end());
4853     T ret(*w);
4854     for(;w!=end2;w++)
4855       if(*w!=ret)
4856         throw INTERP_KERNEL::Exception("DataArrayInt::checkUniformAndGuess : this is not uniform !");
4857     return ret;
4858   }
4859
4860   /*!
4861    * Checks if all values in \a this array are unique.
4862    *  \return bool - \a true if condition above is true
4863    *  \throw If \a this is not allocated.
4864    *  \throw If \a this->getNumberOfComponents() != 1
4865    */
4866   template <class T>
4867   bool DataArrayDiscrete<T>::hasUniqueValues() const
4868   {
4869     this->checkAllocated();
4870     if(this->getNumberOfComponents()!=1)
4871       throw INTERP_KERNEL::Exception("DataArrayInt::hasOnlyUniqueValues: must be applied on DataArrayInt with only one component, you can call 'rearrange' method before !");
4872     std::size_t nbOfElements(this->getNumberOfTuples());
4873     std::set<T> s(this->begin(),this->end());  // in C++11, should use unordered_set (O(1) complexity)
4874     if (s.size() != nbOfElements)
4875       return false;
4876     return true;
4877   }
4878
4879   /*!
4880    * Copy all components in a specified order from another DataArrayInt.
4881    * The specified components become the first ones in \a this array.
4882    * Both numerical and textual data is copied. The number of tuples in \a this and
4883    * the other array can be different.
4884    *  \param [in] a - the array to copy data from.
4885    *  \param [in] compoIds - sequence of zero based indices of components, data of which is
4886    *              to be copied.
4887    *  \throw If \a a is NULL.
4888    *  \throw If \a compoIds.size() != \a a->getNumberOfComponents().
4889    *  \throw If \a compoIds[i] < 0 or \a compoIds[i] > \a this->getNumberOfComponents().
4890    *
4891    *  \if ENABLE_EXAMPLES
4892    *  \ref py_mcdataarrayint_setselectedcomponents "Here is a Python example".
4893    *  \endif
4894    */
4895   template <class T>
4896   void DataArrayDiscrete<T>::setSelectedComponents(const DataArrayType *a, const std::vector<std::size_t>& compoIds)
4897   {
4898     if(!a)
4899       throw INTERP_KERNEL::Exception("DataArrayInt::setSelectedComponents : input DataArrayInt is NULL !");
4900     this->checkAllocated();
4901     a->checkAllocated();
4902     this->copyPartOfStringInfoFrom2(compoIds,*a);
4903     std::size_t partOfCompoSz=compoIds.size();
4904     std::size_t nbOfCompo = this->getNumberOfComponents();
4905     mcIdType nbOfTuples=std::min(this->getNumberOfTuples(),a->getNumberOfTuples());
4906     const T *ac=a->getConstPointer();
4907     T *nc=this->getPointer();
4908     for(mcIdType i=0;i<nbOfTuples;i++)
4909       for(std::size_t j=0;j<partOfCompoSz;j++,ac++)
4910         nc[nbOfCompo*i+compoIds[j]]=*ac;
4911   }
4912
4913   /*!
4914    * Creates a new DataArrayInt containing IDs (indices) of tuples holding value \b not
4915    * equal to a given one.
4916    *  \param [in] val - the value to ignore within \a this.
4917    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
4918    *          array using decrRef() as it is no more needed.
4919    *  \throw If \a this is not allocated.
4920    *  \throw If \a this->getNumberOfComponents() != 1.
4921    */
4922   template <class T>
4923   DataArrayIdType *DataArrayDiscrete<T>::findIdsNotEqual(T val) const
4924   {
4925     this->checkAllocated();
4926     if(this->getNumberOfComponents()!=1)
4927       throw INTERP_KERNEL::Exception("DataArrayInt::findIdsNotEqual : the array must have only one component, you can call 'rearrange' method before !");
4928     const T *cptr(this->getConstPointer());
4929     MCAuto<DataArrayIdType> ret(DataArrayIdType::New());
4930     ret->alloc(0,1);
4931     mcIdType nbOfTuples(this->getNumberOfTuples());
4932     for(mcIdType i=0;i<nbOfTuples;i++,cptr++)
4933       if(*cptr!=val)
4934         ret->pushBackSilent(i);
4935     return ret.retn();
4936   }
4937   
4938   /*!
4939    * Creates a new DataArrayInt containing IDs (indices) of tuples holding tuple equal to those defined by [ \a tupleBg , \a tupleEnd )
4940    * This method is an extension of  DataArrayInt::findIdsEqual method.
4941    *
4942    *  \param [in] tupleBg - the begin (included) of the input tuple to find within \a this.
4943    *  \param [in] tupleEnd - the end (excluded) of the input tuple to find within \a this.
4944    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
4945    *          array using decrRef() as it is no more needed.
4946    *  \throw If \a this is not allocated.
4947    *  \throw If \a this->getNumberOfComponents() != std::distance(tupleBg,tupleEnd).
4948    * \throw If \a this->getNumberOfComponents() is equal to 0.
4949    * \sa DataArrayInt::findIdsEqual
4950    */
4951   template <class T>
4952   DataArrayIdType *DataArrayDiscrete<T>::findIdsEqualTuple(const T *tupleBg, const T *tupleEnd) const
4953   {
4954     std::size_t nbOfCompoExp=std::distance(tupleBg,tupleEnd);
4955     this->checkAllocated();
4956     if(this->getNumberOfComponents()!=nbOfCompoExp)
4957       {
4958         std::ostringstream oss; oss << "DataArrayInt::findIdsEqualTuple : mismatch of number of components. Input tuple has " << nbOfCompoExp << " whereas this array has " << this->getNumberOfComponents() << " components !";
4959         throw INTERP_KERNEL::Exception(oss.str().c_str());
4960       }
4961     if(nbOfCompoExp==0)
4962       throw INTERP_KERNEL::Exception("DataArrayInt::findIdsEqualTuple : number of components should be > 0 !");
4963     MCAuto<DataArrayIdType> ret(DataArrayIdType::New());
4964     ret->alloc(0,1);
4965     const T *bg(this->begin()),*end2(this->end()),*work(this->begin());
4966     while(work!=end2)
4967       {
4968         work=std::search(work,end2,tupleBg,tupleEnd);
4969         if(work!=end2)
4970           {
4971             std::ptrdiff_t pos=std::distance(bg,work);
4972             if(pos%nbOfCompoExp==0)
4973               ret->pushBackSilent(ToIdType(pos/nbOfCompoExp));
4974             work++;
4975           }
4976       }
4977     return ret.retn();
4978   }
4979
4980   /*!
4981    * Creates a new DataArrayInt containing IDs (indices) of tuples holding value equal to
4982    * one of given values.
4983    *  \param [in] valsBg - an array of values to find within \a this array.
4984    *  \param [in] valsEnd - specifies the end of the array \a valsBg, so that
4985    *              the last value of \a valsBg is \a valsEnd[ -1 ].
4986    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
4987    *          array using decrRef() as it is no more needed.
4988    *  \throw If \a this->getNumberOfComponents() != 1.
4989    */
4990   template <class T>
4991   DataArrayIdType *DataArrayDiscrete<T>::findIdsEqualList(const T *valsBg, const T *valsEnd) const
4992   {
4993     if(this->getNumberOfComponents()!=1)
4994       throw INTERP_KERNEL::Exception("DataArrayInt::findIdsEqualList : the array must have only one component, you can call 'rearrange' method before !");
4995     std::set<T> vals2(valsBg,valsEnd);
4996     const T *cptr(this->getConstPointer());
4997     mcIdType nbOfTuples(this->getNumberOfTuples());
4998     MCAuto<DataArrayIdType> ret(DataArrayIdType::New()); ret->alloc(0,1);
4999     for(mcIdType i=0;i<nbOfTuples;i++,cptr++)
5000       if(vals2.find(*cptr)!=vals2.end())
5001         ret->pushBackSilent(i);
5002     return ret.retn();
5003   }
5004   
5005   /*!
5006    * Creates a new DataArrayInt containing IDs (indices) of tuples holding values \b not
5007    * equal to any of given values.
5008    *  \param [in] valsBg - an array of values to ignore within \a this array.
5009    *  \param [in] valsEnd - specifies the end of the array \a valsBg, so that
5010    *              the last value of \a valsBg is \a valsEnd[ -1 ].
5011    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
5012    *          array using decrRef() as it is no more needed.
5013    *  \throw If \a this->getNumberOfComponents() != 1.
5014    */
5015   template <class T>
5016   DataArrayIdType *DataArrayDiscrete<T>::findIdsNotEqualList(const T *valsBg, const T *valsEnd) const
5017   {
5018     if(this->getNumberOfComponents()!=1)
5019       throw INTERP_KERNEL::Exception("DataArrayInt::findIdsNotEqualList : the array must have only one component, you can call 'rearrange' method before !");
5020     std::set<T> vals2(valsBg,valsEnd);
5021     const T *cptr=this->getConstPointer();
5022     mcIdType nbOfTuples(this->getNumberOfTuples());
5023     MCAuto<DataArrayIdType> ret(DataArrayIdType::New()); ret->alloc(0,1);
5024     for(mcIdType i=0;i<nbOfTuples;i++,cptr++)
5025       if(vals2.find(*cptr)==vals2.end())
5026         ret->pushBackSilent(i);
5027     return ret.retn();
5028   }
5029
5030   /*!
5031    * This method expects to be called when number of components of this is equal to one.
5032    * This method returns the tuple id, if it exists, of the first tuple equal to \b value.
5033    * If not any tuple contains \b value -1 is returned.
5034    * \sa DataArrayInt::presenceOfValue
5035    */
5036   template <class T>
5037   mcIdType DataArrayDiscrete<T>::findIdFirstEqual(T value) const
5038   {
5039     this->checkAllocated();
5040     if(this->getNumberOfComponents()!=1)
5041       throw INTERP_KERNEL::Exception("DataArrayInt::presenceOfValue : the array must have only one component, you can call 'rearrange' method before !");
5042     const T *cptr=this->getConstPointer();
5043     mcIdType nbOfTuples(this->getNumberOfTuples());
5044     const T *ret=std::find(cptr,cptr+nbOfTuples,value);
5045     if(ret!=cptr+nbOfTuples)
5046       return ToIdType(std::distance(cptr,ret));
5047     return -1;
5048   }
5049   
5050   /*!
5051    * This method expects to be called when number of components of this is equal to one.
5052    * This method returns the tuple id, if it exists, of the first tuple so that the value is contained in \b vals.
5053    * If not any tuple contains one of the values contained in 'vals' -1 is returned.
5054    * \sa DataArrayInt::presenceOfValue
5055    */
5056   template <class T>
5057   mcIdType DataArrayDiscrete<T>::findIdFirstEqual(const std::vector<T>& vals) const
5058   {
5059     this->checkAllocated();
5060     if(this->getNumberOfComponents()!=1)
5061       throw INTERP_KERNEL::Exception("DataArrayInt::presenceOfValue : the array must have only one component, you can call 'rearrange' method before !");
5062     std::set<T> vals2(vals.begin(),vals.end());
5063     const T *cptr=this->getConstPointer();
5064     mcIdType nbOfTuples(this->getNumberOfTuples());
5065     for(const T *w=cptr;w!=cptr+nbOfTuples;w++)
5066       if(vals2.find(*w)!=vals2.end())
5067         return ToIdType(std::distance(cptr,w));
5068     return -1;
5069   }
5070
5071   /*!
5072    * This method is an extension of DataArrayInt::findIdFirstEqual method because this method works for DataArrayInt with
5073    * any number of components excepted 0 (an INTERP_KERNEL::Exception is thrown in this case).
5074    * This method searches in \b this is there is a tuple that matched the input parameter \b tupl.
5075    * If any the tuple id is returned. If not -1 is returned.
5076    *
5077    * This method throws an INTERP_KERNEL::Exception if the number of components in \b this mismatches with the size of
5078    * the input vector. An INTERP_KERNEL::Exception is thrown too if \b this is not allocated.
5079    *
5080    * \return tuple id where \b tupl is. -1 if no such tuple exists in \b this.
5081    * \sa DataArrayInt::findIdSequence, DataArrayInt::presenceOfTuple.
5082    */
5083   template <class T>
5084   mcIdType DataArrayDiscrete<T>::findIdFirstEqualTuple(const std::vector<T>& tupl) const
5085   {
5086     this->checkAllocated();
5087     std::size_t nbOfCompo(this->getNumberOfComponents());
5088     if(nbOfCompo==0)
5089       throw INTERP_KERNEL::Exception("DataArrayInt::findIdFirstEqualTuple : 0 components in 'this' !");
5090     if(nbOfCompo!=tupl.size())
5091       {
5092         std::ostringstream oss; oss << "DataArrayInt::findIdFirstEqualTuple : 'this' contains " << nbOfCompo << " components and searching for a tuple of length " << tupl.size() << " !";
5093         throw INTERP_KERNEL::Exception(oss.str().c_str());
5094       }
5095     const T *cptr=this->getConstPointer();
5096     std::size_t nbOfVals=this->getNbOfElems();
5097     for(const T *work=cptr;work!=cptr+nbOfVals;)
5098       {
5099         work=std::search(work,cptr+nbOfVals,tupl.begin(),tupl.end());
5100         if(work!=cptr+nbOfVals)
5101           {
5102             if(std::distance(cptr,work)%nbOfCompo!=0)
5103               work++;
5104             else
5105               return ToIdType (std::distance(cptr,work)/nbOfCompo);
5106           }
5107       }
5108     return -1;
5109   }
5110
5111   /*!
5112    * This method searches the sequence specified in input parameter \b vals in \b this.
5113    * This works only for DataArrayInt having number of components equal to one (if not an INTERP_KERNEL::Exception will be thrown).
5114    * This method differs from DataArrayInt::findIdFirstEqualTuple in that the position is internal raw data is not considered here contrary to DataArrayInt::findIdFirstEqualTuple.
5115    * \sa DataArrayInt::findIdFirstEqualTuple
5116    */
5117   template <class T>
5118   mcIdType DataArrayDiscrete<T>::findIdSequence(const std::vector<T>& vals) const
5119   {
5120     this->checkAllocated();
5121     std::size_t nbOfCompo=this->getNumberOfComponents();
5122     if(nbOfCompo!=1)
5123       throw INTERP_KERNEL::Exception("DataArrayInt::findIdSequence : works only for DataArrayInt instance with one component !");
5124     const T *cptr=this->getConstPointer();
5125     std::size_t nbOfVals=this->getNbOfElems();
5126     const T *loc=std::search(cptr,cptr+nbOfVals,vals.begin(),vals.end());
5127     if(loc!=cptr+nbOfVals)
5128       return ToIdType(std::distance(cptr,loc));
5129     return -1;
5130   }
5131
5132   /*!
5133    * Assigns \a newValue to all elements holding \a oldValue within \a this
5134    * one-dimensional array.
5135    *  \param [in] oldValue - the value to replace.
5136    *  \param [in] newValue - the value to assign.
5137    *  \return mcIdType - number of replacements performed.
5138    *  \throw If \a this is not allocated.
5139    *  \throw If \a this->getNumberOfComponents() != 1.
5140    */
5141   template <class T>
5142   mcIdType DataArrayDiscrete<T>::changeValue(T oldValue, T newValue)
5143   {
5144     this->checkAllocated();
5145     if(this->getNumberOfComponents()!=1)
5146       throw INTERP_KERNEL::Exception("DataArrayInt::changeValue : the array must have only one component, you can call 'rearrange' method before !");
5147     if(oldValue==newValue)
5148       return 0;
5149     T *start(this->getPointer()),*end2(start+this->getNbOfElems());
5150     mcIdType ret(0);
5151     for(T *val=start;val!=end2;val++)
5152       {
5153         if(*val==oldValue)
5154           {
5155             *val=newValue;
5156             ret++;
5157           }
5158       }
5159     if(ret>0)
5160       this->declareAsNew();
5161     return ret;
5162   }
5163
5164   /*!
5165    * This method returns the number of values in \a this that are equals to input parameter \a value.
5166    * This method only works for single component array.
5167    *
5168    * \return a value in [ 0, \c this->getNumberOfTuples() )
5169    *
5170    * \throw If \a this is not allocated
5171    *
5172    */
5173   template <class T>
5174   mcIdType DataArrayDiscrete<T>::count(T value) const
5175   {
5176     mcIdType ret=0;
5177     this->checkAllocated();
5178     if(this->getNumberOfComponents()!=1)
5179       throw INTERP_KERNEL::Exception("DataArrayInt::count : must be applied on DataArrayInt with only one component, you can call 'rearrange' method before !");
5180     const T *vals=this->begin();
5181     std::size_t nbOfElements=this->getNumberOfTuples();
5182     for(std::size_t i=0;i<nbOfElements;i++,vals++)
5183       if(*vals==value)
5184         ret++;
5185     return ret;
5186   }
5187
5188   /*!
5189    * This method is an extension of DataArrayInt::presenceOfValue method because this method works for DataArrayInt with
5190    * any number of components excepted 0 (an INTERP_KERNEL::Exception is thrown in this case).
5191    * This method searches in \b this is there is a tuple that matched the input parameter \b tupl.
5192    * This method throws an INTERP_KERNEL::Exception if the number of components in \b this mismatches with the size of
5193    * the input vector. An INTERP_KERNEL::Exception is thrown too if \b this is not allocated.
5194    * \sa DataArrayInt::findIdFirstEqualTuple
5195    */
5196   template <class T>
5197   bool DataArrayDiscrete<T>::presenceOfTuple(const std::vector<T>& tupl) const
5198   {
5199     return this->findIdFirstEqualTuple(tupl)!=-1;
5200   }
5201   
5202   
5203   /*!
5204    * Returns \a true if a given value is present within \a this one-dimensional array.
5205    *  \param [in] value - the value to find within \a this array.
5206    *  \return bool - \a true in case if \a value is present within \a this array.
5207    *  \throw If \a this is not allocated.
5208    *  \throw If \a this->getNumberOfComponents() != 1.
5209    *  \sa findIdFirstEqual()
5210    */
5211   template <class T>
5212   bool DataArrayDiscrete<T>::presenceOfValue(T value) const
5213   {
5214     return this->findIdFirstEqual(value)!=-1;
5215   }
5216   
5217   /*!
5218    * This method expects to be called when number of components of this is equal to one.
5219    * This method returns true if it exists a tuple so that the value is contained in \b vals.
5220    * If not any tuple contains one of the values contained in 'vals' false is returned.
5221    * \sa DataArrayInt::findIdFirstEqual
5222    */
5223   template <class T>
5224   bool DataArrayDiscrete<T>::presenceOfValue(const std::vector<T>& vals) const
5225   {
5226     return this->findIdFirstEqual(vals)!=-1;
5227   }
5228
5229   /*!
5230    * Accumulates values of each component of \a this array.
5231    *  \param [out] res - an array of length \a this->getNumberOfComponents(), allocated
5232    *         by the caller, that is filled by this method with sum value for each
5233    *         component.
5234    *  \throw If \a this is not allocated.
5235    */
5236   template <class T>
5237   void DataArrayDiscrete<T>::accumulate(T *res) const
5238   {
5239     this->checkAllocated();
5240     const T *ptr=this->getConstPointer();
5241     mcIdType nbTuple(this->getNumberOfTuples());
5242     std::size_t nbComps(this->getNumberOfComponents());
5243     std::fill(res,res+nbComps,0);
5244     for(mcIdType i=0;i<nbTuple;i++)
5245       std::transform(ptr+i*nbComps,ptr+(i+1)*nbComps,res,res,std::plus<T>());
5246   }
5247   
5248   template <class T>
5249   T DataArrayDiscrete<T>::accumulate(std::size_t compId) const
5250   {
5251     this->checkAllocated();
5252     const T *ptr=this->getConstPointer();
5253     mcIdType nbTuple(this->getNumberOfTuples());
5254     std::size_t nbComps(this->getNumberOfComponents());
5255     if(compId>=nbComps) // compId >= 0 (it is a size_t)
5256       throw INTERP_KERNEL::Exception("DataArrayInt::accumulate : Invalid compId specified : No such nb of components !");
5257     T ret=0;
5258     for(mcIdType i=0;i<nbTuple;i++)
5259       ret+=ptr[i*nbComps+compId];
5260     return ret;
5261   }
5262
5263   /*!
5264    * This method accumulate using addition tuples in \a this using input index array [ \a bgOfIndex, \a endOfIndex ).
5265    * The returned array will have same number of components than \a this and number of tuples equal to
5266    * \c std::distance(bgOfIndex,endOfIndex) \b minus \b one.
5267    *
5268    * The input index array is expected to be ascendingly sorted in which the all referenced ids should be in [0, \c this->getNumberOfTuples).
5269    *
5270    * \param [in] bgOfIndex - begin (included) of the input index array.
5271    * \param [in] endOfIndex - end (excluded) of the input index array.
5272    * \return DataArrayInt * - the new instance having the same number of components than \a this.
5273    *
5274    * \throw If bgOfIndex or end is NULL.
5275    * \throw If input index array is not ascendingly sorted.
5276    * \throw If there is an id in [ \a bgOfIndex, \a endOfIndex ) not in [0, \c this->getNumberOfTuples).
5277    * \throw If std::distance(bgOfIndex,endOfIndex)==0.
5278    */
5279   template <class T>
5280   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::accumulatePerChunck(const mcIdType *bgOfIndex, const mcIdType *endOfIndex) const
5281   {
5282     if(!bgOfIndex || !endOfIndex)
5283       throw INTERP_KERNEL::Exception("DataArrayInt::accumulatePerChunck : input pointer NULL !");
5284     this->checkAllocated();
5285     std::size_t nbCompo(this->getNumberOfComponents());
5286     mcIdType nbOfTuples(this->getNumberOfTuples());
5287     mcIdType sz=ToIdType(std::distance(bgOfIndex,endOfIndex));
5288     if(sz<1)
5289       throw INTERP_KERNEL::Exception("DataArrayInt::accumulatePerChunck : invalid size of input index array !");
5290     sz--;
5291     MCAuto<DataArrayType> ret=DataArrayType::New(); ret->alloc(sz,nbCompo);
5292     const mcIdType *w=bgOfIndex;
5293     if(*w<0 || *w>=nbOfTuples)
5294       throw INTERP_KERNEL::Exception("DataArrayInt::accumulatePerChunck : The first element of the input index not in [0,nbOfTuples) !");
5295     const T *srcPt=this->begin()+(*w)*nbCompo;
5296     T *tmp=ret->getPointer();
5297     for(mcIdType i=0;i<sz;i++,tmp+=nbCompo,w++)
5298       {
5299         std::fill(tmp,tmp+nbCompo,0);
5300         if(w[1]>=w[0])
5301           {
5302             for(mcIdType j=w[0];j<w[1];j++,srcPt+=nbCompo)
5303               {
5304                 if(j>=0 && j<nbOfTuples)
5305                   std::transform(srcPt,srcPt+nbCompo,tmp,tmp,std::plus<T>());
5306                 else
5307                   {
5308                     std::ostringstream oss; oss << "DataArrayInt::accumulatePerChunck : At rank #" << i << " the input index array points to id " << j << " should be in [0," << nbOfTuples << ") !";
5309                     throw INTERP_KERNEL::Exception(oss.str().c_str());
5310                   }
5311               }
5312           }
5313         else
5314           {
5315             std::ostringstream oss; oss << "DataArrayInt::accumulatePerChunck : At rank #" << i << " the input index array is not in ascendingly sorted.";
5316             throw INTERP_KERNEL::Exception(oss.str().c_str());
5317           }
5318       }
5319     ret->copyStringInfoFrom(*this);
5320     return ret.retn();
5321   }
5322
5323   /*!
5324    * Returns in a single walk in \a this the min value and the max value in \a this.
5325    * \a this is expected to be single component array.
5326    *
5327    * \param [out] minValue - the min value in \a this.
5328    * \param [out] maxValue - the max value in \a this.
5329    *
5330    * \sa getMinValueInArray, getMinValue, getMaxValueInArray, getMaxValue
5331    */
5332   template <class T>
5333   void DataArrayDiscrete<T>::getMinMaxValues(T& minValue, T& maxValue) const
5334   {
5335     this->checkAllocated();
5336     if(this->getNumberOfComponents()!=1)
5337       throw INTERP_KERNEL::Exception("DataArrayInt::getMinMaxValues : must be applied on DataArrayInt with only one component !");
5338     std::size_t nbElements(this->getNumberOfTuples());
5339     const T *pt(this->begin());
5340     minValue=std::numeric_limits<T>::max(); maxValue=-std::numeric_limits<T>::max();
5341     for(std::size_t i=0;i<nbElements;i++,pt++)
5342       {
5343         if(*pt<minValue)
5344           minValue=*pt;
5345         if(*pt>maxValue)
5346           maxValue=*pt;
5347       }
5348   }
5349
5350   /*!
5351    * Modify all elements of \a this array, so that
5352    * an element _x_ becomes \f$ numerator / x \f$.
5353    *  \warning If an exception is thrown because of presence of 0 element in \a this
5354    *           array, all elements processed before detection of the zero element remain
5355    *           modified.
5356    *  \param [in] numerator - the numerator used to modify array elements.
5357    *  \throw If \a this is not allocated.
5358    *  \throw If there is an element equal to 0 in \a this array.
5359    */
5360   template <class T>
5361   void DataArrayDiscrete<T>::applyInv(T numerator)
5362   {
5363     this->checkAllocated();
5364     T *ptr=this->getPointer();
5365     std::size_t nbOfElems=this->getNbOfElems();
5366     for(std::size_t i=0;i<nbOfElems;i++,ptr++)
5367       {
5368         if(*ptr!=0)
5369           {
5370             *ptr=numerator/(*ptr);
5371           }
5372         else
5373           {
5374             std::ostringstream oss; oss << "DataArrayInt::applyInv : presence of null value in tuple #" << i/(this->getNumberOfComponents()) << " component #" << i%(this->getNumberOfComponents());
5375             oss << " !";
5376             throw INTERP_KERNEL::Exception(oss.str().c_str());
5377           }
5378       }
5379     this->declareAsNew();
5380   }
5381
5382   /*!
5383    * Modify all elements of \a this array, so that
5384    * an element _x_ becomes \f$ x / val \f$.
5385    *  \param [in] val - the denominator used to modify array elements.
5386    *  \throw If \a this is not allocated.
5387    *  \throw If \a val == 0.
5388    */
5389   template <class T>
5390   void DataArrayDiscrete<T>::applyDivideBy(T val)
5391   {
5392     if(val==0)
5393       throw INTERP_KERNEL::Exception("DataArrayInt::applyDivideBy : Trying to divide by 0 !");
5394     this->checkAllocated();
5395     T *ptr=this->getPointer();
5396     std::size_t nbOfElems=this->getNbOfElems();
5397     std::transform(ptr,ptr+nbOfElems,ptr,std::bind(std::divides<T>(),std::placeholders::_1,val));
5398     this->declareAsNew();
5399   }
5400
5401   /*!
5402    * Modify all elements of \a this array, so that
5403    * an element _x_ becomes  <em> x % val </em>.
5404    *  \param [in] val - the divisor used to modify array elements.
5405    *  \throw If \a this is not allocated.
5406    *  \throw If \a val <= 0.
5407    */
5408   template <class T>
5409   void DataArrayDiscrete<T>::applyModulus(T val)
5410   {
5411     if(val<=0)
5412       throw INTERP_KERNEL::Exception("DataArrayInt::applyDivideBy : Trying to operate modulus on value <= 0 !");
5413     this->checkAllocated();
5414     T *ptr=this->getPointer();
5415     std::size_t nbOfElems=this->getNbOfElems();
5416     std::transform(ptr,ptr+nbOfElems,ptr,std::bind(std::modulus<T>(),std::placeholders::_1,val));
5417     this->declareAsNew();
5418   }
5419
5420   /*!
5421    * Modify all elements of \a this array, so that
5422    * an element _x_ becomes <em> val % x </em>.
5423    *  \warning If an exception is thrown because of presence of an element <= 0 in \a this
5424    *           array, all elements processed before detection of the zero element remain
5425    *           modified.
5426    *  \param [in] val - the divident used to modify array elements.
5427    *  \throw If \a this is not allocated.
5428    *  \throw If there is an element equal to or less than 0 in \a this array.
5429    */
5430   template <class T>
5431   void DataArrayDiscrete<T>::applyRModulus(T val)
5432   {
5433     this->checkAllocated();
5434     T *ptr=this->getPointer();
5435     std::size_t nbOfElems=this->getNbOfElems();
5436     for(std::size_t i=0;i<nbOfElems;i++,ptr++)
5437       {
5438         if(*ptr>0)
5439           {
5440             *ptr=val%(*ptr);
5441           }
5442         else
5443           {
5444             std::ostringstream oss; oss << "DataArrayInt::applyRModulus : presence of value <=0 in tuple #" << i/(this->getNumberOfComponents()) << " component #" << i%(this->getNumberOfComponents());
5445             oss << " !";
5446             throw INTERP_KERNEL::Exception(oss.str().c_str());
5447           }
5448       }
5449     this->declareAsNew();
5450   }
5451
5452   /*!
5453    * Modify all elements of \a this array, so that
5454    * an element _x_ becomes <em> val ^ x </em>.
5455    *  \param [in] val - the value used to apply pow on all array elements.
5456    *  \throw If \a this is not allocated.
5457    *  \throw If \a val < 0.
5458    */
5459   template <class T>
5460   void DataArrayDiscrete<T>::applyPow(T val)
5461   {
5462     this->checkAllocated();
5463     if(val<0)
5464       throw INTERP_KERNEL::Exception("DataArrayInt::applyPow : input pow in < 0 !");
5465     T *ptr=this->getPointer();
5466     std::size_t nbOfElems=this->getNbOfElems();
5467     if(val==0)
5468       {
5469         std::fill(ptr,ptr+nbOfElems,1);
5470         return ;
5471       }
5472     for(std::size_t i=0;i<nbOfElems;i++,ptr++)
5473       {
5474         T tmp=1;
5475         for(T j=0;j<val;j++)
5476           tmp*=*ptr;
5477         *ptr=tmp;
5478       }
5479     this->declareAsNew();
5480   }
5481   
5482   /*!
5483    * Modify all elements of \a this array, so that
5484    * an element _x_ becomes \f$ val ^ x \f$.
5485    *  \param [in] val - the value used to apply pow on all array elements.
5486    *  \throw If \a this is not allocated.
5487    *  \throw If there is an element < 0 in \a this array.
5488    *  \warning If an exception is thrown because of presence of 0 element in \a this
5489    *           array, all elements processed before detection of the zero element remain
5490    *           modified.
5491    */
5492   template <class T>
5493   void DataArrayDiscrete<T>::applyRPow(T val)
5494   {
5495     this->checkAllocated();
5496     T *ptr=this->getPointer();
5497     std::size_t nbOfElems=this->getNbOfElems();
5498     for(std::size_t i=0;i<nbOfElems;i++,ptr++)
5499       {
5500         if(*ptr>=0)
5501           {
5502             T tmp=1;
5503             for(T j=0;j<*ptr;j++)
5504               tmp*=val;
5505             *ptr=tmp;
5506           }
5507         else
5508           {
5509             std::ostringstream oss; oss << "DataArrayInt::applyRPow : presence of negative value in tuple #" << i/(this->getNumberOfComponents()) << " component #" << i%(this->getNumberOfComponents());
5510             oss << " !";
5511             throw INTERP_KERNEL::Exception(oss.str().c_str());
5512           }
5513       }
5514     this->declareAsNew();
5515   }
5516
5517   /*!
5518    * This method works only on data array with one component.
5519    * This method returns a newly allocated array storing stored ascendantly tuple ids in \b this so that
5520    * this[*id] in [\b vmin,\b vmax)
5521    *
5522    * \param [in] vmin begin of range. This value is included in range (included).
5523    * \param [in] vmax end of range. This value is \b not included in range (excluded).
5524    * \return a newly allocated data array that the caller should deal with.
5525    *
5526    * \sa DataArrayInt::findIdsNotInRange , DataArrayInt::findIdsStricltyNegative
5527    */
5528   template <class T>
5529   DataArrayIdType *DataArrayDiscrete<T>::findIdsInRange(T vmin, T vmax) const
5530   {
5531     InRange<T> ir(vmin,vmax);
5532     MCAuto<DataArrayIdType> ret(this->findIdsAdv(ir));
5533     return ret.retn();
5534   }
5535   
5536   /*!
5537    * This method works only on data array with one component.
5538    * This method returns a newly allocated array storing stored ascendantly tuple ids in \b this so that
5539    * this[*id] \b not in [\b vmin,\b vmax)
5540    *
5541    * \param [in] vmin begin of range. This value is \b not included in range (excluded).
5542    * \param [in] vmax end of range. This value is included in range (included).
5543    * \return a newly allocated data array that the caller should deal with.
5544    *
5545    * \sa DataArrayInt::findIdsInRange , DataArrayInt::findIdsStricltyNegative
5546    */
5547   template <class T>
5548   DataArrayIdType *DataArrayDiscrete<T>::findIdsNotInRange(T vmin, T vmax) const
5549   {
5550     NotInRange<T> nir(vmin,vmax);
5551     MCAuto<DataArrayIdType> ret(this->findIdsAdv(nir));
5552     return ret.retn();
5553   }
5554
5555   /*!
5556    * This method works only on data array with one component.
5557    * 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.
5558    *
5559    * \param [in] vmin begin of range. This value is included in range (included).
5560    * \param [in] vmax end of range. This value is \b not included in range (excluded).
5561    * \return if all ids in \a this are so that (*this)[i]==i for all i in [ 0, \c this->getNumberOfTuples() ). */
5562   template <class T>
5563   bool DataArrayDiscrete<T>::checkAllIdsInRange(T vmin, T vmax) const
5564   {
5565     this->checkAllocated();
5566     if(this->getNumberOfComponents()!=1)
5567       throw INTERP_KERNEL::Exception("DataArrayInt::checkAllIdsInRange : this must have exactly one component !");
5568     mcIdType nbOfTuples(this->getNumberOfTuples());
5569     bool ret=true;
5570     const T *cptr=this->getConstPointer();
5571     for(mcIdType i=0;i<nbOfTuples;i++,cptr++)
5572       {
5573         if(*cptr>=vmin && *cptr<vmax)
5574           { ret=ret && *cptr==i; }
5575         else
5576           {
5577             std::ostringstream oss; oss << "DataArrayInt::checkAllIdsInRange : tuple #" << i << " has value " << *cptr << " should be in [" << vmin << "," << vmax << ") !";
5578             throw INTERP_KERNEL::Exception(oss.str().c_str());
5579           }
5580       }
5581     return ret;
5582   }
5583
5584   /*!
5585    * Returns a new DataArrayInt which contains a complement of elements of \a this
5586    * one-dimensional array. I.e. the result array contains all elements from the range [0,
5587    * \a nbOfElement) not present in \a this array.
5588    *  \param [in] nbOfElement - maximal size of the result array.
5589    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
5590    *         array using decrRef() as it is no more needed.
5591    *  \throw If \a this is not allocated.
5592    *  \throw If \a this->getNumberOfComponents() != 1.
5593    *  \throw If any element \a x of \a this array violates condition ( 0 <= \a x < \a
5594    *         nbOfElement ).
5595    */
5596   template <class T>
5597   DataArrayIdType *DataArrayDiscrete<T>::buildComplement(mcIdType nbOfElement) const
5598   {
5599     this->checkAllocated();
5600     if(this->getNumberOfComponents()!=1)
5601       throw INTERP_KERNEL::Exception("DataArrayInt::buildComplement : only single component allowed !");
5602     std::vector<bool> tmp(nbOfElement);
5603     const T *pt=this->getConstPointer();
5604     std::size_t nbOfElements=this->getNumberOfTuples();
5605     for(const T *w=pt;w!=pt+nbOfElements;w++)
5606       if(*w>=0 && *w<nbOfElement)
5607         tmp[*w]=true;
5608       else
5609         throw INTERP_KERNEL::Exception("DataArrayInt::buildComplement : an element is not in valid range : [0,nbOfElement) !");
5610     std::size_t nbOfRetVal=std::count(tmp.begin(),tmp.end(),false);
5611     DataArrayIdType *ret=DataArrayIdType::New();
5612     ret->alloc(nbOfRetVal,1);
5613     mcIdType j=0;
5614     mcIdType *retPtr=ret->getPointer();
5615     for(mcIdType i=0;i<nbOfElement;i++)
5616       if(!tmp[i])
5617         retPtr[j++]=i;
5618     return ret;
5619   }
5620
5621   /*!
5622    * Returns a new DataArrayInt containing elements of \a this one-dimensional missing
5623    * from an \a other one-dimensional array.
5624    *  \param [in] other - a DataArrayInt containing elements not to include in the result array.
5625    *  \return DataArrayInt * - a new instance of DataArrayInt with one component. The
5626    *         caller is to delete this array using decrRef() as it is no more needed.
5627    *  \throw If \a other is NULL.
5628    *  \throw If \a other is not allocated.
5629    *  \throw If \a other->getNumberOfComponents() != 1.
5630    *  \throw If \a this is not allocated.
5631    *  \throw If \a this->getNumberOfComponents() != 1.
5632    *  \sa DataArrayInt::buildSubstractionOptimized()
5633    */
5634   template <class T>
5635   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::buildSubstraction(const DataArrayType *other) const
5636   {
5637     if(!other)
5638       throw INTERP_KERNEL::Exception("DataArrayInt::buildSubstraction : DataArrayInt pointer in input is NULL !");
5639     this->checkAllocated();
5640     other->checkAllocated();
5641     if(this->getNumberOfComponents()!=1)
5642       throw INTERP_KERNEL::Exception("DataArrayInt::buildSubstraction : only single component allowed !");
5643     if(other->getNumberOfComponents()!=1)
5644       throw INTERP_KERNEL::Exception("DataArrayInt::buildSubstraction : only single component allowed for other type !");
5645     const T *pt=this->getConstPointer();
5646     std::size_t nbOfElements=this->getNumberOfTuples();
5647     std::set<T> s1(pt,pt+nbOfElements);
5648     pt=other->getConstPointer();
5649     nbOfElements=other->getNumberOfTuples();
5650     std::set<T> s2(pt,pt+nbOfElements);
5651     std::vector<T> r;
5652     std::set_difference(s1.begin(),s1.end(),s2.begin(),s2.end(),std::back_insert_iterator< std::vector<T> >(r));
5653     DataArrayType *ret=DataArrayType::New();
5654     ret->alloc(r.size(),1);
5655     std::copy(r.begin(),r.end(),ret->getPointer());
5656     return ret;
5657   }
5658
5659   /*!
5660    * \a this is expected to have one component and to be sorted ascendingly (as for \a other).
5661    * \a other is expected to be a part of \a this. If not DataArrayInt::buildSubstraction should be called instead.
5662    *
5663    * \param [in] other an array with one component and expected to be sorted ascendingly.
5664    * \ret list of ids in \a this but not in \a other.
5665    * \sa DataArrayInt::buildSubstraction
5666    */
5667   template <class T>
5668   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::buildSubstractionOptimized(const DataArrayType *other) const
5669   {
5670     static const char *MSG="DataArrayInt::buildSubstractionOptimized : only single component allowed !";
5671     if(!other) throw INTERP_KERNEL::Exception("DataArrayInt::buildSubstractionOptimized : NULL input array !");
5672     this->checkAllocated(); other->checkAllocated();
5673     if(this->getNumberOfComponents()!=1) throw INTERP_KERNEL::Exception(MSG);
5674     if(other->getNumberOfComponents()!=1) throw INTERP_KERNEL::Exception(MSG);
5675     const T *pt1Bg(this->begin()),*pt1End(this->end()),*pt2Bg(other->begin()),*pt2End(other->end());
5676     const T *work1(pt1Bg),*work2(pt2Bg);
5677     MCAuto<DataArrayType> ret(DataArrayType::New()); ret->alloc(0,1);
5678     for(;work1!=pt1End;work1++)
5679       {
5680         if(work2!=pt2End && *work1==*work2)
5681           work2++;
5682         else
5683           ret->pushBackSilent(*work1);
5684       }
5685     return ret.retn();
5686   }
5687
5688   /*!
5689    * Returns a new DataArrayInt which contains all elements of \a this and a given
5690    * one-dimensional arrays. The result array does not contain any duplicates
5691    * and its values are sorted in ascending order.
5692    *  \param [in] other - an array to unite with \a this one.
5693    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
5694    *         array using decrRef() as it is no more needed.
5695    *  \throw If \a this or \a other is not allocated.
5696    *  \throw If \a this->getNumberOfComponents() != 1.
5697    *  \throw If \a other->getNumberOfComponents() != 1.
5698    */
5699   template <class T>
5700   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::buildUnion(const DataArrayType *other) const
5701   {
5702     std::vector<const DataArrayType *>arrs(2);
5703     arrs[0]=dynamic_cast<const DataArrayType *>(this); arrs[1]=other;
5704     return DataArrayDiscrete<T>::BuildUnion(arrs);
5705   }
5706
5707   /*!
5708    * Returns a new DataArrayInt which contains elements present in both \a this and a given
5709    * one-dimensional arrays. The result array does not contain any duplicates
5710    * and its values are sorted in ascending order.
5711    *  \param [in] other - an array to intersect with \a this one.
5712    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
5713    *         array using decrRef() as it is no more needed.
5714    *  \throw If \a this or \a other is not allocated.
5715    *  \throw If \a this->getNumberOfComponents() != 1.
5716    *  \throw If \a other->getNumberOfComponents() != 1.
5717    */
5718   template <class T>
5719   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::buildIntersection(const DataArrayType *other) const
5720   {
5721     std::vector<const DataArrayType *>arrs(2);
5722     arrs[0]=dynamic_cast<const DataArrayType *>(this); arrs[1]=other;
5723     return DataArrayDiscrete<T>::BuildIntersection(arrs);
5724   }
5725   /*!
5726    * This method can be applied on allocated with one component DataArrayInt instance.
5727    * 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.
5728    * Number of tuples of returned array is equal to size of \a this->buildUnique() + 1.
5729    * Last value of returned array is equal to \a this->getNumberOfTuples()
5730    * 
5731    * \b Example:
5732    * - \a this : [0, 1, 1, 2, 2, 3, 4, 4, 5, 5, 5, 11]
5733    * - \a return is : [0, 1, 3, 5, 6, 8, 11, 12]
5734    *
5735    * \return a newly allocated array containing the indexed array format of groups by same consecutive value.
5736    * \throw if \a this is not allocated or if \a this has not exactly one component.
5737    * \sa DataArrayInt::buildUnique, MEDCouplingSkyLineArray::groupPacks
5738    */
5739   template <class T>
5740   DataArrayIdType *DataArrayDiscrete<T>::indexOfSameConsecutiveValueGroups() const
5741   {
5742     this->checkAllocated();
5743     if(this->getNumberOfComponents()!=1)
5744       throw INTERP_KERNEL::Exception("DataArrayInt::indexOfSameConsecutiveValueGroups : only single component allowed !");
5745     const T *pt(this->begin());
5746     const T *const ptEnd(this->end()) , * const ptBg(this->begin());
5747     // first find nb of different values in this
5748     std::size_t nbOfTuplesOut(0);
5749     while( pt != ptEnd )
5750     {
5751       T val(*pt);
5752       const T *endOfPack(std::find_if(pt+1,ptEnd,[val](T elt){ return val!=elt; }));
5753       pt = endOfPack;
5754       ++nbOfTuplesOut;
5755     }
5756     MCAuto<DataArrayIdType> ret(DataArrayIdType::New()); ret->alloc(nbOfTuplesOut+1,1);
5757     mcIdType *retPtr(ret->getPointer()); *retPtr++ = 0;
5758     pt = this->begin();
5759     while( pt != ptEnd )
5760     {
5761       T val(*pt);
5762       const T *endOfPack(std::find_if(pt+1,ptEnd,[val](T elt){ return val!=elt; }));
5763       *retPtr++ = ToIdType( std::distance(ptBg,endOfPack) );
5764       pt = endOfPack;
5765       ++nbOfTuplesOut;
5766     }
5767     return ret.retn();
5768   }
5769
5770   /*!
5771    * This method can be applied on allocated with one component DataArrayInt instance.
5772    * This method is typically relevant for sorted arrays. All consecutive duplicated items in \a this will appear only once in returned DataArrayInt instance.
5773    * 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]
5774    *
5775    * \return a newly allocated array that contain the result of the unique operation applied on \a this.
5776    * \throw if \a this is not allocated or if \a this has not exactly one component.
5777    * \sa DataArrayInt::buildUniqueNotSorted, DataArrayInt::indexOfSameConsecutiveValueGroups
5778    */
5779   template <class T>
5780   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::buildUnique() const
5781   {
5782     this->checkAllocated();
5783     if(this->getNumberOfComponents()!=1)
5784       throw INTERP_KERNEL::Exception("DataArrayInt::buildUnique : only single component allowed !");
5785     std::size_t nbOfElements(this->getNumberOfTuples());
5786     MCAuto<DataArrayType> tmp(DataArrayType::New());
5787     tmp->deepCopyFrom(*this);
5788     T *data(tmp->getPointer());
5789     T *last(std::unique(data,data+nbOfElements));
5790     MCAuto<DataArrayType> ret(DataArrayType::New());
5791     ret->alloc(std::distance(data,last),1);
5792     std::copy(data,last,ret->getPointer());
5793     return ret.retn();
5794   }
5795
5796   /*!
5797    * This method can be applied on allocated with one component DataArrayInt instance.
5798    * This method keep elements only once by keeping the same order in \a this that is not expected to be sorted.
5799    *
5800    * \return a newly allocated array that contain the result of the unique operation applied on \a this.
5801    *
5802    * \throw if \a this is not allocated or if \a this has not exactly one component.
5803    *
5804    * \sa DataArrayInt::buildUnique
5805    */
5806   template <class T>
5807   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::buildUniqueNotSorted() const
5808   {
5809     this->checkAllocated();
5810     if(this->getNumberOfComponents()!=1)
5811       throw INTERP_KERNEL::Exception("DataArrayInt::buildUniqueNotSorted : only single component allowed !");
5812     T minVal,maxVal;
5813     this->getMinMaxValues(minVal,maxVal);
5814     std::vector<bool> b(maxVal-minVal+1,false);
5815     const T *ptBg(this->begin()),*endBg(this->end());
5816     MCAuto<DataArrayType> ret(DataArrayType::New()); ret->alloc(0,1);
5817     for(const T *pt=ptBg;pt!=endBg;pt++)
5818       {
5819         if(!b[*pt-minVal])
5820           {
5821             ret->pushBackSilent(*pt);
5822             b[*pt-minVal]=true;
5823           }
5824       }
5825     ret->copyStringInfoFrom(*this);
5826     return ret.retn();
5827   }
5828
5829   /*!
5830    * Returns a new DataArrayInt which contains size of every of groups described by \a this
5831    * "index" array. Such "index" array is returned for example by
5832    * \ref MEDCoupling::MEDCouplingUMesh::buildDescendingConnectivity
5833    * "MEDCouplingUMesh::buildDescendingConnectivity" and
5834    * \ref MEDCoupling::MEDCouplingUMesh::getNodalConnectivityIndex
5835    * "MEDCouplingUMesh::getNodalConnectivityIndex" etc.
5836    * This method performs the reverse operation of DataArrayInt::computeOffsetsFull.
5837    *  \return DataArrayInt * - a new instance of DataArrayInt, whose number of tuples
5838    *          equals to \a this->getNumberOfComponents() - 1, and number of components is 1.
5839    *          The caller is to delete this array using decrRef() as it is no more needed.
5840    *  \throw If \a this is not allocated.
5841    *  \throw If \a this->getNumberOfComponents() != 1.
5842    *  \throw If \a this->getNumberOfTuples() < 2.
5843    *
5844    *  \b Example: <br>
5845    *         - this contains [1,3,6,7,7,9,15]
5846    *         - result array contains [2,3,1,0,2,6],
5847    *          where 2 = 3 - 1, 3 = 6 - 3, 1 = 7 - 6 etc.
5848    *
5849    * \sa DataArrayInt::computeOffsetsFull
5850    */
5851   template <class T>
5852   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::deltaShiftIndex() const
5853   {
5854     this->checkAllocated();
5855     if(this->getNumberOfComponents()!=1)
5856       throw INTERP_KERNEL::Exception("DataArrayInt::deltaShiftIndex : only single component allowed !");
5857     std::size_t nbOfElements=this->getNumberOfTuples();
5858     if(nbOfElements<2)
5859       throw INTERP_KERNEL::Exception("DataArrayInt::deltaShiftIndex : 1 tuple at least must be present in 'this' !");
5860     const T *ptr=this->getConstPointer();
5861     DataArrayType *ret=DataArrayType::New();
5862     ret->alloc(nbOfElements-1,1);
5863     T *out=ret->getPointer();
5864     std::transform(ptr+1,ptr+nbOfElements,ptr,out,std::minus<T>());
5865     return ret;
5866   }
5867
5868   /*!
5869    * Modifies \a this one-dimensional array so that value of each element \a x
5870    * of \a this array (\a a) is computed as \f$ x_i = \sum_{j=0}^{i-1} a[ j ] \f$.
5871    * Or: for each i>0 new[i]=new[i-1]+old[i-1] for i==0 new[i]=0. Number of tuples
5872    * and components remains the same.<br>
5873    * This method is useful for allToAllV in MPI with contiguous policy. This method
5874    * differs from computeOffsetsFull() in that the number of tuples is \b not changed by
5875    * this one.
5876    *  \throw If \a this is not allocated.
5877    *  \throw If \a this->getNumberOfComponents() != 1.
5878    *
5879    *  \b Example: <br>
5880    *          - Before \a this contains [3,5,1,2,0,8]
5881    *          - After \a this contains  [0,3,8,9,11,11]<br>
5882    *          Note that the last element 19 = 11 + 8 is missing because size of \a this
5883    *          array is retained and thus there is no space to store the last element.
5884    */
5885   template <class T>
5886   void DataArrayDiscrete<T>::computeOffsets()
5887   {
5888     this->checkAllocated();
5889     if(this->getNumberOfComponents()!=1)
5890       throw INTERP_KERNEL::Exception("DataArrayInt::computeOffsets : only single component allowed !");
5891     std::size_t nbOfElements=this->getNumberOfTuples();
5892     if(nbOfElements==0)
5893       return ;
5894     T *work=this->getPointer();
5895     T tmp=work[0];
5896     work[0]=0;
5897     for(std::size_t i=1;i<nbOfElements;i++)
5898       {
5899         T tmp2=work[i];
5900         work[i]=work[i-1]+tmp;
5901         tmp=tmp2;
5902       }
5903     this->declareAsNew();
5904   }
5905
5906   /*!
5907    * Modifies \a this one-dimensional array so that value of each element \a x
5908    * of \a this array (\a a) is computed as \f$ x_i = \sum_{j=0}^{i-1} a[ j ] \f$.
5909    * Or: for each i>0 new[i]=new[i-1]+old[i-1] for i==0 new[i]=0. Number
5910    * components remains the same and number of tuples is inceamented by one.<br>
5911    * This method is useful for allToAllV in MPI with contiguous policy. This method
5912    * differs from computeOffsets() in that the number of tuples is changed by this one.
5913    * This method performs the reverse operation of DataArrayInt::deltaShiftIndex.
5914    *  \throw If \a this is not allocated.
5915    *  \throw If \a this->getNumberOfComponents() != 1.
5916    *
5917    *  \b Example: <br>
5918    *          - Before \a this contains [3,5,1,2,0,8]
5919    *          - After \a this contains  [0,3,8,9,11,11,19]<br>
5920    * \sa DataArrayInt::deltaShiftIndex
5921    */
5922   template <class T>
5923   void DataArrayDiscrete<T>::computeOffsetsFull()
5924   {
5925     this->checkAllocated();
5926     if(this->getNumberOfComponents()!=1)
5927       throw INTERP_KERNEL::Exception("DataArrayInt::computeOffsetsFull : only single component allowed !");
5928     std::size_t nbOfElements=this->getNumberOfTuples();
5929     T *ret=(T *)malloc((nbOfElements+1)*sizeof(T));
5930     const T *work=this->getConstPointer();
5931     ret[0]=0;
5932     for(std::size_t i=0;i<nbOfElements;i++)
5933       ret[i+1]=work[i]+ret[i];
5934     this->useArray(ret,true,DeallocType::C_DEALLOC,nbOfElements+1,1);
5935     this->declareAsNew();
5936   }
5937
5938   /*!
5939    * Returns two new DataArrayInt instances whose contents is computed from that of \a this and \a listOfIds arrays as follows.
5940    * \a this is expected to be an offset format ( as returned by DataArrayInt::computeOffsetsFull ) that is to say with one component
5941    * and ** sorted strictly increasingly **. \a listOfIds is expected to be sorted ascendingly (not strictly needed for \a listOfIds).
5942    * This methods searches in \a this, considered as a set of contiguous \c this->getNumberOfComponents() ranges, all ids in \a listOfIds
5943    * filling completely one of the ranges in \a this.
5944    *
5945    * \param [in] listOfIds a list of ids that has to be sorted ascendingly.
5946    * \param [out] rangeIdsFetched the range ids fetched
5947    * \param [out] idsInInputListThatFetch contains the list of ids in \a listOfIds that are \b fully included in a range in \a this. So
5948    *              \a idsInInputListThatFetch is a part of input \a listOfIds.
5949    *
5950    * \sa DataArrayInt::computeOffsetsFull
5951    *
5952    *  \b Example: <br>
5953    *          - \a this : [0,3,7,9,15,18]
5954    *          - \a listOfIds contains  [0,1,2,3,7,8,15,16,17]
5955    *          - \a rangeIdsFetched result array: [0,2,4]
5956    *          - \a idsInInputListThatFetch result array: [0,1,2,7,8,15,16,17]
5957    * In this example id 3 in input \a listOfIds is alone so it do not appear in output \a idsInInputListThatFetch.
5958    * <br>
5959    */
5960   template <class T>
5961   void DataArrayDiscrete<T>::findIdsRangesInListOfIds(const DataArrayType *listOfIds, DataArrayIdType *& rangeIdsFetched, DataArrayType *& idsInInputListThatFetch) const
5962   {
5963     if(!listOfIds)
5964       throw INTERP_KERNEL::Exception("DataArrayInt::findIdsRangesInListOfIds : input list of ids is null !");
5965     listOfIds->checkAllocated(); this->checkAllocated();
5966     if(listOfIds->getNumberOfComponents()!=1)
5967       throw INTERP_KERNEL::Exception("DataArrayInt::findIdsRangesInListOfIds : input list of ids must have exactly one component !");
5968     if(this->getNumberOfComponents()!=1)
5969       throw INTERP_KERNEL::Exception("DataArrayInt::findIdsRangesInListOfIds : this must have exactly one component !");
5970     MCAuto<DataArrayIdType> ret0=DataArrayIdType::New(); ret0->alloc(0,1);
5971     MCAuto<DataArrayType> ret1=DataArrayType::New(); ret1->alloc(0,1);
5972     const T *tupPtr(listOfIds->begin()), *tupEnd(listOfIds->end());
5973     const T *offBg(this->begin()),*offEnd(this->end()-1);
5974     const T *offPtr(offBg);
5975     while(tupPtr!=tupEnd && offPtr!=offEnd)
5976       {
5977         if(*tupPtr==*offPtr)
5978           {
5979             T i=offPtr[0];
5980             while(i<offPtr[1] && *tupPtr==i && tupPtr!=tupEnd) { i++; tupPtr++; }
5981             if(i==offPtr[1])
5982               {
5983                 ret0->pushBackSilent(ToIdType(std::distance(offBg,offPtr)));
5984                 ret1->pushBackValsSilent(tupPtr-(offPtr[1]-offPtr[0]),tupPtr);
5985                 offPtr++;
5986               }
5987           }
5988         else
5989           { if(*tupPtr<*offPtr) tupPtr++; else offPtr++; }
5990       }
5991     rangeIdsFetched=ret0.retn();
5992     idsInInputListThatFetch=ret1.retn();
5993   }
5994
5995   /*!
5996    * Returns a new DataArrayInt whose contents is computed from that of \a this and \a
5997    * offsets arrays as follows. \a offsets is a one-dimensional array considered as an
5998    * "index" array of a "iota" array, thus, whose each element gives an index of a group
5999    * beginning within the "iota" array. And \a this is a one-dimensional array
6000    * considered as a selector of groups described by \a offsets to include into the result array.
6001    *  \throw If \a offsets is NULL.
6002    *  \throw If \a offsets is not allocated.
6003    *  \throw If \a offsets->getNumberOfComponents() != 1.
6004    *  \throw If \a offsets is not monotonically increasing.
6005    *  \throw If \a this is not allocated.
6006    *  \throw If \a this->getNumberOfComponents() != 1.
6007    *  \throw If any element of \a this is not a valid index for \a offsets array.
6008    *
6009    *  \b Example: <br>
6010    *          - \a this: [0,2,3]
6011    *          - \a offsets: [0,3,6,10,14,20]
6012    *          - result array: [0,1,2,6,7,8,9,10,11,12,13] == <br>
6013    *            \c range(0,3) + \c range(6,10) + \c range(10,14) ==<br>
6014    *            \c range( \a offsets[ \a this[0] ], offsets[ \a this[0]+1 ]) +
6015    *            \c range( \a offsets[ \a this[1] ], offsets[ \a this[1]+1 ]) +
6016    *            \c range( \a offsets[ \a this[2] ], offsets[ \a this[2]+1 ])
6017    */
6018   template <class T>
6019   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::buildExplicitArrByRanges(const DataArrayType *offsets) const
6020   {
6021     if(!offsets)
6022       throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrByRanges : DataArrayInt pointer in input is NULL !");
6023     this->checkAllocated();
6024     if(this->getNumberOfComponents()!=1)
6025       throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrByRanges : only single component allowed !");
6026     offsets->checkAllocated();
6027     if(offsets->getNumberOfComponents()!=1)
6028       throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrByRanges : input array should have only single component !");
6029     mcIdType othNbTuples=offsets->getNumberOfTuples()-1;
6030     mcIdType nbOfTuples=this->getNumberOfTuples();
6031     T retNbOftuples=0;
6032     const T *work=this->getConstPointer();
6033     const T *offPtr=offsets->getConstPointer();
6034     for(mcIdType i=0;i<nbOfTuples;i++)
6035       {
6036         T val=work[i];
6037         if(val>=0 && val<othNbTuples)
6038           {
6039             T delta=offPtr[val+1]-offPtr[val];
6040             if(delta>=0)
6041               retNbOftuples+=delta;
6042             else
6043               {
6044                 std::ostringstream oss; oss << "DataArrayInt::buildExplicitArrByRanges : Tuple #" << val << " of offset array has a delta < 0 !";
6045                 throw INTERP_KERNEL::Exception(oss.str().c_str());
6046               }
6047           }
6048         else
6049           {
6050             std::ostringstream oss; oss << "DataArrayInt::buildExplicitArrByRanges : Tuple #" << i << " in this contains " << val;
6051             oss << " whereas offsets array is of size " << othNbTuples+1 << " !";
6052             throw INTERP_KERNEL::Exception(oss.str().c_str());
6053           }
6054       }
6055     MCAuto<DataArrayType> ret=DataArrayType::New();
6056     ret->alloc(retNbOftuples,1);
6057     T *retPtr=ret->getPointer();
6058     for(mcIdType i=0;i<nbOfTuples;i++)
6059       {
6060         T val=work[i];
6061         T start=offPtr[val];
6062         T off=offPtr[val+1]-start;
6063         for(T j=0;j<off;j++,retPtr++)
6064           *retPtr=start+j;
6065       }
6066     return ret.retn();
6067   }
6068
6069   /*!
6070    * Returns a new DataArrayInt whose contents is computed using \a this that must be a
6071    * scaled array (monotonically increasing).
6072   from that of \a this and \a
6073    * offsets arrays as follows. \a offsets is a one-dimensional array considered as an
6074    * "index" array of a "iota" array, thus, whose each element gives an index of a group
6075    * beginning within the "iota" array. And \a this is a one-dimensional array
6076    * considered as a selector of groups described by \a offsets to include into the result array.
6077    *  \throw If \a  is NULL.
6078    *  \throw If \a this is not allocated.
6079    *  \throw If \a this->getNumberOfComponents() != 1.
6080    *  \throw If \a this->getNumberOfTuples() == 0.
6081    *  \throw If \a this is not monotonically increasing.
6082    *  \throw If any element of ids in ( \a bg \a stop \a step ) points outside the scale in \a this.
6083    *
6084    *  \b Example: <br>
6085    *          - \a bg , \a stop and \a step : (0,5,2)
6086    *          - \a this: [0,3,6,10,14,20]
6087    *          - result array: [0,0,0, 2,2,2,2, 4,4,4,4,4,4] == <br>
6088    */
6089   template <class T>
6090   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::buildExplicitArrOfSliceOnScaledArr(T bg, T stop, T step) const
6091   {
6092     if(!this->isAllocated())
6093       throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrOfSliceOnScaledArr : not allocated array !");
6094     if(this->getNumberOfComponents()!=1)
6095       throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrOfSliceOnScaledArr : number of components is expected to be equal to one !");
6096     mcIdType nbOfTuples(this->getNumberOfTuples());
6097     if(nbOfTuples==0)
6098       throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrOfSliceOnScaledArr : number of tuples must be != 0 !");
6099     const T *ids(this->begin());
6100     mcIdType nbOfEltsInSlc=DataArrayTools<T>::GetNumberOfItemGivenBESRelative(bg,stop,step,"DataArrayInt::buildExplicitArrOfSliceOnScaledArr");
6101     T sz(0),pos(bg);
6102     for(mcIdType i=0;i<nbOfEltsInSlc;i++,pos+=step)
6103       {
6104         if(pos>=0 && pos<nbOfTuples-1)
6105           {
6106             T delta(ids[pos+1]-ids[pos]);
6107             sz+=delta;
6108             if(delta<0)
6109               {
6110                 std::ostringstream oss; oss << "DataArrayInt::buildExplicitArrOfSliceOnScaledArr : At pos #" << i << " of input slice, value is " << pos << " and at this pos this is not monotonically increasing !";
6111                 throw INTERP_KERNEL::Exception(oss.str().c_str());
6112               }
6113           }
6114         else
6115           {
6116             std::ostringstream oss; oss << "DataArrayInt::buildExplicitArrOfSliceOnScaledArr : At pos #" << i << " of input slice, value is " << pos << " should be in [0," << nbOfTuples-1 << ") !";
6117             throw INTERP_KERNEL::Exception(oss.str().c_str());
6118           }
6119       }
6120     MCAuto<DataArrayType> ret(DataArrayType::New()); ret->alloc(sz,1);
6121     T *retPtr(ret->getPointer());
6122     pos=bg;
6123     for(mcIdType i=0;i<nbOfEltsInSlc;i++,pos+=step)
6124       {
6125         T delta(ids[pos+1]-ids[pos]);
6126         for(T j=0;j<delta;j++,retPtr++)
6127           *retPtr=pos;
6128       }
6129     return ret.retn();
6130   }
6131
6132   /*!
6133    * 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.
6134    * 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
6135    * in tuple **i** of returned DataArrayInt.
6136    * If ranges overlapped (in theory it should not) this method do not detect it and always returns the first range.
6137    *
6138    * 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)]
6139    * The return DataArrayInt will contain : **[0,4,1,2,2,3]**
6140    *
6141    * \param [in] ranges typically come from output of MEDCouplingUMesh::ComputeRangesFromTypeDistribution. Each range is specified like this : 1st component is
6142    *             for lower value included and 2nd component is the upper value of corresponding range **excluded**.
6143    * \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
6144    *        is thrown if no ranges in \a ranges contains value in \a this.
6145    *
6146    * \sa DataArrayInt::findIdInRangeForEachTuple
6147    */
6148   template <class T>
6149   DataArrayIdType *DataArrayDiscrete<T>::findRangeIdForEachTuple(const DataArrayType *ranges) const
6150   {
6151     if(!ranges)
6152       throw INTERP_KERNEL::Exception("DataArrayInt::findRangeIdForEachTuple : null input pointer !");
6153     if(ranges->getNumberOfComponents()!=2)
6154       throw INTERP_KERNEL::Exception("DataArrayInt::findRangeIdForEachTuple : input DataArrayInt instance should have 2 components !");
6155     this->checkAllocated();
6156     if(this->getNumberOfComponents()!=1)
6157       throw INTERP_KERNEL::Exception("DataArrayInt::findRangeIdForEachTuple : this should have only one component !");
6158     mcIdType nbTuples(this->getNumberOfTuples());
6159     MCAuto<DataArrayIdType> ret=DataArrayIdType::New(); ret->alloc(nbTuples,1);
6160     mcIdType nbOfRanges(ranges->getNumberOfTuples());
6161     const T *rangesPtr=ranges->getConstPointer();
6162     mcIdType *retPtr=ret->getPointer();
6163     const T *inPtr=this->getConstPointer();
6164     for(mcIdType i=0;i<nbTuples;i++,retPtr++)
6165       {
6166         T val=inPtr[i];
6167         bool found=false;
6168         for(mcIdType j=0;j<nbOfRanges && !found;j++)
6169           if(val>=rangesPtr[2*j] && val<rangesPtr[2*j+1])
6170             { *retPtr=j; found=true; }
6171         if(found)
6172           continue;
6173         else
6174           {
6175             std::ostringstream oss; oss << "DataArrayInt::findRangeIdForEachTuple : tuple #" << i << " not found by any ranges !";
6176             throw INTERP_KERNEL::Exception(oss.str().c_str());
6177           }
6178       }
6179     return ret.retn();
6180   }
6181
6182   /*!
6183    * 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.
6184    * 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
6185    * in tuple **i** of returned DataArrayInt.
6186    * If ranges overlapped (in theory it should not) this method do not detect it and always returns the sub position of the first range.
6187    *
6188    * 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)]
6189    * The return DataArrayInt will contain : **[1,2,4,0,2,2]**
6190    * This method is often called in pair with DataArrayInt::findRangeIdForEachTuple method.
6191    *
6192    * \param [in] ranges typically come from output of MEDCouplingUMesh::ComputeRangesFromTypeDistribution. Each range is specified like this : 1st component is
6193    *             for lower value included and 2nd component is the upper value of corresponding range **excluded**.
6194    * \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
6195    *        is thrown if no ranges in \a ranges contains value in \a this.
6196    * \sa DataArrayInt::findRangeIdForEachTuple
6197    */
6198   template <class T>
6199   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::findIdInRangeForEachTuple(const DataArrayType *ranges) const
6200   {
6201     if(!ranges)
6202       throw INTERP_KERNEL::Exception("DataArrayInt::findIdInRangeForEachTuple : null input pointer !");
6203     if(ranges->getNumberOfComponents()!=2)
6204       throw INTERP_KERNEL::Exception("DataArrayInt::findIdInRangeForEachTuple : input DataArrayInt instance should have 2 components !");
6205     this->checkAllocated();
6206     if(this->getNumberOfComponents()!=1)
6207       throw INTERP_KERNEL::Exception("DataArrayInt::findIdInRangeForEachTuple : this should have only one component !");
6208     mcIdType nbTuples=this->getNumberOfTuples();
6209     MCAuto<DataArrayType> ret=DataArrayType::New(); ret->alloc(nbTuples,1);
6210     mcIdType nbOfRanges=ranges->getNumberOfTuples();
6211     const T *rangesPtr=ranges->getConstPointer();
6212     T *retPtr=ret->getPointer();
6213     const T *inPtr=this->getConstPointer();
6214     for(mcIdType i=0;i<nbTuples;i++,retPtr++)
6215       {
6216         T val=inPtr[i];
6217         bool found=false;
6218         for(mcIdType j=0;j<nbOfRanges && !found;j++)
6219           if(val>=rangesPtr[2*j] && val<rangesPtr[2*j+1])
6220             { *retPtr=val-rangesPtr[2*j]; found=true; }
6221         if(found)
6222           continue;
6223         else
6224           {
6225             std::ostringstream oss; oss << "DataArrayInt::findIdInRangeForEachTuple : tuple #" << i << " not found by any ranges !";
6226             throw INTERP_KERNEL::Exception(oss.str().c_str());
6227           }
6228       }
6229     return ret.retn();
6230   }
6231
6232   /*!
6233    * \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).
6234    * 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).
6235    * 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 !
6236    * If this method has correctly worked, \a this will be able to be considered as a linked list.
6237    * This method does nothing if number of tuples is lower of equal to 1.
6238    *
6239    * This method is useful for users having an unstructured mesh having only SEG2 to rearrange internally the connectivity without any coordinates consideration.
6240    *
6241    * \sa MEDCouplingUMesh::orderConsecutiveCells1D, DataArrayInt::fromLinkedListOfPairToList
6242    */
6243   template <class T>
6244   void DataArrayDiscrete<T>::sortEachPairToMakeALinkedList()
6245   {
6246     this->checkAllocated();
6247     if(this->getNumberOfComponents()!=2)
6248       throw INTERP_KERNEL::Exception("DataArrayInt::sortEachPairToMakeALinkedList : Only works on DataArrayInt instance with nb of components equal to 2 !");
6249     mcIdType nbOfTuples(this->getNumberOfTuples());
6250     if(nbOfTuples<=1)
6251       return ;
6252     T *conn(this->getPointer());
6253     for(mcIdType i=1;i<nbOfTuples;i++,conn+=2)
6254       {
6255         if(i>1)
6256           {
6257             if(conn[2]==conn[3])
6258               {
6259                 std::ostringstream oss; oss << "DataArrayInt::sortEachPairToMakeALinkedList : In the tuple #" << i << " presence of a pair filled with same ids !";
6260                 throw INTERP_KERNEL::Exception(oss.str().c_str());
6261               }
6262             if(conn[2]!=conn[1] && conn[3]==conn[1] && conn[2]!=conn[0])
6263               std::swap(conn[2],conn[3]);
6264             //not(conn[2]==conn[1] && conn[3]!=conn[1] && conn[3]!=conn[0])
6265             if(conn[2]!=conn[1] || conn[3]==conn[1] || conn[3]==conn[0])
6266               {
6267                 std::ostringstream oss; oss << "DataArrayInt::sortEachPairToMakeALinkedList : In the tuple #" << i << " something is invalid !";
6268                 throw INTERP_KERNEL::Exception(oss.str().c_str());
6269               }
6270           }
6271         else
6272           {
6273             if(conn[0]==conn[1] || conn[2]==conn[3])
6274               throw INTERP_KERNEL::Exception("DataArrayInt::sortEachPairToMakeALinkedList : In the 2 first tuples presence of a pair filled with same ids !");
6275             T tmp[4];
6276             std::set<T> s;
6277             s.insert(conn,conn+4);
6278             if(s.size()!=3)
6279               throw INTERP_KERNEL::Exception("DataArrayInt::sortEachPairToMakeALinkedList : This can't be considered as a linked list regarding 2 first tuples !");
6280             if(std::count(conn,conn+4,conn[0])==2)
6281               {
6282                 tmp[0]=conn[1];
6283                 tmp[1]=conn[0];
6284                 tmp[2]=conn[0];
6285                 if(conn[2]==conn[0])
6286                   { tmp[3]=conn[3]; }
6287                 else
6288                   { tmp[3]=conn[2];}
6289                 std::copy(tmp,tmp+4,conn);
6290               }
6291             else
6292               {//here we are sure to have (std::count(conn,conn+4,conn[1])==2)
6293                 if(conn[1]==conn[3])
6294                   std::swap(conn[2],conn[3]);
6295               }
6296           }
6297       }
6298   }
6299
6300   /*!
6301    * \a this is expected to be a correctly linked list of pairs.
6302    *
6303    * \sa DataArrayInt::sortEachPairToMakeALinkedList
6304    */
6305   template <class T>
6306   MCAuto<typename Traits<T>::ArrayType> DataArrayDiscrete<T>::fromLinkedListOfPairToList() const
6307   {
6308     this->checkAllocated();
6309     this->checkNbOfComps(2,"DataArrayInt::fromLinkedListOfPairToList : this is expected to have 2 components");
6310     mcIdType nbTuples(this->getNumberOfTuples());
6311     if(nbTuples<1)
6312       throw INTERP_KERNEL::Exception("DataArrayInt::fromLinkedListOfPairToList : no tuples in this ! Not a linked list !");
6313     MCAuto<DataArrayType> ret(DataArrayType::New()); ret->alloc(nbTuples+1,1);
6314     const T *thisPtr(this->begin());
6315     T *retPtr(ret->getPointer());
6316     retPtr[0]=thisPtr[0];
6317     for(mcIdType i=0;i<nbTuples;i++)
6318       {
6319         retPtr[i+1]=thisPtr[2*i+1];
6320         if(i<nbTuples-1)
6321           if(thisPtr[2*i+1]!=thisPtr[2*(i+1)+0])
6322             {
6323               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 ?";
6324               throw INTERP_KERNEL::Exception(oss.str());
6325             }
6326       }
6327     return ret;
6328   }
6329
6330   /*!
6331    * This method returns all different values found in \a this. This method throws if \a this has not been allocated.
6332    * But the number of components can be different from one.
6333    * \return a newly allocated array (that should be dealt by the caller) containing different values in \a this.
6334    */
6335   template <class T>
6336   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::getDifferentValues() const
6337   {
6338     this->checkAllocated();
6339     std::set<T> ret;
6340     ret.insert(this->begin(),this->end());
6341     MCAuto<DataArrayType> ret2=DataArrayType::New();
6342     ret2->alloc(ret.size(),1);
6343     std::copy(ret.begin(),ret.end(),ret2->getPointer());
6344     return ret2.retn();
6345   }
6346
6347   /*!
6348    * This method is a refinement of DataArrayInt::getDifferentValues because it returns not only different values in \a this but also, for each of
6349    * them it tells which tuple id have this id.
6350    * This method works only on arrays with one component (if it is not the case call DataArrayInt::rearrange(1) ).
6351    * This method returns two arrays having same size.
6352    * 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.
6353    * 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]]
6354    */
6355   template <class T>
6356   std::vector<DataArrayIdType *> DataArrayDiscrete<T>::partitionByDifferentValues(std::vector<T>& differentIds) const
6357   {
6358     this->checkAllocated();
6359     if(this->getNumberOfComponents()!=1)
6360       throw INTERP_KERNEL::Exception("DataArrayInt::partitionByDifferentValues : this should have only one component !");
6361     mcIdType id=0;
6362     std::map<T,mcIdType> m,m2,m3;
6363     for(const T *w=this->begin();w!=this->end();w++)
6364       m[*w]++;
6365     differentIds.resize(m.size());
6366     std::vector<DataArrayIdType *> ret(m.size());
6367     std::vector<mcIdType *> retPtr(m.size());
6368     for(typename std::map<T,mcIdType>::const_iterator it=m.begin();it!=m.end();it++,id++)
6369       {
6370         m2[(*it).first]=id;
6371         ret[id]=DataArrayIdType::New();
6372         ret[id]->alloc((*it).second,1);
6373         retPtr[id]=ret[id]->getPointer();
6374         differentIds[id]=(*it).first;
6375       }
6376     id=0;
6377     for(const T *w=this->begin();w!=this->end();w++,id++)
6378       {
6379         retPtr[m2[*w]][m3[*w]++]=id;
6380       }
6381     return ret;
6382   }
6383
6384   /*!
6385    * This method split ids in [0, \c this->getNumberOfTuples() ) using \a this array as a field of weight (>=0 each).
6386    * The aim of this method is to return a set of \a nbOfSlices chunk of contiguous ids as balanced as possible.
6387    *
6388    * \param [in] nbOfSlices - number of slices expected.
6389    * \return - a vector having a size equal to \a nbOfSlices giving the start (included) and the stop (excluded) of each chunks.
6390    *
6391    * \sa DataArray::GetSlice
6392    * \throw If \a this is not allocated or not with exactly one component.
6393    * \throw If an element in \a this if < 0.
6394    */
6395   template <class T>
6396   std::vector< std::pair<mcIdType,mcIdType> > DataArrayDiscrete<T>::splitInBalancedSlices(mcIdType nbOfSlices) const
6397   {
6398     if(!this->isAllocated() || this->getNumberOfComponents()!=1)
6399       throw INTERP_KERNEL::Exception("DataArrayInt::splitInBalancedSlices : this array should have number of components equal to one and must be allocated !");
6400     if(nbOfSlices<=0)
6401       throw INTERP_KERNEL::Exception("DataArrayInt::splitInBalancedSlices : number of slices must be >= 1 !");
6402     T sum(this->accumulate((std::size_t)0));
6403     mcIdType nbOfTuples(this->getNumberOfTuples());
6404     T sumPerSlc(sum/FromIdType<T>(nbOfSlices));
6405     mcIdType pos(0);
6406     const T *w(this->begin());
6407     std::vector< std::pair<mcIdType,mcIdType> > ret(nbOfSlices);
6408     for(mcIdType i=0;i<nbOfSlices;i++)
6409       {
6410         std::pair<mcIdType, mcIdType> p(pos,-1);
6411         T locSum(0);
6412         while(locSum<sumPerSlc && pos<nbOfTuples) { pos++; locSum+=*w++; }
6413         if(i!=nbOfSlices-1)
6414           p.second=pos;
6415         else
6416           p.second=nbOfTuples;
6417         ret[i]=p;
6418       }
6419     return ret;
6420   }
6421
6422   /*!
6423    * Modify \a this array so that each value becomes a modulus of division of this value by
6424    * a value of another DataArrayInt. There are 3 valid cases.
6425    * 1.  The arrays have same number of tuples and components. Then each value of
6426    *    \a this array is divided by the corresponding value of \a other one, i.e.:
6427    *   _a_ [ i, j ] %= _other_ [ i, j ].
6428    * 2.  The arrays have same number of tuples and \a other array has one component. Then
6429    *   _a_ [ i, j ] %= _other_ [ i, 0 ].
6430    * 3.  The arrays have same number of components and \a other array has one tuple. Then
6431    *   _a_ [ i, j ] %= _a2_ [ 0, j ].
6432    *
6433    *  \warning No check of division by zero is performed!
6434    *  \param [in] other - a divisor array.
6435    *  \throw If \a other is NULL.
6436    *  \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples() and
6437    *         \a this->getNumberOfComponents() != \a other->getNumberOfComponents() and
6438    *         \a other has number of both tuples and components not equal to 1.
6439    */
6440   template <class T>
6441   void DataArrayDiscrete<T>::modulusEqual(const DataArrayType *other)
6442   {
6443     if(!other)
6444       throw INTERP_KERNEL::Exception("DataArrayInt::modulusEqual : input DataArrayInt instance is NULL !");
6445     const char *msg="Nb of tuples mismatch for DataArrayInt::modulusEqual !";
6446     this->checkAllocated(); other->checkAllocated();
6447     mcIdType nbOfTuple(this->getNumberOfTuples());
6448     mcIdType nbOfTuple2(other->getNumberOfTuples());
6449     std::size_t nbOfComp(this->getNumberOfComponents());
6450     std::size_t nbOfComp2(other->getNumberOfComponents());
6451     if(nbOfTuple==nbOfTuple2)
6452       {
6453         if(nbOfComp==nbOfComp2)
6454           {
6455             std::transform(this->begin(),this->end(),other->begin(),this->getPointer(),std::modulus<T>());
6456           }
6457         else if(nbOfComp2==1)
6458           {
6459             if(nbOfComp2==nbOfComp)
6460               {
6461                 T *ptr=this->getPointer();
6462                 const T *ptrc=other->getConstPointer();
6463                 for(mcIdType i=0;i<nbOfTuple;i++)
6464                   std::transform(ptr+i*nbOfComp,ptr+(i+1)*nbOfComp,ptr+i*nbOfComp,std::bind(std::modulus<T>(),std::placeholders::_1,*ptrc++));
6465               }
6466             else
6467               throw INTERP_KERNEL::Exception(msg);
6468           }
6469         else
6470           throw INTERP_KERNEL::Exception(msg);
6471       }
6472     else if(nbOfTuple2==1)
6473       {
6474         T *ptr=this->getPointer();
6475         const T *ptrc=other->getConstPointer();
6476         for(mcIdType i=0;i<nbOfTuple;i++)
6477           std::transform(ptr+i*nbOfComp,ptr+(i+1)*nbOfComp,ptrc,ptr+i*nbOfComp,std::modulus<T>());
6478       }
6479     else
6480       throw INTERP_KERNEL::Exception(msg);
6481     this->declareAsNew();
6482   }
6483
6484   /*!
6485    * Apply pow on values of another DataArrayInt to values of \a this one.
6486    *
6487    *  \param [in] other - an array to pow to \a this one.
6488    *  \throw If \a other is NULL.
6489    *  \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples()
6490    *  \throw If \a this->getNumberOfComponents() != 1 or \a other->getNumberOfComponents() != 1
6491    *  \throw If there is a negative value in \a other.
6492    */
6493   template <class T>
6494   void DataArrayDiscrete<T>::powEqual(const DataArrayType *other)
6495   {
6496     if(!other)
6497       throw INTERP_KERNEL::Exception("DataArrayInt::powEqual : input instance is null !");
6498     mcIdType nbOfTuple=this->getNumberOfTuples();
6499     mcIdType nbOfTuple2=other->getNumberOfTuples();
6500     std::size_t nbOfComp=this->getNumberOfComponents();
6501     std::size_t nbOfComp2=other->getNumberOfComponents();
6502     if(nbOfTuple!=nbOfTuple2)
6503       throw INTERP_KERNEL::Exception("DataArrayInt::powEqual : number of tuples mismatches !");
6504     if(nbOfComp!=1 || nbOfComp2!=1)
6505       throw INTERP_KERNEL::Exception("DataArrayInt::powEqual : number of components of both arrays must be equal to 1 !");
6506     T *ptr=this->getPointer();
6507     const T *ptrc=other->begin();
6508     for(mcIdType i=0;i<nbOfTuple;i++,ptrc++,ptr++)
6509       {
6510         if(*ptrc>=0)
6511           {
6512             T tmp=1;
6513             for(T j=0;j<*ptrc;j++)
6514               tmp*=*ptr;
6515             *ptr=tmp;
6516           }
6517         else
6518           {
6519             std::ostringstream oss; oss << "DataArrayInt::powEqual : on tuple #" << i << " of other value is < 0 (" << *ptrc << ") !";
6520             throw INTERP_KERNEL::Exception(oss.str().c_str());
6521           }
6522       }
6523     this->declareAsNew();
6524   }
6525
6526   ////////////////////////////////////
6527   /*!
6528    * Useless method for end user. Only for MPI/Corba/File serialsation for multi arrays class.
6529    * Server side.
6530    */
6531   template <class T>
6532   void DataArrayDiscrete<T>::getTinySerializationIntInformation(std::vector<mcIdType>& tinyInfo) const
6533   {
6534     tinyInfo.resize(2);
6535     if(this->isAllocated())
6536       {
6537         tinyInfo[0]=this->getNumberOfTuples();
6538         tinyInfo[1]=ToIdType(this->getNumberOfComponents());
6539       }
6540     else
6541       {
6542         tinyInfo[0]=-1;
6543         tinyInfo[1]=-1;
6544       }
6545   }
6546
6547   /*!
6548    * Useless method for end user. Only for MPI/Corba/File serialsation for multi arrays class.
6549    * Server side.
6550    */
6551   template <class T>
6552   void DataArrayDiscrete<T>::getTinySerializationStrInformation(std::vector<std::string>& tinyInfo) const
6553   {
6554     if(this->isAllocated())
6555       {
6556         std::size_t nbOfCompo(this->getNumberOfComponents());
6557         tinyInfo.resize(nbOfCompo+1);
6558         tinyInfo[0]=this->getName();
6559         for(std::size_t i=0;i<nbOfCompo;i++)
6560           tinyInfo[i+1]=this->getInfoOnComponent(i);
6561       }
6562     else
6563       {
6564         tinyInfo.resize(1);
6565         tinyInfo[0]=this->getName();
6566       }
6567   }
6568
6569   /*!
6570    * Useless method for end user. Only for MPI/Corba/File serialsation for multi arrays class.
6571    * This method returns if a feeding is needed.
6572    */
6573   template <class T>
6574   bool DataArrayDiscrete<T>::resizeForUnserialization(const std::vector<mcIdType>& tinyInfoI)
6575   {
6576     mcIdType nbOfTuple=tinyInfoI[0];
6577     mcIdType nbOfComp=tinyInfoI[1];
6578     if(nbOfTuple!=-1 || nbOfComp!=-1)
6579       {
6580         this->alloc(nbOfTuple,nbOfComp);
6581         return true;
6582       }
6583     return false;
6584   }
6585
6586   /*!
6587    * Useless method for end user. Only for MPI/Corba/File serialsation for multi arrays class.
6588    * This method returns if a feeding is needed.
6589    */
6590   template <class T>
6591   void DataArrayDiscrete<T>::finishUnserialization(const std::vector<mcIdType>& tinyInfoI, const std::vector<std::string>& tinyInfoS)
6592   {
6593     this->setName(tinyInfoS[0]);
6594     if(this->isAllocated())
6595       {
6596         mcIdType nbOfCompo=tinyInfoI[1];
6597         for(mcIdType i=0;i<nbOfCompo;i++)
6598           this->setInfoOnComponent(i,tinyInfoS[i+1]);
6599       }
6600   }
6601
6602   ////////////////////////////////////
6603
6604   /*!
6605    * Returns a new DataArrayInt that is the result of pow of two given arrays. There are 3
6606    * valid cases.
6607    *
6608    *  \param [in] a1 - an array to pow up.
6609    *  \param [in] a2 - another array to sum up.
6610    *  \return DataArrayInt * - the new instance of DataArrayInt.
6611    *          The caller is to delete this result array using decrRef() as it is no more
6612    *          needed.
6613    *  \throw If either \a a1 or \a a2 is NULL.
6614    *  \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples()
6615    *  \throw If \a a1->getNumberOfComponents() != 1 or \a a2->getNumberOfComponents() != 1.
6616    *  \throw If there is a negative value in \a a2.
6617    */
6618   template <class T>
6619   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::Pow(const DataArrayType *a1, const DataArrayType *a2)
6620   {
6621     if(!a1 || !a2)
6622       throw INTERP_KERNEL::Exception("DataArrayInt::Pow : at least one of input instances is null !");
6623     mcIdType nbOfTuple=a1->getNumberOfTuples();
6624     mcIdType nbOfTuple2=a2->getNumberOfTuples();
6625     std::size_t nbOfComp=a1->getNumberOfComponents();
6626     std::size_t nbOfComp2=a2->getNumberOfComponents();
6627     if(nbOfTuple!=nbOfTuple2)
6628       throw INTERP_KERNEL::Exception("DataArrayInt::Pow : number of tuples mismatches !");
6629     if(nbOfComp!=1 || nbOfComp2!=1)
6630       throw INTERP_KERNEL::Exception("DataArrayInt::Pow : number of components of both arrays must be equal to 1 !");
6631     MCAuto<DataArrayType> ret=DataArrayType::New(); ret->alloc(nbOfTuple,1);
6632     const T *ptr1(a1->begin()),*ptr2(a2->begin());
6633     T *ptr=ret->getPointer();
6634     for(mcIdType i=0;i<nbOfTuple;i++,ptr1++,ptr2++,ptr++)
6635       {
6636         if(*ptr2>=0)
6637           {
6638             T tmp=1;
6639             for(T j=0;j<*ptr2;j++)
6640               tmp*=*ptr1;
6641             *ptr=tmp;
6642           }
6643         else
6644           {
6645             std::ostringstream oss; oss << "DataArrayInt::Pow : on tuple #" << i << " of a2 value is < 0 (" << *ptr2 << ") !";
6646             throw INTERP_KERNEL::Exception(oss.str().c_str());
6647           }
6648       }
6649     return ret.retn();
6650   }
6651
6652   /*!
6653    * Returns a new DataArrayInt that is a modulus of two given arrays. There are 3
6654    * valid cases.
6655    * 1.  The arrays have same number of tuples and components. Then each value of
6656    *   the result array (_a_) is a division of the corresponding values of \a a1 and
6657    *   \a a2, i.e.: _a_ [ i, j ] = _a1_ [ i, j ] % _a2_ [ i, j ].
6658    * 2.  The arrays have same number of tuples and one array, say _a2_, has one
6659    *   component. Then
6660    *   _a_ [ i, j ] = _a1_ [ i, j ] % _a2_ [ i, 0 ].
6661    * 3.  The arrays have same number of components and one array, say _a2_, has one
6662    *   tuple. Then
6663    *   _a_ [ i, j ] = _a1_ [ i, j ] % _a2_ [ 0, j ].
6664    *
6665    * Info on components is copied either from the first array (in the first case) or from
6666    * the array with maximal number of elements (getNbOfElems()).
6667    *  \warning No check of division by zero is performed!
6668    *  \param [in] a1 - a dividend array.
6669    *  \param [in] a2 - a divisor array.
6670    *  \return DataArrayInt * - the new instance of DataArrayInt.
6671    *          The caller is to delete this result array using decrRef() as it is no more
6672    *          needed.
6673    *  \throw If either \a a1 or \a a2 is NULL.
6674    *  \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples() and
6675    *         \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents() and
6676    *         none of them has number of tuples or components equal to 1.
6677    */
6678   template <class T>
6679   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::Modulus(const DataArrayType *a1, const DataArrayType *a2)
6680   {
6681     if(!a1 || !a2)
6682       throw INTERP_KERNEL::Exception("DataArrayInt::Modulus : input DataArrayInt instance is NULL !");
6683     mcIdType nbOfTuple1(a1->getNumberOfTuples());
6684     mcIdType nbOfTuple2(a2->getNumberOfTuples());
6685     std::size_t nbOfComp1(a1->getNumberOfComponents());
6686     std::size_t nbOfComp2(a2->getNumberOfComponents());
6687     if(nbOfTuple2==nbOfTuple1)
6688       {
6689         if(nbOfComp1==nbOfComp2)
6690           {
6691             MCAuto<DataArrayType> ret=DataArrayType::New();
6692             ret->alloc(nbOfTuple2,nbOfComp1);
6693             std::transform(a1->begin(),a1->end(),a2->begin(),ret->getPointer(),std::modulus<T>());
6694             ret->copyStringInfoFrom(*a1);
6695             return ret.retn();
6696           }
6697         else if(nbOfComp2==1)
6698           {
6699             MCAuto<DataArrayType> ret=DataArrayType::New();
6700             ret->alloc(nbOfTuple1,nbOfComp1);
6701             const T *a2Ptr=a2->getConstPointer();
6702             const T *a1Ptr=a1->getConstPointer();
6703             T *res=ret->getPointer();
6704             for(mcIdType i=0;i<nbOfTuple1;i++)
6705               res=std::transform(a1Ptr+i*nbOfComp1,a1Ptr+(i+1)*nbOfComp1,res,std::bind(std::modulus<T>(),std::placeholders::_1,a2Ptr[i]));
6706             ret->copyStringInfoFrom(*a1);
6707             return ret.retn();
6708           }
6709         else
6710           {
6711             a1->checkNbOfComps(nbOfComp2,"Nb of components mismatch for array Modulus !");
6712             return 0;
6713           }
6714       }
6715     else if(nbOfTuple2==1)
6716       {
6717         a1->checkNbOfComps(nbOfComp2,"Nb of components mismatch for array Modulus !");
6718         MCAuto<DataArrayType> ret=DataArrayType::New();
6719         ret->alloc(nbOfTuple1,nbOfComp1);
6720         const T *a1ptr=a1->getConstPointer(),*a2ptr=a2->getConstPointer();
6721         T *pt=ret->getPointer();
6722         for(mcIdType i=0;i<nbOfTuple1;i++)
6723           pt=std::transform(a1ptr+i*nbOfComp1,a1ptr+(i+1)*nbOfComp1,a2ptr,pt,std::modulus<T>());
6724         ret->copyStringInfoFrom(*a1);
6725         return ret.retn();
6726       }
6727     else
6728       {
6729         a1->checkNbOfTuples(nbOfTuple2,"Nb of tuples mismatch for array Modulus !");//will always throw an exception
6730         return 0;
6731       }
6732   }
6733
6734   /*!
6735    * 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
6736    * input array \a ids2.
6737    * \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.
6738    * 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
6739    * inversely.
6740    * In case of success both assertion will be true (no throw) :
6741    * \c ids1->renumber(ret)->isEqual(ids2) where \a ret is the return of this method.
6742    * \c ret->transformWithIndArr(ids2)->isEqual(ids1)
6743    *
6744    * \b Example:
6745    * - \a ids1 : [3,1,103,4,6,10,-7,205]
6746    * - \a ids2 : [-7,1,205,10,6,3,103,4]
6747    * - \a return is : [5,1,6,7,4,3,0,2] because ids2[5]==ids1[0], ids2[1]==ids1[1], ids2[6]==ids1[2]...
6748    *
6749    * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
6750    *          array using decrRef() as it is no more needed.
6751    * \throw If either ids1 or ids2 is null not allocated or not with one components.
6752    *
6753    * \sa DataArrayInt::findIdForEach, DataArrayInt::FindPermutationFromFirstToSecondDuplicate, DataArrayInt::rankOfElementInThis
6754    */
6755   template<class T>
6756   DataArrayIdType *DataArrayDiscrete<T>::FindPermutationFromFirstToSecond(const DataArrayType *ids1, const DataArrayType *ids2)
6757   {
6758     if(!ids1 || !ids2)
6759       throw INTERP_KERNEL::Exception("DataArrayInt::FindPermutationFromFirstToSecond : the two input arrays must be not null !");
6760     if(!ids1->isAllocated() || !ids2->isAllocated())
6761       throw INTERP_KERNEL::Exception("DataArrayInt::FindPermutationFromFirstToSecond : the two input arrays must be allocated !");
6762     if(ids1->getNumberOfComponents()!=1 || ids2->getNumberOfComponents()!=1)
6763       throw INTERP_KERNEL::Exception("DataArrayInt::FindPermutationFromFirstToSecond : the two input arrays have exactly one component !");
6764     if(ids1->getNumberOfTuples()!=ids2->getNumberOfTuples())
6765       {
6766         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 !";
6767         throw INTERP_KERNEL::Exception(oss.str().c_str());
6768       }
6769     MCAuto<DataArrayType> c1(ids1->deepCopy());
6770     MCAuto<DataArrayType> c2(ids2->deepCopy());
6771     c1->sort(true); c2->sort(true);
6772     if(!c1->isEqualWithoutConsideringStr(*c2))
6773       throw INTERP_KERNEL::Exception("DataArrayInt::FindPermutationFromFirstToSecond : the two arrays are not lying on same ids ! Impossible to find a permutation between the 2 arrays !");
6774     MCAuto<DataArrayIdType> p1=ids1->checkAndPreparePermutation();
6775     MCAuto<DataArrayIdType> p2=ids2->checkAndPreparePermutation();
6776     p2=p2->invertArrayO2N2N2O(p2->getNumberOfTuples());
6777     p2=p2->selectByTupleIdSafe(p1->begin(),p1->end());
6778     return p2.retn();
6779   }
6780
6781   /*!
6782    * 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
6783    * input array \a ids2.
6784    * \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.
6785    * 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
6786    * inversely.
6787    * The difference with DataArrayInt::FindPermutationFromFirstToSecond is that this method supports multiple same values in \a ids1 and \a ids2 whereas 
6788    * DataArrayInt::FindPermutationFromFirstToSecond doesn't. It implies that this method my be slower than the DataArrayInt::FindPermutationFromFirstToSecond one.
6789    * 
6790    * In case of success both assertion will be true (no throw) :
6791    * \c ids1->renumber(ret)->isEqual(ids2) where \a ret is the return of this method.
6792    * \c ret->transformWithIndArr(ids2)->isEqual(ids1)
6793    *
6794    * \b Example:
6795    * - \a ids1 : [5, 3, 2, 1, 4, 5, 2, 1, 0, 11, 5, 4]
6796    * - \a ids2 : [0, 1, 1, 2, 2, 3, 4, 4, 5, 5, 5, 11]
6797    * - \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]...
6798    *
6799    * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
6800    *          array using decrRef() as it is no more needed.
6801    * \throw If either ids1 or ids2 is null not allocated or not with one components.
6802    *
6803    * \sa DataArrayInt::findIdForEach, DataArrayInt::FindPermutationFromFirstToSecond, DataArrayInt::occurenceRankInThis
6804    */
6805   template<class T>
6806   DataArrayIdType *DataArrayDiscrete<T>::FindPermutationFromFirstToSecondDuplicate(const DataArrayType *ids1, const DataArrayType *ids2)
6807   {
6808     if(!ids1 || !ids2)
6809       throw INTERP_KERNEL::Exception("DataArrayInt::FindPermutationFromFirstToSecondDuplicate : the two input arrays must be not null !");
6810     constexpr char MSG0[] = "DataArrayInt::FindPermutationFromFirstToSecondDuplicate :";
6811     ids1->checkAllocated(); ids2->checkAllocated();
6812     ids1->checkNbOfComps(1,MSG0); ids2->checkNbOfComps(1,MSG0);
6813     mcIdType nbTuples(ids1->getNumberOfTuples());
6814     if(nbTuples != ids2->getNumberOfTuples())
6815       {
6816         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 !";
6817         throw INTERP_KERNEL::Exception(oss.str().c_str());
6818       }
6819     MCAuto<DataArrayIdType> ret(DataArrayIdType::New()); ret->alloc(nbTuples,1);
6820     MCAuto<DataArrayIdType> oids2(ids2->occurenceRankInThis());
6821     std::map< std::pair<T,mcIdType>, mcIdType> m;
6822     mcIdType pos(0);
6823     const mcIdType *oids2Ptr(oids2->begin());
6824     for(const T * it2 = ids2->begin() ; it2 != ids2->end() ; ++it2, ++oids2Ptr, ++pos)
6825       m[{*it2,*oids2Ptr}] = pos;
6826     mcIdType *retPtr(ret->getPointer());
6827     //
6828     std::map<T,mcIdType> mOccurence1; // see DataArrayInt::occurenceRankInThis : avoid to compute additionnal temporary array
6829     //
6830     for(const T * it1 = ids1->begin() ; it1 != ids1->end() ; ++it1, ++retPtr)
6831     {
6832       auto it = mOccurence1.find(*it1);
6833       mcIdType occRk1;
6834       if( it == mOccurence1.end() )
6835       {
6836         occRk1 = 0;
6837         mOccurence1[*it1] = 1;
6838       }
6839       else
6840       {
6841         occRk1 = (*it).second++;
6842       }
6843       //
6844       auto it2 = m.find({*it1,occRk1});
6845       if(it2 != m.end())
6846       {
6847         *retPtr = (*it2).second;
6848       }
6849       else
6850       {
6851         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 !"; 
6852         throw INTERP_KERNEL::Exception(oss.str());
6853       }
6854       
6855     }
6856     return ret.retn();
6857   }
6858
6859   /*!
6860    * Returns a C array which is a renumbering map in "Old to New" mode for the input array.
6861    * This map, if applied to \a start array, would make it sorted. For example, if
6862    * \a start array contents are [9,10,0,6,4,11,3,7] then the contents of the result array is
6863    * [5,6,0,3,2,7,1,4].
6864    *  \param [in] start - pointer to the first element of the array for which the
6865    *         permutation map is computed.
6866    *  \param [in] end - pointer specifying the end of the array \a start, so that
6867    *         the last value of \a start is \a end[ -1 ].
6868    *  \return mcIdType * - the result permutation array that the caller is to delete as it is no
6869    *         more needed.
6870    *  \throw If there are equal values in the input array.
6871    */
6872   template<class T>
6873   mcIdType *DataArrayDiscrete<T>::CheckAndPreparePermutation(const T *start, const T *end)
6874   {
6875     std::size_t sz=std::distance(start,end);
6876     mcIdType *ret=(mcIdType *)malloc(sz*sizeof(mcIdType));
6877     T *work=new T[sz];
6878     std::copy(start,end,work);
6879     std::sort(work,work+sz);
6880     if(std::unique(work,work+sz)!=work+sz)
6881       {
6882         delete [] work;
6883         free(ret);
6884         throw INTERP_KERNEL::Exception("Some elements are equals in the specified array !");
6885       }
6886     std::map<T,mcIdType> m;
6887     for(T *workPt=work;workPt!=work+sz;workPt++)
6888       m[*workPt]=ToIdType(std::distance(work,workPt));
6889     mcIdType *iter2=ret;
6890     for(const T *iter=start;iter!=end;iter++,iter2++)
6891       *iter2=m[*iter];
6892     delete [] work;
6893     return ret;
6894   }
6895
6896   /*!
6897    * Returns a new DataArrayInt by concatenating two given arrays, so that (1) the number
6898    * of tuples in the result array is <em> a1->getNumberOfTuples() + a2->getNumberOfTuples() -
6899    * offsetA2</em> and (2)
6900    * the number of component in the result array is same as that of each of given arrays.
6901    * First \a offsetA2 tuples of \a a2 are skipped and thus are missing from the result array.
6902    * Info on components is copied from the first of the given arrays. Number of components
6903    * in the given arrays must be the same.
6904    *  \param [in] a1 - an array to include in the result array.
6905    *  \param [in] a2 - another array to include in the result array.
6906    *  \param [in] offsetA2 - number of tuples of \a a2 to skip.
6907    *  \return DataArrayInt * - the new instance of DataArrayInt.
6908    *          The caller is to delete this result array using decrRef() as it is no more
6909    *          needed.
6910    *  \throw If either \a a1 or \a a2 is NULL.
6911    *  \throw If \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents().
6912    */
6913   template <class T>
6914   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::Aggregate(const DataArrayType *a1, const DataArrayType *a2, T offsetA2)
6915   {
6916     if(!a1 || !a2)
6917       throw INTERP_KERNEL::Exception("DataArrayInt::Aggregate : input DataArrayInt instance is NULL !");
6918     std::size_t nbOfComp(a1->getNumberOfComponents());
6919     if(nbOfComp!=a2->getNumberOfComponents())
6920       throw INTERP_KERNEL::Exception("Nb of components mismatch for array Aggregation !");
6921     mcIdType nbOfTuple1(a1->getNumberOfTuples()),nbOfTuple2(a2->getNumberOfTuples());
6922     MCAuto<DataArrayType> ret(DataArrayType::New());
6923     ret->alloc(nbOfTuple1+nbOfTuple2-offsetA2,nbOfComp);
6924     T *pt=std::copy(a1->begin(),a1->end(),ret->getPointer());
6925     std::copy(a2->getConstPointer()+offsetA2*nbOfComp,a2->getConstPointer()+nbOfTuple2*nbOfComp,pt);
6926     ret->copyStringInfoFrom(*a1);
6927     return ret.retn();
6928   }
6929
6930   /*!
6931    * Returns a new DataArrayInt by concatenating all given arrays, so that (1) the number
6932    * of tuples in the result array is a sum of the number of tuples of given arrays and (2)
6933    * the number of component in the result array is same as that of each of given arrays.
6934    * Info on components is copied from the first of the given arrays. Number of components
6935    * in the given arrays must be  the same.
6936    * If the number of non null of elements in \a arr is equal to one the returned object is a copy of it
6937    * not the object itself.
6938    *  \param [in] arr - a sequence of arrays to include in the result array.
6939    *  \return DataArrayInt * - the new instance of DataArrayInt.
6940    *          The caller is to delete this result array using decrRef() as it is no more
6941    *          needed.
6942    *  \throw If all arrays within \a arr are NULL.
6943    *  \throw If getNumberOfComponents() of arrays within \a arr.
6944    */
6945   template <class T>
6946   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::Aggregate(const std::vector<const DataArrayType *>& arr)
6947   {
6948     std::vector<const DataArrayType *> a;
6949     for(typename std::vector<const DataArrayType *>::const_iterator it4=arr.begin();it4!=arr.end();it4++)
6950       if(*it4)
6951         a.push_back(*it4);
6952     if(a.empty())
6953       throw INTERP_KERNEL::Exception("DataArrayInt::Aggregate : input list must be NON EMPTY !");
6954     typename std::vector<const DataArrayType *>::const_iterator it=a.begin();
6955     std::size_t nbOfComp((*it)->getNumberOfComponents());
6956     mcIdType nbt((*it++)->getNumberOfTuples());
6957     for(;it!=a.end();it++)
6958       {
6959         if((*it)->getNumberOfComponents()!=nbOfComp)
6960           throw INTERP_KERNEL::Exception("DataArrayInt::Aggregate : Nb of components mismatch for array aggregation !");
6961         nbt+=(*it)->getNumberOfTuples();
6962       }
6963     MCAuto<DataArrayType> ret=DataArrayType::New();
6964     ret->alloc(nbt,nbOfComp);
6965     T *pt=ret->getPointer();
6966     for(it=a.begin();it!=a.end();it++)
6967       pt=std::copy((*it)->getConstPointer(),(*it)->getConstPointer()+(*it)->getNbOfElems(),pt);
6968     ret->copyStringInfoFrom(*(a[0]));
6969     return ret.retn();
6970   }
6971
6972   /*!
6973    * This method takes as input a list of DataArrayInt instances \a arrs that represent each a packed index arrays.
6974    * A packed index array is an allocated array with one component, and at least one tuple. The first element
6975    * of each array in \a arrs must be 0. Each array in \a arrs is expected to be increasingly monotonic.
6976    * 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.
6977    *
6978    * \return DataArrayInt * - a new object to be managed by the caller.
6979    */
6980   template <class T>
6981   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::AggregateIndexes(const std::vector<const DataArrayType *>& arrs)
6982   {
6983     mcIdType retSz=1;
6984     for(typename std::vector<const DataArrayType *>::const_iterator it4=arrs.begin();it4!=arrs.end();it4++)
6985       {
6986         if(*it4)
6987           {
6988             (*it4)->checkAllocated();
6989             if((*it4)->getNumberOfComponents()!=1)
6990               {
6991                 std::ostringstream oss; oss << "DataArrayInt::AggregateIndexes : presence of a DataArrayInt instance with nb of compo != 1 at pos " << std::distance(arrs.begin(),it4) << " !";
6992                 throw INTERP_KERNEL::Exception(oss.str().c_str());
6993               }
6994             mcIdType nbTupl((*it4)->getNumberOfTuples());
6995             if(nbTupl<1)
6996               {
6997                 std::ostringstream oss; oss << "DataArrayInt::AggregateIndexes : presence of a DataArrayInt instance with nb of tuples < 1 at pos " << std::distance(arrs.begin(),it4) << " !";
6998                 throw INTERP_KERNEL::Exception(oss.str().c_str());
6999               }
7000             if((*it4)->front()!=0)
7001               {
7002                 std::ostringstream oss; oss << "DataArrayInt::AggregateIndexes : presence of a DataArrayInt instance with front value != 0 at pos " << std::distance(arrs.begin(),it4) << " !";
7003                 throw INTERP_KERNEL::Exception(oss.str().c_str());
7004               }
7005             retSz+=nbTupl-1;
7006           }
7007         else
7008           {
7009             std::ostringstream oss; oss << "DataArrayInt::AggregateIndexes : presence of a null instance at pos " << std::distance(arrs.begin(),it4) << " !";
7010             throw INTERP_KERNEL::Exception(oss.str().c_str());
7011           }
7012       }
7013     if(arrs.empty())
7014       throw INTERP_KERNEL::Exception("DataArrayInt::AggregateIndexes : input list must be NON EMPTY !");
7015     MCAuto<DataArrayType> ret=DataArrayType::New();
7016     ret->alloc(retSz,1);
7017     T *pt=ret->getPointer(); *pt++=0;
7018     for(typename std::vector<const DataArrayType *>::const_iterator it=arrs.begin();it!=arrs.end();it++)
7019       pt=std::transform((*it)->begin()+1,(*it)->end(),pt,std::bind(std::plus<T>(),std::placeholders::_1,pt[-1]));
7020     ret->copyStringInfoFrom(*(arrs[0]));
7021     return ret.retn();
7022   }
7023
7024   /*!
7025    * Returns a new DataArrayInt which contains all elements of given one-dimensional
7026    * arrays. The result array does not contain any duplicates and its values
7027    * are sorted in ascending order.
7028    *  \param [in] arr - sequence of DataArrayInt's to unite.
7029    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
7030    *         array using decrRef() as it is no more needed.
7031    *  \throw If any \a arr[i] is not allocated.
7032    *  \throw If \a arr[i]->getNumberOfComponents() != 1.
7033    */
7034   template <class T>
7035   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::BuildUnion(const std::vector<const DataArrayType *>& arr)
7036   {
7037     std::vector<const DataArrayType *> a;
7038     for(typename std::vector<const DataArrayType *>::const_iterator it4=arr.begin();it4!=arr.end();it4++)
7039       if(*it4)
7040         a.push_back(*it4);
7041     for(typename std::vector<const DataArrayType *>::const_iterator it=a.begin();it!=a.end();it++)
7042       {
7043         (*it)->checkAllocated();
7044         if((*it)->getNumberOfComponents()!=1)
7045           throw INTERP_KERNEL::Exception("DataArrayInt::BuildUnion : only single component allowed !");
7046       }
7047     //
7048     std::set<T> r;
7049     for(typename std::vector<const DataArrayType *>::const_iterator it=a.begin();it!=a.end();it++)
7050       {
7051         const T *pt=(*it)->getConstPointer();
7052         mcIdType nbOfTuples((*it)->getNumberOfTuples());
7053         r.insert(pt,pt+nbOfTuples);
7054       }
7055     DataArrayType *ret=DataArrayType::New();
7056     ret->alloc(r.size(),1);
7057     std::copy(r.begin(),r.end(),ret->getPointer());
7058     return ret;
7059   }
7060
7061   /*!
7062    * Returns a new DataArrayInt which contains elements present in each of given one-dimensional
7063    * arrays. The result array does not contain any duplicates and its values
7064    * are sorted in ascending order.
7065    *  \param [in] arr - sequence of DataArrayInt's to intersect.
7066    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
7067    *         array using decrRef() as it is no more needed.
7068    *  \throw If any \a arr[i] is not allocated.
7069    *  \throw If \a arr[i]->getNumberOfComponents() != 1.
7070    */
7071   template <class T>
7072   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::BuildIntersection(const std::vector<const DataArrayType *>& arr)
7073   {
7074     std::vector<const DataArrayType *> a;
7075     for(typename std::vector<const DataArrayType *>::const_iterator it4=arr.begin();it4!=arr.end();it4++)
7076       if(*it4)
7077         a.push_back(*it4);
7078     for(typename std::vector<const DataArrayType *>::const_iterator it=a.begin();it!=a.end();it++)
7079       {
7080         (*it)->checkAllocated();
7081         if((*it)->getNumberOfComponents()!=1)
7082           throw INTERP_KERNEL::Exception("DataArrayInt::BuildIntersection : only single component allowed !");
7083       }
7084     //
7085     std::set<T> r;
7086     for(typename std::vector<const DataArrayType *>::const_iterator it=a.begin();it!=a.end();it++)
7087       {
7088         const T *pt=(*it)->getConstPointer();
7089         mcIdType nbOfTuples((*it)->getNumberOfTuples());
7090         std::set<T> s1(pt,pt+nbOfTuples);
7091         if(it!=a.begin())
7092           {
7093             std::set<T> r2;
7094             std::set_intersection(r.begin(),r.end(),s1.begin(),s1.end(),inserter(r2,r2.end()));
7095             r=r2;
7096           }
7097         else
7098           r=s1;
7099       }
7100     DataArrayType *ret(DataArrayType::New());
7101     ret->alloc(r.size(),1);
7102     std::copy(r.begin(),r.end(),ret->getPointer());
7103     return ret;
7104   }
7105
7106   /*!
7107    * This method allows to put a vector of vector of integer into a more compact data structure (skyline).
7108    * This method is not available into python because no available optimized data structure available to map std::vector< std::vector<mcIdType> >.
7109    *
7110    * \param [in] v the input data structure to be translate into skyline format.
7111    * \param [out] data the first element of the skyline format. The user is expected to deal with newly allocated array.
7112    * \param [out] dataIndex the second element of the skyline format.
7113    */
7114   template <class T>
7115   void DataArrayDiscrete<T>::PutIntoToSkylineFrmt(const std::vector< std::vector<T> >& v, DataArrayType *& data, DataArrayIdType *& dataIndex)
7116   {
7117     std::size_t sz(v.size());
7118     MCAuto<DataArrayType> retDat(DataArrayType::New());
7119     MCAuto<DataArrayIdType> retIdx(DataArrayIdType::New());
7120     retIdx->alloc(sz+1,1);
7121     mcIdType *ptid(retIdx->getPointer()); *ptid=0;
7122     for(std::size_t i=0;i<sz;i++,ptid++)
7123       ptid[1]=ptid[0]+ToIdType(v[i].size());
7124     retDat->alloc(retIdx->back(),1);
7125     T *pt=retDat->getPointer();
7126     for(std::size_t i=0;i<sz;i++)
7127       pt=std::copy(v[i].begin(),v[i].end(),pt);
7128     data=retDat.retn(); dataIndex=retIdx.retn();
7129   }
7130
7131   /*!
7132    * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
7133    * (\ref numbering-indirect).
7134    * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
7135    * The selection of extraction is done standardly in new2old format.
7136    * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
7137    *
7138    * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7139    * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7140    * \param [in] arrIn arr origin array from which the extraction will be done.
7141    * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7142    * \param [out] arrOut the resulting array
7143    * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7144    * \sa DataArrayInt::ExtractFromIndexedArraysSlice
7145    */
7146   template <class T>
7147   void DataArrayDiscrete<T>::ExtractFromIndexedArrays(const mcIdType *idsOfSelectBg, const mcIdType *idsOfSelectEnd,
7148                                                       const DataArrayType *arrIn, const DataArrayIdType *arrIndxIn,
7149                                                       DataArrayType* &arrOut, DataArrayIdType* &arrIndexOut)
7150   {
7151     if(!arrIn || !arrIndxIn)
7152       throw INTERP_KERNEL::Exception("DataArrayInt::ExtractFromIndexedArrays : input pointer is NULL !");
7153     arrIn->checkAllocated(); arrIndxIn->checkAllocated();
7154     if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
7155       throw INTERP_KERNEL::Exception("DataArrayInt::ExtractFromIndexedArrays : input arrays must have exactly one component !");
7156     std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
7157     const T *arrInPtr=arrIn->begin();
7158     const mcIdType *arrIndxPtr=arrIndxIn->begin();
7159     mcIdType nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
7160     if(nbOfGrps<0)
7161       throw INTERP_KERNEL::Exception("DataArrayInt::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
7162     mcIdType maxSizeOfArr(arrIn->getNumberOfTuples());
7163     MCAuto<DataArrayType> arro=DataArrayType::New();
7164     MCAuto<DataArrayIdType> arrIo=DataArrayIdType::New();
7165     arrIo->alloc(sz+1,1);
7166     const mcIdType *idsIt=idsOfSelectBg;
7167     mcIdType *work=arrIo->getPointer();
7168     *work++=0;
7169     mcIdType lgth=0;
7170     for(std::size_t i=0;i<sz;i++,work++,idsIt++)
7171       {
7172         if(*idsIt>=0 && *idsIt<nbOfGrps)
7173           lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
7174         else
7175           {
7176             std::ostringstream oss; oss << "DataArrayInt::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
7177             throw INTERP_KERNEL::Exception(oss.str());
7178           }
7179         if(lgth>=work[-1])
7180           *work=lgth;
7181         else
7182           {
7183             std::ostringstream oss; oss << "DataArrayInt::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
7184             oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
7185             throw INTERP_KERNEL::Exception(oss.str());
7186           }
7187       }
7188     arro->alloc(lgth,1);
7189     T *data=arro->getPointer();
7190     idsIt=idsOfSelectBg;
7191     for(std::size_t i=0;i<sz;i++,idsIt++)
7192       {
7193         if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
7194           data=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],data);
7195         else
7196           {
7197             std::ostringstream oss; oss << "DataArrayInt::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
7198             oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
7199             throw INTERP_KERNEL::Exception(oss.str());
7200           }
7201       }
7202     arrOut=arro.retn();
7203     arrIndexOut=arrIo.retn();
7204   }
7205
7206   /*!
7207    * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
7208    * (\ref numbering-indirect).
7209    * 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 ).
7210    * The selection of extraction is done standardly in new2old format.
7211    * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
7212    *
7213    * \param [in] idsOfSelectStart begin of set of ids of the input extraction (included)
7214    * \param [in] idsOfSelectStop end of set of ids of the input extraction (excluded)
7215    * \param [in] idsOfSelectStep step of set of ids of the input extraction
7216    * \param [in] arrIn arr origin array from which the extraction will be done.
7217    * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7218    * \param [out] arrOut the resulting array
7219    * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7220    * \sa DataArrayInt::ExtractFromIndexedArrays
7221    */
7222   template <class T>
7223   void DataArrayDiscrete<T>::ExtractFromIndexedArraysSlice(mcIdType idsOfSelectStart, mcIdType idsOfSelectStop, mcIdType idsOfSelectStep,
7224                                                            const DataArrayType *arrIn, const DataArrayIdType *arrIndxIn,
7225                                                            DataArrayType* &arrOut, DataArrayIdType* &arrIndexOut)
7226   {
7227     if(!arrIn || !arrIndxIn)
7228       throw INTERP_KERNEL::Exception("DataArrayInt::ExtractFromIndexedArraysSlice : input pointer is NULL !");
7229     arrIn->checkAllocated(); arrIndxIn->checkAllocated();
7230     if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
7231       throw INTERP_KERNEL::Exception("DataArrayInt::ExtractFromIndexedArraysSlice : input arrays must have exactly one component !");
7232     mcIdType sz=DataArray::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArraysSlice : Input slice ");
7233     const T *arrInPtr=arrIn->begin();
7234     const mcIdType *arrIndxPtr=arrIndxIn->begin();
7235     mcIdType nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
7236     if(nbOfGrps<0)
7237       throw INTERP_KERNEL::Exception("DataArrayInt::ExtractFromIndexedArraysSlice : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
7238     mcIdType maxSizeOfArr(arrIn->getNumberOfTuples());
7239     MCAuto<DataArrayType> arro=DataArrayType::New();
7240     MCAuto<DataArrayIdType> arrIo=DataArrayIdType::New();
7241     arrIo->alloc(sz+1,1);
7242     mcIdType idsIt=idsOfSelectStart;
7243     mcIdType *work=arrIo->getPointer();
7244     *work++=0;
7245     mcIdType lgth=0;
7246     for(mcIdType i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
7247       {
7248         if(idsIt>=0 && idsIt<nbOfGrps)
7249           lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
7250         else
7251           {
7252             std::ostringstream oss; oss << "DataArrayInt::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
7253             throw INTERP_KERNEL::Exception(oss.str());
7254           }
7255         if(lgth>=work[-1])
7256           *work=lgth;
7257         else
7258           {
7259             std::ostringstream oss; oss << "DataArrayInt::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
7260             oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
7261             throw INTERP_KERNEL::Exception(oss.str());
7262           }
7263       }
7264     arro->alloc(lgth,1);
7265     T *data=arro->getPointer();
7266     idsIt=idsOfSelectStart;
7267     for(mcIdType i=0;i<sz;i++,idsIt+=idsOfSelectStep)
7268       {
7269         if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
7270           data=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],data);
7271         else
7272           {
7273             std::ostringstream oss; oss << "DataArrayInt::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
7274             oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
7275             throw INTERP_KERNEL::Exception(oss.str());
7276           }
7277       }
7278     arrOut=arro.retn();
7279     arrIndexOut=arrIo.retn();
7280   }
7281
7282   /*!
7283    * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7284    * 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
7285    * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
7286    * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitly a result output arrays.
7287    *
7288    * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7289    * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7290    * \param [in] arrIn arr origin array from which the extraction will be done.
7291    * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7292    * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
7293    * \param [in] srcArrIndex index array of \b srcArr
7294    * \param [out] arrOut the resulting array
7295    * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7296    *
7297    * \sa DataArrayInt::SetPartOfIndexedArraysSameIdx
7298    */
7299   template <class T>
7300   void DataArrayDiscrete<T>::SetPartOfIndexedArrays(const mcIdType *idsOfSelectBg, const mcIdType *idsOfSelectEnd,
7301                                                     const DataArrayType *arrIn, const DataArrayIdType *arrIndxIn,
7302                                                     const DataArrayType *srcArr, const DataArrayIdType *srcArrIndex,
7303                                                     DataArrayType* &arrOut, DataArrayIdType* &arrIndexOut)
7304   {
7305     if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7306       throw INTERP_KERNEL::Exception("DataArrayInt::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
7307     MCAuto<DataArrayType> arro=DataArrayType::New();
7308     MCAuto<DataArrayIdType> arrIo=DataArrayIdType::New();
7309     mcIdType nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7310     std::vector<bool> v(nbOfTuples,true);
7311     mcIdType offset=0;
7312     const mcIdType *arrIndxInPtr=arrIndxIn->begin();
7313     const mcIdType *srcArrIndexPtr=srcArrIndex->begin();
7314     for(const mcIdType *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
7315       {
7316         if(*it>=0 && *it<nbOfTuples)
7317           {
7318             v[*it]=false;
7319             offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
7320           }
7321         else
7322           {
7323             std::ostringstream oss; oss << "DataArrayInt::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
7324             throw INTERP_KERNEL::Exception(oss.str());
7325           }
7326       }
7327     srcArrIndexPtr=srcArrIndex->begin();
7328     arrIo->alloc(nbOfTuples+1,1);
7329     arro->alloc(arrIn->getNumberOfTuples()+offset,1);
7330     const T *arrInPtr=arrIn->begin();
7331     const T *srcArrPtr=srcArr->begin();
7332     mcIdType *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
7333     T *arroPtr=arro->getPointer();
7334     for(mcIdType ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
7335       {
7336         if(v[ii])
7337           {
7338             arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
7339             *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
7340           }
7341         else
7342           {
7343             std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
7344             arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
7345             *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
7346           }
7347       }
7348     arrOut=arro.retn();
7349     arrIndexOut=arrIo.retn();
7350   }
7351
7352   /*!
7353    * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7354    * 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
7355    * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
7356    * This method is an generalization of DataArrayInt::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitly a result output arrays.
7357    *
7358    * \param [in] start begin of set of ids of the input extraction (included)
7359    * \param [in] end end of set of ids of the input extraction (excluded)
7360    * \param [in] step step of the set of ids in range mode.
7361    * \param [in] arrIn arr origin array from which the extraction will be done.
7362    * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7363    * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
7364    * \param [in] srcArrIndex index array of \b srcArr
7365    * \param [out] arrOut the resulting array
7366    * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7367    *
7368    * \sa DataArrayInt::SetPartOfIndexedArraysSameIdx DataArrayInt::SetPartOfIndexedArrays
7369    */
7370   template <class T>
7371   void DataArrayDiscrete<T>::SetPartOfIndexedArraysSlice(mcIdType start, mcIdType end, mcIdType step,
7372                                                          const DataArrayType *arrIn, const DataArrayIdType *arrIndxIn,
7373                                                          const DataArrayType *srcArr, const DataArrayIdType *srcArrIndex,
7374                                                          DataArrayType* &arrOut, DataArrayIdType* &arrIndexOut)
7375   {
7376     if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7377       throw INTERP_KERNEL::Exception("DataArrayInt::SetPartOfIndexedArraysSlice : presence of null pointer in input parameter !");
7378     MCAuto<DataArrayType> arro=DataArrayType::New();
7379     MCAuto<DataArrayIdType> arrIo=DataArrayIdType::New();
7380     mcIdType nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7381     mcIdType offset=0;
7382     const mcIdType *arrIndxInPtr=arrIndxIn->begin();
7383     const mcIdType *srcArrIndexPtr=srcArrIndex->begin();
7384     mcIdType nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"DataArrayInt::SetPartOfIndexedArraysSlice : ");
7385     mcIdType it=start;
7386     for(mcIdType i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
7387       {
7388         if(it>=0 && it<nbOfTuples)
7389           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
7390         else
7391           {
7392             std::ostringstream oss; oss << "DataArrayInt::SetPartOfIndexedArraysSlice : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
7393             throw INTERP_KERNEL::Exception(oss.str());
7394           }
7395       }
7396     srcArrIndexPtr=srcArrIndex->begin();
7397     arrIo->alloc(nbOfTuples+1,1);
7398     arro->alloc(arrIn->getNumberOfTuples()+offset,1);
7399     const T *arrInPtr=arrIn->begin();
7400     const T *srcArrPtr=srcArr->begin();
7401     mcIdType *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
7402     T *arroPtr=arro->getPointer();
7403     for(mcIdType ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
7404       {
7405         mcIdType pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
7406         if(pos<0)
7407           {
7408             arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
7409             *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
7410           }
7411         else
7412           {
7413             arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
7414             *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
7415           }
7416       }
7417     arrOut=arro.retn();
7418     arrIndexOut=arrIo.retn();
7419   }
7420
7421   /*!
7422    * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7423    * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignment do not modify the index in \b arrIndxIn.
7424    *
7425    * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7426    * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7427    * \param [in,out] arrInOut arr origin array from which the extraction will be done.
7428    * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7429    * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
7430    * \param [in] srcArrIndex index array of \b srcArr
7431    *
7432    * \sa DataArrayInt::SetPartOfIndexedArrays
7433    */
7434   template <class T>
7435   void DataArrayDiscrete<T>::SetPartOfIndexedArraysSameIdx(const mcIdType *idsOfSelectBg, const mcIdType *idsOfSelectEnd,
7436                                                            DataArrayType *arrInOut, const DataArrayIdType *arrIndxIn,
7437                                                            const DataArrayType *srcArr, const DataArrayIdType *srcArrIndex)
7438   {
7439     if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7440       throw INTERP_KERNEL::Exception("DataArrayInt::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
7441     mcIdType nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7442     const mcIdType *arrIndxInPtr=arrIndxIn->begin();
7443     const mcIdType *srcArrIndexPtr=srcArrIndex->begin();
7444     T *arrInOutPtr=arrInOut->getPointer();
7445     const T *srcArrPtr=srcArr->begin();
7446     for(const mcIdType *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
7447       {
7448         if(*it>=0 && *it<nbOfTuples)
7449           {
7450             if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
7451               std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
7452             else
7453               {
7454                 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] !";
7455                 throw INTERP_KERNEL::Exception(oss.str());
7456               }
7457           }
7458         else
7459           {
7460             std::ostringstream oss; oss << "DataArrayInt::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
7461             throw INTERP_KERNEL::Exception(oss.str());
7462           }
7463       }
7464   }
7465
7466   /*!
7467    * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7468    * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignment do not modify the index in \b arrIndxIn.
7469    *
7470    * \param [in] start begin of set of ids of the input extraction (included)
7471    * \param [in] end end of set of ids of the input extraction (excluded)
7472    * \param [in] step step of the set of ids in range mode.
7473    * \param [in,out] arrInOut arr origin array from which the extraction will be done.
7474    * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7475    * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
7476    * \param [in] srcArrIndex index array of \b srcArr
7477    *
7478    * \sa DataArrayInt::SetPartOfIndexedArraysSlice DataArrayInt::SetPartOfIndexedArraysSameIdx
7479    */
7480   template <class T>
7481   void DataArrayDiscrete<T>::SetPartOfIndexedArraysSameIdxSlice(mcIdType start, mcIdType end, mcIdType step,
7482                                                                 DataArrayType *arrInOut, const DataArrayIdType *arrIndxIn,
7483                                                                 const DataArrayType *srcArr, const DataArrayIdType *srcArrIndex)
7484   {
7485     if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7486       throw INTERP_KERNEL::Exception("DataArrayInt::SetPartOfIndexedArraysSameIdxSlice : presence of null pointer in input parameter !");
7487     mcIdType nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7488     const mcIdType *arrIndxInPtr=arrIndxIn->begin();
7489     const mcIdType *srcArrIndexPtr=srcArrIndex->begin();
7490     T *arrInOutPtr=arrInOut->getPointer();
7491     const T *srcArrPtr=srcArr->begin();
7492     mcIdType nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"DataArrayInt::SetPartOfIndexedArraysSameIdxSlice : ");
7493     mcIdType it=start;
7494     for(mcIdType i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
7495       {
7496         if(it>=0 && it<nbOfTuples)
7497           {
7498             if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
7499               std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
7500             else
7501               {
7502                 std::ostringstream oss; oss << "DataArrayInt::SetPartOfIndexedArraysSameIdxSlice : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
7503                 throw INTERP_KERNEL::Exception(oss.str());
7504               }
7505           }
7506         else
7507           {
7508             std::ostringstream oss; oss << "DataArrayInt::SetPartOfIndexedArraysSameIdxSlice : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
7509             throw INTERP_KERNEL::Exception(oss.str());
7510           }
7511       }
7512   }
7513
7514   /*!
7515    * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
7516    * 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.
7517    *
7518    * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
7519    * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
7520    * \param [in,out] arr array in which the remove operation will be done.
7521    * \param [in,out] arrIndx array in the remove operation will modify
7522    * \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])
7523    * \return true if \b arr and \b arrIndx have been modified, false if not.
7524    */
7525   template <class T>
7526   bool DataArrayDiscrete<T>::RemoveIdsFromIndexedArrays(const T *idsToRemoveBg, const T *idsToRemoveEnd,
7527                                                         DataArrayType *arr, DataArrayIdType *arrIndx, mcIdType offsetForRemoval)
7528   {
7529     if(!arrIndx || !arr)
7530       throw INTERP_KERNEL::Exception("DataArrayInt::RemoveIdsFromIndexedArrays : some input arrays are empty !");
7531     if(offsetForRemoval<0)
7532       throw INTERP_KERNEL::Exception("DataArrayInt::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
7533     std::set<T> s(idsToRemoveBg,idsToRemoveEnd);
7534     mcIdType nbOfGrps=arrIndx->getNumberOfTuples()-1;
7535     mcIdType *arrIPtr=arrIndx->getPointer();
7536     *arrIPtr++=0;
7537     mcIdType previousArrI=0;
7538     const T *arrPtr=arr->begin();
7539     std::vector<T> arrOut;//no utility to switch to DataArrayInt because copy always needed
7540     for(mcIdType i=0;i<nbOfGrps;i++,arrIPtr++)
7541       {
7542         if(*arrIPtr-previousArrI>offsetForRemoval)
7543           {
7544             for(const T *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
7545               {
7546                 if(s.find(*work)==s.end())
7547                   arrOut.push_back(*work);
7548               }
7549           }
7550         previousArrI=*arrIPtr;
7551         *arrIPtr=ToIdType(arrOut.size());
7552       }
7553     if(arr->getNumberOfTuples()==ToIdType(arrOut.size()))
7554       return false;
7555     arr->alloc(arrOut.size(),1);
7556     std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
7557     return true;
7558   }
7559
7560   /*!
7561    * Returns a new DataArrayInt containing an arithmetic progression
7562    * that is equal to the sequence returned by Python \c range(\a begin,\a  end,\a  step )
7563    * function.
7564    *  \param [in] begin - the start value of the result sequence.
7565    *  \param [in] end - limiting value, so that every value of the result array is less than
7566    *              \a end.
7567    *  \param [in] step - specifies the increment or decrement.
7568    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
7569    *          array using decrRef() as it is no more needed.
7570    *  \throw If \a step == 0.
7571    *  \throw If \a end < \a begin && \a step > 0.
7572    *  \throw If \a end > \a begin && \a step < 0.
7573    */
7574   template <class T>
7575   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::Range(T begin, T end, T step)
7576   {
7577     mcIdType nbOfTuples=DataArrayTools<T>::GetNumberOfItemGivenBESRelative(begin,end,step,"DataArrayInt::Range");
7578     MCAuto<DataArrayType> ret=DataArrayType::New();
7579     ret->alloc(nbOfTuples,1);
7580     T *ptr=ret->getPointer();
7581     if(step>0)
7582       {
7583         for(T i=begin;i<end;i+=step,ptr++)
7584           *ptr=i;
7585       }
7586     else
7587       {
7588         for(T i=begin;i>end;i+=step,ptr++)
7589           *ptr=i;
7590       }
7591     return ret.retn();
7592   }
7593
7594   /*!
7595    * Returns a new DataArrayInt containing a renumbering map in "Old to New" mode computed
7596    * from a zip representation of a surjective format (returned e.g. by
7597    * \ref MEDCoupling::DataArrayDouble::findCommonTuples() "DataArrayDouble::findCommonTuples()"
7598    * for example). The result array minimizes the permutation. <br>
7599    * For more info on renumbering see \ref numbering. <br>
7600    * \b Example: <br>
7601    * - \a nbOfOldTuples: 10
7602    * - \a arr          : [0,3, 5,7,9]
7603    * - \a arrIBg       : [0,2,5]
7604    * - \a newNbOfTuples: 7
7605    * - result array    : [0,1,2,0,3,4,5,4,6,4]
7606    *
7607    *  \param [in] nbOfOldTuples - number of tuples in the initial array \a arr.
7608    *  \param [in] arr - the array of tuple indices grouped by \a arrIBg array.
7609    *  \param [in] arrIBg - the array dividing all indices stored in \a arr into groups of
7610    *         (indices of) equal values. Its every element (except the last one) points to
7611    *         the first element of a group of equal values.
7612    *  \param [in] arrIEnd - specifies the end of \a arrIBg, so that the last element of \a
7613    *          arrIBg is \a arrIEnd[ -1 ].
7614    *  \param [out] newNbOfTuples - number of tuples after surjection application.
7615    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
7616    *          array using decrRef() as it is no more needed.
7617    *  \throw If any value of \a arr breaks condition ( 0 <= \a arr[ i ] < \a nbOfOldTuples ).
7618    */
7619   template <class T>
7620   DataArrayIdType *DataArrayDiscrete<T>::ConvertIndexArrayToO2N(mcIdType nbOfOldTuples, const mcIdType *arr, const mcIdType *arrIBg, const mcIdType *arrIEnd, mcIdType &newNbOfTuples)
7621   {
7622     MCAuto<DataArrayIdType> ret=DataArrayIdType::New();
7623     ret->alloc(nbOfOldTuples,1);
7624     mcIdType *pt=ret->getPointer();
7625     std::fill(pt,pt+nbOfOldTuples,-1);
7626     mcIdType nbOfGrps=ToIdType(std::distance(arrIBg,arrIEnd))-1;
7627     const mcIdType *cIPtr=arrIBg;
7628     for(mcIdType i=0;i<nbOfGrps;i++)
7629       pt[arr[cIPtr[i]]]=-(i+2);
7630     mcIdType newNb=0;
7631     for(mcIdType iNode=0;iNode<nbOfOldTuples;iNode++)
7632       {
7633         if(pt[iNode]<0)
7634           {
7635             if(pt[iNode]==-1)
7636               pt[iNode]=newNb++;
7637             else
7638               {
7639                 mcIdType grpId=-(pt[iNode]+2);
7640                 for(mcIdType j=cIPtr[grpId];j<cIPtr[grpId+1];j++)
7641                   {
7642                     if(arr[j]>=0 && arr[j]<nbOfOldTuples)
7643                       pt[arr[j]]=newNb;
7644                     else
7645                       {
7646                         std::ostringstream oss; oss << "DataArrayInt::ConvertIndexArrayToO2N : With element #" << j << " value is " << arr[j] << " should be in [0," << nbOfOldTuples << ") !";
7647                         throw INTERP_KERNEL::Exception(oss.str().c_str());
7648                       }
7649                   }
7650                 newNb++;
7651               }
7652           }
7653       }
7654     newNbOfTuples=newNb;
7655     return ret.retn();
7656   }
7657
7658   /*!
7659    * Returns a new DataArrayInt which is a minimal partition of elements of \a groups.
7660    * The i-th item of the result array is an ID of a set of elements belonging to a
7661    * unique set of groups, which the i-th element is a part of. This set of elements
7662    * belonging to a unique set of groups is called \a family, so the result array contains
7663    * IDs of families each element belongs to.
7664    *
7665    * \b Example: if we have two groups of elements: \a group1 [0,4] and \a group2 [ 0,1,2 ],
7666    * then there are 3 families:
7667    * - \a family1 (with ID 1) contains element [0] belonging to ( \a group1 + \a group2 ),
7668    * - \a family2 (with ID 2) contains elements [4] belonging to ( \a group1 ),
7669    * - \a family3 (with ID 3) contains element [1,2] belonging to ( \a group2 ), <br>
7670    * and the result array contains IDs of families [ 1,3,3,0,2 ]. <br> Note a family ID 0 which
7671    * stands for the element #3 which is in none of groups.
7672    *
7673    *  \param [in] groups - sequence of groups of element IDs.
7674    *  \param [in] newNb - total number of elements; it must be more than max ID of element
7675    *         in \a groups.
7676    *  \param [out] fidsOfGroups - IDs of families the elements of each group belong to.
7677    *  \return DataArrayInt * - a new instance of DataArrayInt containing IDs of families
7678    *         each element with ID from range [0, \a newNb ) belongs to. The caller is to
7679    *         delete this array using decrRef() as it is no more needed.
7680    *  \throw If any element ID in \a groups violates condition ( 0 <= ID < \a newNb ).
7681    */
7682   template <class T>
7683   DataArrayIdType *DataArrayDiscrete<T>::MakePartition(const std::vector<const DataArrayType *>& groups, mcIdType newNb, std::vector< std::vector<mcIdType> >& fidsOfGroups)
7684   {
7685     std::vector<const DataArrayType *> groups2;
7686     for(typename std::vector<const DataArrayType *>::const_iterator it4=groups.begin();it4!=groups.end();it4++)
7687       if(*it4)
7688         groups2.push_back(*it4);
7689     MCAuto<DataArrayIdType> ret=DataArrayIdType::New();
7690     ret->alloc(newNb,1);
7691     mcIdType *retPtr=ret->getPointer();
7692     std::fill(retPtr,retPtr+newNb,0);
7693     mcIdType fid=1;
7694     for(typename std::vector<const DataArrayType *>::const_iterator iter=groups2.begin();iter!=groups2.end();iter++)
7695       {
7696         const T *ptr=(*iter)->getConstPointer();
7697         std::size_t nbOfElem=(*iter)->getNbOfElems();
7698         mcIdType sfid=fid;
7699         for(mcIdType j=0;j<sfid;j++)
7700           {
7701             bool found=false;
7702             for(std::size_t i=0;i<nbOfElem;i++)
7703               {
7704                 if(ptr[i]>=0 && ptr[i]<newNb)
7705                   {
7706                     if(retPtr[ptr[i]]==j)
7707                       {
7708                         retPtr[ptr[i]]=fid;
7709                         found=true;
7710                       }
7711                   }
7712                 else
7713                   {
7714                     std::ostringstream oss; oss << "DataArrayInt::MakePartition : In group \"" << (*iter)->getName() << "\" in tuple #" << i << " value = " << ptr[i] << " ! Should be in [0," << newNb;
7715                     oss << ") !";
7716                     throw INTERP_KERNEL::Exception(oss.str().c_str());
7717                   }
7718               }
7719             if(found)
7720               fid++;
7721           }
7722       }
7723     fidsOfGroups.clear();
7724     fidsOfGroups.resize(groups2.size());
7725     mcIdType grId=0;
7726     for(typename std::vector<const DataArrayType *>::const_iterator iter=groups2.begin();iter!=groups2.end();iter++,grId++)
7727       {
7728         std::set<mcIdType> tmp;
7729         const T *ptr=(*iter)->getConstPointer();
7730         std::size_t nbOfElem=(*iter)->getNbOfElems();
7731         for(const T *p=ptr;p!=ptr+nbOfElem;p++)
7732           tmp.insert(retPtr[*p]);
7733         fidsOfGroups[grId].insert(fidsOfGroups[grId].end(),tmp.begin(),tmp.end());
7734       }
7735     return ret.retn();
7736   }
7737
7738 }
7739
7740 /// @cond INTERNAL
7741 namespace MEDCouplingImpl
7742 {
7743   template <class T>
7744   class OpSwitchedOn
7745   {
7746   public:
7747     OpSwitchedOn(T *pt):_pt(pt),_cnt(0) { }
7748     void operator()(const bool& b) { if(b) *_pt++=FromIdType<T>(_cnt); _cnt++; }
7749   private:
7750     T *_pt;
7751     MEDCoupling::mcIdType _cnt;
7752   };
7753
7754   template <class T>
7755   class OpSwitchedOff
7756   {
7757   public:
7758     OpSwitchedOff(T *pt):_pt(pt),_cnt(0) { }
7759     void operator()(const bool& b) { if(!b) *_pt++=FromIdType<T>(_cnt); _cnt++; }
7760   private:
7761     T *_pt;
7762     MEDCoupling::mcIdType _cnt;
7763   };
7764 }
7765 /// @endcond
7766
7767 namespace MEDCoupling
7768 {
7769   /*!
7770    * This method returns the list of ids in ascending mode so that v[id]==true.
7771    */
7772   template <class T>
7773   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::BuildListOfSwitchedOn(const std::vector<bool>& v)
7774   {
7775     std::size_t sz(std::count(v.begin(),v.end(),true));
7776     MCAuto<DataArrayType> ret(DataArrayType::New()); ret->alloc(sz,1);
7777     std::for_each(v.begin(),v.end(),MEDCouplingImpl::OpSwitchedOn<T>(ret->getPointer()));
7778     return ret.retn();
7779   }
7780
7781   /*!
7782    * This method returns the list of ids in ascending mode so that v[id]==false.
7783    */
7784   template <class T>
7785   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::BuildListOfSwitchedOff(const std::vector<bool>& v)
7786   {
7787     std::size_t sz(std::count(v.begin(),v.end(),false));
7788     MCAuto<DataArrayType> ret(DataArrayType::New()); ret->alloc(sz,1);
7789     std::for_each(v.begin(),v.end(),MEDCouplingImpl::OpSwitchedOff<T>(ret->getPointer()));
7790     return ret.retn();
7791   }
7792 }
7793
7794 namespace MEDCoupling
7795 {
7796   /*!
7797    * This method compares content of input vector \a v and \a this.
7798    * 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.
7799    * For performance reasons \a this is expected to be sorted ascendingly. If not an exception will be thrown.
7800    *
7801    * \param [in] v - the vector of 'flags' to be compared with \a this.
7802    *
7803    * \throw If \a this is not sorted ascendingly.
7804    * \throw If \a this has not exactly one component.
7805    * \throw If \a this is not allocated.
7806    */
7807   template<class T>
7808   bool DataArrayDiscreteSigned<T>::isFittingWith(const std::vector<bool>& v) const
7809   {
7810     this->checkAllocated();
7811     if(this->getNumberOfComponents()!=1)
7812       throw INTERP_KERNEL::Exception("DataArrayInt::isFittingWith : number of components of this should be equal to one !");
7813     const T *w(this->begin()),*end2(this->end());
7814     T refVal=-std::numeric_limits<T>::max();
7815     T i=0;
7816     std::vector<bool>::const_iterator it(v.begin());
7817     for(;it!=v.end();it++,i++)
7818       {
7819         if(*it)
7820           {
7821             if(w!=end2)
7822               {
7823                 if(*w++==i)
7824                   {
7825                     if(i>refVal)
7826                       refVal=i;
7827                     else
7828                       {
7829                         std::ostringstream oss; oss << "DataArrayInt::isFittingWith : At pos #" << std::distance(this->begin(),w-1) << " this is not sorted ascendingly !";
7830                         throw INTERP_KERNEL::Exception(oss.str().c_str());
7831                       }
7832                   }
7833                 else
7834                   return false;
7835               }
7836             else
7837               return false;
7838           }
7839       }
7840     return w==end2;
7841   }
7842 }
7843
7844 #endif