Salome HOME
Factorization again
[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   template<class T>
2327   template<class U>
2328   MCAuto< typename Traits<U>::ArrayType > DataArrayTemplateClassic<T>::convertToOtherTypeOfArr() const
2329   {
2330     this->checkAllocated();
2331     MCAuto<typename Traits<U>::ArrayType> ret(Traits<U>::ArrayType::New());
2332     ret->alloc(this->getNumberOfTuples(),this->getNumberOfComponents());
2333     std::size_t nbOfVals(this->getNbOfElems());
2334     const T *src(this->begin());
2335     U *dest(ret->getPointer());
2336     // to make Visual C++ happy : instead of std::size_t nbOfVals=getNbOfElems(); std::copy(src,src+nbOfVals,dest);
2337     //for(const T *src=this->begin();src!=this->end();src++,dest++)
2338     //  *dest=(int)*src;
2339     std::copy(src,src+nbOfVals,dest);
2340     ret->copyStringInfoFrom(*this);
2341     return ret;
2342   }
2343   
2344   /*!
2345    * Creates a new DataArrayDouble and assigns all (textual and numerical) data of \a this
2346    * array to the new one.
2347    *  \return DataArrayDouble * - the new instance of DataArrayInt.
2348    */
2349   template<class T>
2350   MCAuto<DataArrayDouble> DataArrayTemplateClassic<T>::convertToDblArr() const
2351   {
2352     return convertToOtherTypeOfArr<double>();
2353   }
2354
2355   /*!
2356    * Creates a new DataArrayInt and assigns all (textual and numerical) data of \a this
2357    * array to the new one.
2358    *  \return DataArrayInt * - the new instance of DataArrayInt.
2359    */
2360   template<class T>
2361   MCAuto<DataArrayInt> DataArrayTemplateClassic<T>::convertToIntArr() const
2362   {
2363     return convertToOtherTypeOfArr<int>();
2364   }
2365
2366   /*!
2367    * Creates a new DataArrayFloat and assigns all (textual and numerical) data of \a this
2368    * array to the new one.
2369    *  \return DataArrayFloat * - the new instance of DataArrayInt.
2370    */
2371   template<class T>
2372   MCAuto<DataArrayFloat> DataArrayTemplateClassic<T>::convertToFloatArr() const
2373   {
2374     return convertToOtherTypeOfArr<float>();
2375   }
2376
2377   /*!
2378    * Apply a linear function to a given component of \a this array, so that
2379    * an array element <em>(x)</em> becomes \f$ a * x + b \f$.
2380    *  \param [in] a - the first coefficient of the function.
2381    *  \param [in] b - the second coefficient of the function.
2382    *  \param [in] compoId - the index of component to modify.
2383    *  \throw If \a this is not allocated, or \a compoId is not in [0,\c this->getNumberOfComponents() ).
2384    */
2385   template<class T>
2386   void DataArrayTemplateClassic<T>::applyLin(T a, T b, int compoId)
2387   {
2388     this->checkAllocated();
2389     T *ptr(this->getPointer()+compoId);
2390     int nbOfComp(this->getNumberOfComponents()),nbOfTuple(this->getNumberOfTuples());
2391     if(compoId<0 || compoId>=nbOfComp)
2392       {
2393         std::ostringstream oss; oss << "DataArrayDouble::applyLin : The compoId requested (" << compoId << ") is not valid ! Must be in [0," << nbOfComp << ") !";
2394         throw INTERP_KERNEL::Exception(oss.str().c_str());
2395       }
2396     for(int i=0;i<nbOfTuple;i++,ptr+=nbOfComp)
2397       *ptr=a*(*ptr)+b;
2398     this->declareAsNew();
2399   }
2400
2401   /*!
2402    * Apply a linear function to all elements of \a this array, so that
2403    * an element _x_ becomes \f$ a * x + b \f$.
2404    *  \param [in] a - the first coefficient of the function.
2405    *  \param [in] b - the second coefficient of the function.
2406    *  \throw If \a this is not allocated.
2407    */
2408   template<class T>
2409   void DataArrayTemplateClassic<T>::applyLin(T a, T b)
2410   {
2411     this->checkAllocated();
2412     T *ptr(this->getPointer());
2413     std::size_t nbOfElems(this->getNbOfElems());
2414     for(std::size_t i=0;i<nbOfElems;i++,ptr++)
2415       *ptr=a*(*ptr)+b;
2416     this->declareAsNew();
2417   }
2418   
2419   /*!
2420    * Returns a full copy of \a this array except that sign of all elements is reversed.
2421    *  \return DataArrayDouble * - the new instance of DataArrayDouble containing the
2422    *          same number of tuples and component as \a this array.
2423    *          The caller is to delete this result array using decrRef() as it is no more
2424    *          needed.
2425    *  \throw If \a this is not allocated.
2426    */
2427   template<class T>
2428   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::negate() const
2429   {
2430     this->checkAllocated();
2431     MCAuto<typename Traits<T>::ArrayType> newArr(Traits<T>::ArrayType::New());
2432     int nbOfTuples(this->getNumberOfTuples()),nbOfComp(this->getNumberOfComponents());
2433     newArr->alloc(nbOfTuples,nbOfComp);
2434     const T *cptr(this->begin());
2435     std::transform(cptr,cptr+nbOfTuples*nbOfComp,newArr->getPointer(),std::negate<T>());
2436     newArr->copyStringInfoFrom(*this);
2437     return newArr.retn();
2438   }
2439
2440   template<class T>
2441   template<class FCT>
2442   void DataArrayTemplateClassic<T>::somethingEqual(const typename Traits<T>::ArrayType *other)
2443   {
2444     if(!other)
2445       throw INTERP_KERNEL::Exception("DataArray<T>::SomethingEqual : input DataArray<T> instance is NULL !");
2446     const char *msg="Nb of tuples mismatch for DataArrayDouble::multiplyEqual !";
2447     this->checkAllocated();
2448     other->checkAllocated();
2449     int nbOfTuple(this->getNumberOfTuples()),nbOfTuple2(other->getNumberOfTuples());
2450     int nbOfComp(this->getNumberOfComponents()),nbOfComp2(other->getNumberOfComponents());
2451     if(nbOfTuple==nbOfTuple2)
2452       {
2453         if(nbOfComp==nbOfComp2)
2454           {
2455             std::transform(this->begin(),this->end(),other->begin(),this->getPointer(),FCT());
2456           }
2457         else if(nbOfComp2==1)
2458           {
2459             T *ptr(this->getPointer());
2460             const T *ptrc(other->begin());
2461             for(int i=0;i<nbOfTuple;i++)
2462               std::transform(ptr+i*nbOfComp,ptr+(i+1)*nbOfComp,ptr+i*nbOfComp,std::bind2nd(FCT(),*ptrc++));
2463           }
2464         else
2465           throw INTERP_KERNEL::Exception(msg);
2466       }
2467     else if(nbOfTuple2==1)
2468       {
2469         if(nbOfComp2==nbOfComp)
2470           {
2471             T *ptr(this->getPointer());
2472             const T *ptrc(other->begin());
2473             for(int i=0;i<nbOfTuple;i++)
2474               std::transform(ptr+i*nbOfComp,ptr+(i+1)*nbOfComp,ptrc,ptr+i*nbOfComp,FCT());
2475           }
2476         else
2477           throw INTERP_KERNEL::Exception(msg);
2478       }
2479     else
2480       throw INTERP_KERNEL::Exception(msg);
2481     this->declareAsNew();
2482   }
2483   
2484   /*!
2485    * Adds values of another DataArrayDouble to values of \a this one. There are 3
2486    * valid cases.
2487    * 1.  The arrays have same number of tuples and components. Then each value of
2488    *   \a other array is added to the corresponding value of \a this array, i.e.:
2489    *   _a_ [ i, j ] += _other_ [ i, j ].
2490    * 2.  The arrays have same number of tuples and \a other array has one component. Then
2491    *   _a_ [ i, j ] += _other_ [ i, 0 ].
2492    * 3.  The arrays have same number of components and \a other array has one tuple. Then
2493    *   _a_ [ i, j ] += _a2_ [ 0, j ].
2494    *
2495    *  \param [in] other - an array to add to \a this one.
2496    *  \throw If \a other is NULL.
2497    *  \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples() and
2498    *         \a this->getNumberOfComponents() != \a other->getNumberOfComponents() and
2499    *         \a other has number of both tuples and components not equal to 1.
2500    */
2501   template<class T>
2502   void DataArrayTemplateClassic<T>::addEqual(const typename Traits<T>::ArrayType *other)
2503   {
2504     this->somethingEqual< std::plus<T> >(other);
2505   }
2506
2507   /*!
2508    * Subtract values of another DataArrayDouble from values of \a this one. There are 3
2509    * valid cases.
2510    * 1.  The arrays have same number of tuples and components. Then each value of
2511    *   \a other array is subtracted from the corresponding value of \a this array, i.e.:
2512    *   _a_ [ i, j ] -= _other_ [ i, j ].
2513    * 2.  The arrays have same number of tuples and \a other array has one component. Then
2514    *   _a_ [ i, j ] -= _other_ [ i, 0 ].
2515    * 3.  The arrays have same number of components and \a other array has one tuple. Then
2516    *   _a_ [ i, j ] -= _a2_ [ 0, j ].
2517    *
2518    *  \param [in] other - an array to subtract from \a this one.
2519    *  \throw If \a other is NULL.
2520    *  \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples() and
2521    *         \a this->getNumberOfComponents() != \a other->getNumberOfComponents() and
2522    *         \a other has number of both tuples and components not equal to 1.
2523    */
2524   template<class T>
2525   void DataArrayTemplateClassic<T>::substractEqual(const typename Traits<T>::ArrayType *other)
2526   {
2527     this->somethingEqual< std::minus<T> >(other);
2528   }
2529   
2530   /*!
2531    * Multiply values of another DataArrayDouble to values of \a this one. There are 3
2532    * valid cases.
2533    * 1.  The arrays have same number of tuples and components. Then each value of
2534    *   \a other array is multiplied to the corresponding value of \a this array, i.e.
2535    *   _this_ [ i, j ] *= _other_ [ i, j ].
2536    * 2.  The arrays have same number of tuples and \a other array has one component. Then
2537    *   _this_ [ i, j ] *= _other_ [ i, 0 ].
2538    * 3.  The arrays have same number of components and \a other array has one tuple. Then
2539    *   _this_ [ i, j ] *= _a2_ [ 0, j ].
2540    *
2541    *  \param [in] other - an array to multiply to \a this one.
2542    *  \throw If \a other is NULL.
2543    *  \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples() and
2544    *         \a this->getNumberOfComponents() != \a other->getNumberOfComponents() and
2545    *         \a other has number of both tuples and components not equal to 1.
2546    */
2547   template<class T>
2548   void DataArrayTemplateClassic<T>::multiplyEqual(const typename Traits<T>::ArrayType *other)
2549   {
2550     this->somethingEqual< std::multiplies<T> >(other);
2551   }
2552
2553   /*!
2554    * Divide values of \a this array by values of another DataArrayDouble. There are 3
2555    * valid cases.
2556    * 1.  The arrays have same number of tuples and components. Then each value of
2557    *    \a this array is divided by the corresponding value of \a other one, i.e.:
2558    *   _a_ [ i, j ] /= _other_ [ i, j ].
2559    * 2.  The arrays have same number of tuples and \a other array has one component. Then
2560    *   _a_ [ i, j ] /= _other_ [ i, 0 ].
2561    * 3.  The arrays have same number of components and \a other array has one tuple. Then
2562    *   _a_ [ i, j ] /= _a2_ [ 0, j ].
2563    *
2564    *  \warning No check of division by zero is performed!
2565    *  \param [in] other - an array to divide \a this one by.
2566    *  \throw If \a other is NULL.
2567    *  \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples() and
2568    *         \a this->getNumberOfComponents() != \a other->getNumberOfComponents() and
2569    *         \a other has number of both tuples and components not equal to 1.
2570    */
2571   template<class T>
2572   void DataArrayTemplateClassic<T>::divideEqual(const typename Traits<T>::ArrayType *other)
2573   {
2574     this->somethingEqual< std::divides<T> >(other);
2575   }
2576   
2577   template<class T, class FCT>
2578   typename Traits<T>::ArrayType *DivSub(const typename Traits<T>::ArrayType *a1, const typename Traits<T>::ArrayType *a2)
2579   {
2580     if(!a1 || !a2)
2581       throw INTERP_KERNEL::Exception("DivSub : input DataArrayDouble instance is NULL !");
2582     int nbOfTuple1(a1->getNumberOfTuples()),nbOfTuple2(a2->getNumberOfTuples());
2583     int nbOfComp1(a1->getNumberOfComponents()),nbOfComp2(a2->getNumberOfComponents());
2584     if(nbOfTuple2==nbOfTuple1)
2585       {
2586         if(nbOfComp1==nbOfComp2)
2587           {
2588             MCAuto<typename Traits<T>::ArrayType> ret(Traits<T>::ArrayType::New());
2589             ret->alloc(nbOfTuple2,nbOfComp1);
2590             std::transform(a1->begin(),a1->end(),a2->begin(),ret->getPointer(),FCT());
2591             ret->copyStringInfoFrom(*a1);
2592             return ret.retn();
2593           }
2594         else if(nbOfComp2==1)
2595           {
2596             MCAuto<typename Traits<T>::ArrayType> ret(Traits<T>::ArrayType::New());
2597             ret->alloc(nbOfTuple1,nbOfComp1);
2598             const T *a2Ptr(a2->begin()),*a1Ptr(a1->begin());
2599             T *res(ret->getPointer());
2600             for(int i=0;i<nbOfTuple1;i++)
2601               res=std::transform(a1Ptr+i*nbOfComp1,a1Ptr+(i+1)*nbOfComp1,res,std::bind2nd(FCT(),a2Ptr[i]));
2602             ret->copyStringInfoFrom(*a1);
2603             return ret.retn();
2604           }
2605         else
2606           {
2607             a1->checkNbOfComps(nbOfComp2,"Nb of components mismatch for array Divide !");
2608             return 0;
2609           }
2610       }
2611     else if(nbOfTuple2==1)
2612       {
2613         a1->checkNbOfComps(nbOfComp2,"Nb of components mismatch for array Divide !");
2614         MCAuto<typename Traits<T>::ArrayType> ret(Traits<T>::ArrayType::New());
2615         ret->alloc(nbOfTuple1,nbOfComp1);
2616         const T *a1ptr=a1->begin(),*a2ptr(a2->begin());
2617         T *pt(ret->getPointer());
2618         for(int i=0;i<nbOfTuple1;i++)
2619           pt=std::transform(a1ptr+i*nbOfComp1,a1ptr+(i+1)*nbOfComp1,a2ptr,pt,FCT());
2620         ret->copyStringInfoFrom(*a1);
2621         return ret.retn();
2622       }
2623     else
2624       {
2625         a1->checkNbOfTuples(nbOfTuple2,"Nb of tuples mismatch for array Divide !");//will always throw an exception
2626         return 0;
2627       }
2628   }
2629   
2630   /*!
2631    * Returns a new DataArrayDouble that is a subtraction of two given arrays. There are 3
2632    * valid cases.
2633    * 1.  The arrays have same number of tuples and components. Then each value of
2634    *   the result array (_a_) is a subtraction of the corresponding values of \a a1 and
2635    *   \a a2, i.e.: _a_ [ i, j ] = _a1_ [ i, j ] - _a2_ [ i, j ].
2636    * 2.  The arrays have same number of tuples and one array, say _a2_, has one
2637    *   component. Then
2638    *   _a_ [ i, j ] = _a1_ [ i, j ] - _a2_ [ i, 0 ].
2639    * 3.  The arrays have same number of components and one array, say _a2_, has one
2640    *   tuple. Then
2641    *   _a_ [ i, j ] = _a1_ [ i, j ] - _a2_ [ 0, j ].
2642    *
2643    * Info on components is copied either from the first array (in the first case) or from
2644    * the array with maximal number of elements (getNbOfElems()).
2645    *  \param [in] a1 - an array to subtract from.
2646    *  \param [in] a2 - an array to subtract.
2647    *  \return DataArrayDouble * - the new instance of DataArrayDouble.
2648    *          The caller is to delete this result array using decrRef() as it is no more
2649    *          needed.
2650    *  \throw If either \a a1 or \a a2 is NULL.
2651    *  \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples() and
2652    *         \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents() and
2653    *         none of them has number of tuples or components equal to 1.
2654    */
2655   template<class T>
2656   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::Substract(const typename Traits<T>::ArrayType *a1, const typename Traits<T>::ArrayType *a2)
2657   {
2658     return DivSub< T,std::minus<T> >(a1,a2);
2659   }
2660   
2661   /*!
2662    * Returns a new DataArrayDouble that is a division of two given arrays. There are 3
2663    * valid cases.
2664    * 1.  The arrays have same number of tuples and components. Then each value of
2665    *   the result array (_a_) is a division of the corresponding values of \a a1 and
2666    *   \a a2, i.e.: _a_ [ i, j ] = _a1_ [ i, j ] / _a2_ [ i, j ].
2667    * 2.  The arrays have same number of tuples and one array, say _a2_, has one
2668    *   component. Then
2669    *   _a_ [ i, j ] = _a1_ [ i, j ] / _a2_ [ i, 0 ].
2670    * 3.  The arrays have same number of components and one array, say _a2_, has one
2671    *   tuple. Then
2672    *   _a_ [ i, j ] = _a1_ [ i, j ] / _a2_ [ 0, j ].
2673    *
2674    * Info on components is copied either from the first array (in the first case) or from
2675    * the array with maximal number of elements (getNbOfElems()).
2676    *  \warning No check of division by zero is performed!
2677    *  \param [in] a1 - a numerator array.
2678    *  \param [in] a2 - a denominator array.
2679    *  \return DataArrayDouble * - the new instance of DataArrayDouble.
2680    *          The caller is to delete this result array using decrRef() as it is no more
2681    *          needed.
2682    *  \throw If either \a a1 or \a a2 is NULL.
2683    *  \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples() and
2684    *         \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents() and
2685    *         none of them has number of tuples or components equal to 1.
2686    */
2687   template<class T>
2688   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::Divide(const typename Traits<T>::ArrayType *a1, const typename Traits<T>::ArrayType *a2)
2689   {
2690     return DivSub< T,std::divides<T> >(a1,a2);
2691   }
2692
2693   template<class T, class FCT>
2694   typename Traits<T>::ArrayType *MulAdd(const typename Traits<T>::ArrayType *a1, const typename Traits<T>::ArrayType *a2)
2695   {
2696     if(!a1 || !a2)
2697       throw INTERP_KERNEL::Exception("DataArrayDouble::MulAdd : input DataArrayDouble instance is NULL !");
2698     int nbOfTuple(a1->getNumberOfTuples()),nbOfTuple2(a2->getNumberOfTuples());
2699     int nbOfComp(a1->getNumberOfComponents()),nbOfComp2(a2->getNumberOfComponents());
2700     MCAuto<typename Traits<T>::ArrayType> ret=0;
2701     if(nbOfTuple==nbOfTuple2)
2702       {
2703         if(nbOfComp==nbOfComp2)
2704           {
2705             ret=Traits<T>::ArrayType::New();
2706             ret->alloc(nbOfTuple,nbOfComp);
2707             std::transform(a1->begin(),a1->end(),a2->begin(),ret->getPointer(),FCT());
2708             ret->copyStringInfoFrom(*a1);
2709           }
2710         else
2711           {
2712             int nbOfCompMin,nbOfCompMax;
2713             const typename Traits<T>::ArrayType *aMin, *aMax;
2714             if(nbOfComp>nbOfComp2)
2715               {
2716                 nbOfCompMin=nbOfComp2; nbOfCompMax=nbOfComp;
2717                 aMin=a2; aMax=a1;
2718               }
2719             else
2720               {
2721                 nbOfCompMin=nbOfComp; nbOfCompMax=nbOfComp2;
2722                 aMin=a1; aMax=a2;
2723               }
2724             if(nbOfCompMin==1)
2725               {
2726                 ret=Traits<T>::ArrayType::New();
2727                 ret->alloc(nbOfTuple,nbOfCompMax);
2728                 const T *aMinPtr(aMin->begin());
2729                 const T *aMaxPtr(aMax->begin());
2730                 T *res=ret->getPointer();
2731                 for(int i=0;i<nbOfTuple;i++)
2732                   res=std::transform(aMaxPtr+i*nbOfCompMax,aMaxPtr+(i+1)*nbOfCompMax,res,std::bind2nd(FCT(),aMinPtr[i]));
2733                 ret->copyStringInfoFrom(*aMax);
2734               }
2735             else
2736               throw INTERP_KERNEL::Exception("Nb of components mismatch for array MulAdd !");
2737           }
2738       }
2739     else if((nbOfTuple==1 && nbOfTuple2>1) || (nbOfTuple>1 && nbOfTuple2==1))
2740       {
2741         if(nbOfComp==nbOfComp2)
2742           {
2743             int nbOfTupleMax=std::max(nbOfTuple,nbOfTuple2);
2744             const typename Traits<T>::ArrayType *aMin(nbOfTuple>nbOfTuple2?a2:a1);
2745             const typename Traits<T>::ArrayType *aMax(nbOfTuple>nbOfTuple2?a1:a2);
2746             const T *aMinPtr(aMin->begin()),*aMaxPtr(aMax->begin());
2747             ret=Traits<T>::ArrayType::New();
2748             ret->alloc(nbOfTupleMax,nbOfComp);
2749             T *res(ret->getPointer());
2750             for(int i=0;i<nbOfTupleMax;i++)
2751               res=std::transform(aMaxPtr+i*nbOfComp,aMaxPtr+(i+1)*nbOfComp,aMinPtr,res,FCT());
2752             ret->copyStringInfoFrom(*aMax);
2753           }
2754         else
2755           throw INTERP_KERNEL::Exception("Nb of components mismatch for array MulAdd !");
2756       }
2757     else
2758       throw INTERP_KERNEL::Exception("Nb of tuples mismatch for array MulAdd !");
2759     return ret.retn();
2760   }
2761   
2762   /*!
2763    * Returns a new DataArrayDouble that is a product of two given arrays. There are 3
2764    * valid cases.
2765    * 1.  The arrays have same number of tuples and components. Then each value of
2766    *   the result array (_a_) is a product of the corresponding values of \a a1 and
2767    *   \a a2, i.e. _a_ [ i, j ] = _a1_ [ i, j ] * _a2_ [ i, j ].
2768    * 2.  The arrays have same number of tuples and one array, say _a2_, has one
2769    *   component. Then
2770    *   _a_ [ i, j ] = _a1_ [ i, j ] * _a2_ [ i, 0 ].
2771    * 3.  The arrays have same number of components and one array, say _a2_, has one
2772    *   tuple. Then
2773    *   _a_ [ i, j ] = _a1_ [ i, j ] * _a2_ [ 0, j ].
2774    *
2775    * Info on components is copied either from the first array (in the first case) or from
2776    * the array with maximal number of elements (getNbOfElems()).
2777    *  \param [in] a1 - a factor array.
2778    *  \param [in] a2 - another factor array.
2779    *  \return DataArrayDouble * - the new instance of DataArrayDouble.
2780    *          The caller is to delete this result array using decrRef() as it is no more
2781    *          needed.
2782    *  \throw If either \a a1 or \a a2 is NULL.
2783    *  \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples() and
2784    *         \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents() and
2785    *         none of them has number of tuples or components equal to 1.
2786    */
2787   template<class T>
2788   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::Multiply(const typename Traits<T>::ArrayType *a1, const typename Traits<T>::ArrayType *a2)
2789   {
2790     return MulAdd< T , std::multiplies<T> >(a1,a2);
2791   }
2792   
2793   /*!
2794    * Returns a new DataArrayDouble that is a sum of two given arrays. There are 3
2795    * valid cases.
2796    * 1.  The arrays have same number of tuples and components. Then each value of
2797    *   the result array (_a_) is a sum of the corresponding values of \a a1 and \a a2,
2798    *   i.e.: _a_ [ i, j ] = _a1_ [ i, j ] + _a2_ [ i, j ].
2799    * 2.  The arrays have same number of tuples and one array, say _a2_, has one
2800    *   component. Then
2801    *   _a_ [ i, j ] = _a1_ [ i, j ] + _a2_ [ i, 0 ].
2802    * 3.  The arrays have same number of components and one array, say _a2_, has one
2803    *   tuple. Then
2804    *   _a_ [ i, j ] = _a1_ [ i, j ] + _a2_ [ 0, j ].
2805    *
2806    * Info on components is copied either from the first array (in the first case) or from
2807    * the array with maximal number of elements (getNbOfElems()).
2808    *  \param [in] a1 - an array to sum up.
2809    *  \param [in] a2 - another array to sum up.
2810    *  \return DataArrayDouble * - the new instance of DataArrayDouble.
2811    *          The caller is to delete this result array using decrRef() as it is no more
2812    *          needed.
2813    *  \throw If either \a a1 or \a a2 is NULL.
2814    *  \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples() and
2815    *         \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents() and
2816    *         none of them has number of tuples or components equal to 1.
2817    */
2818   template<class T>
2819   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::Add(const typename Traits<T>::ArrayType *a1, const typename Traits<T>::ArrayType *a2)
2820   {
2821     return MulAdd< T , std::plus<T> >(a1,a2);
2822   }
2823   
2824   /*!
2825    * Returns either a \a deep or \a shallow copy of this array. For more info see
2826    * \ref MEDCouplingArrayBasicsCopyDeep and \ref MEDCouplingArrayBasicsCopyShallow.
2827    *  \param [in] dCpy - if \a true, a deep copy is returned, else, a shallow one.
2828    *  \return DataArrayDouble * - either a new instance of DataArrayDouble (if \a dCpy
2829    *          == \a true) or \a this instance (if \a dCpy == \a false).
2830    */
2831   template<class T>
2832   typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::PerformCopyOrIncrRef(bool dCpy, const typename Traits<T>::ArrayType& self)
2833   {
2834     if(dCpy)
2835       return self.deepCopy();
2836     else
2837       {
2838         self.incrRef();
2839         return const_cast<typename Traits<T>::ArrayType *>(&self);
2840       }
2841   }
2842
2843   template<class T>
2844   struct GreatEqual
2845   {
2846     GreatEqual(T v):_v(v) { }
2847     bool operator()(T v) const { return v>=_v; }
2848     T _v;
2849   };
2850   
2851   template<class T>
2852   struct GreaterThan
2853   {
2854     GreaterThan(T v):_v(v) { }
2855     bool operator()(T v) const { return v>_v; }
2856     T _v;
2857   };
2858   
2859   template<class T>
2860   struct LowerEqual
2861   {
2862     LowerEqual(T v):_v(v) { }
2863     bool operator()(T v) const { return v<=_v; }
2864     T _v;
2865   };
2866   
2867   template<class T>
2868   struct LowerThan
2869   {
2870     LowerThan(T v):_v(v) { }
2871     bool operator()(T v) const { return v<_v; }
2872     T _v;
2873   };
2874   
2875   template<class T>
2876   struct InRange
2877   {
2878     InRange(T a, T b):_a(a),_b(b) { }
2879     bool operator()(T v) const { return v>=_a && v<_b; }
2880     T _a,_b;
2881   };
2882
2883 template<class T>
2884 struct NotInRange
2885 {
2886   NotInRange(T a, T b):_a(a),_b(b) { }
2887   bool operator()(T v) const { return v<_a || v>=_b; }
2888   T _a,_b;
2889 };
2890
2891   /*!
2892    * 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.
2893    *
2894    * \return a newly allocated data array that the caller should deal with.
2895    * \sa DataArrayInt::findIdsInRange
2896    */
2897   template<class T>
2898   DataArrayInt *DataArrayTemplateClassic<T>::findIdsStrictlyNegative() const
2899   {
2900     LowerThan<T> lt((T)0);
2901     MCAuto<DataArrayInt> ret(findIdsAdv(lt));
2902     return ret.retn();
2903   }
2904   
2905   template<class T>
2906   MCAuto<DataArrayInt> DataArrayTemplateClassic<T>::findIdsGreaterOrEqualTo(T val) const
2907   {
2908     GreatEqual<T> ge(val);
2909     return findIdsAdv(ge);
2910   }
2911   
2912   template<class T>
2913   MCAuto<DataArrayInt> DataArrayTemplateClassic<T>::findIdsGreaterThan(T val) const
2914   {
2915     GreaterThan<T> gt(val);
2916     return findIdsAdv(gt);
2917   }
2918   
2919   template<class T>
2920   MCAuto<DataArrayInt> DataArrayTemplateClassic<T>::findIdsLowerOrEqualTo(T val) const
2921   {
2922     LowerEqual<T> le(val);
2923     return findIdsAdv(le);
2924   }
2925   
2926   template<class T>
2927   MCAuto<DataArrayInt> DataArrayTemplateClassic<T>::findIdsLowerThan(T val) const
2928   {
2929     LowerThan<T> lt(val);
2930     return findIdsAdv(lt);
2931   }
2932   
2933   /*!
2934    * Checks if all values in \a this array are equal to \a val at precision \a eps.
2935    *  \param [in] val - value to check equality of array values to.
2936    *  \param [in] eps - precision to check the equality.
2937    *  \return bool - \a true if all values are in range (_val_ - _eps_; _val_ + _eps_),
2938    *                 \a false else.
2939    *  \throw If \a this->getNumberOfComponents() != 1
2940    *  \throw If \a this is not allocated.
2941    */
2942   template<class T>
2943   bool DataArrayTemplateFP<T>::isUniform(T val, T eps) const
2944   {
2945     this->checkAllocated();
2946     if(this->getNumberOfComponents()!=1)
2947       throw INTERP_KERNEL::Exception("DataArrayDouble::isUniform : must be applied on DataArrayDouble with only one component, you can call 'rearrange' method before !");
2948     int nbOfTuples(this->getNumberOfTuples());
2949     const T *w(this->begin()),*end2(this->end());
2950     const T vmin(val-eps),vmax(val+eps);
2951     for(;w!=end2;w++)
2952       if(*w<vmin || *w>vmax)
2953         return false;
2954     return true;
2955   }
2956
2957   /*!
2958    * Set all values in \a this array so that the i-th element equals to \a init + i
2959    * (i starts from zero). To know more on filling arrays see \ref MEDCouplingArrayFill.
2960    *  \param [in] init - value to assign to the first element of array.
2961    *  \throw If \a this->getNumberOfComponents() != 1
2962    *  \throw If \a this is not allocated.
2963    */
2964   template<class T>
2965   void DataArrayTemplateFP<T>::iota(T init)
2966   {
2967     this->checkAllocated();
2968     if(this->getNumberOfComponents()!=1)
2969       throw INTERP_KERNEL::Exception("DataArrayDouble::iota : works only for arrays with only one component, you can call 'rearrange' method before !");
2970     T *ptr(this->getPointer());
2971     int ntuples(this->getNumberOfTuples());
2972     for(int i=0;i<ntuples;i++)
2973       ptr[i]=init+T(i);
2974     this->declareAsNew();
2975   }
2976 }
2977
2978 #endif