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