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