Salome HOME
Attempt of Management of profiles in spliter
[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
32 #include <sstream>
33 #include <cstdlib>
34 #include <numeric>
35 #include <algorithm>
36
37 namespace MEDCoupling
38 {
39   template<class T>
40   void MEDCouplingPointer<T>::setInternal(T *pointer)
41   {
42     _internal=pointer;
43     _external=0;
44   }
45
46   template<class T>
47   void MEDCouplingPointer<T>::setExternal(const T *pointer)
48   {
49     _external=pointer;
50     _internal=0;
51   }
52
53   template<class T>
54   MemArray<T>::MemArray(const MemArray<T>& other):_nb_of_elem(0),_nb_of_elem_alloc(0),_ownership(false),_dealloc(0),_param_for_deallocator(0)
55   {
56     if(!other._pointer.isNull())
57       {
58         _nb_of_elem_alloc=other._nb_of_elem;
59         T *pointer=(T*)malloc(_nb_of_elem_alloc*sizeof(T));
60         std::copy(other._pointer.getConstPointer(),other._pointer.getConstPointer()+other._nb_of_elem,pointer);
61         useArray(pointer,true,DeallocType::C_DEALLOC,other._nb_of_elem);
62       }
63   }
64
65   template<class T>
66   void MemArray<T>::useArray(const T *array, bool ownership, DeallocType type, std::size_t nbOfElem)
67   {
68     destroy();
69     _nb_of_elem=nbOfElem;
70     _nb_of_elem_alloc=nbOfElem;
71     if(ownership)
72       _pointer.setInternal(const_cast<T *>(array));
73     else
74       _pointer.setExternal(array);
75     _ownership=ownership;
76     _dealloc=BuildFromType(type);
77   }
78
79   template<class T>
80   void MemArray<T>::useExternalArrayWithRWAccess(const T *array, std::size_t nbOfElem)
81   {
82     destroy();
83     _nb_of_elem=nbOfElem;
84     _nb_of_elem_alloc=nbOfElem;
85     _pointer.setInternal(const_cast<T *>(array));
86     _ownership=false;
87     _dealloc=CPPDeallocator;
88   }
89
90   template<class T>
91   void MemArray<T>::writeOnPlace(std::size_t id, T element0, const T *others, std::size_t sizeOfOthers)
92   {
93     if(id+sizeOfOthers>=_nb_of_elem_alloc)
94       reserve(2*_nb_of_elem+sizeOfOthers+1);
95     T *pointer=_pointer.getPointer();
96     pointer[id]=element0;
97     std::copy(others,others+sizeOfOthers,pointer+id+1);
98     _nb_of_elem=std::max<std::size_t>(_nb_of_elem,id+sizeOfOthers+1);
99   }
100
101   template<class T>
102   void MemArray<T>::pushBack(T elem)
103   {
104     if(_nb_of_elem>=_nb_of_elem_alloc)
105       reserve(_nb_of_elem_alloc>0?2*_nb_of_elem_alloc:1);
106     T *pt=getPointer();
107     pt[_nb_of_elem++]=elem;
108   }
109
110   template<class T>
111   T MemArray<T>::popBack()
112   {
113     if(_nb_of_elem>0)
114       {
115         const T *pt=getConstPointer();
116         return pt[--_nb_of_elem];
117       }
118     throw INTERP_KERNEL::Exception("MemArray::popBack : nothing to pop in array !");
119   }
120
121   template<class T>
122   void MemArray<T>::pack() const
123   {
124     (const_cast<MemArray<T> * >(this))->reserve(_nb_of_elem);
125   }
126
127   template<class T>
128   bool MemArray<T>::isEqual(const MemArray<T>& other, T prec, std::string& reason) const
129   {
130     std::ostringstream oss; oss.precision(15);
131     if(_nb_of_elem!=other._nb_of_elem)
132       {
133         oss << "Number of elements in coarse data of DataArray mismatch : this=" << _nb_of_elem << " other=" << other._nb_of_elem;
134         reason=oss.str();
135         return false;
136       }
137     const T *pt1=_pointer.getConstPointer();
138     const T *pt2=other._pointer.getConstPointer();
139     if(pt1==0 && pt2==0)
140       return true;
141     if(pt1==0 || pt2==0)
142       {
143         oss << "coarse data pointer is defined for only one DataArray instance !";
144         reason=oss.str();
145         return false;
146       }
147     if(pt1==pt2)
148       return true;
149     for(std::size_t i=0;i<_nb_of_elem;i++)
150       if(pt1[i]-pt2[i]<-prec || (pt1[i]-pt2[i])>prec)
151         {
152           oss << "The content of data differs at pos #" << i << " of coarse data ! this[i]=" << pt1[i] << " other[i]=" << pt2[i];
153           reason=oss.str();
154           return false;
155         }
156     return true;
157   }
158
159   /*!
160    * \param [in] sl is typically the number of components
161    * \return True if a not null pointer is present, False if not.
162    */
163   template<class T>
164   bool MemArray<T>::reprHeader(int sl, std::ostream& stream) const
165   {
166     stream << "Number of tuples : ";
167     if(!_pointer.isNull())
168       {
169         if(sl!=0)
170           stream << _nb_of_elem/sl << std::endl << "Internal memory facts : " << _nb_of_elem << "/" << _nb_of_elem_alloc;
171         else
172           stream << "Empty Data";
173       }
174     else
175       stream << "No data";
176     stream << "\n";
177     stream << "Data content :\n";
178     bool ret=!_pointer.isNull();
179     if(!ret)
180       stream << "No data !\n";
181     return ret;
182   }
183
184   /*!
185    * \param [in] sl is typically the number of components
186    */
187   template<class T>
188   void MemArray<T>::repr(int sl, std::ostream& stream) const
189   {
190     if(reprHeader(sl,stream))
191       {
192         const T *data=getConstPointer();
193         if(_nb_of_elem!=0 && sl!=0)
194           {
195             std::size_t nbOfTuples=_nb_of_elem/std::abs(sl);
196             for(std::size_t i=0;i<nbOfTuples;i++)
197               {
198                 stream << "Tuple #" << i << " : ";
199                 std::copy(data,data+sl,std::ostream_iterator<T>(stream," "));
200                 stream << "\n";
201                 data+=sl;
202               }
203           }
204         else
205           stream << "Empty Data\n";
206       }
207   }
208
209   /*!
210    * \param [in] sl is typically the number of components
211    */
212   template<class T>
213   void MemArray<T>::reprZip(int sl, std::ostream& stream) const
214   {
215     stream << "Number of tuples : ";
216     if(!_pointer.isNull())
217       {
218         if(sl!=0)
219           stream << _nb_of_elem/sl;
220         else
221           stream << "Empty Data";
222       }
223     else
224       stream << "No data";
225     stream << "\n";
226     stream << "Data content : ";
227     const T *data=getConstPointer();
228     if(!_pointer.isNull())
229       {
230         if(_nb_of_elem!=0 && sl!=0)
231           {
232             std::size_t nbOfTuples=_nb_of_elem/std::abs(sl);
233             for(std::size_t i=0;i<nbOfTuples;i++)
234               {
235                 stream << "|";
236                 std::copy(data,data+sl,std::ostream_iterator<T>(stream," "));
237                 stream << "| ";
238                 data+=sl;
239               }
240             stream << "\n";
241           }
242         else
243           stream << "Empty Data\n";
244       }
245     else
246       stream << "No data !\n";
247   }
248
249   /*!
250    * \param [in] sl is typically the number of components
251    */
252   template<class T>
253   void MemArray<T>::reprNotTooLong(int sl, std::ostream& stream) const
254   {
255     if(reprHeader(sl,stream))
256       {
257         const T *data=getConstPointer();
258         if(_nb_of_elem!=0 && sl!=0)
259           {
260             std::size_t nbOfTuples=_nb_of_elem/std::abs(sl);
261             if(nbOfTuples<=1000)
262               {
263                 for(std::size_t i=0;i<nbOfTuples;i++)
264                   {
265                     stream << "Tuple #" << i << " : ";
266                     std::copy(data,data+sl,std::ostream_iterator<T>(stream," "));
267                     stream << "\n";
268                     data+=sl;
269                   }
270               }
271             else
272               {// too much tuples -> print the 3 first tuples and 3 last.
273                 stream << "Tuple #0 : ";
274                 std::copy(data,data+sl,std::ostream_iterator<T>(stream," ")); stream << "\n";
275                 stream << "Tuple #1 : ";
276                 std::copy(data+sl,data+2*sl,std::ostream_iterator<T>(stream," ")); stream << "\n";
277                 stream << "Tuple #2 : ";
278                 std::copy(data+2*sl,data+3*sl,std::ostream_iterator<T>(stream," ")); stream << "\n";
279                 stream << "...\n";
280                 stream << "Tuple #" << nbOfTuples-3 << " : ";
281                 std::copy(data+(nbOfTuples-3)*sl,data+(nbOfTuples-2)*sl,std::ostream_iterator<T>(stream," ")); stream << "\n";
282                 stream << "Tuple #" << nbOfTuples-2 << " : ";
283                 std::copy(data+(nbOfTuples-2)*sl,data+(nbOfTuples-1)*sl,std::ostream_iterator<T>(stream," ")); stream << "\n";
284                 stream << "Tuple #" << nbOfTuples-1 << " : ";
285                 std::copy(data+(nbOfTuples-1)*sl,data+nbOfTuples*sl,std::ostream_iterator<T>(stream," ")); stream << "\n";
286               }
287           }
288         else
289           stream << "Empty Data\n";
290       }
291   }
292
293   template<class T>
294   void MemArray<T>::fillWithValue(const T& val)
295   {
296     T *pt=_pointer.getPointer();
297     std::fill(pt,pt+_nb_of_elem,val);
298   }
299
300   template<class T>
301   T *MemArray<T>::fromNoInterlace(int nbOfComp) const
302   {
303     if(nbOfComp<1)
304       throw INTERP_KERNEL::Exception("MemArray<T>::fromNoInterlace : number of components must be > 0 !");
305     const T *pt=_pointer.getConstPointer();
306     std::size_t nbOfTuples=_nb_of_elem/nbOfComp;
307     T *ret=(T*)malloc(_nb_of_elem*sizeof(T));
308     T *w=ret;
309     for(std::size_t i=0;i<nbOfTuples;i++)
310       for(int j=0;j<nbOfComp;j++,w++)
311         *w=pt[j*nbOfTuples+i];
312     return ret;
313   }
314
315   template<class T>
316   T *MemArray<T>::toNoInterlace(int nbOfComp) const
317   {
318     if(nbOfComp<1)
319       throw INTERP_KERNEL::Exception("MemArray<T>::toNoInterlace : number of components must be > 0 !");
320     const T *pt=_pointer.getConstPointer();
321     std::size_t nbOfTuples=_nb_of_elem/nbOfComp;
322     T *ret=(T*)malloc(_nb_of_elem*sizeof(T));
323     T *w=ret;
324     for(int i=0;i<nbOfComp;i++)
325       for(std::size_t j=0;j<nbOfTuples;j++,w++)
326         *w=pt[j*nbOfComp+i];
327     return ret;
328   }
329
330   template<class T>
331   void MemArray<T>::sort(bool asc)
332   {
333     T *pt=_pointer.getPointer();
334     if(asc)
335       std::sort(pt,pt+_nb_of_elem);
336     else
337       {
338         typename std::reverse_iterator<T *> it1(pt+_nb_of_elem);
339         typename std::reverse_iterator<T *> it2(pt);
340         std::sort(it1,it2);
341       }
342   }
343
344   template<class T>
345   void MemArray<T>::reverse(int nbOfComp)
346   {
347     if(nbOfComp<1)
348       throw INTERP_KERNEL::Exception("MemArray<T>::reverse : only supported with 'this' array with ONE or more than ONE component !");
349     T *pt=_pointer.getPointer();
350     if(nbOfComp==1)
351       {
352         std::reverse(pt,pt+_nb_of_elem);
353         return ;
354       }
355     else
356       {
357         T *pt2=pt+_nb_of_elem-nbOfComp;
358         std::size_t nbOfTuples=_nb_of_elem/nbOfComp;
359         for(std::size_t i=0;i<nbOfTuples/2;i++,pt+=nbOfComp,pt2-=nbOfComp)
360           {
361             for(int j=0;j<nbOfComp;j++)
362               std::swap(pt[j],pt2[j]);
363           }
364       }
365   }
366
367   template<class T>
368   void MemArray<T>::alloc(std::size_t nbOfElements)
369   {
370     destroy();
371     _nb_of_elem=nbOfElements;
372     _nb_of_elem_alloc=nbOfElements;
373     _pointer.setInternal((T*)malloc(_nb_of_elem_alloc*sizeof(T)));
374     _ownership=true;
375     _dealloc=CDeallocator;
376   }
377
378   /*!
379    * This method performs systematically an allocation of \a newNbOfElements elements in \a this.
380    * \a _nb_of_elem and \a _nb_of_elem_alloc will \b NOT be systematically equal (contrary to MemArray<T>::reAlloc method.
381    * 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 
382    * \a newNbOfElements. This method is typically used to perform a pushBack to avoid systematic allocations-copy-deallocation.
383    * So after the call of this method the accessible content is perfectly set.
384    * 
385    * So this method should not be confused with MemArray<T>::reserve that is close to MemArray<T>::reAlloc but not same.
386    */
387   template<class T>
388   void MemArray<T>::reserve(std::size_t newNbOfElements)
389   {
390     if(_nb_of_elem_alloc==newNbOfElements)
391       return ;
392     T *pointer=(T*)malloc(newNbOfElements*sizeof(T));
393     std::copy(_pointer.getConstPointer(),_pointer.getConstPointer()+std::min<std::size_t>(_nb_of_elem,newNbOfElements),pointer);
394     if(_ownership)
395       DestroyPointer(const_cast<T *>(_pointer.getConstPointer()),_dealloc,_param_for_deallocator);//Do not use getPointer because in case of _external
396     _pointer.setInternal(pointer);
397     _nb_of_elem=std::min<std::size_t>(_nb_of_elem,newNbOfElements);
398     _nb_of_elem_alloc=newNbOfElements;
399     _ownership=true;
400     _dealloc=CDeallocator;
401     _param_for_deallocator=0;
402   }
403
404   /*!
405    * This method performs systematically an allocation of \a newNbOfElements elements in \a this.
406    * \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 .
407    * The remaining part of the new allocated chunk are available but not set previously !
408    * 
409    * So this method should not be confused with MemArray<T>::reserve that is close to MemArray<T>::reAlloc but not same.
410    */
411   template<class T>
412   void MemArray<T>::reAlloc(std::size_t newNbOfElements)
413   {
414     if(_nb_of_elem==newNbOfElements)
415       return ;
416     T *pointer=(T*)malloc(newNbOfElements*sizeof(T));
417     std::copy(_pointer.getConstPointer(),_pointer.getConstPointer()+std::min<std::size_t>(_nb_of_elem,newNbOfElements),pointer);
418     if(_ownership)
419       DestroyPointer(const_cast<T *>(_pointer.getConstPointer()),_dealloc,_param_for_deallocator);//Do not use getPointer because in case of _external
420     _pointer.setInternal(pointer);
421     _nb_of_elem=newNbOfElements;
422     _nb_of_elem_alloc=newNbOfElements;
423     _ownership=true;
424     _dealloc=CDeallocator;
425     _param_for_deallocator=0;
426   }
427
428   template<class T>
429   void MemArray<T>::CPPDeallocator(void *pt, void *param)
430   {
431     delete [] reinterpret_cast<T*>(pt);
432   }
433
434   template<class T>
435   void MemArray<T>::CDeallocator(void *pt, void *param)
436   {
437     free(pt);
438   }
439
440   template<class T>
441   void MemArray<T>::COffsetDeallocator(void *pt, void *param)
442   {
443     int64_t *offset(reinterpret_cast<int64_t *>(param));
444     char *ptcast(reinterpret_cast<char *>(pt));
445     free(ptcast+*offset);
446   }
447
448   template<class T>
449   typename MemArray<T>::Deallocator MemArray<T>::BuildFromType(DeallocType type)
450   {
451     switch(type)
452     {
453       case DeallocType::CPP_DEALLOC:
454         return CPPDeallocator;
455       case DeallocType::C_DEALLOC:
456         return CDeallocator;
457       case DeallocType::C_DEALLOC_WITH_OFFSET:
458         return COffsetDeallocator;
459       default:
460         throw INTERP_KERNEL::Exception("Invalid deallocation requested ! Unrecognized enum DeallocType !");
461     }
462   }
463
464   template<class T>
465   void MemArray<T>::DestroyPointer(T *pt, typename MemArray<T>::Deallocator dealloc, void *param)
466   {
467     if(dealloc)
468       dealloc(pt,param);
469   }
470
471   template<class T>
472   void MemArray<T>::destroy()
473   {
474     if(_ownership)
475       DestroyPointer(const_cast<T *>(_pointer.getConstPointer()),_dealloc,_param_for_deallocator);//Do not use getPointer because in case of _external
476     _pointer.null();
477     _ownership=false;
478     _dealloc=NULL;
479     _param_for_deallocator=NULL;
480     _nb_of_elem=0;
481     _nb_of_elem_alloc=0;
482   }
483
484   template<class T>
485   MemArray<T> &MemArray<T>::operator=(const MemArray<T>& other)
486   {
487     alloc(other._nb_of_elem);
488     std::copy(other._pointer.getConstPointer(),other._pointer.getConstPointer()+_nb_of_elem,_pointer.getPointer());
489     return *this;
490   }
491
492   //////////////////////////////////
493
494   template<class T>
495   DataArrayIterator<T>::DataArrayIterator(typename Traits<T>::ArrayType *da):_da(da),_tuple_id(0),_nb_comp(0),_nb_tuple(0)
496   {
497     if(_da)
498       {
499         _da->incrRef();
500         if(_da->isAllocated())
501           {
502             _nb_comp=da->getNumberOfComponents();
503             _nb_tuple=da->getNumberOfTuples();
504             _pt=da->getPointer();
505           }
506       }
507   }
508   
509   template<class T>
510   DataArrayIterator<T>::~DataArrayIterator()
511   {
512     if(_da)
513       _da->decrRef();
514   }
515
516   template<class T>
517   typename Traits<T>::ArrayTuple *DataArrayIterator<T>::nextt()
518   {
519     if(_tuple_id<_nb_tuple)
520       {
521         _tuple_id++;
522         typename Traits<T>::ArrayTuple *ret=new typename Traits<T>::ArrayTuple(_pt,_nb_comp);
523         _pt+=_nb_comp;
524         return ret;
525       }
526     else
527       return 0;
528   }
529
530   //////////////////////////////////
531
532   template<class T>
533   DataArrayTuple<T>::DataArrayTuple(T *pt, int nbOfComp):_pt(pt),_nb_of_compo(nbOfComp)
534   {
535   }
536   
537   template<class T>
538   T DataArrayTuple<T>::zeValue() const
539   {
540     if(_nb_of_compo==1)
541       return *_pt;
542     throw INTERP_KERNEL::Exception("DataArrayTuple<T>::zeValue : DataArrayTuple instance has not exactly 1 component -> Not possible to convert it into a single value !");
543   }
544   
545   template<class T>
546   typename Traits<T>::ArrayType *DataArrayTuple<T>::buildDA(int nbOfTuples, int nbOfCompo) const
547   {
548     if((_nb_of_compo==nbOfCompo && nbOfTuples==1) || (_nb_of_compo==nbOfTuples && nbOfCompo==1))
549     {
550       typename Traits<T>::ArrayType *ret=Traits<T>::ArrayType::New();
551       ret->useExternalArrayWithRWAccess(_pt,nbOfTuples,nbOfCompo);
552       return ret;
553     }
554   else
555     {
556       std::ostringstream oss; oss << "DataArrayTuple<T>::buildDA : unable to build a requested DataArrayDouble instance with nbofTuple=" << nbOfTuples << " and nbOfCompo=" << nbOfCompo;
557       oss << ".\nBecause the number of elements in this is " << _nb_of_compo << " !";
558       throw INTERP_KERNEL::Exception(oss.str().c_str());
559     }
560   }
561   
562   //////////////////////////////////
563
564   template<class T>
565   MCAuto< typename Traits<T>::ArrayTypeCh > DataArrayTemplate<T>::NewFromStdVector(const typename std::vector<T>& v)
566   {
567     std::size_t sz(v.size());
568     MCAuto< typename Traits<T>::ArrayTypeCh > ret(Traits<T>::ArrayTypeCh::New());
569     ret->alloc(sz,1);
570     T *pt(ret->getPointer());
571     std::copy(v.begin(),v.end(),pt);
572     return ret;
573   }
574   
575   template<class T>
576   std::vector< MCAuto< typename Traits<T>::ArrayTypeCh > > DataArrayTemplate<T>::explodeComponents() const
577   {
578     checkAllocated();
579     std::size_t sz(getNumberOfComponents());
580     int nbTuples(getNumberOfTuples());
581     std::string name(getName());
582     std::vector<std::string> compNames(getInfoOnComponents());
583     std::vector< MCAuto< typename Traits<T>::ArrayTypeCh > > ret(sz);
584     const T *thisPt(begin());
585     for(std::size_t i=0;i<sz;i++)
586       {
587         MCAuto< typename Traits<T>::ArrayTypeCh > part(Traits<T>::ArrayTypeCh::New());
588         part->alloc(nbTuples,1);
589         part->setName(name);
590         part->setInfoOnComponent(0,compNames[i]);
591         T *otherPt(part->getPointer());
592         for(int j=0;j<nbTuples;j++)
593           otherPt[j]=thisPt[sz*j+i];
594         ret[i]=part;
595       }
596     return ret;
597   }
598   
599   template<class T>
600   std::size_t DataArrayTemplate<T>::getHeapMemorySizeWithoutChildren() const
601   {
602     std::size_t sz(_mem.getNbOfElemAllocated());
603     sz*=sizeof(T);
604     return DataArray::getHeapMemorySizeWithoutChildren()+sz;
605   }
606   
607   /*!
608    * Allocates the raw data in memory. If the memory was already allocated, then it is
609    * freed and re-allocated. See an example of this method use
610    * \ref MEDCouplingArraySteps1WC "here".
611    *  \param [in] nbOfTuple - number of tuples of data to allocate.
612    *  \param [in] nbOfCompo - number of components of data to allocate.
613    *  \throw If \a nbOfTuple < 0 or \a nbOfCompo < 0.
614    */
615   template<class T>
616   void DataArrayTemplate<T>::alloc(std::size_t nbOfTuple, std::size_t nbOfCompo)
617   {
618     _info_on_compo.resize(nbOfCompo);
619     _mem.alloc(nbOfCompo*nbOfTuple);
620     declareAsNew();
621   }
622
623   /*!
624    * Sets a C array to be used as raw data of \a this. The previously set info
625    *  of components is retained and re-sized. 
626    * For more info see \ref MEDCouplingArraySteps1.
627    *  \param [in] array - the C array to be used as raw data of \a this.
628    *  \param [in] ownership - if \a true, \a array will be deallocated at destruction of \a this.
629    *  \param [in] type - specifies how to deallocate \a array. If \a type == MEDCoupling::CPP_DEALLOC,
630    *                     \c delete [] \c array; will be called. If \a type == MEDCoupling::C_DEALLOC,
631    *                     \c free(\c array ) will be called.
632    *  \param [in] nbOfTuple - new number of tuples in \a this.
633    *  \param [in] nbOfCompo - new number of components in \a this.
634    */
635   template<class T>
636   void DataArrayTemplate<T>::useArray(const T *array, bool ownership, DeallocType type, int nbOfTuple, int nbOfCompo)
637   {
638     _info_on_compo.resize(nbOfCompo);
639     _mem.useArray(array,ownership,type,(std::size_t)nbOfTuple*nbOfCompo);
640     declareAsNew();
641   }
642   
643   template<class T>
644   void DataArrayTemplate<T>::useExternalArrayWithRWAccess(const T *array, int nbOfTuple, int nbOfCompo)
645   {
646     _info_on_compo.resize(nbOfCompo);
647     _mem.useExternalArrayWithRWAccess(array,(std::size_t)nbOfTuple*nbOfCompo);
648     declareAsNew();
649   }
650
651   /*!
652    * Returns a value located at specified tuple and component.
653    * This method is equivalent to DataArrayTemplate<T>::getIJ() except that validity of
654    * parameters is checked. So this method is safe but expensive if used to go through
655    * all values of \a this.
656    *  \param [in] tupleId - index of tuple of interest.
657    *  \param [in] compoId - index of component of interest.
658    *  \return double - value located by \a tupleId and \a compoId.
659    *  \throw If \a this is not allocated.
660    *  \throw If condition <em>( 0 <= tupleId < this->getNumberOfTuples() )</em> is violated.
661    *  \throw If condition <em>( 0 <= compoId < this->getNumberOfComponents() )</em> is violated.
662    */
663   template<class T>
664   T DataArrayTemplate<T>::getIJSafe(int tupleId, int compoId) const
665   {
666     checkAllocated();
667     if(tupleId<0 || tupleId>=getNumberOfTuples())
668       {
669         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::getIJSafe : request for tupleId " << tupleId << " should be in [0," << getNumberOfTuples() << ") !";
670         throw INTERP_KERNEL::Exception(oss.str().c_str());
671       }
672     if(compoId<0 || compoId>=(int)getNumberOfComponents())
673       {
674         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::getIJSafe : request for compoId " << compoId << " should be in [0," << getNumberOfComponents() << ") !";
675         throw INTERP_KERNEL::Exception(oss.str().c_str());
676       }
677     return _mem[tupleId*_info_on_compo.size()+compoId];
678   }
679
680   /*!
681    * 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.
682    *
683    * \sa DataArray::getHeapMemorySizeWithoutChildren, DataArrayTemplate<T>::reserve
684    */
685   template<class T>
686   void DataArrayTemplate<T>::pack() const
687   {
688     _mem.pack();
689   }
690
691   /*!
692    * Checks if raw data is allocated. Read more on the raw data
693    * in \ref MEDCouplingArrayBasicsTuplesAndCompo "DataArrays infos" for more information.
694    *  \return bool - \a true if the raw data is allocated, \a false else.
695    */
696   template<class T>
697   bool DataArrayTemplate<T>::isAllocated() const
698   {
699     return getConstPointer()!=0;
700   }
701   
702   /*!
703    * Checks if raw data is allocated and throws an exception if it is not the case.
704    *  \throw If the raw data is not allocated.
705    */
706   template<class T>
707   void DataArrayTemplate<T>::checkAllocated() const
708   {
709     if(!isAllocated())
710       {
711         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::checkAllocated : Array is defined but not allocated ! Call alloc or setValues method first !";
712         throw INTERP_KERNEL::Exception(oss.str().c_str());
713       }
714   }
715   
716   /*!
717    * This method deallocated \a this without modification of information relative to the components.
718    * After call of this method, DataArrayDouble::isAllocated will return false.
719    * If \a this is already not allocated, \a this is let unchanged.
720    */
721   template<class T>
722   void DataArrayTemplate<T>::desallocate()
723   {
724     _mem.destroy();
725   }
726
727   /*!
728    * This method reserve nbOfElems elements in memory ( nbOfElems*8 bytes ) \b without impacting the number of tuples in \a this.
729    * 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.
730    * If \a this has not already been allocated, number of components is set to one.
731    * This method allows to reduce number of reallocations on invocation of DataArrayDouble::pushBackSilent and DataArrayDouble::pushBackValsSilent on \a this.
732    * 
733    * \sa DataArrayDouble::pack, DataArrayDouble::pushBackSilent, DataArrayDouble::pushBackValsSilent
734    */
735   template<class T>
736   void DataArrayTemplate<T>::reserve(std::size_t nbOfElems)
737   {
738     int nbCompo(getNumberOfComponents());
739     if(nbCompo==1)
740       {
741         _mem.reserve(nbOfElems);
742       }
743     else if(nbCompo==0)
744       {
745         _mem.reserve(nbOfElems);
746         _info_on_compo.resize(1);
747       }
748     else
749       {
750         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::reserve : not available for DataArrayDouble with number of components different than 1 !";
751         throw INTERP_KERNEL::Exception(oss.str().c_str());
752       }
753   }
754   
755   /*!
756    * 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
757    * of counter. So the caller is expected to call TimeLabel::declareAsNew on \a this at the end of the push session.
758    *
759    * \param [in] val the value to be added in \a this
760    * \throw If \a this has already been allocated with number of components different from one.
761    * \sa DataArrayDouble::pushBackValsSilent
762    */
763   template<class T>
764   void DataArrayTemplate<T>::pushBackSilent(T val)
765   {
766     int nbCompo(getNumberOfComponents());
767     if(nbCompo==1)
768       _mem.pushBack(val);
769     else if(nbCompo==0)
770       {
771         _info_on_compo.resize(1);
772         _mem.pushBack(val);
773       }
774     else
775       {
776         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::pushBackSilent : not available for DataArrayDouble with number of components different than 1 !";
777         throw INTERP_KERNEL::Exception(oss.str().c_str());
778       }
779   }
780   
781   /*!
782    * 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
783    * of counter. So the caller is expected to call TimeLabel::declareAsNew on \a this at the end of the push session.
784    *
785    *  \param [in] valsBg - an array of values to push at the end of \c this.
786    *  \param [in] valsEnd - specifies the end of the array \a valsBg, so that
787    *              the last value of \a valsBg is \a valsEnd[ -1 ].
788    * \throw If \a this has already been allocated with number of components different from one.
789    * \sa DataArrayDouble::pushBackSilent
790    */
791   template<class T>
792   void DataArrayTemplate<T>::pushBackValsSilent(const T *valsBg, const T *valsEnd)
793   {
794     int nbCompo(getNumberOfComponents());
795     if(nbCompo==1)
796       _mem.insertAtTheEnd(valsBg,valsEnd);
797     else if(nbCompo==0)
798       {
799         _info_on_compo.resize(1);
800         _mem.insertAtTheEnd(valsBg,valsEnd);
801       }
802     else
803       {
804         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::pushBackValsSilent : not available for DataArrayDouble with number of components different than 1 !";
805         throw INTERP_KERNEL::Exception(oss.str().c_str());
806       }
807   }
808   
809   /*!
810    * This method returns silently ( without updating time label in \a this ) the last value, if any and suppress it.
811    * \throw If \a this is already empty.
812    * \throw If \a this has number of components different from one.
813    */
814   template<class T>
815   T DataArrayTemplate<T>::popBackSilent()
816   {
817     if(getNumberOfComponents()==1)
818       return _mem.popBack();
819     else
820       {
821         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::popBackSilent : not available for DataArrayDouble with number of components different than 1 !";
822         throw INTERP_KERNEL::Exception(oss.str().c_str());
823       }
824   }
825   
826   /*!
827    * Allocates the raw data in memory. If exactly same memory as needed already
828    * allocated, it is not re-allocated.
829    *  \param [in] nbOfTuple - number of tuples of data to allocate.
830    *  \param [in] nbOfCompo - number of components of data to allocate.
831    *  \throw If \a nbOfTuple < 0 or \a nbOfCompo < 0.
832    */
833   template<class T>
834   void DataArrayTemplate<T>::allocIfNecessary(int nbOfTuple, int nbOfCompo)
835   {
836     if(isAllocated())
837       {
838         if(nbOfTuple!=getNumberOfTuples() || nbOfCompo!=(int)getNumberOfComponents())
839           alloc(nbOfTuple,nbOfCompo);
840       }
841     else
842       alloc(nbOfTuple,nbOfCompo);
843   }
844
845   /*!
846    * Checks the number of tuples.
847    *  \return bool - \a true if getNumberOfTuples() == 0, \a false else.
848    *  \throw If \a this is not allocated.
849    */
850   template<class T>
851   bool DataArrayTemplate<T>::empty() const
852   {
853     checkAllocated();
854     return getNumberOfTuples()==0;
855   }
856
857   /*!
858    * Copies all the data from another DataArrayDouble. For more info see
859    * \ref MEDCouplingArrayBasicsCopyDeepAssign.
860    *  \param [in] other - another instance of DataArrayDouble to copy data from.
861    *  \throw If the \a other is not allocated.
862    */
863   template<class T>
864   void DataArrayTemplate<T>::deepCopyFrom(const DataArrayTemplate<T>& other)
865   {
866     other.checkAllocated();
867     int nbOfTuples(other.getNumberOfTuples()),nbOfComp(other.getNumberOfComponents());
868     allocIfNecessary(nbOfTuples,nbOfComp);
869     std::size_t nbOfElems((std::size_t)nbOfTuples*nbOfComp);
870     T *pt(getPointer());
871     const T *ptI(other.begin());
872     for(std::size_t i=0;i<nbOfElems;i++)
873       pt[i]=ptI[i];
874     copyStringInfoFrom(other);
875   }
876
877   /*!
878    * Reverse the array values.
879    *  \throw If \a this->getNumberOfComponents() < 1.
880    *  \throw If \a this is not allocated.
881    */
882   template<class T>
883   void DataArrayTemplate<T>::reverse()
884   {
885     checkAllocated();
886     _mem.reverse(getNumberOfComponents());
887     declareAsNew();
888   }
889
890   /*!
891    * Assign \a val to all values in \a this array. To know more on filling arrays see
892    * \ref MEDCouplingArrayFill.
893    *  \param [in] val - the value to fill with.
894    *  \throw If \a this is not allocated.
895    */
896   template<class T>
897   void DataArrayTemplate<T>::fillWithValue(T val)
898   {
899     checkAllocated();
900     _mem.fillWithValue(val);
901     declareAsNew();
902   }
903
904   /*!
905    * Changes number of tuples in the array. If the new number of tuples is smaller
906    * than the current number the array is truncated, otherwise the array is extended.
907    *  \param [in] nbOfTuples - new number of tuples. 
908    *  \throw If \a this is not allocated.
909    *  \throw If \a nbOfTuples is negative.
910    */
911   template<class T>
912   void DataArrayTemplate<T>::reAlloc(std::size_t nbOfTuples)
913   {
914     checkAllocated();
915     _mem.reAlloc(getNumberOfComponents()*nbOfTuples);
916     declareAsNew();
917   }
918
919   /*!
920    * Permutes values of \a this array as required by \a old2New array. The values are
921    * permuted so that \c new[ \a old2New[ i ]] = \c old[ i ]. Number of tuples remains
922    * the same as in \c this one.
923    * If a permutation reduction is needed, subArray() or selectByTupleId() should be used.
924    * For more info on renumbering see \ref numbering.
925    *  \param [in] old2New - C array of length equal to \a this->getNumberOfTuples()
926    *     giving a new position for i-th old value.
927    */
928   template<class T>
929   void DataArrayTemplate<T>::renumberInPlace(const int *old2New)
930   {
931     checkAllocated();
932     int nbTuples(getNumberOfTuples()),nbOfCompo(getNumberOfComponents());
933     T *tmp(new T[nbTuples*nbOfCompo]);
934     const T *iptr(begin());
935     for(int i=0;i<nbTuples;i++)
936       {
937         int v=old2New[i];
938         if(v>=0 && v<nbTuples)
939           std::copy(iptr+nbOfCompo*i,iptr+nbOfCompo*(i+1),tmp+nbOfCompo*v);
940         else
941           {
942             std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::renumberInPlace : At place #" << i << " value is " << v << " ! Should be in [0," << nbTuples << ") !";
943             throw INTERP_KERNEL::Exception(oss.str().c_str());
944           }
945       }
946     std::copy(tmp,tmp+nbTuples*nbOfCompo,getPointer());
947     delete [] tmp;
948     declareAsNew();
949   }
950
951
952   /*!
953    * Permutes values of \a this array as required by \a new2Old array. The values are
954    * permuted so that \c new[ i ] = \c old[ \a new2Old[ i ]]. Number of tuples remains
955    * the same as in \c this one.
956    * For more info on renumbering see \ref numbering.
957    *  \param [in] new2Old - C array of length equal to \a this->getNumberOfTuples()
958    *     giving a previous position of i-th new value.
959    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
960    *          is to delete using decrRef() as it is no more needed.
961    */
962   template<class T>
963   void DataArrayTemplate<T>::renumberInPlaceR(const int *new2Old)
964   {
965     checkAllocated();
966     int nbTuples(getNumberOfTuples()),nbOfCompo(getNumberOfComponents());
967     T *tmp(new T[nbTuples*nbOfCompo]);
968     const T *iptr(begin());
969     for(int i=0;i<nbTuples;i++)
970       {
971         int v=new2Old[i];
972         if(v>=0 && v<nbTuples)
973           std::copy(iptr+nbOfCompo*v,iptr+nbOfCompo*(v+1),tmp+nbOfCompo*i);
974         else
975           {
976             std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::renumberInPlaceR : At place #" << i << " value is " << v << " ! Should be in [0," << nbTuples << ") !";
977             throw INTERP_KERNEL::Exception(oss.str().c_str());
978           }
979       }
980     std::copy(tmp,tmp+nbTuples*nbOfCompo,getPointer());
981     delete [] tmp;
982     declareAsNew();
983   }
984
985   /*!
986    * Sorts values of the array.
987    *  \param [in] asc - \a true means ascending order, \a false, descending.
988    *  \throw If \a this is not allocated.
989    *  \throw If \a this->getNumberOfComponents() != 1.
990    */
991   template<class T>
992   void DataArrayTemplate<T>::sort(bool asc)
993   {
994     checkAllocated();
995     if(getNumberOfComponents()!=1)
996       {
997         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::sort : only supported with 'this' array with ONE component !";
998         throw INTERP_KERNEL::Exception(oss.str().c_str());
999       }
1000     _mem.sort(asc);
1001     declareAsNew();
1002   }
1003
1004   /*!
1005    * Returns a copy of \a this array with values permuted as required by \a old2New array.
1006    * The values are permuted so that  \c new[ \a old2New[ i ]] = \c old[ i ].
1007    * Number of tuples in the result array remains the same as in \c this one.
1008    * If a permutation reduction is needed, renumberAndReduce() should be used.
1009    * For more info on renumbering see \ref numbering.
1010    *  \param [in] old2New - C array of length equal to \a this->getNumberOfTuples()
1011    *          giving a new position for i-th old value.
1012    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1013    *          is to delete using decrRef() as it is no more needed.
1014    *  \throw If \a this is not allocated.
1015    */
1016   template<class T>
1017   typename Traits<T>::ArrayType *DataArrayTemplate<T>::renumber(const int *old2New) const
1018   {
1019     checkAllocated();
1020     int nbTuples(getNumberOfTuples()),nbOfCompo(getNumberOfComponents());
1021     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1022     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1023     ret->alloc(nbTuples,nbOfCompo);
1024     ret->copyStringInfoFrom(*this);
1025     const T *iptr(begin());
1026     T *optr(ret->getPointer());
1027     for(int i=0;i<nbTuples;i++)
1028       std::copy(iptr+nbOfCompo*i,iptr+nbOfCompo*(i+1),optr+nbOfCompo*old2New[i]);
1029     ret->copyStringInfoFrom(*this);
1030     return ret.retn();
1031   }
1032
1033   /*!
1034    * Returns a copy of \a this array with values permuted as required by \a new2Old array.
1035    * The values are permuted so that  \c new[ i ] = \c old[ \a new2Old[ i ]]. Number of
1036    * tuples in the result array remains the same as in \c this one.
1037    * If a permutation reduction is needed, subArray() or selectByTupleId() should be used.
1038    * For more info on renumbering see \ref numbering.
1039    *  \param [in] new2Old - C array of length equal to \a this->getNumberOfTuples()
1040    *     giving a previous position of i-th new value.
1041    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1042    *          is to delete using decrRef() as it is no more needed.
1043    */
1044   template<class T>
1045   typename Traits<T>::ArrayType *DataArrayTemplate<T>::renumberR(const int *new2Old) const
1046   {
1047     checkAllocated();
1048     int nbTuples(getNumberOfTuples()),nbOfCompo(getNumberOfComponents());
1049     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1050     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1051     ret->alloc(nbTuples,nbOfCompo);
1052     ret->copyStringInfoFrom(*this);
1053     const T *iptr(getConstPointer());
1054     T *optr(ret->getPointer());
1055     for(int i=0;i<nbTuples;i++)
1056       std::copy(iptr+nbOfCompo*new2Old[i],iptr+nbOfCompo*(new2Old[i]+1),optr+i*nbOfCompo);
1057     ret->copyStringInfoFrom(*this);
1058     return ret.retn();
1059   }
1060
1061   /*!
1062    * Returns a shorten and permuted copy of \a this array. The new DataArrayDouble is
1063    * of size \a newNbOfTuple and it's values are permuted as required by \a old2New array.
1064    * The values are permuted so that  \c new[ \a old2New[ i ]] = \c old[ i ] for all
1065    * \a old2New[ i ] >= 0. In other words every i-th tuple in \a this array, for which 
1066    * \a old2New[ i ] is negative, is missing from the result array.
1067    * For more info on renumbering see \ref numbering.
1068    *  \param [in] old2New - C array of length equal to \a this->getNumberOfTuples()
1069    *     giving a new position for i-th old tuple and giving negative position for
1070    *     for i-th old tuple that should be omitted.
1071    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1072    *          is to delete using decrRef() as it is no more needed.
1073    */
1074   template<class T>
1075   typename Traits<T>::ArrayType *DataArrayTemplate<T>::renumberAndReduce(const int *old2New, int newNbOfTuple) const
1076   {
1077     checkAllocated();
1078     int nbTuples(getNumberOfTuples()),nbOfCompo(getNumberOfComponents());
1079     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1080     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1081     ret->alloc(newNbOfTuple,nbOfCompo);
1082     const T *iptr=getConstPointer();
1083     T *optr=ret->getPointer();
1084     for(int i=0;i<nbTuples;i++)
1085       {
1086         int w=old2New[i];
1087         if(w>=0)
1088           std::copy(iptr+i*nbOfCompo,iptr+(i+1)*nbOfCompo,optr+w*nbOfCompo);
1089       }
1090     ret->copyStringInfoFrom(*this);
1091     return ret.retn();
1092   }
1093
1094   /*!
1095    * Returns a shorten and permuted copy of \a this array. The new DataArrayDouble is
1096    * of size \a new2OldEnd - \a new2OldBg and it's values are permuted as required by
1097    * \a new2OldBg array.
1098    * The values are permuted so that  \c new[ i ] = \c old[ \a new2OldBg[ i ]].
1099    * This method is equivalent to renumberAndReduce() except that convention in input is
1100    * \c new2old and \b not \c old2new.
1101    * For more info on renumbering see \ref numbering.
1102    *  \param [in] new2OldBg - pointer to the beginning of a permutation array that gives a
1103    *              tuple index in \a this array to fill the i-th tuple in the new array.
1104    *  \param [in] new2OldEnd - specifies the end of the permutation array that starts at
1105    *              \a new2OldBg, so that pointer to a tuple index (\a pi) varies as this:
1106    *              \a new2OldBg <= \a pi < \a new2OldEnd.
1107    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1108    *          is to delete using decrRef() as it is no more needed.
1109    */
1110   template<class T>
1111   typename Traits<T>::ArrayType *DataArrayTemplate<T>::mySelectByTupleId(const mcIdType *new2OldBg, const mcIdType *new2OldEnd) const
1112   {
1113     checkAllocated();
1114     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1115     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1116     std::size_t nbComp(getNumberOfComponents());
1117     ret->alloc(std::distance(new2OldBg,new2OldEnd),nbComp);
1118     ret->copyStringInfoFrom(*this);
1119     T *pt(ret->getPointer());
1120     const T *srcPt(getConstPointer());
1121     std::size_t i(0);
1122     for(const int *w=new2OldBg;w!=new2OldEnd;w++,i++)
1123       std::copy(srcPt+(*w)*nbComp,srcPt+((*w)+1)*nbComp,pt+i*nbComp);
1124     ret->copyStringInfoFrom(*this);
1125     return ret.retn();
1126   }
1127
1128   template<class T>
1129   typename Traits<T>::ArrayType *DataArrayTemplate<T>::mySelectByTupleId(const DataArrayIdType& di) const
1130   {
1131     return this->mySelectByTupleId(di.begin(),di.end());
1132   }
1133
1134   template<class T>
1135   MCAuto<typename Traits<T>::ArrayTypeCh> DataArrayTemplate<T>::selectPartDef(const PartDefinition *pd) const
1136   {
1137     if(!pd)
1138       throw INTERP_KERNEL::Exception("DataArrayTemplate<T>::selectPartDef : null input pointer !");
1139     MCAuto<typename Traits<T>::ArrayTypeCh> ret(Traits<T>::ArrayTypeCh::New());
1140     const SlicePartDefinition *spd(dynamic_cast<const SlicePartDefinition *>(pd));
1141     if(spd)
1142       {
1143         int a,b,c;
1144         spd->getSlice(a,b,c);
1145         if(a==0 && b==(int)getNumberOfTuples() && c==1)
1146           {
1147             DataArrayTemplate<T> *directRet(const_cast<DataArrayTemplate<T> *>(this));
1148             directRet->incrRef();
1149             MCAuto<DataArrayTemplate<T> > ret2(directRet);
1150             return DynamicCastSafe<DataArrayTemplate<T>,typename Traits<T>::ArrayTypeCh>(ret2);
1151           }
1152         else
1153           {
1154             MCAuto<DataArray> ret2(selectByTupleIdSafeSlice(a,b,c));
1155             return DynamicCastSafe<DataArray,typename Traits<T>::ArrayTypeCh>(ret2);
1156           }
1157       }
1158     const DataArrayPartDefinition *dpd(dynamic_cast<const DataArrayPartDefinition *>(pd));
1159     if(dpd)
1160       {
1161         MCAuto<DataArrayInt> arr(dpd->toDAI());
1162         MCAuto<DataArray> ret2(selectByTupleIdSafe(arr->begin(),arr->end()));
1163         return DynamicCastSafe<DataArray,typename Traits<T>::ArrayTypeCh>(ret2);
1164         
1165       }
1166     throw INTERP_KERNEL::Exception("DataArrayTemplate<T>::selectPartDef : unrecognized part def !");
1167   }
1168   
1169   /*!
1170    * Returns a shorten and permuted copy of \a this array. The new DataArrayDouble is
1171    * of size \a new2OldEnd - \a new2OldBg and it's values are permuted as required by
1172    * \a new2OldBg array.
1173    * The values are permuted so that  \c new[ i ] = \c old[ \a new2OldBg[ i ]].
1174    * This method is equivalent to renumberAndReduce() except that convention in input is
1175    * \c new2old and \b not \c old2new.
1176    * This method is equivalent to selectByTupleId() except that it prevents coping data
1177    * from behind the end of \a this array.
1178    * For more info on renumbering see \ref numbering.
1179    *  \param [in] new2OldBg - pointer to the beginning of a permutation array that gives a
1180    *              tuple index in \a this array to fill the i-th tuple in the new array.
1181    *  \param [in] new2OldEnd - specifies the end of the permutation array that starts at
1182    *              \a new2OldBg, so that pointer to a tuple index (\a pi) varies as this:
1183    *              \a new2OldBg <= \a pi < \a new2OldEnd.
1184    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1185    *          is to delete using decrRef() as it is no more needed.
1186    *  \throw If \a new2OldEnd - \a new2OldBg > \a this->getNumberOfTuples().
1187    */
1188   template<class T>
1189   typename Traits<T>::ArrayType *DataArrayTemplate<T>::mySelectByTupleIdSafe(const int *new2OldBg, const int *new2OldEnd) const
1190   {
1191     checkAllocated();
1192     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1193     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1194     int nbComp(getNumberOfComponents()),oldNbOfTuples(getNumberOfTuples());
1195     ret->alloc((int)std::distance(new2OldBg,new2OldEnd),nbComp);
1196     ret->copyStringInfoFrom(*this);
1197     T *pt(ret->getPointer());
1198     const T *srcPt(getConstPointer());
1199     int i(0);
1200     for(const int *w=new2OldBg;w!=new2OldEnd;w++,i++)
1201       if(*w>=0 && *w<oldNbOfTuples)
1202         std::copy(srcPt+(*w)*nbComp,srcPt+((*w)+1)*nbComp,pt+i*nbComp);
1203       else
1204         {
1205           std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::selectByTupleIdSafe : some ids has been detected to be out of [0,this->getNumberOfTuples) !";
1206           throw INTERP_KERNEL::Exception(oss.str().c_str());
1207         }
1208     ret->copyStringInfoFrom(*this);
1209     return ret.retn();
1210   }
1211
1212   /*!
1213    * Changes the number of components within \a this array so that its raw data **does
1214    * not** change, instead splitting this data into tuples changes.
1215    *  \warning This method erases all (name and unit) component info set before!
1216    *  \param [in] newNbOfComp - number of components for \a this array to have.
1217    *  \throw If \a this is not allocated
1218    *  \throw If getNbOfElems() % \a newNbOfCompo != 0.
1219    *  \throw If \a newNbOfCompo is lower than 1.
1220    *  \throw If the rearrange method would lead to a number of tuples higher than 2147483647 (maximal capacity of int32 !).
1221    *  \warning This method erases all (name and unit) component info set before!
1222    */
1223   template<class T>
1224   void DataArrayTemplate<T>::rearrange(int newNbOfCompo)
1225   {
1226     checkAllocated();
1227     if(newNbOfCompo<1)
1228       {
1229         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::rearrange : input newNbOfCompo must be > 0 !";
1230         throw INTERP_KERNEL::Exception(oss.str().c_str());
1231       }
1232     std::size_t nbOfElems=getNbOfElems();
1233     if(nbOfElems%newNbOfCompo!=0)
1234       {
1235         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::rearrange : nbOfElems%newNbOfCompo!=0 !";
1236         throw INTERP_KERNEL::Exception(oss.str().c_str());
1237       }
1238     if(nbOfElems/newNbOfCompo>(std::size_t)std::numeric_limits<int>::max())
1239       {
1240         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::rearrange : the rearrangement leads to too high number of tuples (> 2147483647) !";
1241         throw INTERP_KERNEL::Exception(oss.str().c_str());
1242       }
1243     _info_on_compo.clear();
1244     _info_on_compo.resize(newNbOfCompo);
1245     declareAsNew();
1246   }
1247
1248   /*!
1249    * Changes the number of components within \a this array to be equal to its number
1250    * of tuples, and inversely its number of tuples to become equal to its number of 
1251    * components. So that its raw data **does not** change, instead splitting this
1252    * data into tuples changes.
1253    *  \warning This method erases all (name and unit) component info set before!
1254    *  \warning Do not confuse this method with fromNoInterlace() and toNoInterlace()!
1255    *  \throw If \a this is not allocated.
1256    *  \sa rearrange()
1257    */
1258   template<class T>
1259   void DataArrayTemplate<T>::transpose()
1260   {
1261     checkAllocated();
1262     int nbOfTuples(getNumberOfTuples());
1263     rearrange(nbOfTuples);
1264   }
1265
1266   /*!
1267    * Returns a shorten or extended copy of \a this array. If \a newNbOfComp is less
1268    * than \a this->getNumberOfComponents() then the result array is shorten as each tuple
1269    * is truncated to have \a newNbOfComp components, keeping first components. If \a
1270    * newNbOfComp is more than \a this->getNumberOfComponents() then the result array is
1271    * expanded as each tuple is populated with \a dftValue to have \a newNbOfComp
1272    * components.  
1273    *  \param [in] newNbOfComp - number of components for the new array to have.
1274    *  \param [in] dftValue - value assigned to new values added to the new array.
1275    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1276    *          is to delete using decrRef() as it is no more needed.
1277    *  \throw If \a this is not allocated.
1278    */
1279   template<class T>
1280   typename Traits<T>::ArrayType *DataArrayTemplate<T>::changeNbOfComponents(int newNbOfComp, T dftValue) const
1281   {
1282     checkAllocated();
1283     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1284     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1285     ret->alloc(getNumberOfTuples(),newNbOfComp);
1286     const T *oldc(getConstPointer());
1287     T *nc(ret->getPointer());
1288     int nbOfTuples(getNumberOfTuples()),oldNbOfComp(getNumberOfComponents());
1289     int dim(std::min(oldNbOfComp,newNbOfComp));
1290     for(int i=0;i<nbOfTuples;i++)
1291       {
1292         int j=0;
1293         for(;j<dim;j++)
1294           nc[newNbOfComp*i+j]=oldc[i*oldNbOfComp+j];
1295         for(;j<newNbOfComp;j++)
1296           nc[newNbOfComp*i+j]=dftValue;
1297       }
1298     ret->setName(getName());
1299     for(int i=0;i<dim;i++)
1300       ret->setInfoOnComponent(i,getInfoOnComponent(i));
1301     ret->setName(getName());
1302     return ret.retn();
1303   }
1304
1305   /*!
1306    * Returns a copy of \a this array composed of selected components.
1307    * The new DataArrayDouble has the same number of tuples but includes components
1308    * specified by \a compoIds parameter. So that getNbOfElems() of the result array
1309    * can be either less, same or more than \a this->getNbOfElems().
1310    *  \param [in] compoIds - sequence of zero based indices of components to include
1311    *              into the new array.
1312    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1313    *          is to delete using decrRef() as it is no more needed.
1314    *  \throw If \a this is not allocated.
1315    *  \throw If a component index (\a i) is not valid: 
1316    *         \a i < 0 || \a i >= \a this->getNumberOfComponents().
1317    *
1318    *  \if ENABLE_EXAMPLES
1319    *  \ref py_mcdataarraydouble_KeepSelectedComponents "Here is a Python example".
1320    *  \endif
1321    */
1322   template<class T>
1323   typename Traits<T>::ArrayType *DataArrayTemplate<T>::myKeepSelectedComponents(const std::vector<int>& compoIds) const
1324   {
1325     checkAllocated();
1326     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1327     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1328     std::size_t newNbOfCompo(compoIds.size());
1329     int oldNbOfCompo(getNumberOfComponents());
1330     for(std::vector<int>::const_iterator it=compoIds.begin();it!=compoIds.end();it++)
1331       if((*it)<0 || (*it)>=oldNbOfCompo)
1332         {
1333           std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::keepSelectedComponents : invalid requested component : " << *it << " whereas it should be in [0," << oldNbOfCompo << ") !";
1334           throw INTERP_KERNEL::Exception(oss.str().c_str());
1335         }
1336     int nbOfTuples(getNumberOfTuples());
1337     ret->alloc(nbOfTuples,(int)newNbOfCompo);
1338     ret->copyPartOfStringInfoFrom(*this,compoIds);
1339     const T *oldc(getConstPointer());
1340     T *nc(ret->getPointer());
1341     for(int i=0;i<nbOfTuples;i++)
1342       for(std::size_t j=0;j<newNbOfCompo;j++,nc++)
1343         *nc=oldc[i*oldNbOfCompo+compoIds[j]];
1344     return ret.retn();
1345   }
1346
1347   /*!
1348    * Returns a shorten copy of \a this array. The new DataArrayDouble contains all
1349    * tuples starting from the \a tupleIdBg-th tuple and including all tuples located before
1350    * the \a tupleIdEnd-th one. This methods has a similar behavior as std::string::substr().
1351    * This method is a specialization of selectByTupleIdSafeSlice().
1352    *  \param [in] tupleIdBg - index of the first tuple to copy from \a this array.
1353    *  \param [in] tupleIdEnd - index of the tuple before which the tuples to copy are located.
1354    *          If \a tupleIdEnd == -1, all the tuples till the end of \a this array are copied.
1355    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1356    *          is to delete using decrRef() as it is no more needed.
1357    *  \throw If \a tupleIdBg < 0.
1358    *  \throw If \a tupleIdBg > \a this->getNumberOfTuples().
1359    *  \throw If \a tupleIdEnd != -1 && \a tupleIdEnd < \a this->getNumberOfTuples().
1360    *  \sa DataArrayDouble::selectByTupleIdSafeSlice
1361    */
1362   template<class T>
1363   typename Traits<T>::ArrayType *DataArrayTemplate<T>::subArray(int tupleIdBg, int tupleIdEnd) const
1364   {
1365     checkAllocated();
1366     int nbt(getNumberOfTuples());
1367     if(tupleIdBg<0)
1368       {
1369         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::subArray : The tupleIdBg parameter must be greater than 0 !";
1370         throw INTERP_KERNEL::Exception(oss.str().c_str());
1371       }
1372     if(tupleIdBg>nbt)
1373       {
1374         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << ":subArray : The tupleIdBg parameter is greater than number of tuples !";
1375         throw INTERP_KERNEL::Exception(oss.str().c_str());
1376       }
1377     int trueEnd=tupleIdEnd;
1378     if(tupleIdEnd!=-1)
1379       {
1380         if(tupleIdEnd>nbt)
1381           {
1382             std::ostringstream oss; oss << Traits<T>::ArrayTypeName << ":subArray : The tupleIdBg parameter is greater than number of tuples !";
1383             throw INTERP_KERNEL::Exception(oss.str().c_str());
1384           }
1385       }
1386     else
1387       trueEnd=nbt;
1388     int nbComp(getNumberOfComponents());
1389     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1390     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1391     ret->alloc(trueEnd-tupleIdBg,nbComp);
1392     ret->copyStringInfoFrom(*this);
1393     std::copy(getConstPointer()+tupleIdBg*nbComp,getConstPointer()+trueEnd*nbComp,ret->getPointer());
1394     return ret.retn();
1395   }
1396
1397   /*!
1398    * Returns a shorten copy of \a this array. The new DataArrayDouble contains every
1399    * (\a bg + \c i * \a step)-th tuple of \a this array located before the \a end2-th
1400    * tuple. Indices of the selected tuples are the same as ones returned by the Python
1401    * command \c range( \a bg, \a end2, \a step ).
1402    * This method is equivalent to selectByTupleIdSafe() except that the input array is
1403    * not constructed explicitly.
1404    * For more info on renumbering see \ref numbering.
1405    *  \param [in] bg - index of the first tuple to copy from \a this array.
1406    *  \param [in] end2 - index of the tuple before which the tuples to copy are located.
1407    *  \param [in] step - index increment to get index of the next tuple to copy.
1408    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
1409    *          is to delete using decrRef() as it is no more needed.
1410    *  \sa DataArrayDouble::subArray.
1411    */
1412   template<class T>
1413   typename Traits<T>::ArrayType *DataArrayTemplate<T>::mySelectByTupleIdSafeSlice(int bg, int end2, int step) const
1414   {
1415     checkAllocated();
1416     MCAuto<DataArray> ret0(buildNewEmptyInstance());
1417     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
1418     int nbComp(getNumberOfComponents());
1419     std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::selectByTupleIdSafeSlice : ";
1420     int newNbOfTuples(GetNumberOfItemGivenBESRelative(bg,end2,step,oss.str()));
1421     ret->alloc(newNbOfTuples,nbComp);
1422     T *pt(ret->getPointer());
1423     const T *srcPt(getConstPointer()+bg*nbComp);
1424     for(int i=0;i<newNbOfTuples;i++,srcPt+=step*nbComp)
1425       std::copy(srcPt,srcPt+nbComp,pt+i*nbComp);
1426     ret->copyStringInfoFrom(*this);
1427     return ret.retn();
1428   }
1429   
1430   /*!
1431    * Copy all values from another DataArrayDouble into specified tuples and components
1432    * of \a this array. Textual data is not copied.
1433    * The tree parameters defining set of indices of tuples and components are similar to
1434    * the tree parameters of the Python function \c range(\c start,\c stop,\c step).
1435    *  \param [in] a - the array to copy values from.
1436    *  \param [in] bgTuples - index of the first tuple of \a this array to assign values to.
1437    *  \param [in] endTuples - index of the tuple before which the tuples to assign to
1438    *              are located.
1439    *  \param [in] stepTuples - index increment to get index of the next tuple to assign to.
1440    *  \param [in] bgComp - index of the first component of \a this array to assign values to.
1441    *  \param [in] endComp - index of the component before which the components to assign
1442    *              to are located.
1443    *  \param [in] stepComp - index increment to get index of the next component to assign to.
1444    *  \param [in] strictCompoCompare - if \a true (by default), then \a a->getNumberOfComponents() 
1445    *              must be equal to the number of columns to assign to, else an
1446    *              exception is thrown; if \a false, then it is only required that \a
1447    *              a->getNbOfElems() equals to number of values to assign to (this condition
1448    *              must be respected even if \a strictCompoCompare is \a true). The number of 
1449    *              values to assign to is given by following Python expression:
1450    *              \a nbTargetValues = 
1451    *              \c len(\c range(\a bgTuples,\a endTuples,\a stepTuples)) *
1452    *              \c len(\c range(\a bgComp,\a endComp,\a stepComp)).
1453    *  \throw If \a a is NULL.
1454    *  \throw If \a a is not allocated.
1455    *  \throw If \a this is not allocated.
1456    *  \throw If parameters specifying tuples and components to assign to do not give a
1457    *            non-empty range of increasing indices.
1458    *  \throw If \a a->getNbOfElems() != \a nbTargetValues.
1459    *  \throw If \a strictCompoCompare == \a true && \a a->getNumberOfComponents() !=
1460    *            \c len(\c range(\a bgComp,\a endComp,\a stepComp)).
1461    *
1462    *  \if ENABLE_EXAMPLES
1463    *  \ref py_mcdataarraydouble_setpartofvalues1 "Here is a Python example".
1464    *  \endif
1465    */
1466   template<class T>
1467   void DataArrayTemplate<T>::setPartOfValues1(const typename Traits<T>::ArrayType *a, int bgTuples, int endTuples, int stepTuples, int bgComp, int endComp, int stepComp, bool strictCompoCompare)
1468   {
1469     if(!a)
1470       {
1471         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::setPartOfValues1 : input DataArrayDouble is NULL !";
1472         throw INTERP_KERNEL::Exception(oss.str().c_str());
1473       }
1474     const char msg[]="DataArrayTemplate::setPartOfValues1";
1475     checkAllocated();
1476     a->checkAllocated();
1477     int newNbOfTuples(DataArray::GetNumberOfItemGivenBES(bgTuples,endTuples,stepTuples,msg));
1478     int newNbOfComp(DataArray::GetNumberOfItemGivenBES(bgComp,endComp,stepComp,msg));
1479     int nbComp(getNumberOfComponents()),nbOfTuples(getNumberOfTuples());
1480     DataArray::CheckValueInRangeEx(nbOfTuples,bgTuples,endTuples,"invalid tuple value");
1481     DataArray::CheckValueInRangeEx(nbComp,bgComp,endComp,"invalid component value");
1482     bool assignTech(true);
1483     if(a->getNbOfElems()==(std::size_t)newNbOfTuples*newNbOfComp)
1484       {
1485         if(strictCompoCompare)
1486           a->checkNbOfTuplesAndComp(newNbOfTuples,newNbOfComp,msg);
1487       }
1488     else
1489       {
1490         a->checkNbOfTuplesAndComp(1,newNbOfComp,msg);
1491         assignTech=false;
1492       }
1493     const T *srcPt(a->getConstPointer());
1494     T *pt(getPointer()+bgTuples*nbComp+bgComp);
1495     if(assignTech)
1496       {
1497         for(int i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
1498           for(int j=0;j<newNbOfComp;j++,srcPt++)
1499             pt[j*stepComp]=*srcPt;
1500       }
1501     else
1502       {
1503         for(int i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
1504           {
1505             const T*srcPt2=srcPt;
1506             for(int j=0;j<newNbOfComp;j++,srcPt2++)
1507               pt[j*stepComp]=*srcPt2;
1508           }
1509       }
1510   }
1511   
1512   /*!
1513  * Assign a given value to values at specified tuples and components of \a this array.
1514  * The tree parameters defining set of indices of tuples and components are similar to
1515  * the tree parameters of the Python function \c range(\c start,\c stop,\c step)..
1516  *  \param [in] a - the value to assign.
1517  *  \param [in] bgTuples - index of the first tuple of \a this array to assign to.
1518  *  \param [in] endTuples - index of the tuple before which the tuples to assign to
1519  *              are located.
1520  *  \param [in] stepTuples - index increment to get index of the next tuple to assign to.
1521  *  \param [in] bgComp - index of the first component of \a this array to assign to.
1522  *  \param [in] endComp - index of the component before which the components to assign
1523  *              to are located.
1524  *  \param [in] stepComp - index increment to get index of the next component to assign to.
1525  *  \throw If \a this is not allocated.
1526  *  \throw If parameters specifying tuples and components to assign to, do not give a
1527  *            non-empty range of increasing indices or indices are out of a valid range
1528  *            for \c this array.
1529  *
1530  *  \if ENABLE_EXAMPLES
1531  *  \ref py_mcdataarraydouble_setpartofvaluessimple1 "Here is a Python example".
1532  *  \endif
1533  */
1534   template<class T>
1535   void DataArrayTemplate<T>::setPartOfValuesSimple1(T a, int bgTuples, int endTuples, int stepTuples, int bgComp, int endComp, int stepComp)
1536   {
1537     const char msg[]="DataArrayTemplate::setPartOfValuesSimple1";
1538     checkAllocated();
1539     int newNbOfTuples(DataArray::GetNumberOfItemGivenBES(bgTuples,endTuples,stepTuples,msg));
1540     int newNbOfComp(DataArray::GetNumberOfItemGivenBES(bgComp,endComp,stepComp,msg));
1541     int nbComp(getNumberOfComponents()),nbOfTuples(getNumberOfTuples());
1542     DataArray::CheckValueInRangeEx(nbOfTuples,bgTuples,endTuples,"invalid tuple value");
1543     DataArray::CheckValueInRangeEx(nbComp,bgComp,endComp,"invalid component value");
1544     T *pt=getPointer()+bgTuples*nbComp+bgComp;
1545     for(int i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
1546       for(int j=0;j<newNbOfComp;j++)
1547         pt[j*stepComp]=a;
1548   }
1549   
1550   /*!
1551    * Copy all values from another DataArrayDouble (\a a) into specified tuples and 
1552    * components of \a this array. Textual data is not copied.
1553    * The tuples and components to assign to are defined by C arrays of indices.
1554    * There are two *modes of usage*:
1555    * - If \a a->getNbOfElems() equals to number of values to assign to, then every value
1556    *   of \a a is assigned to its own location within \a this array. 
1557    * - If \a a includes one tuple, then all values of \a a are assigned to the specified
1558    *   components of every specified tuple of \a this array. In this mode it is required
1559    *   that \a a->getNumberOfComponents() equals to the number of specified components.
1560    *
1561    *  \param [in] a - the array to copy values from.
1562    *  \param [in] bgTuples - pointer to an array of tuple indices of \a this array to
1563    *              assign values of \a a to.
1564    *  \param [in] endTuples - specifies the end of the array \a bgTuples, so that
1565    *              pointer to a tuple index <em>(pi)</em> varies as this: 
1566    *              \a bgTuples <= \a pi < \a endTuples.
1567    *  \param [in] bgComp - pointer to an array of component indices of \a this array to
1568    *              assign values of \a a to.
1569    *  \param [in] endComp - specifies the end of the array \a bgTuples, so that
1570    *              pointer to a component index <em>(pi)</em> varies as this: 
1571    *              \a bgComp <= \a pi < \a endComp.
1572    *  \param [in] strictCompoCompare - this parameter is checked only if the
1573    *               *mode of usage* is the first; if it is \a true (default), 
1574    *               then \a a->getNumberOfComponents() must be equal 
1575    *               to the number of specified columns, else this is not required.
1576    *  \throw If \a a is NULL.
1577    *  \throw If \a a is not allocated.
1578    *  \throw If \a this is not allocated.
1579    *  \throw If any index of tuple/component given by <em>bgTuples / bgComp</em> is
1580    *         out of a valid range for \a this array.
1581    *  \throw In the first *mode of usage*, if <em>strictCompoCompare == true </em> and
1582    *         if <em> a->getNumberOfComponents() != (endComp - bgComp) </em>.
1583    *  \throw In the second *mode of usage*, if \a a->getNumberOfTuples() != 1 or
1584    *         <em> a->getNumberOfComponents() != (endComp - bgComp)</em>.
1585    *
1586    *  \if ENABLE_EXAMPLES
1587    *  \ref py_mcdataarraydouble_setpartofvalues2 "Here is a Python example".
1588    *  \endif
1589    */
1590   template<class T>
1591   void DataArrayTemplate<T>::setPartOfValues2(const typename Traits<T>::ArrayType *a, const int *bgTuples, const int *endTuples, const int *bgComp, const int *endComp, bool strictCompoCompare)
1592   {
1593     if(!a)
1594       throw INTERP_KERNEL::Exception("DataArrayDouble::setPartOfValues2 : input DataArrayDouble is NULL !");
1595     const char msg[]="DataArrayTemplate::setPartOfValues2";
1596     checkAllocated();
1597     a->checkAllocated();
1598     int nbComp(getNumberOfComponents()),nbOfTuples(getNumberOfTuples());
1599     for(const int *z=bgComp;z!=endComp;z++)
1600       DataArray::CheckValueInRange(nbComp,*z,"invalid component id");
1601     int newNbOfTuples((int)std::distance(bgTuples,endTuples));
1602     int newNbOfComp((int)std::distance(bgComp,endComp));
1603     bool assignTech(true);
1604     if(a->getNbOfElems()==(std::size_t)newNbOfTuples*newNbOfComp)
1605       {
1606         if(strictCompoCompare)
1607           a->checkNbOfTuplesAndComp(newNbOfTuples,newNbOfComp,msg);
1608       }
1609     else
1610       {
1611         a->checkNbOfTuplesAndComp(1,newNbOfComp,msg);
1612         assignTech=false;
1613       }
1614     T *pt(getPointer());
1615     const T *srcPt(a->getConstPointer());
1616     if(assignTech)
1617       {    
1618         for(const int *w=bgTuples;w!=endTuples;w++)
1619           {
1620             DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1621             for(const int *z=bgComp;z!=endComp;z++,srcPt++)
1622               {    
1623                 pt[(std::size_t)(*w)*nbComp+(*z)]=*srcPt;
1624               }
1625           }
1626       }
1627     else
1628       {
1629         for(const int *w=bgTuples;w!=endTuples;w++)
1630           {
1631             const T *srcPt2=srcPt;
1632             DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1633             for(const int *z=bgComp;z!=endComp;z++,srcPt2++)
1634               {    
1635                 pt[(std::size_t)(*w)*nbComp+(*z)]=*srcPt2;
1636               }
1637           }
1638       }
1639   }
1640   
1641   /*!
1642    * Assign a given value to values at specified tuples and components of \a this array.
1643    * The tuples and components to assign to are defined by C arrays of indices.
1644    *  \param [in] a - the value to assign.
1645    *  \param [in] bgTuples - pointer to an array of tuple indices of \a this array to
1646    *              assign \a a to.
1647    *  \param [in] endTuples - specifies the end of the array \a bgTuples, so that
1648    *              pointer to a tuple index (\a pi) varies as this: 
1649    *              \a bgTuples <= \a pi < \a endTuples.
1650    *  \param [in] bgComp - pointer to an array of component indices of \a this array to
1651    *              assign \a a to.
1652    *  \param [in] endComp - specifies the end of the array \a bgTuples, so that
1653    *              pointer to a component index (\a pi) varies as this: 
1654    *              \a bgComp <= \a pi < \a endComp.
1655    *  \throw If \a this is not allocated.
1656    *  \throw If any index of tuple/component given by <em>bgTuples / bgComp</em> is
1657    *         out of a valid range for \a this array.
1658    *
1659    *  \if ENABLE_EXAMPLES
1660    *  \ref py_mcdataarraydouble_setpartofvaluessimple2 "Here is a Python example".
1661    *  \endif
1662    */
1663   template<class T>
1664   void DataArrayTemplate<T>::setPartOfValuesSimple2(T a, const int *bgTuples, const int *endTuples, const int *bgComp, const int *endComp)
1665   {
1666     checkAllocated();
1667     int nbComp(getNumberOfComponents()),nbOfTuples(getNumberOfTuples());
1668     for(const int *z=bgComp;z!=endComp;z++)
1669       DataArray::CheckValueInRange(nbComp,*z,"invalid component id");
1670     T *pt(getPointer());
1671     for(const int *w=bgTuples;w!=endTuples;w++)
1672       for(const int *z=bgComp;z!=endComp;z++)
1673         {
1674           DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1675           pt[(std::size_t)(*w)*nbComp+(*z)]=a;
1676         }
1677   }
1678   
1679   /*!
1680    * Copy all values from another DataArrayDouble (\a a) into specified tuples and 
1681    * components of \a this array. Textual data is not copied.
1682    * The tuples to assign to are defined by a C array of indices.
1683    * The components to assign to are defined by three values similar to parameters of
1684    * the Python function \c range(\c start,\c stop,\c step).
1685    * There are two *modes of usage*:
1686    * - If \a a->getNbOfElems() equals to number of values to assign to, then every value
1687    *   of \a a is assigned to its own location within \a this array. 
1688    * - If \a a includes one tuple, then all values of \a a are assigned to the specified
1689    *   components of every specified tuple of \a this array. In this mode it is required
1690    *   that \a a->getNumberOfComponents() equals to the number of specified components.
1691    *
1692    *  \param [in] a - the array to copy values from.
1693    *  \param [in] bgTuples - pointer to an array of tuple indices of \a this array to
1694    *              assign values of \a a to.
1695    *  \param [in] endTuples - specifies the end of the array \a bgTuples, so that
1696    *              pointer to a tuple index <em>(pi)</em> varies as this: 
1697    *              \a bgTuples <= \a pi < \a endTuples.
1698    *  \param [in] bgComp - index of the first component of \a this array to assign to.
1699    *  \param [in] endComp - index of the component before which the components to assign
1700    *              to are located.
1701    *  \param [in] stepComp - index increment to get index of the next component to assign to.
1702    *  \param [in] strictCompoCompare - this parameter is checked only in the first
1703    *               *mode of usage*; if \a strictCompoCompare is \a true (default), 
1704    *               then \a a->getNumberOfComponents() must be equal 
1705    *               to the number of specified columns, else this is not required.
1706    *  \throw If \a a is NULL.
1707    *  \throw If \a a is not allocated.
1708    *  \throw If \a this is not allocated.
1709    *  \throw If any index of tuple given by \a bgTuples is out of a valid range for 
1710    *         \a this array.
1711    *  \throw In the first *mode of usage*, if <em>strictCompoCompare == true </em> and
1712    *         if <em> a->getNumberOfComponents()</em> is unequal to the number of components
1713    *         defined by <em>(bgComp,endComp,stepComp)</em>.
1714    *  \throw In the second *mode of usage*, if \a a->getNumberOfTuples() != 1 or
1715    *         <em> a->getNumberOfComponents()</em> is unequal to the number of components
1716    *         defined by <em>(bgComp,endComp,stepComp)</em>.
1717    *  \throw If parameters specifying components to assign to, do not give a
1718    *            non-empty range of increasing indices or indices are out of a valid range
1719    *            for \c this array.
1720    *
1721    *  \if ENABLE_EXAMPLES
1722    *  \ref py_mcdataarraydouble_setpartofvalues3 "Here is a Python example".
1723    *  \endif
1724    */
1725   template<class T>
1726   void DataArrayTemplate<T>::setPartOfValues3(const typename Traits<T>::ArrayType *a, const int *bgTuples, const int *endTuples, int bgComp, int endComp, int stepComp, bool strictCompoCompare)
1727   {
1728     if(!a)
1729       throw INTERP_KERNEL::Exception("DataArrayTemplate::setPartOfValues3 : input DataArrayDouble is NULL !");
1730     const char msg[]="DataArrayTemplate::setPartOfValues3";
1731     checkAllocated();
1732     a->checkAllocated();
1733     int newNbOfComp=DataArray::GetNumberOfItemGivenBES(bgComp,endComp,stepComp,msg);
1734     int nbComp=getNumberOfComponents();
1735     int nbOfTuples=getNumberOfTuples();
1736     DataArray::CheckValueInRangeEx(nbComp,bgComp,endComp,"invalid component value");
1737     int newNbOfTuples=(int)std::distance(bgTuples,endTuples);
1738     bool assignTech=true;
1739     if(a->getNbOfElems()==(std::size_t)newNbOfTuples*newNbOfComp)
1740       {
1741         if(strictCompoCompare)
1742           a->checkNbOfTuplesAndComp(newNbOfTuples,newNbOfComp,msg);
1743       }
1744     else
1745       {
1746         a->checkNbOfTuplesAndComp(1,newNbOfComp,msg);
1747         assignTech=false;
1748       }
1749     T *pt(getPointer()+bgComp);
1750     const T *srcPt(a->getConstPointer());
1751     if(assignTech)
1752       {
1753         for(const int *w=bgTuples;w!=endTuples;w++)
1754           for(int j=0;j<newNbOfComp;j++,srcPt++)
1755             {
1756               DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1757               pt[(std::size_t)(*w)*nbComp+j*stepComp]=*srcPt;
1758             }
1759       }
1760     else
1761       {
1762         for(const int *w=bgTuples;w!=endTuples;w++)
1763           {
1764             const T *srcPt2=srcPt;
1765             for(int j=0;j<newNbOfComp;j++,srcPt2++)
1766               {
1767                 DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1768                 pt[(std::size_t)(*w)*nbComp+j*stepComp]=*srcPt2;
1769               }
1770           }
1771       }
1772   }
1773   
1774   /*!
1775    * Assign a given value to values at specified tuples and components of \a this array.
1776    * The tuples to assign to are defined by a C array of indices.
1777    * The components to assign to are defined by three values similar to parameters of
1778    * the Python function \c range(\c start,\c stop,\c step).
1779    *  \param [in] a - the value to assign.
1780    *  \param [in] bgTuples - pointer to an array of tuple indices of \a this array to
1781    *              assign \a a to.
1782    *  \param [in] endTuples - specifies the end of the array \a bgTuples, so that
1783    *              pointer to a tuple index <em>(pi)</em> varies as this: 
1784    *              \a bgTuples <= \a pi < \a endTuples.
1785    *  \param [in] bgComp - index of the first component of \a this array to assign to.
1786    *  \param [in] endComp - index of the component before which the components to assign
1787    *              to are located.
1788    *  \param [in] stepComp - index increment to get index of the next component to assign to.
1789    *  \throw If \a this is not allocated.
1790    *  \throw If any index of tuple given by \a bgTuples is out of a valid range for 
1791    *         \a this array.
1792    *  \throw If parameters specifying components to assign to, do not give a
1793    *            non-empty range of increasing indices or indices are out of a valid range
1794    *            for \c this array.
1795    *
1796    *  \if ENABLE_EXAMPLES
1797    *  \ref py_mcdataarraydouble_setpartofvaluessimple3 "Here is a Python example".
1798    *  \endif
1799    */
1800   template<class T>
1801   void DataArrayTemplate<T>::setPartOfValuesSimple3(T a, const int *bgTuples, const int *endTuples, int bgComp, int endComp, int stepComp)
1802   {
1803     const char msg[]="DataArrayTemplate::setPartOfValuesSimple3";
1804     checkAllocated();
1805     int newNbOfComp(DataArray::GetNumberOfItemGivenBES(bgComp,endComp,stepComp,msg));
1806     int nbComp(getNumberOfComponents()),nbOfTuples(getNumberOfTuples());
1807     DataArray::CheckValueInRangeEx(nbComp,bgComp,endComp,"invalid component value");
1808     T *pt(getPointer()+bgComp);
1809     for(const int *w=bgTuples;w!=endTuples;w++)
1810       for(int j=0;j<newNbOfComp;j++)
1811         {
1812           DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1813           pt[(std::size_t)(*w)*nbComp+j*stepComp]=a;
1814         }
1815   }
1816
1817   /*!
1818    * Copy all values from another DataArrayDouble into specified tuples and components
1819    * of \a this array. Textual data is not copied.
1820    * The tree parameters defining set of indices of tuples and components are similar to
1821    * the tree parameters of the Python function \c range(\c start,\c stop,\c step).
1822    *  \param [in] a - the array to copy values from.
1823    *  \param [in] bgTuples - index of the first tuple of \a this array to assign values to.
1824    *  \param [in] endTuples - index of the tuple before which the tuples to assign to
1825    *              are located.
1826    *  \param [in] stepTuples - index increment to get index of the next tuple to assign to.
1827    *  \param [in] bgComp - pointer to an array of component indices of \a this array to
1828    *              assign \a a to.
1829    *  \param [in] endComp - specifies the end of the array \a bgTuples, so that
1830    *              pointer to a component index (\a pi) varies as this: 
1831    *              \a bgComp <= \a pi < \a endComp.
1832    *  \param [in] strictCompoCompare - if \a true (by default), then \a a->getNumberOfComponents() 
1833    *              must be equal to the number of columns to assign to, else an
1834    *              exception is thrown; if \a false, then it is only required that \a
1835    *              a->getNbOfElems() equals to number of values to assign to (this condition
1836    *              must be respected even if \a strictCompoCompare is \a true). The number of 
1837    *              values to assign to is given by following Python expression:
1838    *              \a nbTargetValues = 
1839    *              \c len(\c range(\a bgTuples,\a endTuples,\a stepTuples)) *
1840    *              \c len(\c range(\a bgComp,\a endComp,\a stepComp)).
1841    *  \throw If \a a is NULL.
1842    *  \throw If \a a is not allocated.
1843    *  \throw If \a this is not allocated.
1844    *  \throw If parameters specifying tuples and components to assign to do not give a
1845    *            non-empty range of increasing indices.
1846    *  \throw If \a a->getNbOfElems() != \a nbTargetValues.
1847    *  \throw If \a strictCompoCompare == \a true && \a a->getNumberOfComponents() !=
1848    *            \c len(\c range(\a bgComp,\a endComp,\a stepComp)).
1849    *
1850    */
1851   template<class T>
1852   void DataArrayTemplate<T>::setPartOfValues4(const typename Traits<T>::ArrayType *a, int bgTuples, int endTuples, int stepTuples, const int *bgComp, const int *endComp, bool strictCompoCompare)
1853   {if(!a)
1854       throw INTERP_KERNEL::Exception("DataArrayTemplate::setPartOfValues4 : input DataArrayTemplate is NULL !");
1855     const char msg[]="DataArrayTemplate::setPartOfValues4";
1856     checkAllocated();
1857     a->checkAllocated();
1858     int newNbOfTuples(DataArray::GetNumberOfItemGivenBES(bgTuples,endTuples,stepTuples,msg));
1859     int newNbOfComp((int)std::distance(bgComp,endComp));
1860     int nbComp(getNumberOfComponents());
1861     for(const int *z=bgComp;z!=endComp;z++)
1862       DataArray::CheckValueInRange(nbComp,*z,"invalid component id");
1863     int nbOfTuples(getNumberOfTuples());
1864     DataArray::CheckValueInRangeEx(nbOfTuples,bgTuples,endTuples,"invalid tuple value");
1865     bool assignTech(true);
1866     if(a->getNbOfElems()==(std::size_t)newNbOfTuples*newNbOfComp)
1867       {
1868         if(strictCompoCompare)
1869           a->checkNbOfTuplesAndComp(newNbOfTuples,newNbOfComp,msg);
1870       }
1871     else
1872       {
1873         a->checkNbOfTuplesAndComp(1,newNbOfComp,msg);
1874         assignTech=false;
1875       }
1876     const T *srcPt(a->getConstPointer());
1877     T *pt(getPointer()+bgTuples*nbComp);
1878     if(assignTech)
1879       {
1880         for(int i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
1881           for(const int *z=bgComp;z!=endComp;z++,srcPt++)
1882             pt[*z]=*srcPt;
1883       }
1884     else
1885       {
1886       for(int i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
1887         {
1888           const T *srcPt2(srcPt);
1889           for(const int *z=bgComp;z!=endComp;z++,srcPt2++)
1890             pt[*z]=*srcPt2;
1891         }
1892       }
1893   }
1894
1895   template<class T>
1896   void DataArrayTemplate<T>::setPartOfValuesSimple4(T a, int bgTuples, int endTuples, int stepTuples, const int *bgComp, const int *endComp)
1897   {
1898     const char msg[]="DataArrayTemplate::setPartOfValuesSimple4";
1899     checkAllocated();
1900     int newNbOfTuples(DataArray::GetNumberOfItemGivenBES(bgTuples,endTuples,stepTuples,msg));
1901     int nbComp(getNumberOfComponents());
1902     for(const int *z=bgComp;z!=endComp;z++)
1903       DataArray::CheckValueInRange(nbComp,*z,"invalid component id");
1904     int nbOfTuples(getNumberOfTuples());
1905     DataArray::CheckValueInRangeEx(nbOfTuples,bgTuples,endTuples,"invalid tuple value");
1906     T *pt=getPointer()+bgTuples*nbComp;
1907     for(int i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
1908       for(const int *z=bgComp;z!=endComp;z++)
1909         pt[*z]=a;
1910   }
1911   
1912   /*!
1913    * Copy some tuples from another DataArrayDouble into specified tuples
1914    * of \a this array. Textual data is not copied. Both arrays must have equal number of
1915    * components.
1916    * Both the tuples to assign and the tuples to assign to are defined by a DataArrayInt.
1917    * All components of selected tuples are copied.
1918    *  \param [in] a - the array to copy values from.
1919    *  \param [in] tuplesSelec - the array specifying both source tuples of \a a and
1920    *              target tuples of \a this. \a tuplesSelec has two components, and the
1921    *              first component specifies index of the source tuple and the second
1922    *              one specifies index of the target tuple.
1923    *  \throw If \a this is not allocated.
1924    *  \throw If \a a is NULL.
1925    *  \throw If \a a is not allocated.
1926    *  \throw If \a tuplesSelec is NULL.
1927    *  \throw If \a tuplesSelec is not allocated.
1928    *  \throw If <em>this->getNumberOfComponents() != a->getNumberOfComponents()</em>.
1929    *  \throw If \a tuplesSelec->getNumberOfComponents() != 2.
1930    *  \throw If any tuple index given by \a tuplesSelec is out of a valid range for 
1931    *         the corresponding (\a this or \a a) array.
1932    */
1933   template<class T>
1934   void DataArrayTemplate<T>::setPartOfValuesAdv(const typename Traits<T>::ArrayType *a, const DataArrayInt *tuplesSelec)
1935   {
1936     if(!a || !tuplesSelec)
1937       throw INTERP_KERNEL::Exception("DataArrayTemplate::setPartOfValuesAdv : input DataArrayTemplate is NULL !");
1938     checkAllocated();
1939     a->checkAllocated();
1940     tuplesSelec->checkAllocated();
1941     std::size_t nbOfComp(getNumberOfComponents());
1942     if(nbOfComp!=a->getNumberOfComponents())
1943       throw INTERP_KERNEL::Exception("DataArrayTemplate::setPartOfValuesAdv : This and a do not have the same number of components !");
1944     if(tuplesSelec->getNumberOfComponents()!=2)
1945       throw INTERP_KERNEL::Exception("DataArrayTemplate::setPartOfValuesAdv : Expecting to have a tuple selector DataArrayInt instance with exactly 2 components !");
1946     int thisNt(getNumberOfTuples());
1947     int aNt(a->getNumberOfTuples());
1948     T *valsToSet(getPointer());
1949     const T *valsSrc(a->getConstPointer());
1950     for(const int *tuple=tuplesSelec->begin();tuple!=tuplesSelec->end();tuple+=2)
1951     {
1952       if(tuple[1]>=0 && tuple[1]<aNt)
1953         {
1954           if(tuple[0]>=0 && tuple[0]<thisNt)
1955             std::copy(valsSrc+nbOfComp*tuple[1],valsSrc+nbOfComp*(tuple[1]+1),valsToSet+nbOfComp*tuple[0]);
1956           else
1957             {
1958               std::ostringstream oss; oss << "DataArrayTemplate::setPartOfValuesAdv : Tuple #" << std::distance(tuplesSelec->begin(),tuple)/2;
1959               oss << " of 'tuplesSelec' request of tuple id #" << tuple[0] << " in 'this' ! It should be in [0," << thisNt << ") !";
1960               throw INTERP_KERNEL::Exception(oss.str().c_str());
1961             }
1962         }
1963       else
1964         {
1965           std::ostringstream oss; oss << "DataArrayTemplate::setPartOfValuesAdv : Tuple #" << std::distance(tuplesSelec->begin(),tuple)/2;
1966           oss << " of 'tuplesSelec' request of tuple id #" << tuple[1] << " in 'a' ! It should be in [0," << aNt << ") !";
1967           throw INTERP_KERNEL::Exception(oss.str().c_str());
1968         }
1969     }
1970   }
1971   
1972   /*!
1973    * Copy some tuples from another DataArrayDouble (\a aBase) into contiguous tuples
1974    * of \a this array. Textual data is not copied. Both arrays must have equal number of
1975    * components.
1976    * The tuples to assign to are defined by index of the first tuple, and
1977    * their number is defined by \a tuplesSelec->getNumberOfTuples().
1978    * The tuples to copy are defined by values of a DataArrayInt.
1979    * All components of selected tuples are copied.
1980    *  \param [in] tupleIdStart - index of the first tuple of \a this array to assign
1981    *              values to.
1982    *  \param [in] aBase - the array to copy values from.
1983    *  \param [in] tuplesSelec - the array specifying tuples of \a a to copy.
1984    *  \throw If \a this is not allocated.
1985    *  \throw If \a aBase is NULL.
1986    *  \throw If \a aBase is not allocated.
1987    *  \throw If \a tuplesSelec is NULL.
1988    *  \throw If \a tuplesSelec is not allocated.
1989    *  \throw If <em>this->getNumberOfComponents() != aBase->getNumberOfComponents()</em>.
1990    *  \throw If \a tuplesSelec->getNumberOfComponents() != 1.
1991    *  \throw If <em>tupleIdStart + tuplesSelec->getNumberOfTuples() > this->getNumberOfTuples().</em>
1992    *  \throw If any tuple index given by \a tuplesSelec is out of a valid range for 
1993    *         \a aBase array.
1994  */
1995   template<class T>
1996   void DataArrayTemplate<T>::setContigPartOfSelectedValues(int tupleIdStart, const DataArray *aBase, const DataArrayInt *tuplesSelec)
1997   {
1998     if(!aBase || !tuplesSelec)
1999       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValues : input DataArray is NULL !");
2000     const typename Traits<T>::ArrayType *a(dynamic_cast<const typename Traits<T>::ArrayType *>(aBase));
2001     if(!a)
2002       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValues : input DataArray aBase is not a DataArrayDouble !");
2003     checkAllocated();
2004     a->checkAllocated();
2005     tuplesSelec->checkAllocated();
2006     std::size_t nbOfComp(getNumberOfComponents());
2007     if(nbOfComp!=a->getNumberOfComponents())
2008       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValues : This and a do not have the same number of components !");
2009     if(tuplesSelec->getNumberOfComponents()!=1)
2010       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValues : Expecting to have a tuple selector DataArrayInt instance with exactly 1 component !");
2011     int thisNt(getNumberOfTuples());
2012     int aNt(a->getNumberOfTuples());
2013     int nbOfTupleToWrite(tuplesSelec->getNumberOfTuples());
2014     T *valsToSet(getPointer()+tupleIdStart*nbOfComp);
2015     if(tupleIdStart+nbOfTupleToWrite>thisNt)
2016       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValues : invalid number range of values to write !");
2017     const T *valsSrc=a->getConstPointer();
2018     for(const int *tuple=tuplesSelec->begin();tuple!=tuplesSelec->end();tuple++,valsToSet+=nbOfComp)
2019       {
2020         if(*tuple>=0 && *tuple<aNt)
2021           {
2022             std::copy(valsSrc+nbOfComp*(*tuple),valsSrc+nbOfComp*(*tuple+1),valsToSet);
2023           }
2024         else
2025           {
2026             std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::setContigPartOfSelectedValues : Tuple #" << std::distance(tuplesSelec->begin(),tuple);
2027             oss << " of 'tuplesSelec' request of tuple id #" << *tuple << " in 'a' ! It should be in [0," << aNt << ") !";
2028             throw INTERP_KERNEL::Exception(oss.str().c_str());
2029           }
2030       }
2031   }
2032   
2033   /*!
2034    * Copy some tuples from another DataArrayDouble (\a aBase) into contiguous tuples
2035    * of \a this array. Textual data is not copied. Both arrays must have equal number of
2036    * components.
2037    * The tuples to copy are defined by three values similar to parameters of
2038    * the Python function \c range(\c start,\c stop,\c step).
2039    * The tuples to assign to are defined by index of the first tuple, and
2040    * their number is defined by number of tuples to copy.
2041    * All components of selected tuples are copied.
2042    *  \param [in] tupleIdStart - index of the first tuple of \a this array to assign
2043    *              values to.
2044    *  \param [in] aBase - the array to copy values from.
2045    *  \param [in] bg - index of the first tuple to copy of the array \a aBase.
2046    *  \param [in] end2 - index of the tuple of \a aBase before which the tuples to copy
2047    *              are located.
2048    *  \param [in] step - index increment to get index of the next tuple to copy.
2049    *  \throw If \a this is not allocated.
2050    *  \throw If \a aBase is NULL.
2051    *  \throw If \a aBase is not allocated.
2052    *  \throw If <em>this->getNumberOfComponents() != aBase->getNumberOfComponents()</em>.
2053    *  \throw If <em>tupleIdStart + len(range(bg,end2,step)) > this->getNumberOfTuples().</em>
2054    *  \throw If parameters specifying tuples to copy, do not give a
2055    *            non-empty range of increasing indices or indices are out of a valid range
2056    *            for the array \a aBase.
2057    */
2058   template<class T>
2059   void DataArrayTemplate<T>::setContigPartOfSelectedValuesSlice(int tupleIdStart, const DataArray *aBase, int bg, int end2, int step)
2060   {
2061     if(!aBase)
2062       {
2063         std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::setContigPartOfSelectedValuesSlice : input DataArray is NULL !";
2064         throw INTERP_KERNEL::Exception(oss.str().c_str());
2065       }
2066     const typename Traits<T>::ArrayType *a(dynamic_cast<const typename Traits<T>::ArrayType *>(aBase));
2067     if(!a)
2068       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValuesSlice : input DataArray aBase is not a DataArrayDouble !");
2069     checkAllocated();
2070     a->checkAllocated();
2071     std::size_t nbOfComp(getNumberOfComponents());
2072     const char msg[]="DataArrayDouble::setContigPartOfSelectedValuesSlice";
2073     int nbOfTupleToWrite(DataArray::GetNumberOfItemGivenBES(bg,end2,step,msg));
2074     if(nbOfComp!=a->getNumberOfComponents())
2075       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValuesSlice : This and a do not have the same number of components !");
2076     int thisNt(getNumberOfTuples()),aNt(a->getNumberOfTuples());
2077     T *valsToSet(getPointer()+tupleIdStart*nbOfComp);
2078     if(tupleIdStart+nbOfTupleToWrite>thisNt)
2079       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValuesSlice : invalid number range of values to write !");
2080     if(end2>aNt)
2081       throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValuesSlice : invalid range of values to read !");
2082     const T *valsSrc(a->getConstPointer()+bg*nbOfComp);
2083     for(int i=0;i<nbOfTupleToWrite;i++,valsToSet+=nbOfComp,valsSrc+=step*nbOfComp)
2084       {
2085         std::copy(valsSrc,valsSrc+nbOfComp,valsToSet);
2086       }
2087   }
2088
2089   /*!
2090    * Returns a shorten copy of \a this array. The new DataArrayDouble contains ranges
2091    * of tuples specified by \a ranges parameter.
2092    * For more info on renumbering see \ref numbering.
2093    *  \param [in] ranges - std::vector of std::pair's each of which defines a range
2094    *              of tuples in [\c begin,\c end) format.
2095    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
2096    *          is to delete using decrRef() as it is no more needed.
2097    *  \throw If \a end < \a begin.
2098    *  \throw If \a end > \a this->getNumberOfTuples().
2099    *  \throw If \a this is not allocated.
2100    */
2101   template<class T>
2102   typename Traits<T>::ArrayType *DataArrayTemplate<T>::mySelectByTupleRanges(const std::vector<std::pair<int,int> >& ranges) const
2103   {
2104     checkAllocated();
2105     int nbOfComp(getNumberOfComponents()),nbOfTuplesThis(getNumberOfTuples());
2106     if(ranges.empty())
2107       {
2108         MCAuto<DataArray> ret0(buildNewEmptyInstance());
2109         MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
2110         ret->alloc(0,nbOfComp);
2111         ret->copyStringInfoFrom(*this);
2112         return ret.retn();
2113       }
2114     int ref(ranges.front().first),nbOfTuples(0);
2115     bool isIncreasing(true);
2116     for(std::vector<std::pair<int,int> >::const_iterator it=ranges.begin();it!=ranges.end();it++)
2117       {
2118         if((*it).first<=(*it).second)
2119           {
2120             if((*it).first>=0 && (*it).second<=nbOfTuplesThis)
2121               {
2122                 nbOfTuples+=(*it).second-(*it).first;
2123                 if(isIncreasing)
2124                   isIncreasing=ref<=(*it).first;
2125                 ref=(*it).second;
2126               }
2127             else
2128               {
2129                 std::ostringstream oss; oss << "DataArrayTemplate::selectByTupleRanges : on range #" << std::distance(ranges.begin(),it);
2130                 oss << " (" << (*it).first << "," << (*it).second << ") is greater than number of tuples of this :" << nbOfTuples << " !";
2131                 throw INTERP_KERNEL::Exception(oss.str().c_str());
2132               }
2133           }
2134         else
2135           {
2136             std::ostringstream oss; oss << "DataArrayTemplate::selectByTupleRanges : on range #" << std::distance(ranges.begin(),it);
2137             oss << " (" << (*it).first << "," << (*it).second << ") end is before begin !";
2138             throw INTERP_KERNEL::Exception(oss.str().c_str());
2139           }
2140       }
2141     if(isIncreasing && nbOfTuplesThis==nbOfTuples)
2142       return static_cast<typename Traits<T>::ArrayType *>(deepCopy());
2143     MCAuto<DataArray> ret0(buildNewEmptyInstance());
2144     MCAuto< typename Traits<T>::ArrayType > ret(DynamicCastSafe<DataArray,typename Traits<T>::ArrayType>(ret0));
2145     ret->alloc(nbOfTuples,nbOfComp);
2146     ret->copyStringInfoFrom(*this);
2147     const T *src(getConstPointer());
2148     T *work(ret->getPointer());
2149     for(std::vector<std::pair<int,int> >::const_iterator it=ranges.begin();it!=ranges.end();it++)
2150       work=std::copy(src+(*it).first*nbOfComp,src+(*it).second*nbOfComp,work);
2151     return ret.retn();
2152   }
2153
2154   /*!
2155    * Returns the first value of \a this. 
2156    *  \return double - the last value of \a this array.
2157    *  \throw If \a this is not allocated.
2158    *  \throw If \a this->getNumberOfComponents() != 1.
2159    *  \throw If \a this->getNumberOfTuples() < 1.
2160    */
2161   template<class T>
2162   T DataArrayTemplate<T>::front() const
2163   {
2164     checkAllocated();
2165     if(getNumberOfComponents()!=1)
2166       throw INTERP_KERNEL::Exception("DataArrayTemplate::front : number of components not equal to one !");
2167     int nbOfTuples(getNumberOfTuples());
2168     if(nbOfTuples<1)
2169       throw INTERP_KERNEL::Exception("DataArrayTemplate::front : number of tuples must be >= 1 !");
2170     return *(getConstPointer());
2171   }
2172   
2173   /*!
2174    * Returns the last value of \a this. 
2175    *  \return double - the last value of \a this array.
2176    *  \throw If \a this is not allocated.
2177    *  \throw If \a this->getNumberOfComponents() != 1.
2178    *  \throw If \a this->getNumberOfTuples() < 1.
2179    */
2180   template<class T>
2181   T DataArrayTemplate<T>::back() const
2182   {
2183     checkAllocated();
2184     if(getNumberOfComponents()!=1)
2185       throw INTERP_KERNEL::Exception("DataArrayTemplate::back : number of components not equal to one !");
2186     int nbOfTuples(getNumberOfTuples());
2187     if(nbOfTuples<1)
2188       throw INTERP_KERNEL::Exception("DataArrayTemplate::back : number of tuples must be >= 1 !");
2189     return *(getConstPointer()+nbOfTuples-1);
2190   }
2191   
2192   /*!
2193    * Returns the maximal value and its location within \a this one-dimensional array.
2194    *  \param [out] tupleId - index of the tuple holding the maximal value.
2195    *  \return double - the maximal value among all values of \a this array.
2196    *  \throw If \a this->getNumberOfComponents() != 1
2197    *  \throw If \a this->getNumberOfTuples() < 1
2198    *  \sa getMaxAbsValue, getMinValue
2199    */
2200   template<class T>
2201   T DataArrayTemplate<T>::getMaxValue(int& tupleId) const
2202   {
2203     checkAllocated();
2204     if(getNumberOfComponents()!=1)
2205       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 !");
2206     int nbOfTuples(getNumberOfTuples());
2207     if(nbOfTuples<=0)
2208       throw INTERP_KERNEL::Exception("DataArrayDouble::getMaxValue : array exists but number of tuples must be > 0 !");
2209     const T *vals(getConstPointer());
2210     const T *loc(std::max_element(vals,vals+nbOfTuples));
2211     tupleId=(int)std::distance(vals,loc);
2212     return *loc;
2213   }
2214   
2215   /*!
2216    * Returns the maximal value within \a this array that is allowed to have more than
2217    *  one component.
2218    *  \return double - the maximal value among all values of \a this array.
2219    *  \throw If \a this is not allocated.
2220    *  \sa getMaxAbsValueInArray, getMinValueInArray
2221    */
2222   template<class T>
2223   T DataArrayTemplate<T>::getMaxValueInArray() const
2224   {
2225     checkAllocated();
2226     const T *loc(std::max_element(begin(),end()));
2227     return *loc;
2228   }
2229   
2230   /*!
2231    * Returns the maximal absolute value in \a this and the first occurrence location associated to it.
2232    * \return the element in this (positive or negative) having the max abs value in \a this.
2233    *  \throw If \a this is not allocated.
2234    *  \throw If \a this is non one component array.
2235    *  \throw If \a this is empty.
2236    */
2237   template<class T>
2238   T DataArrayTemplate<T>::getMaxAbsValue(std::size_t& tupleId) const
2239   {
2240     checkAllocated();
2241     if(getNumberOfComponents()!=1)
2242       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 !");
2243     std::size_t nbTuples(this->getNumberOfTuples());
2244     if(nbTuples==0)
2245       throw INTERP_KERNEL::Exception("DataArrayTemplate<T>::getMaxAbsValue : empty array !");
2246     T ret((T)-1);
2247     tupleId=0;
2248     const T *pt(begin());
2249     for(std::size_t i=0;i<nbTuples;i++,pt++)
2250       {
2251         T cand(std::abs(*pt));
2252         if(cand>ret)
2253           {
2254             ret=cand;
2255             tupleId=i;
2256           }
2257       }
2258     return this->getIJ(tupleId,0);
2259   }
2260
2261   /*!
2262    * Returns the maximal absolute value in \a this.
2263    *  \throw If \a this is not allocated.
2264    *  \throw If \a this is non one component array.
2265    *  \throw If \a this is empty.
2266    */
2267   template<class T>
2268   T DataArrayTemplate<T>::getMaxAbsValueInArray() const
2269   {
2270     std::size_t dummy;
2271     return getMaxAbsValue(dummy);
2272   }
2273
2274   /*!
2275    * Returns the minimal value and its location within \a this one-dimensional array.
2276    *  \param [out] tupleId - index of the tuple holding the minimal value.
2277    *  \return double - the minimal value among all values of \a this array.
2278    *  \throw If \a this->getNumberOfComponents() != 1
2279    *  \throw If \a this->getNumberOfTuples() < 1
2280    */
2281   template<class T>
2282   T DataArrayTemplate<T>::getMinValue(int& tupleId) const
2283   {
2284     checkAllocated();
2285     if(getNumberOfComponents()!=1)
2286       throw INTERP_KERNEL::Exception("DataArrayDouble::getMinValue : must be applied on DataArrayDouble with only one component, you can call 'rearrange' method before call 'getMinValueInArray' method !");
2287     int nbOfTuples(getNumberOfTuples());
2288     if(nbOfTuples<=0)
2289       throw INTERP_KERNEL::Exception("DataArrayDouble::getMinValue : array exists but number of tuples must be > 0 !");
2290     const T *vals(getConstPointer());
2291     const T *loc(std::min_element(vals,vals+nbOfTuples));
2292     tupleId=(int)std::distance(vals,loc);
2293     return *loc;
2294   }
2295   
2296   /*!
2297    * Returns the minimal value within \a this array that is allowed to have more than
2298    *  one component.
2299    *  \return double - the minimal value among all values of \a this array.
2300    *  \throw If \a this is not allocated.
2301    */
2302   template<class T>
2303   T DataArrayTemplate<T>::getMinValueInArray() const
2304   {
2305     checkAllocated();
2306     const T *loc=std::min_element(begin(),end());
2307     return *loc;
2308   }
2309   
2310   template<class T>
2311   void DataArrayTemplate<T>::circularPermutation(int nbOfShift)
2312   {
2313     checkAllocated();
2314     int nbOfCompo(getNumberOfComponents()),nbTuples(getNumberOfTuples());
2315     int effNbSh(EffectiveCircPerm(nbOfShift,nbTuples));
2316     if(effNbSh==0)
2317       return ;
2318     T *work(getPointer());
2319     if(effNbSh<nbTuples-effNbSh)
2320       {
2321         typename INTERP_KERNEL::AutoPtr<T> buf(new T[effNbSh*nbOfCompo]);
2322         std::copy(work,work+effNbSh*nbOfCompo,(T *)buf);
2323         std::copy(work+effNbSh*nbOfCompo,work+nbTuples*nbOfCompo,work);// ze big shift
2324         std::copy((T *)buf,(T *)buf+effNbSh*nbOfCompo,work+(nbTuples-effNbSh)*nbOfCompo);
2325       }
2326     else
2327       {
2328         typename INTERP_KERNEL::AutoPtr<T> buf(new T[(nbTuples-effNbSh)*nbOfCompo]);
2329         std::copy(work+effNbSh*nbOfCompo,work+nbTuples*nbOfCompo,(T *)buf);
2330         std::copy(work,work+effNbSh*nbOfCompo,work+(nbTuples-effNbSh)*nbOfCompo);// ze big shift
2331         std::copy((T*)buf,(T *)buf+(nbTuples-effNbSh)*nbOfCompo,work);
2332       }
2333   }
2334   
2335   template<class T>
2336   void DataArrayTemplate<T>::circularPermutationPerTuple(int nbOfShift)
2337   {
2338     checkAllocated();
2339     int nbOfCompo(getNumberOfComponents()),nbTuples(getNumberOfTuples());
2340     int effNbSh(EffectiveCircPerm(nbOfShift,nbOfCompo));
2341     if(effNbSh==0)
2342       return ;
2343     T *work(getPointer());
2344     if(effNbSh<nbOfCompo-effNbSh)
2345       {
2346         typename INTERP_KERNEL::AutoPtr<T> buf(new T[effNbSh]);
2347         for(int i=0;i<nbTuples;i++,work+=nbOfCompo)
2348           {
2349             std::copy(work,work+effNbSh,(T *)buf);
2350             std::copy(work+effNbSh,work+nbOfCompo,work);// ze big shift
2351             std::copy((T *)buf,(T *)buf+effNbSh,work+(nbOfCompo-effNbSh));
2352           }
2353       }
2354     else
2355       {
2356         typename INTERP_KERNEL::AutoPtr<T> buf(new T[nbOfCompo-effNbSh]);
2357         for(int i=0;i<nbTuples;i++,work+=nbOfCompo)
2358           {
2359             std::copy(work+effNbSh,work+nbOfCompo,(T *)buf);
2360             std::copy(work,work+effNbSh,work+(nbOfCompo-effNbSh));// ze big shift
2361             std::copy((T*)buf,(T *)buf+(nbOfCompo-effNbSh),work);
2362           }
2363       }
2364     std::vector<std::string> sts(nbOfCompo);
2365     for(int i=0;i<nbOfCompo;i++)
2366       sts[i]=_info_on_compo[(i+effNbSh)%nbOfCompo];
2367     setInfoOnComponents(sts);
2368   }
2369   
2370   template<class T>
2371   void DataArrayTemplate<T>::reversePerTuple()
2372   {
2373     checkAllocated();
2374     int nbOfCompo(getNumberOfComponents()),nbTuples(getNumberOfTuples());
2375     if(nbOfCompo<=1)
2376       return ;
2377     T *work(getPointer());
2378     for(int i=0;i<nbTuples;i++,work+=nbOfCompo)
2379       std::reverse(work,work+nbOfCompo);
2380     std::reverse(_info_on_compo.begin(),_info_on_compo.end());
2381   }
2382
2383   /*!
2384    * Assign pointer to one array to a pointer to another appay. Reference counter of
2385    * \a arrayToSet is incremented / decremented.
2386    *  \param [in] newArray - the pointer to array to assign to \a arrayToSet.
2387    *  \param [in,out] arrayToSet - the pointer to array to assign to.
2388    */
2389   template<class T>
2390   void DataArrayTemplate<T>::SetArrayIn(typename Traits<T>::ArrayType *newArray, typename Traits<T>::ArrayType* &arrayToSet)
2391   {
2392     if(newArray!=arrayToSet)
2393       {
2394         if(arrayToSet)
2395           arrayToSet->decrRef();
2396         arrayToSet=newArray;
2397         if(arrayToSet)
2398           arrayToSet->incrRef();
2399       }
2400   }
2401
2402     /*!
2403    * Assign zero to all values in \a this array. To know more on filling arrays see
2404    * \ref MEDCouplingArrayFill.
2405    * \throw If \a this is not allocated.
2406    */
2407   template<class T>
2408   void DataArrayTemplate<T>::fillWithZero()
2409   {
2410     fillWithValue((T)0);
2411   }
2412
2413   //////////////////////////////
2414
2415   template<class T>
2416   template<class U>
2417   MCAuto< typename Traits<U>::ArrayType > DataArrayTemplateClassic<T>::convertToOtherTypeOfArr() const
2418   {
2419     this->checkAllocated();
2420     MCAuto<typename Traits<U>::ArrayType> ret(Traits<U>::ArrayType::New());
2421     ret->alloc(this->getNumberOfTuples(),this->getNumberOfComponents());
2422     std::size_t nbOfVals(this->getNbOfElems());
2423     const T *src(this->begin());
2424     U *dest(ret->getPointer());
2425     // to make Visual C++ happy : instead of std::size_t nbOfVals=getNbOfElems(); std::copy(src,src+nbOfVals,dest);
2426     //for(const T *src=this->begin();src!=this->end();src++,dest++)
2427     //  *dest=(int)*src;
2428     std::copy(src,src+nbOfVals,dest);
2429     ret->copyStringInfoFrom(*this);
2430     return ret;
2431   }
2432   
2433   /*!
2434    * Creates a new DataArrayDouble and assigns all (textual and numerical) data of \a this
2435    * array to the new one.
2436    *  \return DataArrayDouble * - the new instance of DataArrayInt.
2437    */
2438   template<class T>
2439   MCAuto<DataArrayDouble> DataArrayTemplateClassic<T>::convertToDblArr() const
2440   {
2441     return convertToOtherTypeOfArr<double>();
2442   }
2443
2444   /*!
2445    * Creates a new DataArrayInt and assigns all (textual and numerical) data of \a this
2446    * array to the new one.
2447    *  \return DataArrayInt * - the new instance of DataArrayInt.
2448    */
2449   template<class T>
2450   MCAuto<DataArrayInt> DataArrayTemplateClassic<T>::convertToIntArr() const
2451   {
2452     return convertToOtherTypeOfArr<int>();
2453   }
2454
2455   /*!
2456    * Creates a new DataArrayFloat and assigns all (textual and numerical) data of \a this
2457    * array to the new one.
2458    *  \return DataArrayFloat * - the new instance of DataArrayInt.
2459    */
2460   template<class T>
2461   MCAuto<DataArrayFloat> DataArrayTemplateClassic<T>::convertToFloatArr() const
2462   {
2463     return convertToOtherTypeOfArr<float>();
2464   }
2465
2466   /*!
2467    * Apply a linear function to a given component of \a this array, so that
2468    * an array element <em>(x)</em> becomes \f$ a * x + b \f$.
2469    *  \param [in] a - the first coefficient of the function.
2470    *  \param [in] b - the second coefficient of the function.
2471    *  \param [in] compoId - the index of component to modify.
2472    *  \throw If \a this is not allocated, or \a compoId is not in [0,\c this->getNumberOfComponents() ).
2473    */
2474   template<class T>
2475   void DataArrayTemplateClassic<T>::applyLin(T a, T b, int compoId)
2476   {
2477     this->checkAllocated();
2478     T *ptr(this->getPointer()+compoId);
2479     int nbOfComp(this->getNumberOfComponents()),nbOfTuple(this->getNumberOfTuples());
2480     if(compoId<0 || compoId>=nbOfComp)
2481       {
2482         std::ostringstream oss; oss << "DataArrayDouble::applyLin : The compoId requested (" << compoId << ") is not valid ! Must be in [0," << nbOfComp << ") !";
2483         throw INTERP_KERNEL::Exception(oss.str().c_str());
2484       }
2485     for(int i=0;i<nbOfTuple;i++,ptr+=nbOfComp)
2486       *ptr=a*(*ptr)+b;
2487     this->declareAsNew();
2488   }
2489
2490   /*!
2491    * Apply a linear function to all elements of \a this array, so that
2492    * an element _x_ becomes \f$ a * x + b \f$.
2493    *  \param [in] a - the first coefficient of the function.
2494    *  \param [in] b - the second coefficient of the function.
2495    *  \throw If \a this is not allocated.
2496    */
2497   template<class T>
2498   void DataArrayTemplateClassic<T>::applyLin(T a, T b)
2499   {
2500     this->checkAllocated();
2501     T *ptr(this->getPointer());
2502     std::size_t nbOfElems(this->getNbOfElems());
2503     for(std::size_t i=0;i<nbOfElems;i++,ptr++)
2504       *ptr=a*(*ptr)+b;
2505     this->declareAsNew();
2506   }
2507   
2508   /*!
2509    * Returns a full copy of \a this array except that sign of all elements is reversed.
2510    *  \return DataArrayDouble * - the new instance of DataArrayDouble containing the
2511    *          same number of tuples and component as \a this array.
2512    *          The caller is to delete this result array using decrRef() as it is no more
2513    *          needed.
2514    *  \throw If \a this is not allocated.
2515    */
2516   template<class T>
2517   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::negate() const
2518   {
2519     this->checkAllocated();
2520     MCAuto<typename Traits<T>::ArrayType> newArr(Traits<T>::ArrayType::New());
2521     int nbOfTuples(this->getNumberOfTuples()),nbOfComp(this->getNumberOfComponents());
2522     newArr->alloc(nbOfTuples,nbOfComp);
2523     const T *cptr(this->begin());
2524     std::transform(cptr,cptr+nbOfTuples*nbOfComp,newArr->getPointer(),std::negate<T>());
2525     newArr->copyStringInfoFrom(*this);
2526     return newArr.retn();
2527   }
2528
2529   template<class T>
2530   template<class FCT>
2531   void DataArrayTemplateClassic<T>::somethingEqual(const typename Traits<T>::ArrayType *other)
2532   {
2533     if(!other)
2534       throw INTERP_KERNEL::Exception("DataArray<T>::SomethingEqual : input DataArray<T> instance is NULL !");
2535     const char *msg="Nb of tuples mismatch for DataArrayDouble::multiplyEqual !";
2536     this->checkAllocated();
2537     other->checkAllocated();
2538     int nbOfTuple(this->getNumberOfTuples()),nbOfTuple2(other->getNumberOfTuples());
2539     int nbOfComp(this->getNumberOfComponents()),nbOfComp2(other->getNumberOfComponents());
2540     if(nbOfTuple==nbOfTuple2)
2541       {
2542         if(nbOfComp==nbOfComp2)
2543           {
2544             std::transform(this->begin(),this->end(),other->begin(),this->getPointer(),FCT());
2545           }
2546         else if(nbOfComp2==1)
2547           {
2548             T *ptr(this->getPointer());
2549             const T *ptrc(other->begin());
2550             for(int i=0;i<nbOfTuple;i++)
2551               std::transform(ptr+i*nbOfComp,ptr+(i+1)*nbOfComp,ptr+i*nbOfComp,std::bind2nd(FCT(),*ptrc++));
2552           }
2553         else
2554           throw INTERP_KERNEL::Exception(msg);
2555       }
2556     else if(nbOfTuple2==1)
2557       {
2558         if(nbOfComp2==nbOfComp)
2559           {
2560             T *ptr(this->getPointer());
2561             const T *ptrc(other->begin());
2562             for(int i=0;i<nbOfTuple;i++)
2563               std::transform(ptr+i*nbOfComp,ptr+(i+1)*nbOfComp,ptrc,ptr+i*nbOfComp,FCT());
2564           }
2565         else
2566           throw INTERP_KERNEL::Exception(msg);
2567       }
2568     else
2569       throw INTERP_KERNEL::Exception(msg);
2570     this->declareAsNew();
2571   }
2572   
2573   /*!
2574    * Adds values of another DataArrayDouble to values of \a this one. There are 3
2575    * valid cases.
2576    * 1.  The arrays have same number of tuples and components. Then each value of
2577    *   \a other array is added to the corresponding value of \a this array, i.e.:
2578    *   _a_ [ i, j ] += _other_ [ i, j ].
2579    * 2.  The arrays have same number of tuples and \a other array has one component. Then
2580    *   _a_ [ i, j ] += _other_ [ i, 0 ].
2581    * 3.  The arrays have same number of components and \a other array has one tuple. Then
2582    *   _a_ [ i, j ] += _a2_ [ 0, j ].
2583    *
2584    *  \param [in] other - an array to add to \a this one.
2585    *  \throw If \a other is NULL.
2586    *  \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples() and
2587    *         \a this->getNumberOfComponents() != \a other->getNumberOfComponents() and
2588    *         \a other has number of both tuples and components not equal to 1.
2589    */
2590   template<class T>
2591   void DataArrayTemplateClassic<T>::addEqual(const typename Traits<T>::ArrayType *other)
2592   {
2593     this->somethingEqual< std::plus<T> >(other);
2594   }
2595
2596   /*!
2597    * Subtract values of another DataArrayDouble from values of \a this one. There are 3
2598    * valid cases.
2599    * 1.  The arrays have same number of tuples and components. Then each value of
2600    *   \a other array is subtracted from the corresponding value of \a this array, i.e.:
2601    *   _a_ [ i, j ] -= _other_ [ i, j ].
2602    * 2.  The arrays have same number of tuples and \a other array has one component. Then
2603    *   _a_ [ i, j ] -= _other_ [ i, 0 ].
2604    * 3.  The arrays have same number of components and \a other array has one tuple. Then
2605    *   _a_ [ i, j ] -= _a2_ [ 0, j ].
2606    *
2607    *  \param [in] other - an array to subtract from \a this one.
2608    *  \throw If \a other is NULL.
2609    *  \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples() and
2610    *         \a this->getNumberOfComponents() != \a other->getNumberOfComponents() and
2611    *         \a other has number of both tuples and components not equal to 1.
2612    */
2613   template<class T>
2614   void DataArrayTemplateClassic<T>::substractEqual(const typename Traits<T>::ArrayType *other)
2615   {
2616     this->somethingEqual< std::minus<T> >(other);
2617   }
2618   
2619   /*!
2620    * Multiply values of another DataArrayDouble to values of \a this one. There are 3
2621    * valid cases.
2622    * 1.  The arrays have same number of tuples and components. Then each value of
2623    *   \a other array is multiplied to the corresponding value of \a this array, i.e.
2624    *   _this_ [ i, j ] *= _other_ [ i, j ].
2625    * 2.  The arrays have same number of tuples and \a other array has one component. Then
2626    *   _this_ [ i, j ] *= _other_ [ i, 0 ].
2627    * 3.  The arrays have same number of components and \a other array has one tuple. Then
2628    *   _this_ [ i, j ] *= _a2_ [ 0, j ].
2629    *
2630    *  \param [in] other - an array to multiply to \a this one.
2631    *  \throw If \a other is NULL.
2632    *  \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples() and
2633    *         \a this->getNumberOfComponents() != \a other->getNumberOfComponents() and
2634    *         \a other has number of both tuples and components not equal to 1.
2635    */
2636   template<class T>
2637   void DataArrayTemplateClassic<T>::multiplyEqual(const typename Traits<T>::ArrayType *other)
2638   {
2639     this->somethingEqual< std::multiplies<T> >(other);
2640   }
2641
2642   /*!
2643    * Divide values of \a this array by values of another DataArrayDouble. There are 3
2644    * valid cases.
2645    * 1.  The arrays have same number of tuples and components. Then each value of
2646    *    \a this array is divided by the corresponding value of \a other one, i.e.:
2647    *   _a_ [ i, j ] /= _other_ [ i, j ].
2648    * 2.  The arrays have same number of tuples and \a other array has one component. Then
2649    *   _a_ [ i, j ] /= _other_ [ i, 0 ].
2650    * 3.  The arrays have same number of components and \a other array has one tuple. Then
2651    *   _a_ [ i, j ] /= _a2_ [ 0, j ].
2652    *
2653    *  \warning No check of division by zero is performed!
2654    *  \param [in] other - an array to divide \a this one by.
2655    *  \throw If \a other is NULL.
2656    *  \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples() and
2657    *         \a this->getNumberOfComponents() != \a other->getNumberOfComponents() and
2658    *         \a other has number of both tuples and components not equal to 1.
2659    */
2660   template<class T>
2661   void DataArrayTemplateClassic<T>::divideEqual(const typename Traits<T>::ArrayType *other)
2662   {
2663     this->somethingEqual< std::divides<T> >(other);
2664   }
2665   
2666   template<class T, class FCT>
2667   typename Traits<T>::ArrayType *DivSub(const typename Traits<T>::ArrayType *a1, const typename Traits<T>::ArrayType *a2)
2668   {
2669     if(!a1 || !a2)
2670       throw INTERP_KERNEL::Exception("DivSub : input DataArrayDouble instance is NULL !");
2671     int nbOfTuple1(a1->getNumberOfTuples()),nbOfTuple2(a2->getNumberOfTuples());
2672     int nbOfComp1(a1->getNumberOfComponents()),nbOfComp2(a2->getNumberOfComponents());
2673     if(nbOfTuple2==nbOfTuple1)
2674       {
2675         if(nbOfComp1==nbOfComp2)
2676           {
2677             MCAuto<typename Traits<T>::ArrayType> ret(Traits<T>::ArrayType::New());
2678             ret->alloc(nbOfTuple2,nbOfComp1);
2679             std::transform(a1->begin(),a1->end(),a2->begin(),ret->getPointer(),FCT());
2680             ret->copyStringInfoFrom(*a1);
2681             return ret.retn();
2682           }
2683         else if(nbOfComp2==1)
2684           {
2685             MCAuto<typename Traits<T>::ArrayType> ret(Traits<T>::ArrayType::New());
2686             ret->alloc(nbOfTuple1,nbOfComp1);
2687             const T *a2Ptr(a2->begin()),*a1Ptr(a1->begin());
2688             T *res(ret->getPointer());
2689             for(int i=0;i<nbOfTuple1;i++)
2690               res=std::transform(a1Ptr+i*nbOfComp1,a1Ptr+(i+1)*nbOfComp1,res,std::bind2nd(FCT(),a2Ptr[i]));
2691             ret->copyStringInfoFrom(*a1);
2692             return ret.retn();
2693           }
2694         else
2695           {
2696             a1->checkNbOfComps(nbOfComp2,"Nb of components mismatch for array Divide !");
2697             return 0;
2698           }
2699       }
2700     else if(nbOfTuple2==1)
2701       {
2702         a1->checkNbOfComps(nbOfComp2,"Nb of components mismatch for array Divide !");
2703         MCAuto<typename Traits<T>::ArrayType> ret(Traits<T>::ArrayType::New());
2704         ret->alloc(nbOfTuple1,nbOfComp1);
2705         const T *a1ptr=a1->begin(),*a2ptr(a2->begin());
2706         T *pt(ret->getPointer());
2707         for(int i=0;i<nbOfTuple1;i++)
2708           pt=std::transform(a1ptr+i*nbOfComp1,a1ptr+(i+1)*nbOfComp1,a2ptr,pt,FCT());
2709         ret->copyStringInfoFrom(*a1);
2710         return ret.retn();
2711       }
2712     else
2713       {
2714         a1->checkNbOfTuples(nbOfTuple2,"Nb of tuples mismatch for array Divide !");//will always throw an exception
2715         return 0;
2716       }
2717   }
2718   
2719   /*!
2720    * Returns a new DataArrayDouble that is a subtraction of two given arrays. There are 3
2721    * valid cases.
2722    * 1.  The arrays have same number of tuples and components. Then each value of
2723    *   the result array (_a_) is a subtraction of the corresponding values of \a a1 and
2724    *   \a a2, i.e.: _a_ [ i, j ] = _a1_ [ i, j ] - _a2_ [ i, j ].
2725    * 2.  The arrays have same number of tuples and one array, say _a2_, has one
2726    *   component. Then
2727    *   _a_ [ i, j ] = _a1_ [ i, j ] - _a2_ [ i, 0 ].
2728    * 3.  The arrays have same number of components and one array, say _a2_, has one
2729    *   tuple. Then
2730    *   _a_ [ i, j ] = _a1_ [ i, j ] - _a2_ [ 0, j ].
2731    *
2732    * Info on components is copied either from the first array (in the first case) or from
2733    * the array with maximal number of elements (getNbOfElems()).
2734    *  \param [in] a1 - an array to subtract from.
2735    *  \param [in] a2 - an array to subtract.
2736    *  \return DataArrayDouble * - the new instance of DataArrayDouble.
2737    *          The caller is to delete this result array using decrRef() as it is no more
2738    *          needed.
2739    *  \throw If either \a a1 or \a a2 is NULL.
2740    *  \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples() and
2741    *         \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents() and
2742    *         none of them has number of tuples or components equal to 1.
2743    */
2744   template<class T>
2745   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::Substract(const typename Traits<T>::ArrayType *a1, const typename Traits<T>::ArrayType *a2)
2746   {
2747     return DivSub< T,std::minus<T> >(a1,a2);
2748   }
2749   
2750   /*!
2751    * Returns a new DataArrayDouble that is a division of two given arrays. There are 3
2752    * valid cases.
2753    * 1.  The arrays have same number of tuples and components. Then each value of
2754    *   the result array (_a_) is a division of the corresponding values of \a a1 and
2755    *   \a a2, i.e.: _a_ [ i, j ] = _a1_ [ i, j ] / _a2_ [ i, j ].
2756    * 2.  The arrays have same number of tuples and one array, say _a2_, has one
2757    *   component. Then
2758    *   _a_ [ i, j ] = _a1_ [ i, j ] / _a2_ [ i, 0 ].
2759    * 3.  The arrays have same number of components and one array, say _a2_, has one
2760    *   tuple. Then
2761    *   _a_ [ i, j ] = _a1_ [ i, j ] / _a2_ [ 0, j ].
2762    *
2763    * Info on components is copied either from the first array (in the first case) or from
2764    * the array with maximal number of elements (getNbOfElems()).
2765    *  \warning No check of division by zero is performed!
2766    *  \param [in] a1 - a numerator array.
2767    *  \param [in] a2 - a denominator array.
2768    *  \return DataArrayDouble * - the new instance of DataArrayDouble.
2769    *          The caller is to delete this result array using decrRef() as it is no more
2770    *          needed.
2771    *  \throw If either \a a1 or \a a2 is NULL.
2772    *  \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples() and
2773    *         \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents() and
2774    *         none of them has number of tuples or components equal to 1.
2775    */
2776   template<class T>
2777   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::Divide(const typename Traits<T>::ArrayType *a1, const typename Traits<T>::ArrayType *a2)
2778   {
2779     return DivSub< T,std::divides<T> >(a1,a2);
2780   }
2781
2782   template<class T, class FCT>
2783   typename Traits<T>::ArrayType *MulAdd(const typename Traits<T>::ArrayType *a1, const typename Traits<T>::ArrayType *a2)
2784   {
2785     if(!a1 || !a2)
2786       throw INTERP_KERNEL::Exception("DataArrayDouble::MulAdd : input DataArrayDouble instance is NULL !");
2787     int nbOfTuple(a1->getNumberOfTuples()),nbOfTuple2(a2->getNumberOfTuples());
2788     int nbOfComp(a1->getNumberOfComponents()),nbOfComp2(a2->getNumberOfComponents());
2789     MCAuto<typename Traits<T>::ArrayType> ret=0;
2790     if(nbOfTuple==nbOfTuple2)
2791       {
2792         if(nbOfComp==nbOfComp2)
2793           {
2794             ret=Traits<T>::ArrayType::New();
2795             ret->alloc(nbOfTuple,nbOfComp);
2796             std::transform(a1->begin(),a1->end(),a2->begin(),ret->getPointer(),FCT());
2797             ret->copyStringInfoFrom(*a1);
2798           }
2799         else
2800           {
2801             int nbOfCompMin,nbOfCompMax;
2802             const typename Traits<T>::ArrayType *aMin, *aMax;
2803             if(nbOfComp>nbOfComp2)
2804               {
2805                 nbOfCompMin=nbOfComp2; nbOfCompMax=nbOfComp;
2806                 aMin=a2; aMax=a1;
2807               }
2808             else
2809               {
2810                 nbOfCompMin=nbOfComp; nbOfCompMax=nbOfComp2;
2811                 aMin=a1; aMax=a2;
2812               }
2813             if(nbOfCompMin==1)
2814               {
2815                 ret=Traits<T>::ArrayType::New();
2816                 ret->alloc(nbOfTuple,nbOfCompMax);
2817                 const T *aMinPtr(aMin->begin());
2818                 const T *aMaxPtr(aMax->begin());
2819                 T *res=ret->getPointer();
2820                 for(int i=0;i<nbOfTuple;i++)
2821                   res=std::transform(aMaxPtr+i*nbOfCompMax,aMaxPtr+(i+1)*nbOfCompMax,res,std::bind2nd(FCT(),aMinPtr[i]));
2822                 ret->copyStringInfoFrom(*aMax);
2823               }
2824             else
2825               throw INTERP_KERNEL::Exception("Nb of components mismatch for array MulAdd !");
2826           }
2827       }
2828     else if((nbOfTuple==1 && nbOfTuple2>1) || (nbOfTuple>1 && nbOfTuple2==1))
2829       {
2830         if(nbOfComp==nbOfComp2)
2831           {
2832             int nbOfTupleMax=std::max(nbOfTuple,nbOfTuple2);
2833             const typename Traits<T>::ArrayType *aMin(nbOfTuple>nbOfTuple2?a2:a1);
2834             const typename Traits<T>::ArrayType *aMax(nbOfTuple>nbOfTuple2?a1:a2);
2835             const T *aMinPtr(aMin->begin()),*aMaxPtr(aMax->begin());
2836             ret=Traits<T>::ArrayType::New();
2837             ret->alloc(nbOfTupleMax,nbOfComp);
2838             T *res(ret->getPointer());
2839             for(int i=0;i<nbOfTupleMax;i++)
2840               res=std::transform(aMaxPtr+i*nbOfComp,aMaxPtr+(i+1)*nbOfComp,aMinPtr,res,FCT());
2841             ret->copyStringInfoFrom(*aMax);
2842           }
2843         else
2844           throw INTERP_KERNEL::Exception("Nb of components mismatch for array MulAdd !");
2845       }
2846     else
2847       throw INTERP_KERNEL::Exception("Nb of tuples mismatch for array MulAdd !");
2848     return ret.retn();
2849   }
2850   
2851   /*!
2852    * Returns a new DataArrayDouble that is a product of two given arrays. There are 3
2853    * valid cases.
2854    * 1.  The arrays have same number of tuples and components. Then each value of
2855    *   the result array (_a_) is a product of the corresponding values of \a a1 and
2856    *   \a a2, i.e. _a_ [ i, j ] = _a1_ [ i, j ] * _a2_ [ i, j ].
2857    * 2.  The arrays have same number of tuples and one array, say _a2_, has one
2858    *   component. Then
2859    *   _a_ [ i, j ] = _a1_ [ i, j ] * _a2_ [ i, 0 ].
2860    * 3.  The arrays have same number of components and one array, say _a2_, has one
2861    *   tuple. Then
2862    *   _a_ [ i, j ] = _a1_ [ i, j ] * _a2_ [ 0, j ].
2863    *
2864    * Info on components is copied either from the first array (in the first case) or from
2865    * the array with maximal number of elements (getNbOfElems()).
2866    *  \param [in] a1 - a factor array.
2867    *  \param [in] a2 - another factor array.
2868    *  \return DataArrayDouble * - the new instance of DataArrayDouble.
2869    *          The caller is to delete this result array using decrRef() as it is no more
2870    *          needed.
2871    *  \throw If either \a a1 or \a a2 is NULL.
2872    *  \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples() and
2873    *         \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents() and
2874    *         none of them has number of tuples or components equal to 1.
2875    */
2876   template<class T>
2877   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::Multiply(const typename Traits<T>::ArrayType *a1, const typename Traits<T>::ArrayType *a2)
2878   {
2879     return MulAdd< T , std::multiplies<T> >(a1,a2);
2880   }
2881   
2882   /*!
2883    * Returns a new DataArrayDouble that is a sum of two given arrays. There are 3
2884    * valid cases.
2885    * 1.  The arrays have same number of tuples and components. Then each value of
2886    *   the result array (_a_) is a sum of the corresponding values of \a a1 and \a a2,
2887    *   i.e.: _a_ [ i, j ] = _a1_ [ i, j ] + _a2_ [ i, j ].
2888    * 2.  The arrays have same number of tuples and one array, say _a2_, has one
2889    *   component. Then
2890    *   _a_ [ i, j ] = _a1_ [ i, j ] + _a2_ [ i, 0 ].
2891    * 3.  The arrays have same number of components and one array, say _a2_, has one
2892    *   tuple. Then
2893    *   _a_ [ i, j ] = _a1_ [ i, j ] + _a2_ [ 0, j ].
2894    *
2895    * Info on components is copied either from the first array (in the first case) or from
2896    * the array with maximal number of elements (getNbOfElems()).
2897    *  \param [in] a1 - an array to sum up.
2898    *  \param [in] a2 - another array to sum up.
2899    *  \return DataArrayDouble * - the new instance of DataArrayDouble.
2900    *          The caller is to delete this result array using decrRef() as it is no more
2901    *          needed.
2902    *  \throw If either \a a1 or \a a2 is NULL.
2903    *  \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples() and
2904    *         \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents() and
2905    *         none of them has number of tuples or components equal to 1.
2906    */
2907   template<class T>
2908   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::Add(const typename Traits<T>::ArrayType *a1, const typename Traits<T>::ArrayType *a2)
2909   {
2910     return MulAdd< T , std::plus<T> >(a1,a2);
2911   }
2912   
2913   /*!
2914    * Returns either a \a deep or \a shallow copy of this array. For more info see
2915    * \ref MEDCouplingArrayBasicsCopyDeep and \ref MEDCouplingArrayBasicsCopyShallow.
2916    *  \param [in] dCpy - if \a true, a deep copy is returned, else, a shallow one.
2917    *  \return DataArrayDouble * - either a new instance of DataArrayDouble (if \a dCpy
2918    *          == \a true) or \a this instance (if \a dCpy == \a false).
2919    */
2920   template<class T>
2921   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::PerformCopyOrIncrRef(bool dCpy, const typename Traits<T>::ArrayType& self)
2922   {
2923     if(dCpy)
2924       return self.deepCopy();
2925     else
2926       {
2927         self.incrRef();
2928         return const_cast<typename Traits<T>::ArrayType *>(&self);
2929       }
2930   }
2931
2932   template<class T>
2933   struct GreatEqual
2934   {
2935     GreatEqual(T v):_v(v) { }
2936     bool operator()(T v) const { return v>=_v; }
2937     T _v;
2938   };
2939   
2940   template<class T>
2941   struct GreaterThan
2942   {
2943     GreaterThan(T v):_v(v) { }
2944     bool operator()(T v) const { return v>_v; }
2945     T _v;
2946   };
2947   
2948   template<class T>
2949   struct LowerEqual
2950   {
2951     LowerEqual(T v):_v(v) { }
2952     bool operator()(T v) const { return v<=_v; }
2953     T _v;
2954   };
2955   
2956   template<class T>
2957   struct LowerThan
2958   {
2959     LowerThan(T v):_v(v) { }
2960     bool operator()(T v) const { return v<_v; }
2961     T _v;
2962   };
2963   
2964   template<class T>
2965   struct InRange
2966   {
2967     InRange(T a, T b):_a(a),_b(b) { }
2968     bool operator()(T v) const { return v>=_a && v<_b; }
2969     T _a,_b;
2970   };
2971
2972 template<class T>
2973 struct NotInRange
2974 {
2975   NotInRange(T a, T b):_a(a),_b(b) { }
2976   bool operator()(T v) const { return v<_a || v>=_b; }
2977   T _a,_b;
2978 };
2979
2980   /*!
2981    * 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.
2982    *
2983    * \return a newly allocated data array that the caller should deal with.
2984    * \sa DataArrayInt::findIdsInRange
2985    */
2986   template<class T>
2987   DataArrayInt *DataArrayTemplateClassic<T>::findIdsStrictlyNegative() const
2988   {
2989     LowerThan<T> lt((T)0);
2990     MCAuto<DataArrayInt> ret(findIdsAdv(lt));
2991     return ret.retn();
2992   }
2993   
2994   template<class T>
2995   MCAuto<DataArrayInt> DataArrayTemplateClassic<T>::findIdsGreaterOrEqualTo(T val) const
2996   {
2997     GreatEqual<T> ge(val);
2998     return findIdsAdv(ge);
2999   }
3000   
3001   template<class T>
3002   MCAuto<DataArrayInt> DataArrayTemplateClassic<T>::findIdsGreaterThan(T val) const
3003   {
3004     GreaterThan<T> gt(val);
3005     return findIdsAdv(gt);
3006   }
3007   
3008   template<class T>
3009   MCAuto<DataArrayInt> DataArrayTemplateClassic<T>::findIdsLowerOrEqualTo(T val) const
3010   {
3011     LowerEqual<T> le(val);
3012     return findIdsAdv(le);
3013   }
3014   
3015   template<class T>
3016   MCAuto<DataArrayInt> DataArrayTemplateClassic<T>::findIdsLowerThan(T val) const
3017   {
3018     LowerThan<T> lt(val);
3019     return findIdsAdv(lt);
3020   }
3021
3022   /*!
3023    * Returns a new DataArrayDouble by aggregating two given arrays, so that (1) the number
3024    * of components in the result array is a sum of the number of components of given arrays
3025    * and (2) the number of tuples in the result array is same as that of each of given
3026    * arrays. In other words the i-th tuple of result array includes all components of
3027    * i-th tuples of all given arrays.
3028    * Number of tuples in the given arrays must be  the same.
3029    *  \param [in] a1 - an array to include in the result array.
3030    *  \param [in] a2 - another array to include in the result array.
3031    *  \return DataArrayDouble * - the new instance of DataArrayDouble.
3032    *          The caller is to delete this result array using decrRef() as it is no more
3033    *          needed.
3034    *  \throw If both \a a1 and \a a2 are NULL.
3035    *  \throw If any given array is not allocated.
3036    *  \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples()
3037    */
3038   template<class T>
3039   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::Meld(const typename Traits<T>::ArrayType *a1, const typename Traits<T>::ArrayType *a2)
3040   {
3041     std::vector<const typename Traits<T>::ArrayType *> arr(2);
3042     arr[0]=a1; arr[1]=a2;
3043     return Meld(arr);
3044   }
3045
3046   /*!
3047    * Returns a new DataArrayDouble by aggregating all given arrays, so that (1) the number
3048    * of components in the result array is a sum of the number of components of given arrays
3049    * and (2) the number of tuples in the result array is same as that of each of given
3050    * arrays. In other words the i-th tuple of result array includes all components of
3051    * i-th tuples of all given arrays.
3052    * Number of tuples in the given arrays must be  the same.
3053    *  \param [in] arr - a sequence of arrays to include in the result array.
3054    *  \return DataArrayDouble * - the new instance of DataArrayDouble.
3055    *          The caller is to delete this result array using decrRef() as it is no more
3056    *          needed.
3057    *  \throw If all arrays within \a arr are NULL.
3058    *  \throw If any given array is not allocated.
3059    *  \throw If getNumberOfTuples() of arrays within \a arr is different.
3060    */
3061   template<class T>
3062   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::Meld(const std::vector<const typename Traits<T>::ArrayType *>& arr)
3063   {
3064     std::vector<const typename Traits<T>::ArrayType *> a;
3065     for(typename std::vector<const typename Traits<T>::ArrayType *>::const_iterator it4=arr.begin();it4!=arr.end();it4++)
3066       if(*it4)
3067         a.push_back(*it4);
3068     if(a.empty())
3069       throw INTERP_KERNEL::Exception("DataArrayDouble::Meld : input list must contain at least one NON EMPTY DataArrayDouble !");
3070     typename std::vector<const typename Traits<T>::ArrayType *>::const_iterator it;
3071     for(it=a.begin();it!=a.end();it++)
3072       (*it)->checkAllocated();
3073     it=a.begin();
3074     std::size_t nbOfTuples((*it)->getNumberOfTuples());
3075     std::vector<int> nbc(a.size());
3076     std::vector<const T *> pts(a.size());
3077     nbc[0]=(*it)->getNumberOfComponents();
3078     pts[0]=(*it++)->getConstPointer();
3079     for(int i=1;it!=a.end();it++,i++)
3080       {
3081         if(nbOfTuples!=(*it)->getNumberOfTuples())
3082           throw INTERP_KERNEL::Exception("DataArrayDouble::Meld : mismatch of number of tuples !");
3083         nbc[i]=(*it)->getNumberOfComponents();
3084         pts[i]=(*it)->getConstPointer();
3085       }
3086     int totalNbOfComp=std::accumulate(nbc.begin(),nbc.end(),0);
3087     typename Traits<T>::ArrayType *ret(Traits<T>::ArrayType::New());
3088     ret->alloc(nbOfTuples,totalNbOfComp);
3089     T *retPtr(ret->getPointer());
3090     for(std::size_t i=0;i<nbOfTuples;i++)
3091       for(std::size_t j=0;j<a.size();j++)
3092         {
3093           retPtr=std::copy(pts[j],pts[j]+nbc[j],retPtr);
3094           pts[j]+=nbc[j];
3095         }
3096     int k=0;
3097     for(int i=0;i<(int)a.size();i++)
3098       for(int j=0;j<nbc[i];j++,k++)
3099         ret->setInfoOnComponent(k,a[i]->getInfoOnComponent(j));
3100     return ret;
3101   }
3102
3103   /*!
3104    * Returns a new DataArrayDouble holding the same values as \a this array but differently
3105    * arranged in memory. If \a this array holds 2 components of 3 values:
3106    * \f$ x_0,x_1,x_2,y_0,y_1,y_2 \f$, then the result array holds these values arranged
3107    * as follows: \f$ x_0,y_0,x_1,y_1,x_2,y_2 \f$.
3108    *  \warning Do not confuse this method with transpose()!
3109    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
3110    *          is to delete using decrRef() as it is no more needed.
3111    *  \throw If \a this is not allocated.
3112    */
3113   template<class T>
3114   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::fromNoInterlace() const
3115   {
3116     if(this->_mem.isNull())
3117       throw INTERP_KERNEL::Exception("DataArrayDouble::fromNoInterlace : Not defined array !");
3118     T *tab(this->_mem.fromNoInterlace(this->getNumberOfComponents()));
3119     MCAuto<typename Traits<T>::ArrayType> ret(Traits<T>::ArrayType::New());
3120     ret->useArray(tab,true,DeallocType::C_DEALLOC,this->getNumberOfTuples(),this->getNumberOfComponents());
3121     return ret.retn();
3122   }
3123
3124   /*!
3125    * Returns a new DataArrayDouble holding the same values as \a this array but differently
3126    * arranged in memory. If \a this array holds 2 components of 3 values:
3127    * \f$ x_0,y_0,x_1,y_1,x_2,y_2 \f$, then the result array holds these values arranged
3128    * as follows: \f$ x_0,x_1,x_2,y_0,y_1,y_2 \f$.
3129    *  \warning Do not confuse this method with transpose()!
3130    *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
3131    *          is to delete using decrRef() as it is no more needed.
3132    *  \throw If \a this is not allocated.
3133    */
3134   template<class T>
3135   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::toNoInterlace() const
3136   {
3137     if(this->_mem.isNull())
3138       throw INTERP_KERNEL::Exception("DataArrayDouble::toNoInterlace : Not defined array !");
3139     T *tab(this->_mem.toNoInterlace(this->getNumberOfComponents()));
3140     MCAuto<typename Traits<T>::ArrayType> ret(Traits<T>::ArrayType::New());
3141     ret->useArray(tab,true,DeallocType::C_DEALLOC,this->getNumberOfTuples(),this->getNumberOfComponents());
3142     return ret.retn();
3143   }
3144   
3145   /*!
3146    * Appends components of another array to components of \a this one, tuple by tuple.
3147    * So that the number of tuples of \a this array remains the same and the number of 
3148    * components increases.
3149    *  \param [in] other - the DataArrayDouble to append to \a this one.
3150    *  \throw If \a this is not allocated.
3151    *  \throw If \a this and \a other arrays have different number of tuples.
3152    *
3153    *  \if ENABLE_EXAMPLES
3154    *  \ref cpp_mcdataarraydouble_meldwith "Here is a C++ example".
3155    *
3156    *  \ref py_mcdataarraydouble_meldwith "Here is a Python example".
3157    *  \endif
3158    */
3159   template<class T>
3160   void DataArrayTemplateClassic<T>::meldWith(const typename Traits<T>::ArrayType *other)
3161   {
3162     this->checkAllocated();
3163     other->checkAllocated();
3164     std::size_t nbOfTuples(this->getNumberOfTuples());
3165     if(nbOfTuples!=other->getNumberOfTuples())
3166       throw INTERP_KERNEL::Exception("DataArrayDouble::meldWith : mismatch of number of tuples !");
3167     int nbOfComp1(this->getNumberOfComponents()),nbOfComp2(other->getNumberOfComponents());
3168     T *newArr=(T *)malloc((nbOfTuples*(nbOfComp1+nbOfComp2))*sizeof(T));
3169     T *w=newArr;
3170     const T *inp1(this->begin()),*inp2(other->begin());
3171     for(std::size_t i=0;i<nbOfTuples;i++,inp1+=nbOfComp1,inp2+=nbOfComp2)
3172       {
3173         w=std::copy(inp1,inp1+nbOfComp1,w);
3174         w=std::copy(inp2,inp2+nbOfComp2,w);
3175       }
3176     this->useArray(newArr,true,DeallocType::C_DEALLOC,nbOfTuples,nbOfComp1+nbOfComp2);
3177     std::vector<int> compIds(nbOfComp2);
3178     for(int i=0;i<nbOfComp2;i++)
3179       compIds[i]=nbOfComp1+i;
3180     this->copyPartOfStringInfoFrom2(compIds,*other);
3181   }
3182
3183   /*!
3184    * 
3185    * \param [in] nbTimes specifies the nb of times each tuples in \a this will be duplicated contiguouly in returned DataArrayDouble instance.
3186    *             \a nbTimes  should be at least equal to 1.
3187    * \return a newly allocated DataArrayDouble having one component and number of tuples equal to \a nbTimes * \c this->getNumberOfTuples.
3188    * \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.
3189    */
3190   template<class T>
3191   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::duplicateEachTupleNTimes(int nbTimes) const
3192   {
3193     this->checkAllocated();
3194     if(this->getNumberOfComponents()!=1)
3195       throw INTERP_KERNEL::Exception("DataArrayDouble::duplicateEachTupleNTimes : this should have only one component !");
3196     if(nbTimes<1)
3197       throw INTERP_KERNEL::Exception("DataArrayDouble::duplicateEachTupleNTimes : nb times should be >= 1 !");
3198     int nbTuples(this->getNumberOfTuples());
3199     const T *inPtr(this->begin());
3200     MCAuto<typename Traits<T>::ArrayType> ret(Traits<T>::ArrayType::New()); ret->alloc(nbTimes*nbTuples,1);
3201     T *retPtr(ret->getPointer());
3202     for(int i=0;i<nbTuples;i++,inPtr++)
3203       {
3204         T val(*inPtr);
3205         for(int j=0;j<nbTimes;j++,retPtr++)
3206           *retPtr=val;
3207       }
3208     ret->copyStringInfoFrom(*this);
3209     return ret.retn();
3210   }
3211   
3212   template<class T>
3213   void DataArrayTemplateClassic<T>::aggregate(const typename Traits<T>::ArrayType *other)
3214   {
3215     if(!other)
3216       throw INTERP_KERNEL::Exception("DataArrayDouble::aggregate : null pointer !");
3217     if(this->getNumberOfComponents()!=other->getNumberOfComponents())
3218       throw INTERP_KERNEL::Exception("DataArrayDouble::aggregate : mismatch number of components !");
3219     this->_mem.insertAtTheEnd(other->begin(),other->end());
3220   }
3221
3222   /*!
3223    * Converts every value of \a this array to its absolute value.
3224    * \b WARNING this method is non const. If a new DataArrayDouble instance should be built containing the result of abs DataArrayDouble::computeAbs
3225    * should be called instead.
3226    *
3227    * \throw If \a this is not allocated.
3228    * \sa DataArrayDouble::computeAbs
3229    */
3230   template<class T>
3231   void DataArrayTemplateClassic<T>::abs()
3232   {
3233     this->checkAllocated();
3234     T *ptr(this->getPointer());
3235     std::size_t nbOfElems(this->getNbOfElems());
3236     std::transform(ptr,ptr+nbOfElems,ptr,std::ptr_fun<T,T>(std::abs));
3237     this->declareAsNew();
3238   }
3239
3240   /*!
3241    * This method builds a new instance of \a this object containing the result of std::abs applied of all elements in \a this.
3242    * This method is a const method (that do not change any values in \a this) contrary to  DataArrayDouble::abs method.
3243    *
3244    * \return DataArrayDouble * - the new instance of DataArrayDouble containing the
3245    *         same number of tuples and component as \a this array.
3246    *         The caller is to delete this result array using decrRef() as it is no more
3247    *         needed.
3248    * \throw If \a this is not allocated.
3249    * \sa DataArrayDouble::abs
3250    */
3251   template<class T>
3252   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::computeAbs() const
3253   {
3254     this->checkAllocated();
3255     MCAuto<typename Traits<T>::ArrayType> newArr(Traits<T>::ArrayType::New());
3256     int nbOfTuples(this->getNumberOfTuples());
3257     int nbOfComp(this->getNumberOfComponents());
3258     newArr->alloc(nbOfTuples,nbOfComp);
3259     std::transform(this->begin(),this->end(),newArr->getPointer(),std::ptr_fun<T,T>(std::abs));
3260     newArr->copyStringInfoFrom(*this);
3261     return newArr.retn();
3262   }
3263
3264   /*!
3265    * Returns either a \a deep or \a shallow copy of this array. For more info see
3266    * \ref MEDCouplingArrayBasicsCopyDeep and \ref MEDCouplingArrayBasicsCopyShallow.
3267    *  \param [in] dCpy - if \a true, a deep copy is returned, else, a shallow one.
3268    *  \return DataArrayDouble * - either a new instance of DataArrayDouble (if \a dCpy
3269    *          == \a true) or \a this instance (if \a dCpy == \a false).
3270    */
3271   template<class T>
3272   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::performCopyOrIncrRef(bool dCpy) const
3273   {
3274     const typename Traits<T>::ArrayType *thisC(static_cast<const typename Traits<T>::ArrayType *>(this));
3275     return DataArrayTemplateClassic<T>::PerformCopyOrIncrRef(dCpy,*thisC);
3276   }
3277
3278   /*!
3279    * Computes for each tuple the sum of number of components values in the tuple and return it.
3280    * 
3281    * \return DataArrayDouble * - the new instance of DataArrayDouble containing the
3282    *          same number of tuples as \a this array and one component.
3283    *          The caller is to delete this result array using decrRef() as it is no more
3284    *          needed.
3285    *  \throw If \a this is not allocated.
3286    */
3287   template<class T>
3288   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::sumPerTuple() const
3289   {
3290     this->checkAllocated();
3291     std::size_t nbOfComp(this->getNumberOfComponents()),nbOfTuple(this->getNumberOfTuples());
3292     MCAuto<typename Traits<T>::ArrayType> ret(Traits<T>::ArrayType::New());
3293     ret->alloc(nbOfTuple,1);
3294     const T *src(this->begin());
3295     T *dest(ret->getPointer());
3296     for(std::size_t i=0;i<nbOfTuple;i++,dest++,src+=nbOfComp)
3297       *dest=std::accumulate(src,src+nbOfComp,(T)0);
3298     return ret.retn();
3299   }
3300
3301   /*!
3302    * Set all values in \a this array so that the i-th element equals to \a init + i
3303    * (i starts from zero). To know more on filling arrays see \ref MEDCouplingArrayFill.
3304    *  \param [in] init - value to assign to the first element of array.
3305    *  \throw If \a this->getNumberOfComponents() != 1
3306    *  \throw If \a this is not allocated.
3307    */
3308   template<class T>
3309   void DataArrayTemplateClassic<T>::iota(T init)
3310   {
3311     this->checkAllocated();
3312     if(this->getNumberOfComponents()!=1)
3313       throw INTERP_KERNEL::Exception("DataArrayDouble::iota : works only for arrays with only one component, you can call 'rearrange' method before !");
3314     T *ptr(this->getPointer());
3315     std::size_t ntuples(this->getNumberOfTuples());
3316     for(std::size_t i=0;i<ntuples;i++)
3317       ptr[i]=init+(T)i;
3318     this->declareAsNew();
3319   }
3320
3321   template<class T>
3322   struct ImplReprTraits { static void SetPrecision(std::ostream& oss) { } };
3323
3324   template<>
3325   struct ImplReprTraits<double> {  static void SetPrecision(std::ostream& oss) { oss.precision(17); } };
3326   
3327   template<>
3328   struct ImplReprTraits<float> {  static void SetPrecision(std::ostream& oss) { oss.precision(7); } };
3329   
3330   template<class T>
3331   void DataArrayTemplateClassic<T>::reprStream(std::ostream& stream) const
3332   {
3333     stream << "Name of " << Traits<T>::ReprStr << " array : \"" << this->_name << "\"\n";
3334     reprWithoutNameStream(stream);
3335   }
3336
3337   template<class T>
3338   void DataArrayTemplateClassic<T>::reprZipStream(std::ostream& stream) const
3339   {
3340     stream << "Name of " << Traits<T>::ReprStr << " array : \"" << this->_name << "\"\n";
3341     reprZipWithoutNameStream(stream);
3342   }
3343
3344   template<class T>
3345   void DataArrayTemplateClassic<T>::reprNotTooLongStream(std::ostream& stream) const
3346   {
3347     stream << "Name of "<< Traits<T>::ReprStr << " array : \"" << this->_name << "\"\n";
3348     reprNotTooLongWithoutNameStream(stream);
3349   }
3350
3351   template<class T>
3352   void DataArrayTemplateClassic<T>::reprWithoutNameStream(std::ostream& stream) const
3353   {
3354     DataArray::reprWithoutNameStream(stream);
3355     ImplReprTraits<T>::SetPrecision(stream);
3356     this->_mem.repr(this->getNumberOfComponents(),stream);
3357   }
3358
3359   template<class T>
3360   void DataArrayTemplateClassic<T>::reprZipWithoutNameStream(std::ostream& stream) const
3361   {
3362     DataArray::reprWithoutNameStream(stream);
3363     ImplReprTraits<T>::SetPrecision(stream);
3364     this->_mem.reprZip(this->getNumberOfComponents(),stream);
3365   }
3366
3367   template<class T>
3368   void DataArrayTemplateClassic<T>::reprNotTooLongWithoutNameStream(std::ostream& stream) const
3369   {
3370     DataArray::reprWithoutNameStream(stream);
3371     ImplReprTraits<T>::SetPrecision(stream);
3372     this->_mem.reprNotTooLong(this->getNumberOfComponents(),stream);
3373   }
3374
3375   /*!
3376    * This method is close to repr method except that when \a this has more than 1000 tuples, all tuples are not
3377    * printed out to avoid to consume too much space in interpretor.
3378    * \sa repr
3379    */
3380   template<class T>
3381   std::string DataArrayTemplateClassic<T>::reprNotTooLong() const
3382   {
3383     std::ostringstream ret;
3384     reprNotTooLongStream(ret);
3385     return ret.str();
3386   }
3387   
3388   /*!
3389    * Returns a textual and human readable representation of \a this instance of
3390    * DataArrayInt. This text is shown when a DataArrayInt is printed in Python.
3391    * \return std::string - text describing \a this DataArrayInt.
3392    *
3393    * \sa reprNotTooLong, reprZip
3394    */
3395   template<class T>
3396   std::string DataArrayTemplateClassic<T>::repr() const
3397   {
3398     std::ostringstream ret;
3399     DataArrayTemplateClassic<T>::reprStream(ret);
3400     return ret.str();
3401   }
3402   
3403   template<class T>
3404   std::string DataArrayTemplateClassic<T>::reprZip() const
3405   {
3406     std::ostringstream ret;
3407     DataArrayTemplateClassic<T>::reprZipStream(ret);
3408     return ret.str();
3409   }
3410   
3411   /////////////////////////////////
3412   
3413   /*!
3414    * Checks if all values in \a this array are equal to \a val at precision \a eps.
3415    *  \param [in] val - value to check equality of array values to.
3416    *  \param [in] eps - precision to check the equality.
3417    *  \return bool - \a true if all values are in range (_val_ - _eps_; _val_ + _eps_),
3418    *                 \a false else.
3419    *  \throw If \a this->getNumberOfComponents() != 1
3420    *  \throw If \a this is not allocated.
3421    */
3422   template<class T>
3423   bool DataArrayTemplateFP<T>::isUniform(T val, T eps) const
3424   {
3425     this->checkAllocated();
3426     if(this->getNumberOfComponents()!=1)
3427       throw INTERP_KERNEL::Exception("DataArrayDouble::isUniform : must be applied on DataArrayDouble with only one component, you can call 'rearrange' method before !");
3428     const T *w(this->begin()),*end2(this->end());
3429     const T vmin(val-eps),vmax(val+eps);
3430     for(;w!=end2;w++)
3431       if(*w<vmin || *w>vmax)
3432         return false;
3433     return true;
3434   }
3435
3436   /*!
3437    * Equivalent to DataArrayInt::isEqual except that if false the reason of
3438    * mismatch is given.
3439    * 
3440    * \param [in] other the instance to be compared with \a this
3441    * \param [out] reason In case of inequality returns the reason.
3442    * \sa DataArrayInt::isEqual
3443    */
3444   template<class T>
3445   bool DataArrayDiscrete<T>::isEqualIfNotWhy(const DataArrayDiscrete<T>& other, std::string& reason) const
3446   {
3447     if(!this->areInfoEqualsIfNotWhy(other,reason))
3448       return false;
3449     return this->_mem.isEqual(other._mem,0,reason);
3450   }
3451
3452   /*!
3453    * Checks if \a this and another DataArrayInt are fully equal. For more info see
3454    * \ref MEDCouplingArrayBasicsCompare.
3455    *  \param [in] other - an instance of DataArrayInt to compare with \a this one.
3456    *  \return bool - \a true if the two arrays are equal, \a false else.
3457    */
3458   template<class T>
3459   bool DataArrayDiscrete<T>::isEqual(const DataArrayDiscrete<T>& other) const
3460   {
3461     std::string tmp;
3462     return isEqualIfNotWhy(other,tmp);
3463   }
3464   
3465   /*!
3466    * Returns a new instance of DataArrayInt. The caller is to delete this array
3467    * using decrRef() as it is no more needed.
3468    */
3469   template<class T>
3470   typename Traits<T>::ArrayType *DataArrayDiscrete<T>::New()
3471   {
3472     return new typename Traits<T>::ArrayType;
3473   }
3474   
3475   /*!
3476    * Checks if values of \a this and another DataArrayInt are equal. For more info see
3477    * \ref MEDCouplingArrayBasicsCompare.
3478    *  \param [in] other - an instance of DataArrayInt to compare with \a this one.
3479    *  \return bool - \a true if the values of two arrays are equal, \a false else.
3480    */
3481   template<class T>
3482   bool DataArrayDiscrete<T>::isEqualWithoutConsideringStr(const DataArrayDiscrete<T>& other) const
3483   {
3484     std::string tmp;
3485     return this->_mem.isEqual(other._mem,0,tmp);
3486   }
3487
3488   /*!
3489    * Checks if values of \a this and another DataArrayInt are equal. Comparison is
3490    * performed on sorted value sequences.
3491    * For more info see\ref MEDCouplingArrayBasicsCompare.
3492    *  \param [in] other - an instance of DataArrayInt to compare with \a this one.
3493    *  \return bool - \a true if the sorted values of two arrays are equal, \a false else.
3494    */
3495   template<class T>
3496   bool DataArrayDiscrete<T>::isEqualWithoutConsideringStrAndOrder(const typename Traits<T>::ArrayType& other) const
3497   {
3498     MCAuto<typename Traits<T>::ArrayType> a((static_cast<const typename Traits<T>::ArrayType *>(this))->deepCopy());
3499     MCAuto<typename Traits<T>::ArrayType> b((static_cast<const typename Traits<T>::ArrayType *>(&other))->deepCopy());
3500     a->sort();
3501     b->sort();
3502     return a->isEqualWithoutConsideringStr(*b);
3503   }
3504   
3505   template<class T>
3506   template<class ALG>
3507   void DataArrayDiscrete<T>::switchOnTupleAlg(T val, std::vector<bool>& vec, ALG algo) const
3508   {
3509     this->checkAllocated();
3510     if(this->getNumberOfComponents()!=1)
3511       throw INTERP_KERNEL::Exception("DataArrayInt::switchOnTupleEqualTo : number of components of this should be equal to one !");
3512     int nbOfTuples(this->getNumberOfTuples());
3513     if(nbOfTuples!=(int)vec.size())
3514       throw INTERP_KERNEL::Exception("DataArrayInt::switchOnTupleEqualTo : number of tuples of this should be equal to size of input vector of bool !");
3515     const T *pt(this->begin());
3516     for(int i=0;i<nbOfTuples;i++)
3517       if(algo(pt[i],val))
3518         vec[i]=true;
3519   }
3520   
3521   /*!
3522    * 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
3523    * put True to the corresponding entry in \a vec.
3524    * \a vec is expected to be with the same size than the number of tuples of \a this.
3525    *
3526    *  \sa DataArrayInt::switchOnTupleNotEqualTo.
3527    */
3528   template<class T>
3529   void DataArrayDiscrete<T>::switchOnTupleEqualTo(T val, std::vector<bool>& vec) const
3530   {
3531     switchOnTupleAlg(val,vec,std::equal_to<T>());
3532   }
3533
3534   /*!
3535    * 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
3536    * put True to the corresponding entry in \a vec.
3537    * \a vec is expected to be with the same size than the number of tuples of \a this.
3538    * 
3539    *  \sa DataArrayInt::switchOnTupleEqualTo.
3540    */
3541   template<class T>
3542   void DataArrayDiscrete<T>::switchOnTupleNotEqualTo(T val, std::vector<bool>& vec) const
3543   {
3544     switchOnTupleAlg(val,vec,std::not_equal_to<T>());
3545   }
3546
3547   /*!
3548    * Creates a new one-dimensional DataArrayInt of the same size as \a this and a given
3549    * one-dimensional arrays that must be of the same length. The result array describes
3550    * correspondence between \a this and \a other arrays, so that 
3551    * <em> other.getIJ(i,0) == this->getIJ(ret->getIJ(i),0)</em>. If such a permutation is
3552    * not possible because some element in \a other is not in \a this, an exception is thrown.
3553    *  \param [in] other - an array to compute permutation to.
3554    *  \return DataArrayInt * - a new instance of DataArrayInt, which is a permutation array
3555    * from \a this to \a other. The caller is to delete this array using decrRef() as it is
3556    * no more needed.
3557    *  \throw If \a this->getNumberOfComponents() != 1.
3558    *  \throw If \a other->getNumberOfComponents() != 1.
3559    *  \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples().
3560    *  \throw If \a other includes a value which is not in \a this array.
3561    * 
3562    *  \if ENABLE_EXAMPLES
3563    *  \ref cpp_mcdataarrayint_buildpermutationarr "Here is a C++ example".
3564    *
3565    *  \ref py_mcdataarrayint_buildpermutationarr "Here is a Python example".
3566    *  \endif
3567    */
3568   template<class T>
3569   DataArrayIdType *DataArrayDiscrete<T>::buildPermutationArr(const DataArrayDiscrete<T>& other) const
3570   {
3571     this->checkAllocated();
3572     if(this->getNumberOfComponents()!=1 || other.getNumberOfComponents()!=1)
3573       throw INTERP_KERNEL::Exception("DataArrayInt::buildPermutationArr : 'this' and 'other' have to have exactly ONE component !");
3574     std::size_t nbTuple(this->getNumberOfTuples());
3575     other.checkAllocated();
3576     if(nbTuple!=other.getNumberOfTuples())
3577       throw INTERP_KERNEL::Exception("DataArrayInt::buildPermutationArr : 'this' and 'other' must have the same number of tuple !");
3578     MCAuto<DataArrayIdType> ret(DataArrayIdType::New());
3579     ret->alloc(nbTuple,1);
3580     ret->fillWithValue(-1);
3581     const T *pt(this->begin());
3582     std::map<int,mcIdType> mm;
3583     for(std::size_t i=0;i<nbTuple;i++)
3584       mm[pt[i]]=(mcIdType)i;
3585     pt=other.begin();
3586     mcIdType *retToFill(ret->getPointer());
3587     for(std::size_t i=0;i<nbTuple;i++)
3588       {
3589         std::map<int,int>::const_iterator it=mm.find(pt[i]);
3590         if(it==mm.end())
3591           {
3592             std::ostringstream oss; oss << "DataArrayInt::buildPermutationArr : Arrays mismatch : element (" << pt[i] << ") in 'other' not findable in 'this' !";
3593             throw INTERP_KERNEL::Exception(oss.str().c_str());
3594           }
3595         retToFill[i]=(*it).second;
3596       }
3597     return ret.retn();
3598   }
3599
3600   /*!
3601    * Elements of \a partOfThis are expected to be included in \a this.
3602    * The returned array \a ret is so that this[ret]==partOfThis
3603    *
3604    * 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]
3605    * the return array will contain [3,2,5,7].
3606    *
3607    * \a this is expected to be a 1 compo allocated array.
3608    * \param [in] partOfThis - A 1 compo allocated array
3609    * \return - A newly allocated array to be dealed by caller having the same number of tuples than \a partOfThis.
3610    * \throw if two same element is present twice in \a this
3611    * \throw if an element in \a partOfThis is \b NOT in \a this.
3612    */
3613   template<class T>
3614   DataArrayIdType *DataArrayDiscrete<T>::indicesOfSubPart(const DataArrayDiscrete<T>& partOfThis) const
3615   {
3616     if(this->getNumberOfComponents()!=1 || partOfThis.getNumberOfComponents()!=1)
3617       throw INTERP_KERNEL::Exception("DataArrayInt::indicesOfSubPart : this and input array must be one component array !");
3618     this->checkAllocated(); partOfThis.checkAllocated();
3619     std::size_t thisNbTuples(this->getNumberOfTuples()),nbTuples(partOfThis.getNumberOfTuples());
3620     const T *thisPt(this->begin()),*pt(partOfThis.begin());
3621     MCAuto<DataArrayIdType> ret(DataArrayIdType::New());
3622     ret->alloc(nbTuples,1);
3623     mcIdType *retPt(ret->getPointer());
3624     std::map<int,mcIdType> m;
3625     for(std::size_t i=0;i<thisNbTuples;i++,thisPt++)
3626       m[*thisPt]=(mcIdType)i;
3627     if(m.size()!=thisNbTuples)
3628       throw INTERP_KERNEL::Exception("DataArrayInt::indicesOfSubPart : some elements appears more than once !");
3629     for(std::size_t i=0;i<nbTuples;i++,retPt++,pt++)
3630       {
3631         std::map<int,mcIdType>::const_iterator it(m.find(*pt));
3632         if(it!=m.end())
3633           *retPt=(*it).second;
3634         else
3635           {
3636             std::ostringstream oss; oss << "DataArrayInt::indicesOfSubPart : At pos #" << i << " of input array value is " << *pt << " not in this !";
3637             throw INTERP_KERNEL::Exception(oss.str());
3638           }
3639       }
3640     return ret.retn();
3641   }
3642
3643   /*!
3644    * Checks that \a this array is consistently **increasing** or **decreasing** in value.
3645    * If not an exception is thrown.
3646    *  \param [in] increasing - if \a true, the array values should be increasing.
3647    *  \throw If sequence of values is not strictly monotonic in agreement with \a
3648    *         increasing arg.
3649    *  \throw If \a this->getNumberOfComponents() != 1.
3650    *  \throw If \a this is not allocated.
3651    */
3652   template<class T>
3653   void DataArrayDiscrete<T>::checkMonotonic(bool increasing) const
3654   {
3655     if(!isMonotonic(increasing))
3656       {
3657         if (increasing)
3658           throw INTERP_KERNEL::Exception("DataArrayInt::checkMonotonic : 'this' is not INCREASING monotonic !");
3659         else
3660           throw INTERP_KERNEL::Exception("DataArrayInt::checkMonotonic : 'this' is not DECREASING monotonic !");
3661       }
3662   }
3663
3664   /*!
3665    * Checks that \a this array is consistently **increasing** or **decreasing** in value.
3666    *  \param [in] increasing - if \a true, array values should be increasing.
3667    *  \return bool - \a true if values change in accordance with \a increasing arg.
3668    *  \throw If \a this->getNumberOfComponents() != 1.
3669    *  \throw If \a this is not allocated.
3670    */
3671   template<class T>
3672   bool DataArrayDiscrete<T>::isMonotonic(bool increasing) const
3673   {
3674     this->checkAllocated();
3675     if(this->getNumberOfComponents()!=1)
3676       throw INTERP_KERNEL::Exception("DataArrayInt::isMonotonic : only supported with 'this' array with ONE component !");
3677     std::size_t nbOfElements(this->getNumberOfTuples());
3678     const T *ptr(this->begin());
3679     if(nbOfElements==0)
3680       return true;
3681     T ref(ptr[0]);
3682     if(increasing)
3683       {
3684         for(std::size_t i=1;i<nbOfElements;i++)
3685           {
3686             if(ptr[i]>=ref)
3687               ref=ptr[i];
3688             else
3689               return false;
3690           }
3691       }
3692     else
3693       {
3694         for(std::size_t i=1;i<nbOfElements;i++)
3695           {
3696             if(ptr[i]<=ref)
3697               ref=ptr[i];
3698             else
3699               return false;
3700           }
3701       }
3702     return true;
3703   }
3704
3705   /*!
3706    * This method check that array consistently INCREASING or DECREASING in value.
3707    */
3708   template<class T>
3709   bool DataArrayDiscrete<T>::isStrictlyMonotonic(bool increasing) const
3710   {
3711     this->checkAllocated();
3712     if(this->getNumberOfComponents()!=1)
3713       throw INTERP_KERNEL::Exception("DataArrayInt::isStrictlyMonotonic : only supported with 'this' array with ONE component !");
3714     std::size_t nbOfElements(this->getNumberOfTuples());
3715     const T *ptr(this->begin());
3716     if(nbOfElements==0)
3717       return true;
3718     T ref(ptr[0]);
3719     if(increasing)
3720       {
3721         for(std::size_t i=1;i<nbOfElements;i++)
3722           {
3723             if(ptr[i]>ref)
3724               ref=ptr[i];
3725             else
3726               return false;
3727           }
3728       }
3729     else
3730       {
3731         for(std::size_t i=1;i<nbOfElements;i++)
3732           {
3733             if(ptr[i]<ref)
3734               ref=ptr[i];
3735             else
3736               return false;
3737           }
3738       }
3739     return true;
3740   }
3741
3742   /*!
3743    * This method check that array consistently INCREASING or DECREASING in value.
3744    */
3745   template<class T>
3746   void DataArrayDiscrete<T>::checkStrictlyMonotonic(bool increasing) const
3747   {
3748     if(!isStrictlyMonotonic(increasing))
3749       {
3750         if (increasing)
3751           throw INTERP_KERNEL::Exception("DataArrayInt::checkStrictlyMonotonic : 'this' is not strictly INCREASING monotonic !");
3752         else
3753           throw INTERP_KERNEL::Exception("DataArrayInt::checkStrictlyMonotonic : 'this' is not strictly DECREASING monotonic !");
3754       }
3755   }
3756
3757   /*!
3758    * Returns an integer value characterizing \a this array, which is useful for a quick
3759    * comparison of many instances of DataArrayInt.
3760    *  \return int - the hash value.
3761    *  \throw If \a this is not allocated.
3762    */
3763   template<class T>
3764   int DataArrayDiscrete<T>::getHashCode() const
3765   {
3766     this->checkAllocated();
3767     std::size_t nbOfElems(this->getNbOfElems());
3768     int ret=nbOfElems*65536;
3769     int delta=3;
3770     if(nbOfElems>48)
3771       delta=nbOfElems/8;
3772     T ret0(0);
3773     const T *pt(this->begin());
3774     for(std::size_t i=0;i<nbOfElems;i+=delta)
3775       ret0+=pt[i] & 0x1FFF;
3776     return ret+ret0;
3777   }
3778
3779   template<class T>
3780   void DataArrayDiscrete<T>::reprCppStream(const std::string& varName, std::ostream& stream) const
3781   {
3782     std::size_t nbTuples(this->getNumberOfTuples()),nbComp(this->getNumberOfComponents());
3783     const T *data(this->getConstPointer());
3784     stream << Traits<T>::ArrayTypeName << " *" << varName << "=" << Traits<T>::ArrayTypeName << "::New();" << std::endl;
3785     if(nbTuples*nbComp>=1)
3786       {
3787         stream << "const int " << varName << "Data[" << nbTuples*nbComp << "]={";
3788         std::copy(data,data+nbTuples*nbComp-1,std::ostream_iterator<int>(stream,","));
3789         stream << data[nbTuples*nbComp-1] << "};" << std::endl;
3790         stream << varName << "->useArray(" << varName << "Data,false,CPP_DEALLOC," << nbTuples << "," << nbComp << ");" << std::endl;
3791       }
3792     else
3793       stream << varName << "->alloc(" << nbTuples << "," << nbComp << ");" << std::endl;
3794     stream << varName << "->setName(\"" << this->getName() << "\");" << std::endl;
3795   }
3796
3797   /*!
3798    * Method that gives a quick overvien of \a this for python.
3799    */
3800   template<class T>
3801   void DataArrayDiscrete<T>::reprQuickOverview(std::ostream& stream) const
3802   {
3803     static const std::size_t MAX_NB_OF_BYTE_IN_REPR=300;
3804     stream << Traits<T>::ArrayTypeName << " C++ instance at " << this << ". ";
3805     if(this->isAllocated())
3806       {
3807         std::size_t nbOfCompo(this->getNumberOfComponents());
3808         if(nbOfCompo>=1)
3809           {
3810             std::size_t nbOfTuples(this->getNumberOfTuples());
3811             stream << "Number of tuples : " << nbOfTuples << ". Number of components : " << nbOfCompo << "." << std::endl;
3812             reprQuickOverviewData(stream,MAX_NB_OF_BYTE_IN_REPR);
3813           }
3814         else
3815           stream << "Number of components : 0.";
3816       }
3817     else
3818       stream << "*** No data allocated ****";
3819   }
3820
3821   template<class T>
3822   void DataArrayDiscrete<T>::reprQuickOverviewData(std::ostream& stream, std::size_t maxNbOfByteInRepr) const
3823   {
3824     const T *data(this->begin());
3825     std::size_t nbOfTuples(this->getNumberOfTuples()),nbOfCompo(this->getNumberOfComponents());
3826     std::ostringstream oss2; oss2 << "[";
3827     std::string oss2Str(oss2.str());
3828     bool isFinished=true;
3829     for(int i=0;i<nbOfTuples && isFinished;i++)
3830       {
3831         if(nbOfCompo>1)
3832           {
3833             oss2 << "(";
3834             for(int j=0;j<nbOfCompo;j++,data++)
3835               {
3836                 oss2 << *data;
3837                 if(j!=nbOfCompo-1) oss2 << ", ";
3838               }
3839             oss2 << ")";
3840           }
3841         else
3842           oss2 << *data++;
3843         if(i!=nbOfTuples-1) oss2 << ", ";
3844         std::string oss3Str(oss2.str());
3845         if(oss3Str.length()<maxNbOfByteInRepr)
3846           oss2Str=oss3Str;
3847         else
3848           isFinished=false;
3849       }
3850     stream << oss2Str;
3851     if(!isFinished)
3852       stream << "... ";
3853     stream << "]";
3854   }
3855
3856   template<class T>
3857   void DataArrayDiscrete<T>::writeVTK(std::ostream& ofs, int indent, const std::string& type, const std::string& nameInFile, DataArrayByte *byteArr) const
3858   {
3859     static const char SPACE[4]={' ',' ',' ',' '};
3860     this->checkAllocated();
3861     std::string idt(indent,' ');
3862     ofs << idt << "<DataArray type=\"" << type << "\" Name=\"" << nameInFile << "\" NumberOfComponents=\"" << this->getNumberOfComponents() << "\"";
3863     if(byteArr)
3864       {
3865         ofs << " format=\"appended\" offset=\"" << byteArr->getNumberOfTuples() << "\">";
3866         if(std::string(type)==Traits<T>::VTKReprStr)
3867           {
3868             const char *data(reinterpret_cast<const char *>(this->begin()));
3869             std::size_t sz(this->getNbOfElems()*sizeof(T));
3870             byteArr->insertAtTheEnd(data,data+sz);
3871             byteArr->insertAtTheEnd(SPACE,SPACE+4);
3872           }
3873         else if(std::string(type)=="Int8")
3874           {
3875             INTERP_KERNEL::AutoPtr<char> tmp(new char[this->getNbOfElems()]);
3876             std::copy(this->begin(),this->end(),(char *)tmp);
3877             byteArr->insertAtTheEnd((char *)tmp,(char *)tmp+this->getNbOfElems());
3878             byteArr->insertAtTheEnd(SPACE,SPACE+4);
3879           }
3880         else if(std::string(type)=="UInt8")
3881           {
3882             INTERP_KERNEL::AutoPtr<unsigned char> tmp(new unsigned char[this->getNbOfElems()]);
3883             std::copy(this->begin(),this->end(),(unsigned char *)tmp);
3884             byteArr->insertAtTheEnd((unsigned char *)tmp,(unsigned char *)tmp+this->getNbOfElems());
3885             byteArr->insertAtTheEnd(SPACE,SPACE+4);
3886           }
3887         else
3888           {
3889             std::ostringstream oss;
3890             oss << Traits<T>::ArrayTypeName << "::writeVTK : Only " << Traits<T>::VTKReprStr << ", Int8 and UInt8 supported !";
3891             throw INTERP_KERNEL::Exception(oss.str());
3892           }
3893       }
3894     else
3895       {
3896         ofs << " RangeMin=\"" << this->getMinValueInArray() << "\" RangeMax=\"" << this->getMaxValueInArray() << "\" format=\"ascii\">\n" << idt;
3897         std::copy(this->begin(),this->end(),std::ostream_iterator<int>(ofs," "));
3898       }
3899       ofs << std::endl << idt << "</DataArray>\n";
3900   }
3901
3902   /*!
3903    * Modifies in place \a this one-dimensional array so that each value \a v = \a indArrBg[ \a v ],
3904    * i.e. a current value is used as in index to get a new value from \a indArrBg.
3905    *  \param [in] indArrBg - pointer to the first element of array of new values to assign
3906    *         to \a this array.
3907    *  \param [in] indArrEnd - specifies the end of the array \a indArrBg, so that
3908    *              the last value of \a indArrBg is \a indArrEnd[ -1 ].
3909    *  \throw If \a this->getNumberOfComponents() != 1
3910    *  \throw If any value of \a this can't be used as a valid index for
3911    *         [\a indArrBg, \a indArrEnd).
3912    *
3913    *  \sa changeValue, findIdForEach
3914    */
3915   template<class T>
3916   void DataArrayDiscrete<T>::transformWithIndArr(const T *indArrBg, const T *indArrEnd)
3917   {
3918     this->checkAllocated();
3919     if(this->getNumberOfComponents()!=1)
3920       throw INTERP_KERNEL::Exception("Call transformWithIndArr method on DataArrayInt with only one component, you can call 'rearrange' method before !");
3921     std::size_t nbElemsIn(std::distance(indArrBg,indArrEnd)),nbOfTuples(this->getNumberOfTuples());
3922     T *pt(this->getPointer());
3923     for(std::size_t i=0;i<nbOfTuples;i++,pt++)
3924       {
3925         if(*pt>=0 && *pt<nbElemsIn)
3926           *pt=indArrBg[*pt];
3927         else
3928           {
3929             std::ostringstream oss; oss << "DataArrayInt::transformWithIndArr : error on tuple #" << i << " of this value is " << *pt << ", should be in [0," << nbElemsIn << ") !";
3930             throw INTERP_KERNEL::Exception(oss.str());
3931           }
3932       }
3933     this->declareAsNew();
3934   }
3935
3936   template<class T>
3937   void DataArrayDiscrete<T>::transformWithIndArr(const MapKeyVal<T>& m)
3938   {
3939     this->checkAllocated();
3940     if(this->getNumberOfComponents()!=1)
3941       throw INTERP_KERNEL::Exception("Call transformWithIndArr method on DataArrayInt with only one component, you can call 'rearrange' method before !");
3942     const typename std::map<T,T>& dat(m.data());
3943     std::size_t nbOfTuples(this->getNumberOfTuples());
3944     T *pt(this->getPointer());
3945     for(std::size_t i=0;i<nbOfTuples;i++,pt++)
3946       {
3947         typename std::map<T,T>::const_iterator it(dat.find(*pt));
3948         if(it!=dat.end())
3949           *pt=(*it).second;
3950         else
3951           {
3952             std::ostringstream oss; oss << "DataArrayInt::transformWithIndArr : error on tuple #" << i << " of this value is " << *pt << " not in map !";
3953             throw INTERP_KERNEL::Exception(oss.str());
3954           }
3955       }
3956     this->declareAsNew();
3957   }
3958
3959   /*!
3960    * Creates a new DataArrayInt containing IDs (indices) of tuples holding value equal to a
3961    * given one. The ids are sorted in the ascending order.
3962    *  \param [in] val - the value to find within \a this.
3963    *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
3964    *          array using decrRef() as it is no more needed.
3965    *  \throw If \a this is not allocated.
3966    *  \throw If \a this->getNumberOfComponents() != 1.
3967    *  \sa DataArrayInt::findIdsEqualTuple
3968    */
3969   template<class T>
3970   DataArrayIdType *DataArrayDiscrete<T>::findIdsEqual(T val) const
3971   {
3972     this->checkAllocated();
3973     if(this->getNumberOfComponents()!=1)
3974       throw INTERP_KERNEL::Exception("DataArrayInt::findIdsEqual : the array must have only one component, you can call 'rearrange' method before !");
3975     const T *cptr(this->getConstPointer());
3976     MCAuto<DataArrayIdType> ret(DataArrayIdType::New()); ret->alloc(0,1);
3977     std::size_t nbOfTuples(this->getNumberOfTuples());
3978     for(std::size_t i=0;i<nbOfTuples;i++,cptr++)
3979       if(*cptr==val)
3980         ret->pushBackSilent(ToIdType(i));
3981     return ret.retn();
3982   }
3983
3984   ////////////////////////////////////
3985
3986   /*!
3987    * This method compares content of input vector \a v and \a this.
3988    * 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.
3989    * For performance reasons \a this is expected to be sorted ascendingly. If not an exception will be thrown.
3990    *
3991    * \param [in] v - the vector of 'flags' to be compared with \a this.
3992    *
3993    * \throw If \a this is not sorted ascendingly.
3994    * \throw If \a this has not exactly one component.
3995    * \throw If \a this is not allocated.
3996    */
3997   template<class T>
3998   bool DataArrayDiscreteSigned<T>::isFittingWith(const std::vector<bool>& v) const
3999   {
4000     this->checkAllocated();
4001     if(this->getNumberOfComponents()!=1)
4002       throw INTERP_KERNEL::Exception("DataArrayInt::isFittingWith : number of components of this should be equal to one !");
4003     const T *w(this->begin()),*end2(this->end());
4004     T refVal=-std::numeric_limits<T>::max();
4005     int i=0;
4006     std::vector<bool>::const_iterator it(v.begin());
4007     for(;it!=v.end();it++,i++)
4008       {
4009         if(*it)
4010           {
4011             if(w!=end2)
4012               {
4013                 if(*w++==i)
4014                   {
4015                     if(i>refVal)
4016                       refVal=i;
4017                     else
4018                       {
4019                         std::ostringstream oss; oss << "DataArrayInt::isFittingWith : At pos #" << std::distance(this->begin(),w-1) << " this is not sorted ascendingly !";
4020                         throw INTERP_KERNEL::Exception(oss.str().c_str());
4021                       }
4022                   }
4023                 else
4024                   return false;
4025               }
4026             else
4027               return false;
4028           }
4029       }
4030     return w==end2;
4031   }
4032 }
4033
4034 #endif