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