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