Salome HOME
[EDF17279] : integration computation
[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  * \param [in] seg2 : coordinates of input seg2 expected to have spacedim==2
3616  * \param [in] tri3 : coordinates of input tri3 also expected to have spacedim==2
3617  * \param [out] coeffs : the result of integration normalized to 1. along \a seg2 inside tri3 sorted by the node id of \a tri3
3618  * \param [out] length : the length of seg2. That is too say the length of integration
3619  */
3620 void DataArrayDouble::ComputeIntegralOfSeg2IntoTri3(const double seg2[4], const double tri3[6], double coeffs[3], double& length)
3621 {
3622   length=INTERP_KERNEL::norme_vecteur(seg2,seg2+2);
3623   constexpr double eps(std::numeric_limits<double>::min());
3624   double n2(INTERP_KERNEL::norme_vecteur(tri3,tri3+2));
3625   n2=std::min(n2,INTERP_KERNEL::norme_vecteur(tri3+2,tri3+4)); n2=std::min(n2,INTERP_KERNEL::norme_vecteur(tri3+4,tri3));
3626   double myeps(eps*n2);
3627   if(length>myeps*1000.)
3628     {
3629       constexpr unsigned NB_EVAL=10;
3630       constexpr double NB_EVAL_FL=(double)NB_EVAL;
3631       constexpr double INTEG_LEN(1./NB_EVAL_FL);
3632       double curPt[2],curBaryCoo[3];
3633       double dirVect[2]={seg2[2]-seg2[0],seg2[3]-seg2[1]};
3634       coeffs[0]=0.; coeffs[1]=0.; coeffs[2]=0.;
3635       for(unsigned i=0;i<NB_EVAL;i++)
3636         {
3637           curPt[0]=seg2[0]+(0.5+(double)i)*INTEG_LEN*dirVect[0];
3638           curPt[1]=seg2[1]+(0.5+(double)i)*INTEG_LEN*dirVect[1];
3639           INTERP_KERNEL::barycentric_coords<2>(tri3,curPt,curBaryCoo);
3640           curBaryCoo[0]*=INTEG_LEN; curBaryCoo[1]*=INTEG_LEN; curBaryCoo[2]*=INTEG_LEN;
3641           coeffs[0]+=curBaryCoo[0]; coeffs[1]+=curBaryCoo[1]; coeffs[2]+=curBaryCoo[2];
3642         }
3643     }
3644   else
3645     {
3646       double mid[2];
3647       INTERP_KERNEL::mid_of_seg2(seg2,seg2+2,mid);
3648       INTERP_KERNEL::barycentric_coords<2>(tri3,mid,coeffs);
3649     }
3650 }
3651
3652 /*!
3653  * Low static method that operates 3D rotation of \a nbNodes 3D nodes whose coordinates are arranged in \a coords
3654  * around the center point \a center and with angle \a angle.
3655  */
3656 void DataArrayDouble::Rotate2DAlg(const double *center, double angle, int nbNodes, const double *coordsIn, double *coordsOut)
3657 {
3658   double cosa=cos(angle);
3659   double sina=sin(angle);
3660   double matrix[4];
3661   matrix[0]=cosa; matrix[1]=-sina; matrix[2]=sina; matrix[3]=cosa;
3662   double tmp[2];
3663   for(int i=0; i<nbNodes; i++)
3664     {
3665       std::transform(coordsIn+i*2,coordsIn+(i+1)*2,center,tmp,std::minus<double>());
3666       coordsOut[i*2]=matrix[0]*tmp[0]+matrix[1]*tmp[1]+center[0];
3667       coordsOut[i*2+1]=matrix[2]*tmp[0]+matrix[3]*tmp[1]+center[1];
3668     }
3669 }
3670
3671 DataArrayDoubleIterator::DataArrayDoubleIterator(DataArrayDouble *da):DataArrayIterator<double>(da)
3672 {
3673 }
3674
3675 DataArrayDoubleTuple::DataArrayDoubleTuple(double *pt, int nbOfComp):DataArrayTuple<double>(pt,nbOfComp)
3676 {
3677 }
3678
3679
3680 std::string DataArrayDoubleTuple::repr() const
3681 {
3682   std::ostringstream oss; oss.precision(17); oss << "(";
3683   for(int i=0;i<_nb_of_compo-1;i++)
3684     oss << _pt[i] << ", ";
3685   oss << _pt[_nb_of_compo-1] << ")";
3686   return oss.str();
3687 }
3688
3689 double DataArrayDoubleTuple::doubleValue() const
3690 {
3691   return this->zeValue();
3692 }
3693
3694 /*!
3695  * This method returns a newly allocated instance the caller should dealed with by a MEDCoupling::DataArrayDouble::decrRef.
3696  * This method performs \b no copy of data. The content is only referenced using MEDCoupling::DataArrayDouble::useArray with ownership set to \b false.
3697  * 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
3698  * \b nbOfCompo=1 and \bnbOfTuples==this->_nb_of_elem.
3699  */
3700 DataArrayDouble *DataArrayDoubleTuple::buildDADouble(int nbOfTuples, int nbOfCompo) const
3701 {
3702   return this->buildDA(nbOfTuples,nbOfCompo);
3703 }
3704
3705 /*!
3706  * Returns a new instance of DataArrayInt. The caller is to delete this array
3707  * using decrRef() as it is no more needed. 
3708  */
3709 DataArrayInt *DataArrayInt::New()
3710 {
3711   return new DataArrayInt;
3712 }
3713
3714 /*!
3715  * Returns the only one value in \a this, if and only if number of elements
3716  * (nb of tuples * nb of components) is equal to 1, and that \a this is allocated.
3717  *  \return double - the sole value stored in \a this array.
3718  *  \throw If at least one of conditions stated above is not fulfilled.
3719  */
3720 int DataArrayInt::intValue() const
3721 {
3722   if(isAllocated())
3723     {
3724       if(getNbOfElems()==1)
3725         {
3726           return *getConstPointer();
3727         }
3728       else
3729         throw INTERP_KERNEL::Exception("DataArrayInt::intValue : DataArrayInt instance is allocated but number of elements is not equal to 1 !");
3730     }
3731   else
3732     throw INTERP_KERNEL::Exception("DataArrayInt::intValue : DataArrayInt instance is not allocated !");
3733 }
3734
3735 /*!
3736  * Returns an integer value characterizing \a this array, which is useful for a quick
3737  * comparison of many instances of DataArrayInt.
3738  *  \return int - the hash value.
3739  *  \throw If \a this is not allocated.
3740  */
3741 int DataArrayInt::getHashCode() const
3742 {
3743   checkAllocated();
3744   std::size_t nbOfElems=getNbOfElems();
3745   int ret=nbOfElems*65536;
3746   int delta=3;
3747   if(nbOfElems>48)
3748     delta=nbOfElems/8;
3749   int ret0=0;
3750   const int *pt=begin();
3751   for(std::size_t i=0;i<nbOfElems;i+=delta)
3752     ret0+=pt[i] & 0x1FFF;
3753   return ret+ret0;
3754 }
3755
3756 /*!
3757  * Returns a full copy of \a this. For more info on copying data arrays see
3758  * \ref MEDCouplingArrayBasicsCopyDeep.
3759  *  \return DataArrayInt * - a new instance of DataArrayInt.
3760  */
3761 DataArrayInt32 *DataArrayInt32::deepCopy() const
3762 {
3763   return new DataArrayInt32(*this);
3764 }
3765
3766 /*!
3767  * Returns a textual and human readable representation of \a this instance of
3768  * DataArrayInt. This text is shown when a DataArrayInt is printed in Python.
3769  * \return std::string - text describing \a this DataArrayInt.
3770  * 
3771  * \sa reprNotTooLong, reprZip
3772  */
3773 std::string DataArrayInt::repr() const
3774 {
3775   std::ostringstream ret;
3776   reprStream(ret);
3777   return ret.str();
3778 }
3779
3780 std::string DataArrayInt::reprZip() const
3781 {
3782   std::ostringstream ret;
3783   reprZipStream(ret);
3784   return ret.str();
3785 }
3786
3787 void DataArrayInt::writeVTK(std::ostream& ofs, int indent, const std::string& type, const std::string& nameInFile, DataArrayByte *byteArr) const
3788 {
3789   static const char SPACE[4]={' ',' ',' ',' '};
3790   checkAllocated();
3791   std::string idt(indent,' ');
3792   ofs << idt << "<DataArray type=\"" << type << "\" Name=\"" << nameInFile << "\" NumberOfComponents=\"" << getNumberOfComponents() << "\"";
3793   if(byteArr)
3794     {
3795       ofs << " format=\"appended\" offset=\"" << byteArr->getNumberOfTuples() << "\">";
3796       if(std::string(type)=="Int32")
3797         {
3798           const char *data(reinterpret_cast<const char *>(begin()));
3799           std::size_t sz(getNbOfElems()*sizeof(int));
3800           byteArr->insertAtTheEnd(data,data+sz);
3801           byteArr->insertAtTheEnd(SPACE,SPACE+4);
3802         }
3803       else if(std::string(type)=="Int8")
3804         {
3805           INTERP_KERNEL::AutoPtr<char> tmp(new char[getNbOfElems()]);
3806           std::copy(begin(),end(),(char *)tmp);
3807           byteArr->insertAtTheEnd((char *)tmp,(char *)tmp+getNbOfElems());
3808           byteArr->insertAtTheEnd(SPACE,SPACE+4);
3809         }
3810       else if(std::string(type)=="UInt8")
3811         {
3812           INTERP_KERNEL::AutoPtr<unsigned char> tmp(new unsigned char[getNbOfElems()]);
3813           std::copy(begin(),end(),(unsigned char *)tmp);
3814           byteArr->insertAtTheEnd((unsigned char *)tmp,(unsigned char *)tmp+getNbOfElems());
3815           byteArr->insertAtTheEnd(SPACE,SPACE+4);
3816         }
3817       else
3818         throw INTERP_KERNEL::Exception("DataArrayInt::writeVTK : Only Int32, Int8 and UInt8 supported !");
3819     }
3820   else
3821     {
3822       ofs << " RangeMin=\"" << getMinValueInArray() << "\" RangeMax=\"" << getMaxValueInArray() << "\" format=\"ascii\">\n" << idt;
3823       std::copy(begin(),end(),std::ostream_iterator<int>(ofs," "));
3824     }
3825   ofs << std::endl << idt << "</DataArray>\n";
3826 }
3827
3828 void DataArrayInt::reprCppStream(const std::string& varName, std::ostream& stream) const
3829 {
3830   int nbTuples=getNumberOfTuples(),nbComp=getNumberOfComponents();
3831   const int *data=getConstPointer();
3832   stream << "DataArrayInt *" << varName << "=DataArrayInt::New();" << std::endl;
3833   if(nbTuples*nbComp>=1)
3834     {
3835       stream << "const int " << varName << "Data[" << nbTuples*nbComp << "]={";
3836       std::copy(data,data+nbTuples*nbComp-1,std::ostream_iterator<int>(stream,","));
3837       stream << data[nbTuples*nbComp-1] << "};" << std::endl;
3838       stream << varName << "->useArray(" << varName << "Data,false,CPP_DEALLOC," << nbTuples << "," << nbComp << ");" << std::endl;
3839     }
3840   else
3841     stream << varName << "->alloc(" << nbTuples << "," << nbComp << ");" << std::endl;
3842   stream << varName << "->setName(\"" << getName() << "\");" << std::endl;
3843 }
3844
3845 /*!
3846  * Method that gives a quick overvien of \a this for python.
3847  */
3848 void DataArrayInt::reprQuickOverview(std::ostream& stream) const
3849 {
3850   static const std::size_t MAX_NB_OF_BYTE_IN_REPR=300;
3851   stream << "DataArrayInt C++ instance at " << this << ". ";
3852   if(isAllocated())
3853     {
3854       int nbOfCompo=(int)_info_on_compo.size();
3855       if(nbOfCompo>=1)
3856         {
3857           int nbOfTuples=getNumberOfTuples();
3858           stream << "Number of tuples : " << nbOfTuples << ". Number of components : " << nbOfCompo << "." << std::endl;
3859           reprQuickOverviewData(stream,MAX_NB_OF_BYTE_IN_REPR);
3860         }
3861       else
3862         stream << "Number of components : 0.";
3863     }
3864   else
3865     stream << "*** No data allocated ****";
3866 }
3867
3868 void DataArrayInt::reprQuickOverviewData(std::ostream& stream, std::size_t maxNbOfByteInRepr) const
3869 {
3870   const int *data=begin();
3871   int nbOfTuples=getNumberOfTuples();
3872   int nbOfCompo=(int)_info_on_compo.size();
3873   std::ostringstream oss2; oss2 << "[";
3874   std::string oss2Str(oss2.str());
3875   bool isFinished=true;
3876   for(int i=0;i<nbOfTuples && isFinished;i++)
3877     {
3878       if(nbOfCompo>1)
3879         {
3880           oss2 << "(";
3881           for(int j=0;j<nbOfCompo;j++,data++)
3882             {
3883               oss2 << *data;
3884               if(j!=nbOfCompo-1) oss2 << ", ";
3885             }
3886           oss2 << ")";
3887         }
3888       else
3889         oss2 << *data++;
3890       if(i!=nbOfTuples-1) oss2 << ", ";
3891       std::string oss3Str(oss2.str());
3892       if(oss3Str.length()<maxNbOfByteInRepr)
3893         oss2Str=oss3Str;
3894       else
3895         isFinished=false;
3896     }
3897   stream << oss2Str;
3898   if(!isFinished)
3899     stream << "... ";
3900   stream << "]";
3901 }
3902
3903 /*!
3904  * Computes distribution of values of \a this one-dimensional array between given value
3905  * ranges (casts). This method is typically useful for entity number splitting by types,
3906  * for example. 
3907  *  \warning The values contained in \a arrBg should be sorted ascendently. No
3908  *           check of this is be done. If not, the result is not warranted. 
3909  *  \param [in] arrBg - the array of ascending values defining the value ranges. The i-th
3910  *         value of \a arrBg (\a arrBg[ i ]) gives the lowest value of the i-th range,
3911  *         and the greatest value of the i-th range equals to \a arrBg[ i+1 ] - 1. \a
3912  *         arrBg containing \a n values defines \a n-1 ranges. The last value of \a arrBg
3913  *         should be more than every value in \a this array.
3914  *  \param [in] arrEnd - specifies the end of the array \a arrBg, so that
3915  *              the last value of \a arrBg is \a arrEnd[ -1 ].
3916  *  \param [out] castArr - a new instance of DataArrayInt, of same size as \a this array
3917  *         (same number of tuples and components), the caller is to delete 
3918  *         using decrRef() as it is no more needed.
3919  *         This array contains indices of ranges for every value of \a this array. I.e.
3920  *         the i-th value of \a castArr gives the index of range the i-th value of \a this
3921  *         belongs to. Or, in other words, this parameter contains for each tuple in \a
3922  *         this in which cast it holds.
3923  *  \param [out] rankInsideCast - a new instance of DataArrayInt, of same size as \a this
3924  *         array, the caller is to delete using decrRef() as it is no more needed.
3925  *         This array contains ranks of values of \a this array within ranges
3926  *         they belongs to. I.e. the i-th value of \a rankInsideCast gives the rank of
3927  *         the i-th value of \a this array within the \a castArr[ i ]-th range, to which
3928  *         the i-th value of \a this belongs to. Or, in other words, this param contains 
3929  *         for each tuple its rank inside its cast. The rank is computed as difference
3930  *         between the value and the lowest value of range.
3931  *  \param [out] castsPresent - a new instance of DataArrayInt, containing indices of
3932  *         ranges (casts) to which at least one value of \a this array belongs.
3933  *         Or, in other words, this param contains the casts that \a this contains.
3934  *         The caller is to delete this array using decrRef() as it is no more needed.
3935  *
3936  * \b Example: If \a this contains [6,5,0,3,2,7,8,1,4] and \a arrBg contains [0,4,9] then
3937  *            the output of this method will be : 
3938  * - \a castArr       : [1,1,0,0,0,1,1,0,1]
3939  * - \a rankInsideCast: [2,1,0,3,2,3,4,1,0]
3940  * - \a castsPresent  : [0,1]
3941  *
3942  * I.e. values of \a this array belong to 2 ranges: #0 and #1. Value 6 belongs to the
3943  * range #1 and its rank within this range is 2; etc.
3944  *
3945  *  \throw If \a this->getNumberOfComponents() != 1.
3946  *  \throw If \a arrEnd - arrBg < 2.
3947  *  \throw If any value of \a this is not less than \a arrEnd[-1].
3948  */
3949 void DataArrayInt::splitByValueRange(const int *arrBg, const int *arrEnd,
3950                                      DataArrayInt *& castArr, DataArrayInt *& rankInsideCast, DataArrayInt *& castsPresent) const
3951 {
3952   checkAllocated();
3953   if(getNumberOfComponents()!=1)
3954     throw INTERP_KERNEL::Exception("Call splitByValueRange  method on DataArrayInt with only one component, you can call 'rearrange' method before !");
3955   int nbOfTuples=getNumberOfTuples();
3956   std::size_t nbOfCast=std::distance(arrBg,arrEnd);
3957   if(nbOfCast<2)
3958     throw INTERP_KERNEL::Exception("DataArrayInt::splitByValueRange : The input array giving the cast range values should be of size >=2 !");
3959   nbOfCast--;
3960   const int *work=getConstPointer();
3961   typedef std::reverse_iterator<const int *> rintstart;
3962   rintstart bg(arrEnd);//OK no problem because size of 'arr' is greater or equal 2
3963   rintstart end2(arrBg);
3964   MCAuto<DataArrayInt> ret1=DataArrayInt::New();
3965   MCAuto<DataArrayInt> ret2=DataArrayInt::New();
3966   MCAuto<DataArrayInt> ret3=DataArrayInt::New();
3967   ret1->alloc(nbOfTuples,1);
3968   ret2->alloc(nbOfTuples,1);
3969   int *ret1Ptr=ret1->getPointer();
3970   int *ret2Ptr=ret2->getPointer();
3971   std::set<std::size_t> castsDetected;
3972   for(int i=0;i<nbOfTuples;i++)
3973     {
3974       rintstart res=std::find_if(bg,end2,std::bind2nd(std::less_equal<int>(), work[i]));
3975       std::size_t pos=std::distance(bg,res);
3976       std::size_t pos2=nbOfCast-pos;
3977       if(pos2<nbOfCast)
3978         {
3979           ret1Ptr[i]=(int)pos2;
3980           ret2Ptr[i]=work[i]-arrBg[pos2];
3981           castsDetected.insert(pos2);
3982         }
3983       else
3984         {
3985           std::ostringstream oss; oss << "DataArrayInt::splitByValueRange : At rank #" << i << " the value is " << work[i] << " should be in [0," << *bg << ") !";
3986           throw INTERP_KERNEL::Exception(oss.str().c_str());
3987         }
3988     }
3989   ret3->alloc((int)castsDetected.size(),1);
3990   std::copy(castsDetected.begin(),castsDetected.end(),ret3->getPointer());
3991   castArr=ret1.retn();
3992   rankInsideCast=ret2.retn();
3993   castsPresent=ret3.retn();
3994 }
3995
3996 /*!
3997  * 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 ).
3998  * 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 ).
3999  * This method works only if \a this is allocated and single component. If not an exception will be thrown.
4000  *
4001  * \param [out] strt - the start of the range (included) if true is returned.
4002  * \param [out] sttoopp - the end of the range (not included) if true is returned.
4003  * \param [out] stteepp - the step of the range if true is returned.
4004  * \return the verdict of the check.
4005  *
4006  * \sa DataArray::GetNumberOfItemGivenBES
4007  */
4008 bool DataArrayInt::isRange(int& strt, int& sttoopp, int& stteepp) const
4009 {
4010   checkAllocated();
4011   if(getNumberOfComponents()!=1)
4012     throw INTERP_KERNEL::Exception("DataArrayInt::isRange : this must be single component array !");
4013   int nbTuples(getNumberOfTuples());
4014   if(nbTuples==0)
4015     { strt=0; sttoopp=0; stteepp=1; return true; }
4016   const int *pt(begin());
4017   strt=*pt; 
4018   if(nbTuples==1)
4019     { sttoopp=strt+1; stteepp=1; return true; }
4020   strt=*pt; sttoopp=pt[nbTuples-1];
4021   if(strt==sttoopp)
4022     return false;
4023   if(sttoopp>strt)
4024     {
4025       sttoopp++;
4026       int a(sttoopp-1-strt),tmp(strt);
4027       if(a%(nbTuples-1)!=0)
4028         return false;
4029       stteepp=a/(nbTuples-1);
4030       for(int i=0;i<nbTuples;i++,tmp+=stteepp)
4031         if(pt[i]!=tmp)
4032           return false;
4033       return true;
4034     }
4035   else
4036     {
4037       sttoopp--;
4038       int a(strt-sttoopp-1),tmp(strt);
4039       if(a%(nbTuples-1)!=0)
4040         return false;
4041       stteepp=-(a/(nbTuples-1));
4042       for(int i=0;i<nbTuples;i++,tmp+=stteepp)
4043         if(pt[i]!=tmp)
4044           return false;
4045       return true;
4046     }
4047 }
4048
4049
4050 /*!
4051  * Modifies in place \a this one-dimensional array so that each value \a v = \a indArrBg[ \a v ],
4052  * i.e. a current value is used as in index to get a new value from \a indArrBg.
4053  *  \param [in] indArrBg - pointer to the first element of array of new values to assign
4054  *         to \a this array.
4055  *  \param [in] indArrEnd - specifies the end of the array \a indArrBg, so that
4056  *              the last value of \a indArrBg is \a indArrEnd[ -1 ].
4057  *  \throw If \a this->getNumberOfComponents() != 1
4058  *  \throw If any value of \a this can't be used as a valid index for 
4059  *         [\a indArrBg, \a indArrEnd).
4060  *
4061  *  \sa changeValue, findIdForEach
4062  */
4063 void DataArrayInt::transformWithIndArr(const int *indArrBg, const int *indArrEnd)
4064 {
4065   this->checkAllocated();
4066   if(this->getNumberOfComponents()!=1)
4067     throw INTERP_KERNEL::Exception("Call transformWithIndArr method on DataArrayInt with only one component, you can call 'rearrange' method before !");
4068   int nbElemsIn((int)std::distance(indArrBg,indArrEnd)),nbOfTuples(getNumberOfTuples()),*pt(getPointer());
4069   for(int i=0;i<nbOfTuples;i++,pt++)
4070     {
4071       if(*pt>=0 && *pt<nbElemsIn)
4072         *pt=indArrBg[*pt];
4073       else
4074         {
4075           std::ostringstream oss; oss << "DataArrayInt::transformWithIndArr : error on tuple #" << i << " of this value is " << *pt << ", should be in [0," << nbElemsIn << ") !";
4076           throw INTERP_KERNEL::Exception(oss.str());
4077         }
4078     }
4079   this->declareAsNew();
4080 }
4081
4082 void DataArrayInt::transformWithIndArr(const MapKeyVal<int>& m)
4083 {
4084   this->checkAllocated();
4085   if(this->getNumberOfComponents()!=1)
4086     throw INTERP_KERNEL::Exception("Call transformWithIndArr method on DataArrayInt with only one component, you can call 'rearrange' method before !");
4087   const std::map<int,int>& dat(m.data());
4088   int nbOfTuples(getNumberOfTuples()),*pt(getPointer());
4089   for(int i=0;i<nbOfTuples;i++,pt++)
4090     {
4091       std::map<int,int>::const_iterator it(dat.find(*pt));
4092       if(it!=dat.end())
4093         *pt=(*it).second;
4094       else
4095         {
4096           std::ostringstream oss; oss << "DataArrayInt::transformWithIndArr : error on tuple #" << i << " of this value is " << *pt << " not in map !";
4097           throw INTERP_KERNEL::Exception(oss.str());
4098         }
4099     }
4100   this->declareAsNew();
4101 }
4102
4103 /*!
4104  * Creates a one-dimensional DataArrayInt (\a res) whose contents are computed from 
4105  * values of \a this (\a a) and the given (\a indArr) arrays as follows:
4106  * \a res[ \a indArr[ \a a[ i ]]] = i. I.e. for each value in place i \a v = \a a[ i ],
4107  * new value in place \a indArr[ \a v ] is i.
4108  *  \param [in] indArrBg - the array holding indices within the result array to assign
4109  *         indices of values of \a this array pointing to values of \a indArrBg.
4110  *  \param [in] indArrEnd - specifies the end of the array \a indArrBg, so that
4111  *              the last value of \a indArrBg is \a indArrEnd[ -1 ].
4112  *  \return DataArrayInt * - the new instance of DataArrayInt.
4113  *          The caller is to delete this result array using decrRef() as it is no more
4114  *          needed.
4115  *  \throw If \a this->getNumberOfComponents() != 1.
4116  *  \throw If any value of \a this array is not a valid index for \a indArrBg array.
4117  *  \throw If any value of \a indArrBg is not a valid index for \a this array.
4118  */
4119 DataArrayInt *DataArrayInt::transformWithIndArrR(const int *indArrBg, const int *indArrEnd) const
4120 {
4121   checkAllocated();
4122   if(getNumberOfComponents()!=1)
4123     throw INTERP_KERNEL::Exception("Call transformWithIndArrR method on DataArrayInt with only one component, you can call 'rearrange' method before !");
4124   int nbElemsIn=(int)std::distance(indArrBg,indArrEnd);
4125   int nbOfTuples=getNumberOfTuples();
4126   const int *pt=getConstPointer();
4127   MCAuto<DataArrayInt> ret=DataArrayInt::New();
4128   ret->alloc(nbOfTuples,1);
4129   ret->fillWithValue(-1);
4130   int *tmp=ret->getPointer();
4131   for(int i=0;i<nbOfTuples;i++,pt++)
4132     {
4133       if(*pt>=0 && *pt<nbElemsIn)
4134         {
4135           int pos=indArrBg[*pt];
4136           if(pos>=0 && pos<nbOfTuples)
4137             tmp[pos]=i;
4138           else
4139             {
4140               std::ostringstream oss; oss << "DataArrayInt::transformWithIndArrR : error on tuple #" << i << " value of new pos is " << pos << " ( indArrBg[" << *pt << "]) ! Should be in [0," << nbOfTuples << ") !";
4141               throw INTERP_KERNEL::Exception(oss.str().c_str());
4142             }
4143         }
4144       else
4145         {
4146           std::ostringstream oss; oss << "DataArrayInt::transformWithIndArrR : error on tuple #" << i << " value is " << *pt << " and indirectionnal array as a size equal to " << nbElemsIn << " !";
4147           throw INTERP_KERNEL::Exception(oss.str().c_str());
4148         }
4149     }
4150   return ret.retn();
4151 }
4152
4153 /*!
4154  * Creates a one-dimensional DataArrayInt of given length, whose contents are computed
4155  * from values of \a this array, which is supposed to contain a renumbering map in 
4156  * "Old to New" mode. The result array contains a renumbering map in "New to Old" mode.
4157  * To know how to use the renumbering maps see \ref numbering.
4158  *  \param [in] newNbOfElem - the number of tuples in the result array.
4159  *  \return DataArrayInt * - the new instance of DataArrayInt.
4160  *          The caller is to delete this result array using decrRef() as it is no more
4161  *          needed.
4162  * 
4163  *  \if ENABLE_EXAMPLES
4164  *  \ref cpp_mcdataarrayint_invertarrayo2n2n2o "Here is a C++ example".<br>
4165  *  \ref py_mcdataarrayint_invertarrayo2n2n2o  "Here is a Python example".
4166  *  \endif
4167  */
4168 DataArrayInt *DataArrayInt::invertArrayO2N2N2O(int newNbOfElem) const
4169 {
4170   MCAuto<DataArrayInt> ret(DataArrayInt::New());
4171   ret->alloc(newNbOfElem,1);
4172   int nbOfOldNodes(this->getNumberOfTuples());
4173   const int *old2New(begin());
4174   int *pt(ret->getPointer());
4175   for(int i=0;i!=nbOfOldNodes;i++)
4176     {
4177       int newp(old2New[i]);
4178       if(newp!=-1)
4179         {
4180           if(newp>=0 && newp<newNbOfElem)
4181             pt[newp]=i;
4182           else
4183             {
4184               std::ostringstream oss; oss << "DataArrayInt::invertArrayO2N2N2O : At place #" << i << " the newplace is " << newp << " must be in [0," << newNbOfElem << ") !";
4185               throw INTERP_KERNEL::Exception(oss.str().c_str());
4186             }
4187         }
4188     }
4189   return ret.retn();
4190 }
4191
4192 /*!
4193  * This method is similar to DataArrayInt::invertArrayO2N2N2O except that 
4194  * 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]
4195  */
4196 DataArrayInt *DataArrayInt::invertArrayO2N2N2OBis(int newNbOfElem) const
4197 {
4198   MCAuto<DataArrayInt> ret=DataArrayInt::New();
4199   ret->alloc(newNbOfElem,1);
4200   int nbOfOldNodes=getNumberOfTuples();
4201   const int *old2New=getConstPointer();
4202   int *pt=ret->getPointer();
4203   for(int i=nbOfOldNodes-1;i>=0;i--)
4204     {
4205       int newp(old2New[i]);
4206       if(newp!=-1)
4207         {
4208           if(newp>=0 && newp<newNbOfElem)
4209             pt[newp]=i;
4210           else
4211             {
4212               std::ostringstream oss; oss << "DataArrayInt::invertArrayO2N2N2OBis : At place #" << i << " the newplace is " << newp << " must be in [0," << newNbOfElem << ") !";
4213               throw INTERP_KERNEL::Exception(oss.str().c_str());
4214             }
4215         }
4216     }
4217   return ret.retn();
4218 }
4219
4220 /*!
4221  * Creates a one-dimensional DataArrayInt of given length, whose contents are computed
4222  * from values of \a this array, which is supposed to contain a renumbering map in 
4223  * "New to Old" mode. The result array contains a renumbering map in "Old to New" mode.
4224  * To know how to use the renumbering maps see \ref numbering.
4225  *  \param [in] newNbOfElem - the number of tuples in the result array.
4226  *  \return DataArrayInt * - the new instance of DataArrayInt.
4227  *          The caller is to delete this result array using decrRef() as it is no more
4228  *          needed.
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 invertArrayN2O2O2NOptimized
4235  *  \endif
4236  */
4237 DataArrayInt *DataArrayInt::invertArrayN2O2O2N(int oldNbOfElem) const
4238 {
4239   checkAllocated();
4240   MCAuto<DataArrayInt> ret=DataArrayInt::New();
4241   ret->alloc(oldNbOfElem,1);
4242   const int *new2Old=getConstPointer();
4243   int *pt=ret->getPointer();
4244   std::fill(pt,pt+oldNbOfElem,-1);
4245   int nbOfNewElems=getNumberOfTuples();
4246   for(int i=0;i<nbOfNewElems;i++)
4247     {
4248       int v(new2Old[i]);
4249       if(v>=0 && v<oldNbOfElem)
4250         pt[v]=i;
4251       else
4252         {
4253           std::ostringstream oss; oss << "DataArrayInt::invertArrayN2O2O2N : in new id #" << i << " old value is " << v << " expected to be in [0," << oldNbOfElem << ") !";
4254           throw INTERP_KERNEL::Exception(oss.str().c_str());
4255         }
4256     }
4257   return ret.retn();
4258 }
4259
4260 /*!
4261  * Creates a map, whose contents are computed
4262  * from values of \a this array, which is supposed to contain a renumbering map in 
4263  * "New to Old" mode. The result array contains a renumbering map in "Old to New" mode.
4264  * To know how to use the renumbering maps see \ref numbering.
4265  *  \param [in] newNbOfElem - the number of tuples in the result array.
4266  *  \return MapII  - the new instance of Map.
4267  * 
4268  *  \if ENABLE_EXAMPLES
4269  *  \ref cpp_mcdataarrayint_invertarrayn2o2o2n "Here is a C++ example".
4270  *
4271  *  \ref py_mcdataarrayint_invertarrayn2o2o2n "Here is a Python example".
4272  *  \sa invertArrayN2O2O2N, giveN2OOptimized, MEDCouplingPointSet::renumberNodesInConn
4273  *  \endif
4274  */
4275 MCAuto< MapKeyVal<int> > DataArrayInt32::invertArrayN2O2O2NOptimized() const
4276 {
4277   checkAllocated();
4278   if(getNumberOfComponents()!=1)
4279     throw INTERP_KERNEL::Exception("DataArrayInt32::invertArrayN2O2O2NOptimized : single component expected !");
4280   MCAuto< MapKeyVal<int> > ret(MapKeyVal<int>::New());
4281   std::map<int,int>& m(ret->data());
4282   const int *new2Old(begin());
4283   std::size_t nbOfNewElems(this->getNumberOfTuples());
4284   for(std::size_t i=0;i<nbOfNewElems;i++)
4285     {
4286       int v(new2Old[i]);
4287       m[v]=i;
4288     }
4289   return ret;
4290 }
4291
4292 /*!
4293  * Creates a map, whose contents are computed
4294  * from values of \a this array, which is supposed to contain a renumbering map in 
4295  * "New to Old" mode. The result array contains a renumbering map in "New to Old" mode as C++ map for performance reasons.
4296  *
4297  * \sa invertArrayN2O2O2NOptimized, MEDCouplingPointSet::renumberNodesInConn
4298  */
4299 MCAuto< MapKeyVal<int> > DataArrayInt32::giveN2OOptimized() const
4300 {
4301   checkAllocated();
4302   if(getNumberOfComponents()!=1)
4303     throw INTERP_KERNEL::Exception("DataArrayInt32::giveN2OOptimized : single component expected !");
4304   MCAuto< MapKeyVal<int> > ret(MapKeyVal<int>::New());
4305   std::map<int,int>& m(ret->data());
4306   const int *new2Old(begin());
4307   std::size_t nbOfNewElems(this->getNumberOfTuples());
4308   for(std::size_t i=0;i<nbOfNewElems;i++)
4309     {
4310       int v(new2Old[i]);
4311       m[i]=v;
4312     }
4313   return ret;
4314 }
4315
4316 /*!
4317  * Returns a new DataArrayInt containing a renumbering map in "Old to New" mode.
4318  * This map, if applied to \a this array, would make it sorted. For example, if
4319  * \a this array contents are [9,10,0,6,4,11,3,7] then the contents of the result array
4320  * are [5,6,0,3,2,7,1,4]; if this result array (\a res) is used as an argument in call
4321  * \a this->renumber(\a res) then the returned array contains [0,3,4,6,7,9,10,11].
4322  * This method is useful for renumbering (in MED file for example). For more info
4323  * on renumbering see \ref numbering.
4324  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
4325  *          array using decrRef() as it is no more needed.
4326  *  \throw If \a this is not allocated.
4327  *  \throw If \a this->getNumberOfComponents() != 1.
4328  *  \throw If there are equal values in \a this array.
4329  */
4330 DataArrayInt *DataArrayInt::checkAndPreparePermutation() const
4331 {
4332   checkAllocated();
4333   if(getNumberOfComponents()!=1)
4334     throw INTERP_KERNEL::Exception("DataArrayInt::checkAndPreparePermutation : number of components must == 1 !");
4335   int nbTuples=getNumberOfTuples();
4336   const int *pt=getConstPointer();
4337   int *pt2=CheckAndPreparePermutation(pt,pt+nbTuples);
4338   DataArrayInt *ret=DataArrayInt::New();
4339   ret->useArray(pt2,true,C_DEALLOC,nbTuples,1);
4340   return ret;
4341 }
4342
4343 /*!
4344  * 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
4345  * input array \a ids2.
4346  * \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.
4347  * 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
4348  * inversely.
4349  * In case of success both assertion will be true (no throw) :
4350  * \c ids1->renumber(ret)->isEqual(ids2) where \a ret is the return of this method.
4351  * \c ret->transformWithIndArr(ids2)->isEqual(ids1)
4352  *
4353  * \b Example:
4354  * - \a ids1 : [3,1,103,4,6,10,-7,205]
4355  * - \a ids2 : [-7,1,205,10,6,3,103,4]
4356  * - \a return is : [5,1,6,7,4,3,0,2] because ids2[5]==ids1[0], ids2[1]==ids1[1], ids2[6]==ids1[2]...
4357  *
4358  * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
4359  *          array using decrRef() as it is no more needed.
4360  * \throw If either ids1 or ids2 is null not allocated or not with one components.
4361  * 
4362  * \sa DataArrayInt32::findIdForEach
4363  */
4364 DataArrayInt *DataArrayInt::FindPermutationFromFirstToSecond(const DataArrayInt *ids1, const DataArrayInt *ids2)
4365 {
4366   if(!ids1 || !ids2)
4367     throw INTERP_KERNEL::Exception("DataArrayInt::FindPermutationFromFirstToSecond : the two input arrays must be not null !");
4368   if(!ids1->isAllocated() || !ids2->isAllocated())
4369     throw INTERP_KERNEL::Exception("DataArrayInt::FindPermutationFromFirstToSecond : the two input arrays must be allocated !");
4370   if(ids1->getNumberOfComponents()!=1 || ids2->getNumberOfComponents()!=1)
4371     throw INTERP_KERNEL::Exception("DataArrayInt::FindPermutationFromFirstToSecond : the two input arrays have exactly one component !");
4372   if(ids1->getNumberOfTuples()!=ids2->getNumberOfTuples())
4373     {
4374       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 !";
4375       throw INTERP_KERNEL::Exception(oss.str().c_str());
4376     }
4377   MCAuto<DataArrayInt> p1(ids1->deepCopy());
4378   MCAuto<DataArrayInt> p2(ids2->deepCopy());
4379   p1->sort(true); p2->sort(true);
4380   if(!p1->isEqualWithoutConsideringStr(*p2))
4381     throw INTERP_KERNEL::Exception("DataArrayInt::FindPermutationFromFirstToSecond : the two arrays are not lying on same ids ! Impossible to find a permutation between the 2 arrays !");
4382   p1=ids1->checkAndPreparePermutation();
4383   p2=ids2->checkAndPreparePermutation();
4384   p2=p2->invertArrayO2N2N2O(p2->getNumberOfTuples());
4385   p2=p2->selectByTupleIdSafe(p1->begin(),p1->end());
4386   return p2.retn();
4387 }
4388
4389 /*!
4390  * Returns two arrays describing a surjective mapping from \a this set of values (\a A)
4391  * onto a set of values of size \a targetNb (\a B). The surjective function is 
4392  * \a B[ \a A[ i ]] = i. That is to say that for each \a id in [0,\a targetNb), where \a
4393  * targetNb < \a this->getNumberOfTuples(), there exists at least one tupleId (\a tid) so
4394  * that <em> this->getIJ( tid, 0 ) == id</em>. <br>
4395  * The first of out arrays returns indices of elements of \a this array, grouped by their
4396  * place in the set \a B. The second out array is the index of the first one; it shows how
4397  * many elements of \a A are mapped into each element of \a B. <br>
4398  * For more info on
4399  * mapping and its usage in renumbering see \ref numbering. <br>
4400  * \b Example:
4401  * - \a this: [0,3,2,3,2,2,1,2]
4402  * - \a targetNb: 4
4403  * - \a arr:  [0,  6,  2,4,5,7,  1,3]
4404  * - \a arrI: [0,1,2,6,8]
4405  *
4406  * This result means: <br>
4407  * the element of \a B 0 encounters within \a A once (\a arrI[ 0+1 ] - \a arrI[ 0 ]) and
4408  * its index within \a A is 0 ( \a arr[ 0:1 ] == \a arr[ \a arrI[ 0 ] : \a arrI[ 0+1 ]]);<br>
4409  * the element of \a B 2 encounters within \a A 4 times (\a arrI[ 2+1 ] - \a arrI[ 2 ]) and
4410  * its indices within \a A are [2,4,5,7] ( \a arr[ 2:6 ] == \a arr[ \a arrI[ 2 ] : 
4411  * \a arrI[ 2+1 ]]); <br> etc.
4412  *  \param [in] targetNb - the size of the set \a B. \a targetNb must be equal or more
4413  *         than the maximal value of \a A.
4414  *  \param [out] arr - a new instance of DataArrayInt returning indices of
4415  *         elements of \a this, grouped by their place in the set \a B. The caller is to delete
4416  *         this array using decrRef() as it is no more needed.
4417  *  \param [out] arrI - a new instance of DataArrayInt returning size of groups of equal
4418  *         elements of \a this. The caller is to delete this array using decrRef() as it
4419  *         is no more needed.
4420  *  \throw If \a this is not allocated.
4421  *  \throw If \a this->getNumberOfComponents() != 1.
4422  *  \throw If any value in \a this is more or equal to \a targetNb.
4423  */
4424 void DataArrayInt::changeSurjectiveFormat(int targetNb, DataArrayInt *&arr, DataArrayInt *&arrI) const
4425 {
4426   checkAllocated();
4427   if(getNumberOfComponents()!=1)
4428     throw INTERP_KERNEL::Exception("DataArrayInt::changeSurjectiveFormat : number of components must == 1 !");
4429   int nbOfTuples=getNumberOfTuples();
4430   MCAuto<DataArrayInt> ret(DataArrayInt::New());
4431   MCAuto<DataArrayInt> retI(DataArrayInt::New());
4432   retI->alloc(targetNb+1,1);
4433   const int *input=getConstPointer();
4434   std::vector< std::vector<int> > tmp(targetNb);
4435   for(int i=0;i<nbOfTuples;i++)
4436     {
4437       int tmp2=input[i];
4438       if(tmp2>=0 && tmp2<targetNb)
4439         tmp[tmp2].push_back(i);
4440       else
4441         {
4442           std::ostringstream oss; oss << "DataArrayInt::changeSurjectiveFormat : At pos " << i << " presence of element " << tmp2 << " ! should be in [0," << targetNb << ") !";
4443           throw INTERP_KERNEL::Exception(oss.str().c_str());
4444         }
4445     }
4446   int *retIPtr=retI->getPointer();
4447   *retIPtr=0;
4448   for(std::vector< std::vector<int> >::const_iterator it1=tmp.begin();it1!=tmp.end();it1++,retIPtr++)
4449     retIPtr[1]=retIPtr[0]+(int)((*it1).size());
4450   if(nbOfTuples!=retI->getIJ(targetNb,0))
4451     throw INTERP_KERNEL::Exception("DataArrayInt::changeSurjectiveFormat : big problem should never happen !");
4452   ret->alloc(nbOfTuples,1);
4453   int *retPtr=ret->getPointer();
4454   for(std::vector< std::vector<int> >::const_iterator it1=tmp.begin();it1!=tmp.end();it1++)
4455     retPtr=std::copy((*it1).begin(),(*it1).end(),retPtr);
4456   arr=ret.retn();
4457   arrI=retI.retn();
4458 }
4459
4460
4461 /*!
4462  * Returns a new DataArrayInt containing a renumbering map in "Old to New" mode computed
4463  * from a zip representation of a surjective format (returned e.g. by
4464  * \ref MEDCoupling::DataArrayDouble::findCommonTuples() "DataArrayDouble::findCommonTuples()"
4465  * for example). The result array minimizes the permutation. <br>
4466  * For more info on renumbering see \ref numbering. <br>
4467  * \b Example: <br>
4468  * - \a nbOfOldTuples: 10 
4469  * - \a arr          : [0,3, 5,7,9]
4470  * - \a arrIBg       : [0,2,5]
4471  * - \a newNbOfTuples: 7
4472  * - result array    : [0,1,2,0,3,4,5,4,6,4]
4473  *
4474  *  \param [in] nbOfOldTuples - number of tuples in the initial array \a arr.
4475  *  \param [in] arr - the array of tuple indices grouped by \a arrIBg array.
4476  *  \param [in] arrIBg - the array dividing all indices stored in \a arr into groups of
4477  *         (indices of) equal values. Its every element (except the last one) points to
4478  *         the first element of a group of equal values.
4479  *  \param [in] arrIEnd - specifies the end of \a arrIBg, so that the last element of \a
4480  *          arrIBg is \a arrIEnd[ -1 ].
4481  *  \param [out] newNbOfTuples - number of tuples after surjection application.
4482  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
4483  *          array using decrRef() as it is no more needed.
4484  *  \throw If any value of \a arr breaks condition ( 0 <= \a arr[ i ] < \a nbOfOldTuples ).
4485  */
4486 DataArrayInt *DataArrayInt::ConvertIndexArrayToO2N(int nbOfOldTuples, const int *arr, const int *arrIBg, const int *arrIEnd, int &newNbOfTuples)
4487 {
4488   MCAuto<DataArrayInt> ret=DataArrayInt::New();
4489   ret->alloc(nbOfOldTuples,1);
4490   int *pt=ret->getPointer();
4491   std::fill(pt,pt+nbOfOldTuples,-1);
4492   int nbOfGrps=((int)std::distance(arrIBg,arrIEnd))-1;
4493   const int *cIPtr=arrIBg;
4494   for(int i=0;i<nbOfGrps;i++)
4495     pt[arr[cIPtr[i]]]=-(i+2);
4496   int newNb=0;
4497   for(int iNode=0;iNode<nbOfOldTuples;iNode++)
4498     {
4499       if(pt[iNode]<0)
4500         {
4501           if(pt[iNode]==-1)
4502             pt[iNode]=newNb++;
4503           else
4504             {
4505               int grpId=-(pt[iNode]+2);
4506               for(int j=cIPtr[grpId];j<cIPtr[grpId+1];j++)
4507                 {
4508                   if(arr[j]>=0 && arr[j]<nbOfOldTuples)
4509                     pt[arr[j]]=newNb;
4510                   else
4511                     {
4512                       std::ostringstream oss; oss << "DataArrayInt::ConvertIndexArrayToO2N : With element #" << j << " value is " << arr[j] << " should be in [0," << nbOfOldTuples << ") !";
4513                       throw INTERP_KERNEL::Exception(oss.str().c_str());
4514                     }
4515                 }
4516               newNb++;
4517             }
4518         }
4519     }
4520   newNbOfTuples=newNb;
4521   return ret.retn();
4522 }
4523
4524 /*!
4525  * Returns a new DataArrayInt containing a renumbering map in "New to Old" mode,
4526  * which if applied to \a this array would make it sorted ascendingly.
4527  * For more info on renumbering see \ref numbering. <br>
4528  * \b Example: <br>
4529  * - \a this: [2,0,1,1,0,1,2,0,1,1,0,0]
4530  * - result: [10,0,5,6,1,7,11,2,8,9,3,4]
4531  * - after applying result to \a this: [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2] 
4532  *
4533  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
4534  *          array using decrRef() as it is no more needed.
4535  *  \throw If \a this is not allocated.
4536  *  \throw If \a this->getNumberOfComponents() != 1.
4537  */
4538 DataArrayInt *DataArrayInt::buildPermArrPerLevel() const
4539 {
4540   checkAllocated();
4541   if(getNumberOfComponents()!=1)
4542     throw INTERP_KERNEL::Exception("DataArrayInt::buildPermArrPerLevel : number of components must == 1 !");
4543   int nbOfTuples=getNumberOfTuples();
4544   const int *pt=getConstPointer();
4545   std::map<int,int> m;
4546   MCAuto<DataArrayInt> ret=DataArrayInt::New();
4547   ret->alloc(nbOfTuples,1);
4548   int *opt=ret->getPointer();
4549   for(int i=0;i<nbOfTuples;i++,pt++,opt++)
4550     {
4551       int val=*pt;
4552       std::map<int,int>::iterator it=m.find(val);
4553       if(it!=m.end())
4554         {
4555           *opt=(*it).second;
4556           (*it).second++;
4557         }
4558       else
4559         {
4560           *opt=0;
4561           m.insert(std::pair<int,int>(val,1));
4562         }
4563     }
4564   int sum=0;
4565   for(std::map<int,int>::iterator it=m.begin();it!=m.end();it++)
4566     {
4567       int vt=(*it).second;
4568       (*it).second=sum;
4569       sum+=vt;
4570     }
4571   pt=getConstPointer();
4572   opt=ret->getPointer();
4573   for(int i=0;i<nbOfTuples;i++,pt++,opt++)
4574     *opt+=m[*pt];
4575   //
4576   return ret.retn();
4577 }
4578
4579 /*!
4580  * Checks if \a this array has the given size, and if its contents is equal to an array filled with
4581  * iota(). This method is particularly useful for DataArrayInt instances that represent
4582  * a renumbering array, to check if there is a real need in renumbering.
4583  * This method checks than \a this can be considered as an identity mapping
4584  * of a set having \a sizeExpected elements into itself.
4585  *
4586  *  \param [in] sizeExpected - The number of elements expected.
4587  *  \return bool - \a true if \a this array contents == \a range( \a this->getNumberOfTuples())
4588  *  \throw If \a this is not allocated.
4589  *  \throw If \a this->getNumberOfComponents() != 1.
4590  */
4591 bool DataArrayInt::isIota(int sizeExpected) const
4592 {
4593   checkAllocated();
4594   if(getNumberOfComponents()!=1)
4595     return false;
4596   int nbOfTuples(getNumberOfTuples());
4597   if(nbOfTuples!=sizeExpected)
4598     return false;
4599   const int *pt=getConstPointer();
4600   for(int i=0;i<nbOfTuples;i++,pt++)
4601     if(*pt!=i)
4602       return false;
4603   return true;
4604 }
4605
4606 /*!
4607  * Checks if all values in \a this array are equal to \a val.
4608  *  \param [in] val - value to check equality of array values to.
4609  *  \return bool - \a true if all values are \a val.
4610  *  \throw If \a this is not allocated.
4611  *  \throw If \a this->getNumberOfComponents() != 1
4612  *  \sa DataArrayInt::checkUniformAndGuess
4613  */
4614 bool DataArrayInt::isUniform(int val) const
4615 {
4616   checkAllocated();
4617   if(getNumberOfComponents()!=1)
4618     throw INTERP_KERNEL::Exception("DataArrayInt::isUniform : must be applied on DataArrayInt with only one component, you can call 'rearrange' method before !");
4619   const int *w(begin()),*end2(end());
4620   for(;w!=end2;w++)
4621     if(*w!=val)
4622       return false;
4623   return true;
4624 }
4625
4626 /*!
4627  * This method checks that \a this is uniform. If not and exception will be thrown.
4628  * In case of uniformity the corresponding value is returned.
4629  *
4630  * \return int - the unique value contained in this
4631  * \throw If \a this is not allocated.
4632  * \throw If \a this->getNumberOfComponents() != 1
4633  * \throw If \a this is not uniform.
4634  * \sa DataArrayInt::isUniform
4635  */
4636 int DataArrayInt::checkUniformAndGuess() const
4637 {
4638   checkAllocated();
4639   if(getNumberOfComponents()!=1)
4640     throw INTERP_KERNEL::Exception("DataArrayInt::checkUniformAndGuess : must be applied on DataArrayInt with only one component, you can call 'rearrange' method before !");
4641   if(empty())
4642     throw INTERP_KERNEL::Exception("DataArrayInt::checkUniformAndGuess : this is empty !");
4643   const int *w(begin()),*end2(end());
4644   int ret(*w);
4645   for(;w!=end2;w++)
4646     if(*w!=ret)
4647       throw INTERP_KERNEL::Exception("DataArrayInt::checkUniformAndGuess : this is not uniform !");
4648   return ret;
4649 }
4650
4651 /*!
4652  * Checks if all values in \a this array are unique.
4653  *  \return bool - \a true if condition above is true
4654  *  \throw If \a this is not allocated.
4655  *  \throw If \a this->getNumberOfComponents() != 1
4656  */
4657 bool DataArrayInt::hasUniqueValues() const
4658 {
4659   checkAllocated();
4660   if(getNumberOfComponents()!=1)
4661     throw INTERP_KERNEL::Exception("DataArrayInt::hasOnlyUniqueValues: must be applied on DataArrayInt with only one component, you can call 'rearrange' method before !");
4662   std::size_t nbOfTuples(getNumberOfTuples());
4663   std::set<int> s(begin(),end());  // in C++11, should use unordered_set (O(1) complexity)
4664   if (s.size() != nbOfTuples)
4665     return false;
4666   return true;
4667 }
4668
4669 /*!
4670  * Copy all components in a specified order from another DataArrayInt.
4671  * The specified components become the first ones in \a this array.
4672  * Both numerical and textual data is copied. The number of tuples in \a this and
4673  * the other array can be different.
4674  *  \param [in] a - the array to copy data from.
4675  *  \param [in] compoIds - sequence of zero based indices of components, data of which is
4676  *              to be copied.
4677  *  \throw If \a a is NULL.
4678  *  \throw If \a compoIds.size() != \a a->getNumberOfComponents().
4679  *  \throw If \a compoIds[i] < 0 or \a compoIds[i] > \a this->getNumberOfComponents().
4680  *
4681  *  \if ENABLE_EXAMPLES
4682  *  \ref py_mcdataarrayint_setselectedcomponents "Here is a Python example".
4683  *  \endif
4684  */
4685 void DataArrayInt::setSelectedComponents(const DataArrayInt *a, const std::vector<int>& compoIds)
4686 {
4687   if(!a)
4688     throw INTERP_KERNEL::Exception("DataArrayInt::setSelectedComponents : input DataArrayInt is NULL !");
4689   checkAllocated();
4690   a->checkAllocated();
4691   copyPartOfStringInfoFrom2(compoIds,*a);
4692   std::size_t partOfCompoSz=compoIds.size();
4693   int nbOfCompo=getNumberOfComponents();
4694   int nbOfTuples=std::min(getNumberOfTuples(),a->getNumberOfTuples());
4695   const int *ac=a->getConstPointer();
4696   int *nc=getPointer();
4697   for(int i=0;i<nbOfTuples;i++)
4698     for(std::size_t j=0;j<partOfCompoSz;j++,ac++)
4699       nc[nbOfCompo*i+compoIds[j]]=*ac;
4700 }
4701
4702 DataArrayIntIterator *DataArrayInt::iterator()
4703 {
4704   return new DataArrayIntIterator(this);
4705 }
4706
4707 /*!
4708  * Creates a new DataArrayInt containing IDs (indices) of tuples holding value equal to a
4709  * given one. The ids are sorted in the ascending order.
4710  *  \param [in] val - the value to find within \a this.
4711  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
4712  *          array using decrRef() as it is no more needed.
4713  *  \throw If \a this is not allocated.
4714  *  \throw If \a this->getNumberOfComponents() != 1.
4715  *  \sa DataArrayInt::findIdsEqualTuple
4716  */
4717 DataArrayInt *DataArrayInt::findIdsEqual(int val) const
4718 {
4719   checkAllocated();
4720   if(getNumberOfComponents()!=1)
4721     throw INTERP_KERNEL::Exception("DataArrayInt::findIdsEqual : the array must have only one component, you can call 'rearrange' method before !");
4722   const int *cptr(getConstPointer());
4723   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
4724   int nbOfTuples=getNumberOfTuples();
4725   for(int i=0;i<nbOfTuples;i++,cptr++)
4726     if(*cptr==val)
4727       ret->pushBackSilent(i);
4728   return ret.retn();
4729 }
4730
4731 /*!
4732  * Creates a new DataArrayInt containing IDs (indices) of tuples holding value \b not
4733  * equal to a given one. 
4734  *  \param [in] val - the value to ignore within \a this.
4735  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
4736  *          array using decrRef() as it is no more needed.
4737  *  \throw If \a this is not allocated.
4738  *  \throw If \a this->getNumberOfComponents() != 1.
4739  */
4740 DataArrayInt *DataArrayInt::findIdsNotEqual(int val) const
4741 {
4742   checkAllocated();
4743   if(getNumberOfComponents()!=1)
4744     throw INTERP_KERNEL::Exception("DataArrayInt::findIdsNotEqual : the array must have only one component, you can call 'rearrange' method before !");
4745   const int *cptr(getConstPointer());
4746   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
4747   int nbOfTuples=getNumberOfTuples();
4748   for(int i=0;i<nbOfTuples;i++,cptr++)
4749     if(*cptr!=val)
4750       ret->pushBackSilent(i);
4751   return ret.retn();
4752 }
4753
4754 /*!
4755  * Creates a new DataArrayInt containing IDs (indices) of tuples holding tuple equal to those defined by [ \a tupleBg , \a tupleEnd )
4756  * This method is an extension of  DataArrayInt::findIdsEqual method.
4757  *
4758  *  \param [in] tupleBg - the begin (included) of the input tuple to find within \a this.
4759  *  \param [in] tupleEnd - the end (excluded) of the input tuple to find within \a this.
4760  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
4761  *          array using decrRef() as it is no more needed.
4762  *  \throw If \a this is not allocated.
4763  *  \throw If \a this->getNumberOfComponents() != std::distance(tupleBg,tupleEnd).
4764  * \throw If \a this->getNumberOfComponents() is equal to 0.
4765  * \sa DataArrayInt::findIdsEqual
4766  */
4767 DataArrayInt *DataArrayInt::findIdsEqualTuple(const int *tupleBg, const int *tupleEnd) const
4768 {
4769   std::size_t nbOfCompoExp(std::distance(tupleBg,tupleEnd));
4770   checkAllocated();
4771   if(getNumberOfComponents()!=nbOfCompoExp)
4772     {
4773       std::ostringstream oss; oss << "DataArrayInt::findIdsEqualTuple : mismatch of number of components. Input tuple has " << nbOfCompoExp << " whereas this array has " << getNumberOfComponents() << " components !";
4774       throw INTERP_KERNEL::Exception(oss.str().c_str());
4775     }
4776   if(nbOfCompoExp==0)
4777     throw INTERP_KERNEL::Exception("DataArrayInt::findIdsEqualTuple : number of components should be > 0 !");
4778   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
4779   const int *bg(begin()),*end2(end()),*work(begin());
4780   while(work!=end2)
4781     {
4782       work=std::search(work,end2,tupleBg,tupleEnd);
4783       if(work!=end2)
4784         {
4785           std::size_t pos(std::distance(bg,work));
4786           if(pos%nbOfCompoExp==0)
4787             ret->pushBackSilent(pos/nbOfCompoExp);
4788           work++;
4789         }
4790     }
4791   return ret.retn();
4792 }
4793
4794 /*!
4795  * This method finds for each element \a ELT in [valsBg,valsEnd) elements in \a this equal to it. Associated to ELT
4796  * this method will return the tuple id of last element found. If there is no element in \a this equal to ELT
4797  * an exception will be thrown.
4798  *
4799  * In case of success this[ret]==vals. Samely ret->transformWithIndArr(this->begin(),this->end())==vals.
4800  * Where \a vals is the [valsBg,valsEnd) array and \a ret the array returned by this method.
4801  * This method can be seen as an extension of FindPermutationFromFirstToSecond.
4802  * <br>
4803  * \b Example: <br>
4804  * - \a this: [17,27,2,10,-4,3,12,27,16]
4805  * - \a val : [3,16,-4,27,17]
4806  * - result: [5,8,4,7,0]
4807  *
4808  * \return - An array of size std::distance(valsBg,valsEnd)
4809  *
4810  * \sa DataArrayInt32::FindPermutationFromFirstToSecond
4811  */
4812 MCAuto<DataArrayInt32> DataArrayInt32::findIdForEach(const int *valsBg, const int *valsEnd) const
4813 {
4814   MCAuto<DataArrayInt32> ret(DataArrayInt32::New());
4815   std::size_t nbOfTuplesOut(std::distance(valsBg,valsEnd));
4816   ret->alloc(nbOfTuplesOut,1);
4817   MCAuto< MapKeyVal<int> > zeMap(invertArrayN2O2O2NOptimized());
4818   const std::map<int,int>& dat(zeMap->data());
4819   int *ptToFeed(ret->getPointer());
4820   for(const int *pt=valsBg;pt!=valsEnd;pt++)
4821     {
4822       std::map<int,int>::const_iterator it(dat.find(*pt));
4823       if(it!=dat.end())
4824         *ptToFeed++=(*it).second;
4825       else
4826         {
4827           std::ostringstream oss; oss << "DataArrayInt32::findIdForEach : error for element at place " << std::distance(valsBg,pt);
4828           oss << " of input array value is " << *pt << " which is not in this !";
4829           throw INTERP_KERNEL::Exception(oss.str());
4830         }
4831     }
4832   return ret;
4833 }
4834
4835 /*!
4836  * Assigns \a newValue to all elements holding \a oldValue within \a this
4837  * one-dimensional array.
4838  *  \param [in] oldValue - the value to replace.
4839  *  \param [in] newValue - the value to assign.
4840  *  \return int - number of replacements performed.
4841  *  \throw If \a this is not allocated.
4842  *  \throw If \a this->getNumberOfComponents() != 1.
4843  */
4844 int DataArrayInt::changeValue(int oldValue, int newValue)
4845 {
4846   checkAllocated();
4847   if(getNumberOfComponents()!=1)
4848     throw INTERP_KERNEL::Exception("DataArrayInt::changeValue : the array must have only one component, you can call 'rearrange' method before !");
4849   if(oldValue==newValue)
4850     return 0;
4851   int *start(getPointer()),*end2(start+getNbOfElems());
4852   int ret(0);
4853   for(int *val=start;val!=end2;val++)
4854     {
4855       if(*val==oldValue)
4856         {
4857           *val=newValue;
4858           ret++;
4859         }
4860     }
4861   if(ret>0)
4862     declareAsNew();
4863   return ret;
4864 }
4865
4866 /*!
4867  * Creates a new DataArrayInt containing IDs (indices) of tuples holding value equal to
4868  * one of given values.
4869  *  \param [in] valsBg - an array of values to find within \a this array.
4870  *  \param [in] valsEnd - specifies the end of the array \a valsBg, so that
4871  *              the last value of \a valsBg is \a valsEnd[ -1 ].
4872  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
4873  *          array using decrRef() as it is no more needed.
4874  *  \throw If \a this->getNumberOfComponents() != 1.
4875  */
4876 DataArrayInt *DataArrayInt::findIdsEqualList(const int *valsBg, const int *valsEnd) const
4877 {
4878   if(getNumberOfComponents()!=1)
4879     throw INTERP_KERNEL::Exception("DataArrayInt::findIdsEqualList : the array must have only one component, you can call 'rearrange' method before !");
4880   std::set<int> vals2(valsBg,valsEnd);
4881   const int *cptr(getConstPointer());
4882   std::vector<int> res;
4883   int nbOfTuples(getNumberOfTuples());
4884   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
4885   for(int i=0;i<nbOfTuples;i++,cptr++)
4886     if(vals2.find(*cptr)!=vals2.end())
4887       ret->pushBackSilent(i);
4888   return ret.retn();
4889 }
4890
4891 /*!
4892  * Creates a new DataArrayInt containing IDs (indices) of tuples holding values \b not
4893  * equal to any of given values.
4894  *  \param [in] valsBg - an array of values to ignore within \a this array.
4895  *  \param [in] valsEnd - specifies the end of the array \a valsBg, so that
4896  *              the last value of \a valsBg is \a valsEnd[ -1 ].
4897  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
4898  *          array using decrRef() as it is no more needed.
4899  *  \throw If \a this->getNumberOfComponents() != 1.
4900  */
4901 DataArrayInt *DataArrayInt::findIdsNotEqualList(const int *valsBg, const int *valsEnd) const
4902 {
4903   if(getNumberOfComponents()!=1)
4904     throw INTERP_KERNEL::Exception("DataArrayInt::findIdsNotEqualList : the array must have only one component, you can call 'rearrange' method before !");
4905   std::set<int> vals2(valsBg,valsEnd);
4906   const int *cptr=getConstPointer();
4907   std::vector<int> res;
4908   int nbOfTuples=getNumberOfTuples();
4909   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
4910   for(int i=0;i<nbOfTuples;i++,cptr++)
4911     if(vals2.find(*cptr)==vals2.end())
4912       ret->pushBackSilent(i);
4913   return ret.retn();
4914 }
4915
4916 /*!
4917  * This method is an extension of DataArrayInt::findIdFirstEqual method because this method works for DataArrayInt with
4918  * any number of components excepted 0 (an INTERP_KERNEL::Exception is thrown in this case).
4919  * This method searches in \b this is there is a tuple that matched the input parameter \b tupl.
4920  * If any the tuple id is returned. If not -1 is returned.
4921  * 
4922  * This method throws an INTERP_KERNEL::Exception if the number of components in \b this mismatches with the size of
4923  * the input vector. An INTERP_KERNEL::Exception is thrown too if \b this is not allocated.
4924  *
4925  * \return tuple id where \b tupl is. -1 if no such tuple exists in \b this.
4926  * \sa DataArrayInt::findIdSequence, DataArrayInt::presenceOfTuple.
4927  */
4928 int DataArrayInt::findIdFirstEqualTuple(const std::vector<int>& tupl) const
4929 {
4930   checkAllocated();
4931   int nbOfCompo=getNumberOfComponents();
4932   if(nbOfCompo==0)
4933     throw INTERP_KERNEL::Exception("DataArrayInt::findIdFirstEqualTuple : 0 components in 'this' !");
4934   if(nbOfCompo!=(int)tupl.size())
4935     {
4936       std::ostringstream oss; oss << "DataArrayInt::findIdFirstEqualTuple : 'this' contains " << nbOfCompo << " components and searching for a tuple of length " << tupl.size() << " !";
4937       throw INTERP_KERNEL::Exception(oss.str().c_str());
4938     }
4939   const int *cptr=getConstPointer();
4940   std::size_t nbOfVals=getNbOfElems();
4941   for(const int *work=cptr;work!=cptr+nbOfVals;)
4942     {
4943       work=std::search(work,cptr+nbOfVals,tupl.begin(),tupl.end());
4944       if(work!=cptr+nbOfVals)
4945         {
4946           if(std::distance(cptr,work)%nbOfCompo!=0)
4947             work++;
4948           else
4949             return std::distance(cptr,work)/nbOfCompo;
4950         }
4951     }
4952   return -1;
4953 }
4954
4955 /*!
4956  * This method searches the sequence specified in input parameter \b vals in \b this.
4957  * This works only for DataArrayInt having number of components equal to one (if not an INTERP_KERNEL::Exception will be thrown).
4958  * This method differs from DataArrayInt::findIdFirstEqualTuple in that the position is internal raw data is not considered here contrary to DataArrayInt::findIdFirstEqualTuple.
4959  * \sa DataArrayInt::findIdFirstEqualTuple
4960  */
4961 int DataArrayInt::findIdSequence(const std::vector<int>& vals) const
4962 {
4963   checkAllocated();
4964   int nbOfCompo=getNumberOfComponents();
4965   if(nbOfCompo!=1)
4966     throw INTERP_KERNEL::Exception("DataArrayInt::findIdSequence : works only for DataArrayInt instance with one component !");
4967   const int *cptr=getConstPointer();
4968   std::size_t nbOfVals=getNbOfElems();
4969   const int *loc=std::search(cptr,cptr+nbOfVals,vals.begin(),vals.end());
4970   if(loc!=cptr+nbOfVals)
4971     return std::distance(cptr,loc);
4972   return -1;
4973 }
4974
4975 /*!
4976  * This method expects to be called when number of components of this is equal to one.
4977  * This method returns the tuple id, if it exists, of the first tuple equal to \b value.
4978  * If not any tuple contains \b value -1 is returned.
4979  * \sa DataArrayInt::presenceOfValue
4980  */
4981 int DataArrayInt::findIdFirstEqual(int value) const
4982 {
4983   checkAllocated();
4984   if(getNumberOfComponents()!=1)
4985     throw INTERP_KERNEL::Exception("DataArrayInt::presenceOfValue : the array must have only one component, you can call 'rearrange' method before !");
4986   const int *cptr=getConstPointer();
4987   int nbOfTuples=getNumberOfTuples();
4988   const int *ret=std::find(cptr,cptr+nbOfTuples,value);
4989   if(ret!=cptr+nbOfTuples)
4990     return std::distance(cptr,ret);
4991   return -1;
4992 }
4993
4994 /*!
4995  * This method expects to be called when number of components of this is equal to one.
4996  * This method returns the tuple id, if it exists, of the first tuple so that the value is contained in \b vals.
4997  * If not any tuple contains one of the values contained in 'vals' -1 is returned.
4998  * \sa DataArrayInt::presenceOfValue
4999  */
5000 int DataArrayInt::findIdFirstEqual(const std::vector<int>& vals) const
5001 {
5002   checkAllocated();
5003   if(getNumberOfComponents()!=1)
5004     throw INTERP_KERNEL::Exception("DataArrayInt::presenceOfValue : the array must have only one component, you can call 'rearrange' method before !");
5005   std::set<int> vals2(vals.begin(),vals.end());
5006   const int *cptr=getConstPointer();
5007   int nbOfTuples=getNumberOfTuples();
5008   for(const int *w=cptr;w!=cptr+nbOfTuples;w++)
5009     if(vals2.find(*w)!=vals2.end())
5010       return std::distance(cptr,w);
5011   return -1;
5012 }
5013
5014 /*!
5015  * This method returns the number of values in \a this that are equals to input parameter \a value.
5016  * This method only works for single component array.
5017  *
5018  * \return a value in [ 0, \c this->getNumberOfTuples() )
5019  *
5020  * \throw If \a this is not allocated
5021  *
5022  */
5023 int DataArrayInt::count(int value) const
5024 {
5025   int ret=0;
5026   checkAllocated();
5027   if(getNumberOfComponents()!=1)
5028     throw INTERP_KERNEL::Exception("DataArrayInt::count : must be applied on DataArrayInt with only one component, you can call 'rearrange' method before !");
5029   const int *vals=begin();
5030   int nbOfTuples=getNumberOfTuples();
5031   for(int i=0;i<nbOfTuples;i++,vals++)
5032     if(*vals==value)
5033       ret++;
5034   return ret;
5035 }
5036
5037 /*!
5038  * This method is an extension of DataArrayInt::presenceOfValue method because this method works for DataArrayInt with
5039  * any number of components excepted 0 (an INTERP_KERNEL::Exception is thrown in this case).
5040  * This method searches in \b this is there is a tuple that matched the input parameter \b tupl.
5041  * This method throws an INTERP_KERNEL::Exception if the number of components in \b this mismatches with the size of
5042  * the input vector. An INTERP_KERNEL::Exception is thrown too if \b this is not allocated.
5043  * \sa DataArrayInt::findIdFirstEqualTuple
5044  */
5045 bool DataArrayInt::presenceOfTuple(const std::vector<int>& tupl) const
5046 {
5047   return findIdFirstEqualTuple(tupl)!=-1;
5048 }
5049
5050
5051 /*!
5052  * Returns \a true if a given value is present within \a this one-dimensional array.
5053  *  \param [in] value - the value to find within \a this array.
5054  *  \return bool - \a true in case if \a value is present within \a this array.
5055  *  \throw If \a this is not allocated.
5056  *  \throw If \a this->getNumberOfComponents() != 1.
5057  *  \sa findIdFirstEqual()
5058  */
5059 bool DataArrayInt::presenceOfValue(int value) const
5060 {
5061   return findIdFirstEqual(value)!=-1;
5062 }
5063
5064 /*!
5065  * This method expects to be called when number of components of this is equal to one.
5066  * This method returns true if it exists a tuple so that the value is contained in \b vals.
5067  * If not any tuple contains one of the values contained in 'vals' false is returned.
5068  * \sa DataArrayInt::findIdFirstEqual
5069  */
5070 bool DataArrayInt::presenceOfValue(const std::vector<int>& vals) const
5071 {
5072   return findIdFirstEqual(vals)!=-1;
5073 }
5074
5075 /*!
5076  * Accumulates values of each component of \a this array.
5077  *  \param [out] res - an array of length \a this->getNumberOfComponents(), allocated 
5078  *         by the caller, that is filled by this method with sum value for each
5079  *         component.
5080  *  \throw If \a this is not allocated.
5081  */
5082 void DataArrayInt::accumulate(int *res) const
5083 {
5084   checkAllocated();
5085   const int *ptr=getConstPointer();
5086   int nbTuple=getNumberOfTuples();
5087   int nbComps=getNumberOfComponents();
5088   std::fill(res,res+nbComps,0);
5089   for(int i=0;i<nbTuple;i++)
5090     std::transform(ptr+i*nbComps,ptr+(i+1)*nbComps,res,res,std::plus<int>());
5091 }
5092
5093 int DataArrayInt::accumulate(int compId) const
5094 {
5095   checkAllocated();
5096   const int *ptr=getConstPointer();
5097   int nbTuple=getNumberOfTuples();
5098   int nbComps=getNumberOfComponents();
5099   if(compId<0 || compId>=nbComps)
5100     throw INTERP_KERNEL::Exception("DataArrayInt::accumulate : Invalid compId specified : No such nb of components !");
5101   int ret=0;
5102   for(int i=0;i<nbTuple;i++)
5103     ret+=ptr[i*nbComps+compId];
5104   return ret;
5105 }
5106
5107 /*!
5108  * This method accumulate using addition tuples in \a this using input index array [ \a bgOfIndex, \a endOfIndex ).
5109  * The returned array will have same number of components than \a this and number of tuples equal to
5110  * \c std::distance(bgOfIndex,endOfIndex) \b minus \b one.
5111  *
5112  * The input index array is expected to be ascendingly sorted in which the all referenced ids should be in [0, \c this->getNumberOfTuples).
5113  *
5114  * \param [in] bgOfIndex - begin (included) of the input index array.
5115  * \param [in] endOfIndex - end (excluded) of the input index array.
5116  * \return DataArrayInt * - the new instance having the same number of components than \a this.
5117  * 
5118  * \throw If bgOfIndex or end is NULL.
5119  * \throw If input index array is not ascendingly sorted.
5120  * \throw If there is an id in [ \a bgOfIndex, \a endOfIndex ) not in [0, \c this->getNumberOfTuples).
5121  * \throw If std::distance(bgOfIndex,endOfIndex)==0.
5122  */
5123 DataArrayInt *DataArrayInt::accumulatePerChunck(const int *bgOfIndex, const int *endOfIndex) const
5124 {
5125   if(!bgOfIndex || !endOfIndex)
5126     throw INTERP_KERNEL::Exception("DataArrayInt::accumulatePerChunck : input pointer NULL !");
5127   checkAllocated();
5128   int nbCompo=getNumberOfComponents();
5129   int nbOfTuples=getNumberOfTuples();
5130   int sz=(int)std::distance(bgOfIndex,endOfIndex);
5131   if(sz<1)
5132     throw INTERP_KERNEL::Exception("DataArrayInt::accumulatePerChunck : invalid size of input index array !");
5133   sz--;
5134   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(sz,nbCompo);
5135   const int *w=bgOfIndex;
5136   if(*w<0 || *w>=nbOfTuples)
5137     throw INTERP_KERNEL::Exception("DataArrayInt::accumulatePerChunck : The first element of the input index not in [0,nbOfTuples) !");
5138   const int *srcPt=begin()+(*w)*nbCompo;
5139   int *tmp=ret->getPointer();
5140   for(int i=0;i<sz;i++,tmp+=nbCompo,w++)
5141     {
5142       std::fill(tmp,tmp+nbCompo,0);
5143       if(w[1]>=w[0])
5144         {
5145           for(int j=w[0];j<w[1];j++,srcPt+=nbCompo)
5146             {
5147               if(j>=0 && j<nbOfTuples)
5148                 std::transform(srcPt,srcPt+nbCompo,tmp,tmp,std::plus<int>());
5149               else
5150                 {
5151                   std::ostringstream oss; oss << "DataArrayInt::accumulatePerChunck : At rank #" << i << " the input index array points to id " << j << " should be in [0," << nbOfTuples << ") !";
5152                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5153                 }
5154             }
5155         }
5156       else
5157         {
5158           std::ostringstream oss; oss << "DataArrayInt::accumulatePerChunck : At rank #" << i << " the input index array is not in ascendingly sorted.";
5159           throw INTERP_KERNEL::Exception(oss.str().c_str());
5160         }
5161     }
5162   ret->copyStringInfoFrom(*this);
5163   return ret.retn();
5164 }
5165
5166 /*!
5167  * Returns a new DataArrayInt by concatenating two given arrays, so that (1) the number
5168  * of tuples in the result array is <em> a1->getNumberOfTuples() + a2->getNumberOfTuples() -
5169  * offsetA2</em> and (2)
5170  * the number of component in the result array is same as that of each of given arrays.
5171  * First \a offsetA2 tuples of \a a2 are skipped and thus are missing from the result array.
5172  * Info on components is copied from the first of the given arrays. Number of components
5173  * in the given arrays must be the same.
5174  *  \param [in] a1 - an array to include in the result array.
5175  *  \param [in] a2 - another array to include in the result array.
5176  *  \param [in] offsetA2 - number of tuples of \a a2 to skip.
5177  *  \return DataArrayInt * - the new instance of DataArrayInt.
5178  *          The caller is to delete this result array using decrRef() as it is no more
5179  *          needed.
5180  *  \throw If either \a a1 or \a a2 is NULL.
5181  *  \throw If \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents().
5182  */
5183 DataArrayInt *DataArrayInt::Aggregate(const DataArrayInt *a1, const DataArrayInt *a2, int offsetA2)
5184 {
5185   if(!a1 || !a2)
5186     throw INTERP_KERNEL::Exception("DataArrayInt::Aggregate : input DataArrayInt instance is NULL !");
5187   std::size_t nbOfComp(a1->getNumberOfComponents());
5188   if(nbOfComp!=a2->getNumberOfComponents())
5189     throw INTERP_KERNEL::Exception("Nb of components mismatch for array Aggregation !");
5190   std::size_t nbOfTuple1(a1->getNumberOfTuples()),nbOfTuple2(a2->getNumberOfTuples());
5191   MCAuto<DataArrayInt> ret(DataArrayInt::New());
5192   ret->alloc(nbOfTuple1+nbOfTuple2-offsetA2,nbOfComp);
5193   int *pt=std::copy(a1->begin(),a1->end(),ret->getPointer());
5194   std::copy(a2->getConstPointer()+offsetA2*nbOfComp,a2->getConstPointer()+nbOfTuple2*nbOfComp,pt);
5195   ret->copyStringInfoFrom(*a1);
5196   return ret.retn();
5197 }
5198
5199 /*!
5200  * Returns a new DataArrayInt by concatenating all given arrays, so that (1) the number
5201  * of tuples in the result array is a sum of the number of tuples of given arrays and (2)
5202  * the number of component in the result array is same as that of each of given arrays.
5203  * Info on components is copied from the first of the given arrays. Number of components
5204  * in the given arrays must be  the same.
5205  * If the number of non null of elements in \a arr is equal to one the returned object is a copy of it
5206  * not the object itself.
5207  *  \param [in] arr - a sequence of arrays to include in the result array.
5208  *  \return DataArrayInt * - the new instance of DataArrayInt.
5209  *          The caller is to delete this result array using decrRef() as it is no more
5210  *          needed.
5211  *  \throw If all arrays within \a arr are NULL.
5212  *  \throw If getNumberOfComponents() of arrays within \a arr.
5213  */
5214 DataArrayInt *DataArrayInt::Aggregate(const std::vector<const DataArrayInt *>& arr)
5215 {
5216   std::vector<const DataArrayInt *> a;
5217   for(std::vector<const DataArrayInt *>::const_iterator it4=arr.begin();it4!=arr.end();it4++)
5218     if(*it4)
5219       a.push_back(*it4);
5220   if(a.empty())
5221     throw INTERP_KERNEL::Exception("DataArrayInt::Aggregate : input list must be NON EMPTY !");
5222   std::vector<const DataArrayInt *>::const_iterator it=a.begin();
5223   std::size_t nbOfComp((*it)->getNumberOfComponents()),nbt((*it++)->getNumberOfTuples());
5224   for(int i=1;it!=a.end();it++,i++)
5225     {
5226       if((*it)->getNumberOfComponents()!=nbOfComp)
5227         throw INTERP_KERNEL::Exception("DataArrayInt::Aggregate : Nb of components mismatch for array aggregation !");
5228       nbt+=(*it)->getNumberOfTuples();
5229     }
5230   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5231   ret->alloc(nbt,nbOfComp);
5232   int *pt=ret->getPointer();
5233   for(it=a.begin();it!=a.end();it++)
5234     pt=std::copy((*it)->getConstPointer(),(*it)->getConstPointer()+(*it)->getNbOfElems(),pt);
5235   ret->copyStringInfoFrom(*(a[0]));
5236   return ret.retn();
5237 }
5238
5239 /*!
5240  * This method takes as input a list of DataArrayInt instances \a arrs that represent each a packed index arrays.
5241  * A packed index array is an allocated array with one component, and at least one tuple. The first element
5242  * of each array in \a arrs must be 0. Each array in \a arrs is expected to be increasingly monotonic.
5243  * 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.
5244  * 
5245  * \return DataArrayInt * - a new object to be managed by the caller.
5246  */
5247 DataArrayInt *DataArrayInt::AggregateIndexes(const std::vector<const DataArrayInt *>& arrs)
5248 {
5249   int retSz=1;
5250   for(std::vector<const DataArrayInt *>::const_iterator it4=arrs.begin();it4!=arrs.end();it4++)
5251     {
5252       if(*it4)
5253         {
5254           (*it4)->checkAllocated();
5255           if((*it4)->getNumberOfComponents()!=1)
5256             {
5257               std::ostringstream oss; oss << "DataArrayInt::AggregateIndexes : presence of a DataArrayInt instance with nb of compo != 1 at pos " << std::distance(arrs.begin(),it4) << " !";
5258               throw INTERP_KERNEL::Exception(oss.str().c_str());
5259             }
5260           int nbTupl=(*it4)->getNumberOfTuples();
5261           if(nbTupl<1)
5262             {
5263               std::ostringstream oss; oss << "DataArrayInt::AggregateIndexes : presence of a DataArrayInt instance with nb of tuples < 1 at pos " << std::distance(arrs.begin(),it4) << " !";
5264               throw INTERP_KERNEL::Exception(oss.str().c_str());
5265             }
5266           if((*it4)->front()!=0)
5267             {
5268               std::ostringstream oss; oss << "DataArrayInt::AggregateIndexes : presence of a DataArrayInt instance with front value != 0 at pos " << std::distance(arrs.begin(),it4) << " !";
5269               throw INTERP_KERNEL::Exception(oss.str().c_str());
5270             }
5271           retSz+=nbTupl-1;
5272         }
5273       else
5274         {
5275           std::ostringstream oss; oss << "DataArrayInt::AggregateIndexes : presence of a null instance at pos " << std::distance(arrs.begin(),it4) << " !";
5276           throw INTERP_KERNEL::Exception(oss.str().c_str());
5277         }
5278     }
5279   if(arrs.empty())
5280     throw INTERP_KERNEL::Exception("DataArrayInt::AggregateIndexes : input list must be NON EMPTY !");
5281   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5282   ret->alloc(retSz,1);
5283   int *pt=ret->getPointer(); *pt++=0;
5284   for(std::vector<const DataArrayInt *>::const_iterator it=arrs.begin();it!=arrs.end();it++)
5285     pt=std::transform((*it)->begin()+1,(*it)->end(),pt,std::bind2nd(std::plus<int>(),pt[-1]));
5286   ret->copyStringInfoFrom(*(arrs[0]));
5287   return ret.retn();
5288 }
5289
5290 /*!
5291  * Returns in a single walk in \a this the min value and the max value in \a this.
5292  * \a this is expected to be single component array.
5293  *
5294  * \param [out] minValue - the min value in \a this.
5295  * \param [out] maxValue - the max value in \a this.
5296  *
5297  * \sa getMinValueInArray, getMinValue, getMaxValueInArray, getMaxValue
5298  */
5299 void DataArrayInt::getMinMaxValues(int& minValue, int& maxValue) const
5300 {
5301   checkAllocated();
5302   if(getNumberOfComponents()!=1)
5303     throw INTERP_KERNEL::Exception("DataArrayInt::getMinMaxValues : must be applied on DataArrayInt with only one component !");
5304   int nbTuples(getNumberOfTuples());
5305   const int *pt(begin());
5306   minValue=std::numeric_limits<int>::max(); maxValue=-std::numeric_limits<int>::max();
5307   for(int i=0;i<nbTuples;i++,pt++)
5308     {
5309       if(*pt<minValue)
5310         minValue=*pt;
5311       if(*pt>maxValue)
5312         maxValue=*pt;
5313     }
5314 }
5315
5316 /*!
5317  * Modify all elements of \a this array, so that
5318  * an element _x_ becomes \f$ numerator / x \f$.
5319  *  \warning If an exception is thrown because of presence of 0 element in \a this 
5320  *           array, all elements processed before detection of the zero element remain
5321  *           modified.
5322  *  \param [in] numerator - the numerator used to modify array elements.
5323  *  \throw If \a this is not allocated.
5324  *  \throw If there is an element equal to 0 in \a this array.
5325  */
5326 void DataArrayInt::applyInv(int numerator)
5327 {
5328   checkAllocated();
5329   int *ptr=getPointer();
5330   std::size_t nbOfElems=getNbOfElems();
5331   for(std::size_t i=0;i<nbOfElems;i++,ptr++)
5332     {
5333       if(*ptr!=0)
5334         {
5335           *ptr=numerator/(*ptr);
5336         }
5337       else
5338         {
5339           std::ostringstream oss; oss << "DataArrayInt::applyInv : presence of null value in tuple #" << i/getNumberOfComponents() << " component #" << i%getNumberOfComponents();
5340           oss << " !";
5341           throw INTERP_KERNEL::Exception(oss.str().c_str());
5342         }
5343     }
5344   declareAsNew();
5345 }
5346
5347 /*!
5348  * Modify all elements of \a this array, so that
5349  * an element _x_ becomes \f$ x / val \f$.
5350  *  \param [in] val - the denominator used to modify array elements.
5351  *  \throw If \a this is not allocated.
5352  *  \throw If \a val == 0.
5353  */
5354 void DataArrayInt::applyDivideBy(int val)
5355 {
5356   if(val==0)
5357     throw INTERP_KERNEL::Exception("DataArrayInt::applyDivideBy : Trying to divide by 0 !");
5358   checkAllocated();
5359   int *ptr=getPointer();
5360   std::size_t nbOfElems=getNbOfElems();
5361   std::transform(ptr,ptr+nbOfElems,ptr,std::bind2nd(std::divides<int>(),val));
5362   declareAsNew();
5363 }
5364
5365 /*!
5366  * Modify all elements of \a this array, so that
5367  * an element _x_ becomes  <em> x % val </em>.
5368  *  \param [in] val - the divisor used to modify array elements.
5369  *  \throw If \a this is not allocated.
5370  *  \throw If \a val <= 0.
5371  */
5372 void DataArrayInt::applyModulus(int val)
5373 {
5374   if(val<=0)
5375     throw INTERP_KERNEL::Exception("DataArrayInt::applyDivideBy : Trying to operate modulus on value <= 0 !");
5376   checkAllocated();
5377   int *ptr=getPointer();
5378   std::size_t nbOfElems=getNbOfElems();
5379   std::transform(ptr,ptr+nbOfElems,ptr,std::bind2nd(std::modulus<int>(),val));
5380   declareAsNew();
5381 }
5382
5383 /*!
5384  * This method works only on data array with one component.
5385  * This method returns a newly allocated array storing stored ascendantly tuple ids in \b this so that
5386  * this[*id] in [\b vmin,\b vmax)
5387  * 
5388  * \param [in] vmin begin of range. This value is included in range (included).
5389  * \param [in] vmax end of range. This value is \b not included in range (excluded).
5390  * \return a newly allocated data array that the caller should deal with.
5391  *
5392  * \sa DataArrayInt::findIdsNotInRange , DataArrayInt::findIdsStricltyNegative
5393  */
5394 DataArrayInt *DataArrayInt::findIdsInRange(int vmin, int vmax) const
5395 {
5396   InRange<int> ir(vmin,vmax);
5397   MCAuto<DataArrayInt> ret(findIdsAdv(ir));
5398   return ret.retn();
5399 }
5400
5401 /*!
5402  * This method works only on data array with one component.
5403  * This method returns a newly allocated array storing stored ascendantly tuple ids in \b this so that
5404  * this[*id] \b not in [\b vmin,\b vmax)
5405  * 
5406  * \param [in] vmin begin of range. This value is \b not included in range (excluded).
5407  * \param [in] vmax end of range. This value is included in range (included).
5408  * \return a newly allocated data array that the caller should deal with.
5409  * 
5410  * \sa DataArrayInt::findIdsInRange , DataArrayInt::findIdsStricltyNegative
5411  */
5412 DataArrayInt *DataArrayInt::findIdsNotInRange(int vmin, int vmax) const
5413 {
5414   NotInRange<int> nir(vmin,vmax);
5415   MCAuto<DataArrayInt> ret(findIdsAdv(nir));
5416   return ret.retn();
5417 }
5418
5419 /*!
5420  * This method works only on data array with one component.
5421  * 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.
5422  * 
5423  * \param [in] vmin begin of range. This value is included in range (included).
5424  * \param [in] vmax end of range. This value is \b not included in range (excluded).
5425  * \return if all ids in \a this are so that (*this)[i]==i for all i in [ 0, \c this->getNumberOfTuples() ). */
5426 bool DataArrayInt::checkAllIdsInRange(int vmin, int vmax) const
5427 {
5428   checkAllocated();
5429   if(getNumberOfComponents()!=1)
5430     throw INTERP_KERNEL::Exception("DataArrayInt::checkAllIdsInRange : this must have exactly one component !");
5431   int nbOfTuples=getNumberOfTuples();
5432   bool ret=true;
5433   const int *cptr=getConstPointer();
5434   for(int i=0;i<nbOfTuples;i++,cptr++)
5435     {
5436       if(*cptr>=vmin && *cptr<vmax)
5437         { ret=ret && *cptr==i; }
5438       else
5439         {
5440           std::ostringstream oss; oss << "DataArrayInt::checkAllIdsInRange : tuple #" << i << " has value " << *cptr << " should be in [" << vmin << "," << vmax << ") !";
5441           throw INTERP_KERNEL::Exception(oss.str().c_str());
5442         }
5443     }
5444   return ret;
5445 }
5446
5447 /*!
5448  * Modify all elements of \a this array, so that
5449  * an element _x_ becomes <em> val % x </em>.
5450  *  \warning If an exception is thrown because of presence of an element <= 0 in \a this 
5451  *           array, all elements processed before detection of the zero element remain
5452  *           modified.
5453  *  \param [in] val - the divident used to modify array elements.
5454  *  \throw If \a this is not allocated.
5455  *  \throw If there is an element equal to or less than 0 in \a this array.
5456  */
5457 void DataArrayInt::applyRModulus(int val)
5458 {
5459   checkAllocated();
5460   int *ptr=getPointer();
5461   std::size_t nbOfElems=getNbOfElems();
5462   for(std::size_t i=0;i<nbOfElems;i++,ptr++)
5463     {
5464       if(*ptr>0)
5465         {
5466           *ptr=val%(*ptr);
5467         }
5468       else
5469         {
5470           std::ostringstream oss; oss << "DataArrayInt::applyRModulus : presence of value <=0 in tuple #" << i/getNumberOfComponents() << " component #" << i%getNumberOfComponents();
5471           oss << " !";
5472           throw INTERP_KERNEL::Exception(oss.str().c_str());
5473         }
5474     }
5475   declareAsNew();
5476 }
5477
5478 /*!
5479  * Modify all elements of \a this array, so that
5480  * an element _x_ becomes <em> val ^ x </em>.
5481  *  \param [in] val - the value used to apply pow on all array elements.
5482  *  \throw If \a this is not allocated.
5483  *  \throw If \a val < 0.
5484  */
5485 void DataArrayInt::applyPow(int val)
5486 {
5487   checkAllocated();
5488   if(val<0)
5489     throw INTERP_KERNEL::Exception("DataArrayInt::applyPow : input pow in < 0 !");
5490   int *ptr=getPointer();
5491   std::size_t nbOfElems=getNbOfElems();
5492   if(val==0)
5493     {
5494       std::fill(ptr,ptr+nbOfElems,1);
5495       return ;
5496     }
5497   for(std::size_t i=0;i<nbOfElems;i++,ptr++)
5498     {
5499       int tmp=1;
5500       for(int j=0;j<val;j++)
5501         tmp*=*ptr;
5502       *ptr=tmp;
5503     }
5504   declareAsNew();
5505 }
5506
5507 /*!
5508  * Modify all elements of \a this array, so that
5509  * an element _x_ becomes \f$ val ^ x \f$.
5510  *  \param [in] val - the value used to apply pow on all array elements.
5511  *  \throw If \a this is not allocated.
5512  *  \throw If there is an element < 0 in \a this array.
5513  *  \warning If an exception is thrown because of presence of 0 element in \a this 
5514  *           array, all elements processed before detection of the zero element remain
5515  *           modified.
5516  */
5517 void DataArrayInt::applyRPow(int val)
5518 {
5519   checkAllocated();
5520   int *ptr=getPointer();
5521   std::size_t nbOfElems=getNbOfElems();
5522   for(std::size_t i=0;i<nbOfElems;i++,ptr++)
5523     {
5524       if(*ptr>=0)
5525         {
5526           int tmp=1;
5527           for(int j=0;j<*ptr;j++)
5528             tmp*=val;
5529           *ptr=tmp;
5530         }
5531       else
5532         {
5533           std::ostringstream oss; oss << "DataArrayInt::applyRPow : presence of negative value in tuple #" << i/getNumberOfComponents() << " component #" << i%getNumberOfComponents();
5534           oss << " !";
5535           throw INTERP_KERNEL::Exception(oss.str().c_str());
5536         }
5537     }
5538   declareAsNew();
5539 }
5540
5541 /*!
5542  * Returns a new DataArrayInt which is a minimal partition of elements of \a groups.
5543  * The i-th item of the result array is an ID of a set of elements belonging to a
5544  * unique set of groups, which the i-th element is a part of. This set of elements
5545  * belonging to a unique set of groups is called \a family, so the result array contains
5546  * IDs of families each element belongs to.
5547  *
5548  * \b Example: if we have two groups of elements: \a group1 [0,4] and \a group2 [ 0,1,2 ],
5549  * then there are 3 families:
5550  * - \a family1 (with ID 1) contains element [0] belonging to ( \a group1 + \a group2 ),
5551  * - \a family2 (with ID 2) contains elements [4] belonging to ( \a group1 ),
5552  * - \a family3 (with ID 3) contains element [1,2] belonging to ( \a group2 ), <br>
5553  * and the result array contains IDs of families [ 1,3,3,0,2 ]. <br> Note a family ID 0 which
5554  * stands for the element #3 which is in none of groups.
5555  *
5556  *  \param [in] groups - sequence of groups of element IDs.
5557  *  \param [in] newNb - total number of elements; it must be more than max ID of element
5558  *         in \a groups.
5559  *  \param [out] fidsOfGroups - IDs of families the elements of each group belong to.
5560  *  \return DataArrayInt * - a new instance of DataArrayInt containing IDs of families
5561  *         each element with ID from range [0, \a newNb ) belongs to. The caller is to
5562  *         delete this array using decrRef() as it is no more needed.
5563  *  \throw If any element ID in \a groups violates condition ( 0 <= ID < \a newNb ).
5564  */
5565 DataArrayInt *DataArrayInt::MakePartition(const std::vector<const DataArrayInt *>& groups, int newNb, std::vector< std::vector<int> >& fidsOfGroups)
5566 {
5567   std::vector<const DataArrayInt *> groups2;
5568   for(std::vector<const DataArrayInt *>::const_iterator it4=groups.begin();it4!=groups.end();it4++)
5569     if(*it4)
5570       groups2.push_back(*it4);
5571   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5572   ret->alloc(newNb,1);
5573   int *retPtr=ret->getPointer();
5574   std::fill(retPtr,retPtr+newNb,0);
5575   int fid=1;
5576   for(std::vector<const DataArrayInt *>::const_iterator iter=groups2.begin();iter!=groups2.end();iter++)
5577     {
5578       const int *ptr=(*iter)->getConstPointer();
5579       std::size_t nbOfElem=(*iter)->getNbOfElems();
5580       int sfid=fid;
5581       for(int j=0;j<sfid;j++)
5582         {
5583           bool found=false;
5584           for(std::size_t i=0;i<nbOfElem;i++)
5585             {
5586               if(ptr[i]>=0 && ptr[i]<newNb)
5587                 {
5588                   if(retPtr[ptr[i]]==j)
5589                     {
5590                       retPtr[ptr[i]]=fid;
5591                       found=true;
5592                     }
5593                 }
5594               else
5595                 {
5596                   std::ostringstream oss; oss << "DataArrayInt::MakePartition : In group \"" << (*iter)->getName() << "\" in tuple #" << i << " value = " << ptr[i] << " ! Should be in [0," << newNb;
5597                   oss << ") !";
5598                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5599                 }
5600             }
5601           if(found)
5602             fid++;
5603         }
5604     }
5605   fidsOfGroups.clear();
5606   fidsOfGroups.resize(groups2.size());
5607   int grId=0;
5608   for(std::vector<const DataArrayInt *>::const_iterator iter=groups2.begin();iter!=groups2.end();iter++,grId++)
5609     {
5610       std::set<int> tmp;
5611       const int *ptr=(*iter)->getConstPointer();
5612       std::size_t nbOfElem=(*iter)->getNbOfElems();
5613       for(const int *p=ptr;p!=ptr+nbOfElem;p++)
5614         tmp.insert(retPtr[*p]);
5615       fidsOfGroups[grId].insert(fidsOfGroups[grId].end(),tmp.begin(),tmp.end());
5616     }
5617   return ret.retn();
5618 }
5619
5620 /*!
5621  * Returns a new DataArrayInt which contains all elements of given one-dimensional
5622  * arrays. The result array does not contain any duplicates and its values
5623  * are sorted in ascending order.
5624  *  \param [in] arr - sequence of DataArrayInt's to unite.
5625  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
5626  *         array using decrRef() as it is no more needed.
5627  *  \throw If any \a arr[i] is not allocated.
5628  *  \throw If \a arr[i]->getNumberOfComponents() != 1.
5629  */
5630 DataArrayInt *DataArrayInt::BuildUnion(const std::vector<const DataArrayInt *>& arr)
5631 {
5632   std::vector<const DataArrayInt *> a;
5633   for(std::vector<const DataArrayInt *>::const_iterator it4=arr.begin();it4!=arr.end();it4++)
5634     if(*it4)
5635       a.push_back(*it4);
5636   for(std::vector<const DataArrayInt *>::const_iterator it=a.begin();it!=a.end();it++)
5637     {
5638       (*it)->checkAllocated();
5639       if((*it)->getNumberOfComponents()!=1)
5640         throw INTERP_KERNEL::Exception("DataArrayInt::BuildUnion : only single component allowed !");
5641     }
5642   //
5643   std::set<int> r;
5644   for(std::vector<const DataArrayInt *>::const_iterator it=a.begin();it!=a.end();it++)
5645     {
5646       const int *pt=(*it)->getConstPointer();
5647       int nbOfTuples=(*it)->getNumberOfTuples();
5648       r.insert(pt,pt+nbOfTuples);
5649     }
5650   DataArrayInt *ret=DataArrayInt::New();
5651   ret->alloc((int)r.size(),1);
5652   std::copy(r.begin(),r.end(),ret->getPointer());
5653   return ret;
5654 }
5655
5656 /*!
5657  * Returns a new DataArrayInt which contains elements present in each of given one-dimensional
5658  * arrays. The result array does not contain any duplicates and its values
5659  * are sorted in ascending order.
5660  *  \param [in] arr - sequence of DataArrayInt's to intersect.
5661  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
5662  *         array using decrRef() as it is no more needed.
5663  *  \throw If any \a arr[i] is not allocated.
5664  *  \throw If \a arr[i]->getNumberOfComponents() != 1.
5665  */
5666 DataArrayInt *DataArrayInt::BuildIntersection(const std::vector<const DataArrayInt *>& arr)
5667 {
5668   std::vector<const DataArrayInt *> a;
5669   for(std::vector<const DataArrayInt *>::const_iterator it4=arr.begin();it4!=arr.end();it4++)
5670     if(*it4)
5671       a.push_back(*it4);
5672   for(std::vector<const DataArrayInt *>::const_iterator it=a.begin();it!=a.end();it++)
5673     {
5674       (*it)->checkAllocated();
5675       if((*it)->getNumberOfComponents()!=1)
5676         throw INTERP_KERNEL::Exception("DataArrayInt::BuildIntersection : only single component allowed !");
5677     }
5678   //
5679   std::set<int> r;
5680   for(std::vector<const DataArrayInt *>::const_iterator it=a.begin();it!=a.end();it++)
5681     {
5682       const int *pt=(*it)->getConstPointer();
5683       int nbOfTuples=(*it)->getNumberOfTuples();
5684       std::set<int> s1(pt,pt+nbOfTuples);
5685       if(it!=a.begin())
5686         {
5687           std::set<int> r2;
5688           std::set_intersection(r.begin(),r.end(),s1.begin(),s1.end(),inserter(r2,r2.end()));
5689           r=r2;
5690         }
5691       else
5692         r=s1;
5693     }
5694   DataArrayInt *ret(DataArrayInt::New());
5695   ret->alloc((int)r.size(),1);
5696   std::copy(r.begin(),r.end(),ret->getPointer());
5697   return ret;
5698 }
5699
5700 /// @cond INTERNAL
5701 namespace MEDCouplingImpl
5702 {
5703   class OpSwitchedOn
5704   {
5705   public:
5706     OpSwitchedOn(int *pt):_pt(pt),_cnt(0) { }
5707     void operator()(const bool& b) { if(b) *_pt++=_cnt; _cnt++; }
5708   private:
5709     int *_pt;
5710     int _cnt;
5711   };
5712
5713   class OpSwitchedOff
5714   {
5715   public:
5716     OpSwitchedOff(int *pt):_pt(pt),_cnt(0) { }
5717     void operator()(const bool& b) { if(!b) *_pt++=_cnt; _cnt++; }
5718   private:
5719     int *_pt;
5720     int _cnt;
5721   };
5722 }
5723 /// @endcond
5724
5725 /*!
5726  * This method returns the list of ids in ascending mode so that v[id]==true.
5727  */
5728 DataArrayInt *DataArrayInt::BuildListOfSwitchedOn(const std::vector<bool>& v)
5729 {
5730   int sz((int)std::count(v.begin(),v.end(),true));
5731   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(sz,1);
5732   std::for_each(v.begin(),v.end(),MEDCouplingImpl::OpSwitchedOn(ret->getPointer()));
5733   return ret.retn();
5734 }
5735
5736 /*!
5737  * This method returns the list of ids in ascending mode so that v[id]==false.
5738  */
5739 DataArrayInt *DataArrayInt::BuildListOfSwitchedOff(const std::vector<bool>& v)
5740 {
5741   int sz((int)std::count(v.begin(),v.end(),false));
5742   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(sz,1);
5743   std::for_each(v.begin(),v.end(),MEDCouplingImpl::OpSwitchedOff(ret->getPointer()));
5744   return ret.retn();
5745 }
5746
5747 /*!
5748  * This method allows to put a vector of vector of integer into a more compact data structure (skyline). 
5749  * This method is not available into python because no available optimized data structure available to map std::vector< std::vector<int> >.
5750  *
5751  * \param [in] v the input data structure to be translate into skyline format.
5752  * \param [out] data the first element of the skyline format. The user is expected to deal with newly allocated array.
5753  * \param [out] dataIndex the second element of the skyline format.
5754  */
5755 void DataArrayInt::PutIntoToSkylineFrmt(const std::vector< std::vector<int> >& v, DataArrayInt *& data, DataArrayInt *& dataIndex)
5756 {
5757   int sz((int)v.size());
5758   MCAuto<DataArrayInt> ret0(DataArrayInt::New()),ret1(DataArrayInt::New());
5759   ret1->alloc(sz+1,1);
5760   int *pt(ret1->getPointer()); *pt=0;
5761   for(int i=0;i<sz;i++,pt++)
5762     pt[1]=pt[0]+(int)v[i].size();
5763   ret0->alloc(ret1->back(),1);
5764   pt=ret0->getPointer();
5765   for(int i=0;i<sz;i++)
5766     pt=std::copy(v[i].begin(),v[i].end(),pt);
5767   data=ret0.retn(); dataIndex=ret1.retn();
5768 }
5769
5770 /*!
5771  * Returns a new DataArrayInt which contains a complement of elements of \a this
5772  * one-dimensional array. I.e. the result array contains all elements from the range [0,
5773  * \a nbOfElement) not present in \a this array.
5774  *  \param [in] nbOfElement - maximal size of the result array.
5775  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
5776  *         array using decrRef() as it is no more needed.
5777  *  \throw If \a this is not allocated.
5778  *  \throw If \a this->getNumberOfComponents() != 1.
5779  *  \throw If any element \a x of \a this array violates condition ( 0 <= \a x < \a
5780  *         nbOfElement ).
5781  */
5782 DataArrayInt *DataArrayInt::buildComplement(int nbOfElement) const
5783 {
5784   checkAllocated();
5785   if(getNumberOfComponents()!=1)
5786     throw INTERP_KERNEL::Exception("DataArrayInt::buildComplement : only single component allowed !");
5787   std::vector<bool> tmp(nbOfElement);
5788   const int *pt=getConstPointer();
5789   int nbOfTuples=getNumberOfTuples();
5790   for(const int *w=pt;w!=pt+nbOfTuples;w++)
5791     if(*w>=0 && *w<nbOfElement)
5792       tmp[*w]=true;
5793     else
5794       throw INTERP_KERNEL::Exception("DataArrayInt::buildComplement : an element is not in valid range : [0,nbOfElement) !");
5795   int nbOfRetVal=(int)std::count(tmp.begin(),tmp.end(),false);
5796   DataArrayInt *ret=DataArrayInt::New();
5797   ret->alloc(nbOfRetVal,1);
5798   int j=0;
5799   int *retPtr=ret->getPointer();
5800   for(int i=0;i<nbOfElement;i++)
5801     if(!tmp[i])
5802       retPtr[j++]=i;
5803   return ret;
5804 }
5805
5806 /*!
5807  * Returns a new DataArrayInt containing elements of \a this one-dimensional missing
5808  * from an \a other one-dimensional array.
5809  *  \param [in] other - a DataArrayInt containing elements not to include in the result array.
5810  *  \return DataArrayInt * - a new instance of DataArrayInt with one component. The
5811  *         caller is to delete this array using decrRef() as it is no more needed.
5812  *  \throw If \a other is NULL.
5813  *  \throw If \a other is not allocated.
5814  *  \throw If \a other->getNumberOfComponents() != 1.
5815  *  \throw If \a this is not allocated.
5816  *  \throw If \a this->getNumberOfComponents() != 1.
5817  *  \sa DataArrayInt::buildSubstractionOptimized()
5818  */
5819 DataArrayInt *DataArrayInt::buildSubstraction(const DataArrayInt *other) const
5820 {
5821   if(!other)
5822     throw INTERP_KERNEL::Exception("DataArrayInt::buildSubstraction : DataArrayInt pointer in input is NULL !");
5823   checkAllocated();
5824   other->checkAllocated();
5825   if(getNumberOfComponents()!=1)
5826     throw INTERP_KERNEL::Exception("DataArrayInt::buildSubstraction : only single component allowed !");
5827   if(other->getNumberOfComponents()!=1)
5828     throw INTERP_KERNEL::Exception("DataArrayInt::buildSubstraction : only single component allowed for other type !");
5829   const int *pt=getConstPointer();
5830   int nbOfTuples=getNumberOfTuples();
5831   std::set<int> s1(pt,pt+nbOfTuples);
5832   pt=other->getConstPointer();
5833   nbOfTuples=other->getNumberOfTuples();
5834   std::set<int> s2(pt,pt+nbOfTuples);
5835   std::vector<int> r;
5836   std::set_difference(s1.begin(),s1.end(),s2.begin(),s2.end(),std::back_insert_iterator< std::vector<int> >(r));
5837   DataArrayInt *ret=DataArrayInt::New();
5838   ret->alloc((int)r.size(),1);
5839   std::copy(r.begin(),r.end(),ret->getPointer());
5840   return ret;
5841 }
5842
5843 /*!
5844  * \a this is expected to have one component and to be sorted ascendingly (as for \a other).
5845  * \a other is expected to be a part of \a this. If not DataArrayInt::buildSubstraction should be called instead.
5846  * 
5847  * \param [in] other an array with one component and expected to be sorted ascendingly.
5848  * \ret list of ids in \a this but not in \a other.
5849  * \sa DataArrayInt::buildSubstraction
5850  */
5851 DataArrayInt *DataArrayInt::buildSubstractionOptimized(const DataArrayInt *other) const
5852 {
5853   static const char *MSG="DataArrayInt::buildSubstractionOptimized : only single component allowed !";
5854   if(!other) throw INTERP_KERNEL::Exception("DataArrayInt::buildSubstractionOptimized : NULL input array !");
5855   checkAllocated(); other->checkAllocated();
5856   if(getNumberOfComponents()!=1) throw INTERP_KERNEL::Exception(MSG);
5857   if(other->getNumberOfComponents()!=1) throw INTERP_KERNEL::Exception(MSG);
5858   const int *pt1Bg(begin()),*pt1End(end()),*pt2Bg(other->begin()),*pt2End(other->end());
5859   const int *work1(pt1Bg),*work2(pt2Bg);
5860   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
5861   for(;work1!=pt1End;work1++)
5862     {
5863       if(work2!=pt2End && *work1==*work2)
5864         work2++;
5865       else
5866         ret->pushBackSilent(*work1);
5867     }
5868   return ret.retn();
5869 }
5870
5871
5872 /*!
5873  * Returns a new DataArrayInt which contains all elements of \a this and a given
5874  * one-dimensional arrays. The result array does not contain any duplicates
5875  * and its values are sorted in ascending order.
5876  *  \param [in] other - an array to unite with \a this one.
5877  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
5878  *         array using decrRef() as it is no more needed.
5879  *  \throw If \a this or \a other is not allocated.
5880  *  \throw If \a this->getNumberOfComponents() != 1.
5881  *  \throw If \a other->getNumberOfComponents() != 1.
5882  */
5883 DataArrayInt *DataArrayInt::buildUnion(const DataArrayInt *other) const
5884 {
5885   std::vector<const DataArrayInt *>arrs(2);
5886   arrs[0]=this; arrs[1]=other;
5887   return BuildUnion(arrs);
5888 }
5889
5890
5891 /*!
5892  * Returns a new DataArrayInt which contains elements present in both \a this and a given
5893  * one-dimensional arrays. The result array does not contain any duplicates
5894  * and its values are sorted in ascending order.
5895  *  \param [in] other - an array to intersect with \a this one.
5896  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
5897  *         array using decrRef() as it is no more needed.
5898  *  \throw If \a this or \a other is not allocated.
5899  *  \throw If \a this->getNumberOfComponents() != 1.
5900  *  \throw If \a other->getNumberOfComponents() != 1.
5901  */
5902 DataArrayInt *DataArrayInt::buildIntersection(const DataArrayInt *other) const
5903 {
5904   std::vector<const DataArrayInt *>arrs(2);
5905   arrs[0]=this; arrs[1]=other;
5906   return BuildIntersection(arrs);
5907 }
5908
5909 /*!
5910  * This method can be applied on allocated with one component DataArrayInt instance.
5911  * This method is typically relevant for sorted arrays. All consecutive duplicated items in \a this will appear only once in returned DataArrayInt instance.
5912  * 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]
5913  * 
5914  * \return a newly allocated array that contain the result of the unique operation applied on \a this.
5915  * \throw if \a this is not allocated or if \a this has not exactly one component.
5916  * \sa DataArrayInt::buildUniqueNotSorted
5917  */
5918 DataArrayInt *DataArrayInt::buildUnique() const
5919 {
5920   checkAllocated();
5921   if(getNumberOfComponents()!=1)
5922     throw INTERP_KERNEL::Exception("DataArrayInt::buildUnique : only single component allowed !");
5923   int nbOfTuples=getNumberOfTuples();
5924   MCAuto<DataArrayInt> tmp=deepCopy();
5925   int *data=tmp->getPointer();
5926   int *last=std::unique(data,data+nbOfTuples);
5927   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5928   ret->alloc(std::distance(data,last),1);
5929   std::copy(data,last,ret->getPointer());
5930   return ret.retn();
5931 }
5932
5933 /*!
5934  * This method can be applied on allocated with one component DataArrayInt instance.
5935  * This method keep elements only once by keeping the same order in \a this that is not expected to be sorted.
5936  *
5937  * \return a newly allocated array that contain the result of the unique operation applied on \a this.
5938  *
5939  * \throw if \a this is not allocated or if \a this has not exactly one component.
5940  *
5941  * \sa DataArrayInt::buildUnique
5942  */
5943 DataArrayInt *DataArrayInt::buildUniqueNotSorted() const
5944 {
5945   checkAllocated();
5946     if(getNumberOfComponents()!=1)
5947       throw INTERP_KERNEL::Exception("DataArrayInt::buildUniqueNotSorted : only single component allowed !");
5948   int minVal,maxVal;
5949   getMinMaxValues(minVal,maxVal);
5950   std::vector<bool> b(maxVal-minVal+1,false);
5951   const int *ptBg(begin()),*endBg(end());
5952   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
5953   for(const int *pt=ptBg;pt!=endBg;pt++)
5954     {
5955       if(!b[*pt-minVal])
5956         {
5957           ret->pushBackSilent(*pt);
5958           b[*pt-minVal]=true;
5959         }
5960     }
5961   ret->copyStringInfoFrom(*this);
5962   return ret.retn();
5963 }
5964
5965 /*!
5966  * Returns a new DataArrayInt which contains size of every of groups described by \a this
5967  * "index" array. Such "index" array is returned for example by 
5968  * \ref MEDCoupling::MEDCouplingUMesh::buildDescendingConnectivity
5969  * "MEDCouplingUMesh::buildDescendingConnectivity" and
5970  * \ref MEDCoupling::MEDCouplingUMesh::getNodalConnectivityIndex
5971  * "MEDCouplingUMesh::getNodalConnectivityIndex" etc.
5972  * This method performs the reverse operation of DataArrayInt::computeOffsetsFull.
5973  *  \return DataArrayInt * - a new instance of DataArrayInt, whose number of tuples
5974  *          equals to \a this->getNumberOfComponents() - 1, and number of components is 1.
5975  *          The caller is to delete this array using decrRef() as it is no more needed. 
5976  *  \throw If \a this is not allocated.
5977  *  \throw If \a this->getNumberOfComponents() != 1.
5978  *  \throw If \a this->getNumberOfTuples() < 2.
5979  *
5980  *  \b Example: <br> 
5981  *         - this contains [1,3,6,7,7,9,15]
5982  *         - result array contains [2,3,1,0,2,6],
5983  *          where 2 = 3 - 1, 3 = 6 - 3, 1 = 7 - 6 etc.
5984  *
5985  * \sa DataArrayInt::computeOffsetsFull
5986  */
5987 DataArrayInt *DataArrayInt::deltaShiftIndex() const
5988 {
5989   checkAllocated();
5990   if(getNumberOfComponents()!=1)
5991     throw INTERP_KERNEL::Exception("DataArrayInt::deltaShiftIndex : only single component allowed !");
5992   int nbOfTuples=getNumberOfTuples();
5993   if(nbOfTuples<2)
5994     throw INTERP_KERNEL::Exception("DataArrayInt::deltaShiftIndex : 1 tuple at least must be present in 'this' !");
5995   const int *ptr=getConstPointer();
5996   DataArrayInt *ret=DataArrayInt::New();
5997   ret->alloc(nbOfTuples-1,1);
5998   int *out=ret->getPointer();
5999   std::transform(ptr+1,ptr+nbOfTuples,ptr,out,std::minus<int>());
6000   return ret;
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 of tuples
6007  * and components remains the same.<br>
6008  * This method is useful for allToAllV in MPI with contiguous policy. This method
6009  * differs from computeOffsetsFull() in that the number of tuples is \b not changed by
6010  * this one.
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]<br>
6017  *          Note that the last element 19 = 11 + 8 is missing because size of \a this
6018  *          array is retained and thus there is no space to store the last element.
6019  */
6020 void DataArrayInt::computeOffsets()
6021 {
6022   checkAllocated();
6023   if(getNumberOfComponents()!=1)
6024     throw INTERP_KERNEL::Exception("DataArrayInt::computeOffsets : only single component allowed !");
6025   int nbOfTuples=getNumberOfTuples();
6026   if(nbOfTuples==0)
6027     return ;
6028   int *work=getPointer();
6029   int tmp=work[0];
6030   work[0]=0;
6031   for(int i=1;i<nbOfTuples;i++)
6032     {
6033       int tmp2=work[i];
6034       work[i]=work[i-1]+tmp;
6035       tmp=tmp2;
6036     }
6037   declareAsNew();
6038 }
6039
6040
6041 /*!
6042  * Modifies \a this one-dimensional array so that value of each element \a x
6043  * of \a this array (\a a) is computed as \f$ x_i = \sum_{j=0}^{i-1} a[ j ] \f$.
6044  * Or: for each i>0 new[i]=new[i-1]+old[i-1] for i==0 new[i]=0. Number
6045  * components remains the same and number of tuples is inceamented by one.<br>
6046  * This method is useful for allToAllV in MPI with contiguous policy. This method
6047  * differs from computeOffsets() in that the number of tuples is changed by this one.
6048  * This method performs the reverse operation of DataArrayInt::deltaShiftIndex.
6049  *  \throw If \a this is not allocated.
6050  *  \throw If \a this->getNumberOfComponents() != 1.
6051  *
6052  *  \b Example: <br>
6053  *          - Before \a this contains [3,5,1,2,0,8]
6054  *          - After \a this contains  [0,3,8,9,11,11,19]<br>
6055  * \sa DataArrayInt::deltaShiftIndex
6056  */
6057 void DataArrayInt::computeOffsetsFull()
6058 {
6059   checkAllocated();
6060   if(getNumberOfComponents()!=1)
6061     throw INTERP_KERNEL::Exception("DataArrayInt::computeOffsetsFull : only single component allowed !");
6062   int nbOfTuples=getNumberOfTuples();
6063   int *ret=(int *)malloc((nbOfTuples+1)*sizeof(int));
6064   const int *work=getConstPointer();
6065   ret[0]=0;
6066   for(int i=0;i<nbOfTuples;i++)
6067     ret[i+1]=work[i]+ret[i];
6068   useArray(ret,true,C_DEALLOC,nbOfTuples+1,1);
6069   declareAsNew();
6070 }
6071
6072 /*!
6073  * Returns two new DataArrayInt instances whose contents is computed from that of \a this and \a listOfIds arrays as follows.
6074  * \a this is expected to be an offset format ( as returned by DataArrayInt::computeOffsetsFull ) that is to say with one component
6075  * and ** sorted strictly increasingly **. \a listOfIds is expected to be sorted ascendingly (not strictly needed for \a listOfIds).
6076  * This methods searches in \a this, considered as a set of contiguous \c this->getNumberOfComponents() ranges, all ids in \a listOfIds
6077  * filling completely one of the ranges in \a this.
6078  *
6079  * \param [in] listOfIds a list of ids that has to be sorted ascendingly.
6080  * \param [out] rangeIdsFetched the range ids fetched
6081  * \param [out] idsInInputListThatFetch contains the list of ids in \a listOfIds that are \b fully included in a range in \a this. So
6082  *              \a idsInInputListThatFetch is a part of input \a listOfIds.
6083  *
6084  * \sa DataArrayInt::computeOffsetsFull
6085  *
6086  *  \b Example: <br>
6087  *          - \a this : [0,3,7,9,15,18]
6088  *          - \a listOfIds contains  [0,1,2,3,7,8,15,16,17]
6089  *          - \a rangeIdsFetched result array: [0,2,4]
6090  *          - \a idsInInputListThatFetch result array: [0,1,2,7,8,15,16,17]
6091  * In this example id 3 in input \a listOfIds is alone so it do not appear in output \a idsInInputListThatFetch.
6092  * <br>
6093  */
6094 void DataArrayInt::findIdsRangesInListOfIds(const DataArrayInt *listOfIds, DataArrayInt *& rangeIdsFetched, DataArrayInt *& idsInInputListThatFetch) const
6095 {
6096   if(!listOfIds)
6097     throw INTERP_KERNEL::Exception("DataArrayInt::findIdsRangesInListOfIds : input list of ids is null !");
6098   listOfIds->checkAllocated(); checkAllocated();
6099   if(listOfIds->getNumberOfComponents()!=1)
6100     throw INTERP_KERNEL::Exception("DataArrayInt::findIdsRangesInListOfIds : input list of ids must have exactly one component !");
6101   if(getNumberOfComponents()!=1)
6102     throw INTERP_KERNEL::Exception("DataArrayInt::findIdsRangesInListOfIds : this must have exactly one component !");
6103   MCAuto<DataArrayInt> ret0=DataArrayInt::New(); ret0->alloc(0,1);
6104   MCAuto<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(0,1);
6105   const int *tupEnd(listOfIds->end()),*offBg(begin()),*offEnd(end()-1);
6106   const int *tupPtr(listOfIds->begin()),*offPtr(offBg);
6107   while(tupPtr!=tupEnd && offPtr!=offEnd)
6108     {
6109       if(*tupPtr==*offPtr)
6110         {
6111           int i=offPtr[0];
6112           while(i<offPtr[1] && *tupPtr==i && tupPtr!=tupEnd) { i++; tupPtr++; }
6113           if(i==offPtr[1])
6114             {
6115               ret0->pushBackSilent((int)std::distance(offBg,offPtr));
6116               ret1->pushBackValsSilent(tupPtr-(offPtr[1]-offPtr[0]),tupPtr);
6117               offPtr++;
6118             }
6119         }
6120       else
6121         { if(*tupPtr<*offPtr) tupPtr++; else offPtr++; }
6122     }
6123   rangeIdsFetched=ret0.retn();
6124   idsInInputListThatFetch=ret1.retn();
6125 }
6126
6127 /*!
6128  * Returns a new DataArrayInt whose contents is computed from that of \a this and \a
6129  * offsets arrays as follows. \a offsets is a one-dimensional array considered as an
6130  * "index" array of a "iota" array, thus, whose each element gives an index of a group
6131  * beginning within the "iota" array. And \a this is a one-dimensional array
6132  * considered as a selector of groups described by \a offsets to include into the result array.
6133  *  \throw If \a offsets is NULL.
6134  *  \throw If \a offsets is not allocated.
6135  *  \throw If \a offsets->getNumberOfComponents() != 1.
6136  *  \throw If \a offsets is not monotonically increasing.
6137  *  \throw If \a this is not allocated.
6138  *  \throw If \a this->getNumberOfComponents() != 1.
6139  *  \throw If any element of \a this is not a valid index for \a offsets array.
6140  *
6141  *  \b Example: <br>
6142  *          - \a this: [0,2,3]
6143  *          - \a offsets: [0,3,6,10,14,20]
6144  *          - result array: [0,1,2,6,7,8,9,10,11,12,13] == <br>
6145  *            \c range(0,3) + \c range(6,10) + \c range(10,14) ==<br>
6146  *            \c range( \a offsets[ \a this[0] ], offsets[ \a this[0]+1 ]) + 
6147  *            \c range( \a offsets[ \a this[1] ], offsets[ \a this[1]+1 ]) + 
6148  *            \c range( \a offsets[ \a this[2] ], offsets[ \a this[2]+1 ])
6149  */
6150 DataArrayInt *DataArrayInt::buildExplicitArrByRanges(const DataArrayInt *offsets) const
6151 {
6152   if(!offsets)
6153     throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrByRanges : DataArrayInt pointer in input is NULL !");
6154   checkAllocated();
6155   if(getNumberOfComponents()!=1)
6156     throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrByRanges : only single component allowed !");
6157   offsets->checkAllocated();
6158   if(offsets->getNumberOfComponents()!=1)
6159     throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrByRanges : input array should have only single component !");
6160   int othNbTuples=offsets->getNumberOfTuples()-1;
6161   int nbOfTuples=getNumberOfTuples();
6162   int retNbOftuples=0;
6163   const int *work=getConstPointer();
6164   const int *offPtr=offsets->getConstPointer();
6165   for(int i=0;i<nbOfTuples;i++)
6166     {
6167       int val=work[i];
6168       if(val>=0 && val<othNbTuples)
6169         {
6170           int delta=offPtr[val+1]-offPtr[val];
6171           if(delta>=0)
6172             retNbOftuples+=delta;
6173           else
6174             {
6175               std::ostringstream oss; oss << "DataArrayInt::buildExplicitArrByRanges : Tuple #" << val << " of offset array has a delta < 0 !";
6176               throw INTERP_KERNEL::Exception(oss.str().c_str());
6177             }
6178         }
6179       else
6180         {
6181           std::ostringstream oss; oss << "DataArrayInt::buildExplicitArrByRanges : Tuple #" << i << " in this contains " << val;
6182           oss << " whereas offsets array is of size " << othNbTuples+1 << " !";
6183           throw INTERP_KERNEL::Exception(oss.str().c_str());
6184         }
6185     }
6186   MCAuto<DataArrayInt> ret=DataArrayInt::New();
6187   ret->alloc(retNbOftuples,1);
6188   int *retPtr=ret->getPointer();
6189   for(int i=0;i<nbOfTuples;i++)
6190     {
6191       int val=work[i];
6192       int start=offPtr[val];
6193       int off=offPtr[val+1]-start;
6194       for(int j=0;j<off;j++,retPtr++)
6195         *retPtr=start+j;
6196     }
6197   return ret.retn();
6198 }
6199
6200 /*!
6201  * Returns a new DataArrayInt whose contents is computed using \a this that must be a 
6202  * scaled array (monotonically increasing).
6203 from that of \a this and \a
6204  * offsets arrays as follows. \a offsets is a one-dimensional array considered as an
6205  * "index" array of a "iota" array, thus, whose each element gives an index of a group
6206  * beginning within the "iota" array. And \a this is a one-dimensional array
6207  * considered as a selector of groups described by \a offsets to include into the result array.
6208  *  \throw If \a  is NULL.
6209  *  \throw If \a this is not allocated.
6210  *  \throw If \a this->getNumberOfComponents() != 1.
6211  *  \throw If \a this->getNumberOfTuples() == 0.
6212  *  \throw If \a this is not monotonically increasing.
6213  *  \throw If any element of ids in ( \a bg \a stop \a step ) points outside the scale in \a this.
6214  *
6215  *  \b Example: <br>
6216  *          - \a bg , \a stop and \a step : (0,5,2)
6217  *          - \a this: [0,3,6,10,14,20]
6218  *          - result array: [0,0,0, 2,2,2,2, 4,4,4,4,4,4] == <br>
6219  */
6220 DataArrayInt *DataArrayInt::buildExplicitArrOfSliceOnScaledArr(int bg, int stop, int step) const
6221 {
6222   if(!isAllocated())
6223     throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrOfSliceOnScaledArr : not allocated array !");
6224   if(getNumberOfComponents()!=1)
6225     throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrOfSliceOnScaledArr : number of components is expected to be equal to one !");
6226   int nbOfTuples(getNumberOfTuples());
6227   if(nbOfTuples==0)
6228     throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrOfSliceOnScaledArr : number of tuples must be != 0 !");
6229   const int *ids(begin());
6230   int nbOfEltsInSlc(GetNumberOfItemGivenBESRelative(bg,stop,step,"DataArrayInt::buildExplicitArrOfSliceOnScaledArr")),sz(0),pos(bg);
6231   for(int i=0;i<nbOfEltsInSlc;i++,pos+=step)
6232     {
6233       if(pos>=0 && pos<nbOfTuples-1)
6234         {
6235           int delta(ids[pos+1]-ids[pos]);
6236           sz+=delta;
6237           if(delta<0)
6238             {
6239               std::ostringstream oss; oss << "DataArrayInt::buildExplicitArrOfSliceOnScaledArr : At pos #" << i << " of input slice, value is " << pos << " and at this pos this is not monotonically increasing !";
6240               throw INTERP_KERNEL::Exception(oss.str().c_str());
6241             }          
6242         }
6243       else
6244         {
6245           std::ostringstream oss; oss << "DataArrayInt::buildExplicitArrOfSliceOnScaledArr : At pos #" << i << " of input slice, value is " << pos << " should be in [0," << nbOfTuples-1 << ") !";  
6246           throw INTERP_KERNEL::Exception(oss.str().c_str());
6247         }
6248     }
6249   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(sz,1);
6250   int *retPtr(ret->getPointer());
6251   pos=bg;
6252   for(int i=0;i<nbOfEltsInSlc;i++,pos+=step)
6253     {
6254       int delta(ids[pos+1]-ids[pos]);
6255       for(int j=0;j<delta;j++,retPtr++)
6256         *retPtr=pos;
6257     }
6258   return ret.retn();
6259 }
6260
6261 /*!
6262  * 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.
6263  * 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
6264  * in tuple **i** of returned DataArrayInt.
6265  * If ranges overlapped (in theory it should not) this method do not detect it and always returns the first range.
6266  *
6267  * 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)]
6268  * The return DataArrayInt will contain : **[0,4,1,2,2,3]**
6269  * 
6270  * \param [in] ranges typically come from output of MEDCouplingUMesh::ComputeRangesFromTypeDistribution. Each range is specified like this : 1st component is
6271  *             for lower value included and 2nd component is the upper value of corresponding range **excluded**.
6272  * \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
6273  *        is thrown if no ranges in \a ranges contains value in \a this.
6274  * 
6275  * \sa DataArrayInt::findIdInRangeForEachTuple
6276  */
6277 DataArrayInt *DataArrayInt::findRangeIdForEachTuple(const DataArrayInt *ranges) const
6278 {
6279   if(!ranges)
6280     throw INTERP_KERNEL::Exception("DataArrayInt::findRangeIdForEachTuple : null input pointer !");
6281   if(ranges->getNumberOfComponents()!=2)
6282     throw INTERP_KERNEL::Exception("DataArrayInt::findRangeIdForEachTuple : input DataArrayInt instance should have 2 components !");
6283   checkAllocated();
6284   if(getNumberOfComponents()!=1)
6285     throw INTERP_KERNEL::Exception("DataArrayInt::findRangeIdForEachTuple : this should have only one component !");
6286   int nbTuples=getNumberOfTuples();
6287   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbTuples,1);
6288   int nbOfRanges=ranges->getNumberOfTuples();
6289   const int *rangesPtr=ranges->getConstPointer();
6290   int *retPtr=ret->getPointer();
6291   const int *inPtr=getConstPointer();
6292   for(int i=0;i<nbTuples;i++,retPtr++)
6293     {
6294       int val=inPtr[i];
6295       bool found=false;
6296       for(int j=0;j<nbOfRanges && !found;j++)
6297         if(val>=rangesPtr[2*j] && val<rangesPtr[2*j+1])
6298           { *retPtr=j; found=true; }
6299       if(found)
6300         continue;
6301       else
6302         {
6303           std::ostringstream oss; oss << "DataArrayInt::findRangeIdForEachTuple : tuple #" << i << " not found by any ranges !";
6304           throw INTERP_KERNEL::Exception(oss.str().c_str());
6305         }
6306     }
6307   return ret.retn();
6308 }
6309
6310 /*!
6311  * 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.
6312  * 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
6313  * in tuple **i** of returned DataArrayInt.
6314  * If ranges overlapped (in theory it should not) this method do not detect it and always returns the sub position of the first range.
6315  *
6316  * 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)]
6317  * The return DataArrayInt will contain : **[1,2,4,0,2,2]**
6318  * This method is often called in pair with DataArrayInt::findRangeIdForEachTuple method.
6319  * 
6320  * \param [in] ranges typically come from output of MEDCouplingUMesh::ComputeRangesFromTypeDistribution. Each range is specified like this : 1st component is
6321  *             for lower value included and 2nd component is the upper value of corresponding range **excluded**.
6322  * \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
6323  *        is thrown if no ranges in \a ranges contains value in \a this.
6324  * \sa DataArrayInt::findRangeIdForEachTuple
6325  */
6326 DataArrayInt *DataArrayInt::findIdInRangeForEachTuple(const DataArrayInt *ranges) const
6327 {
6328   if(!ranges)
6329     throw INTERP_KERNEL::Exception("DataArrayInt::findIdInRangeForEachTuple : null input pointer !");
6330   if(ranges->getNumberOfComponents()!=2)
6331     throw INTERP_KERNEL::Exception("DataArrayInt::findIdInRangeForEachTuple : input DataArrayInt instance should have 2 components !");
6332   checkAllocated();
6333   if(getNumberOfComponents()!=1)
6334     throw INTERP_KERNEL::Exception("DataArrayInt::findIdInRangeForEachTuple : this should have only one component !");
6335   int nbTuples=getNumberOfTuples();
6336   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbTuples,1);
6337   int nbOfRanges=ranges->getNumberOfTuples();
6338   const int *rangesPtr=ranges->getConstPointer();
6339   int *retPtr=ret->getPointer();
6340   const int *inPtr=getConstPointer();
6341   for(int i=0;i<nbTuples;i++,retPtr++)
6342     {
6343       int val=inPtr[i];
6344       bool found=false;
6345       for(int j=0;j<nbOfRanges && !found;j++)
6346         if(val>=rangesPtr[2*j] && val<rangesPtr[2*j+1])
6347           { *retPtr=val-rangesPtr[2*j]; found=true; }
6348       if(found)
6349         continue;
6350       else
6351         {
6352           std::ostringstream oss; oss << "DataArrayInt::findIdInRangeForEachTuple : tuple #" << i << " not found by any ranges !";
6353           throw INTERP_KERNEL::Exception(oss.str().c_str());
6354         }
6355     }
6356   return ret.retn();
6357 }
6358
6359 /*!
6360  * \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).
6361  * 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).
6362  * 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 !
6363  * If this method has correctly worked, \a this will be able to be considered as a linked list.
6364  * This method does nothing if number of tuples is lower of equal to 1.
6365  *
6366  * This method is useful for users having an unstructured mesh having only SEG2 to rearrange internally the connectibity without any coordinates consideration.
6367  *
6368  * \sa MEDCouplingUMesh::orderConsecutiveCells1D, DataArrayInt::fromLinkedListOfPairToList
6369  */
6370 void DataArrayInt::sortEachPairToMakeALinkedList()
6371 {
6372   checkAllocated();
6373   if(getNumberOfComponents()!=2)
6374     throw INTERP_KERNEL::Exception("DataArrayInt::sortEachPairToMakeALinkedList : Only works on DataArrayInt instance with nb of components equal to 2 !");
6375   int nbOfTuples(getNumberOfTuples());
6376   if(nbOfTuples<=1)
6377     return ;
6378   int *conn(getPointer());
6379   for(int i=1;i<nbOfTuples;i++,conn+=2)
6380     {
6381       if(i>1)
6382         {
6383           if(conn[2]==conn[3])
6384             {
6385               std::ostringstream oss; oss << "DataArrayInt::sortEachPairToMakeALinkedList : In the tuple #" << i << " presence of a pair filled with same ids !";
6386               throw INTERP_KERNEL::Exception(oss.str().c_str());
6387             }
6388           if(conn[2]!=conn[1] && conn[3]==conn[1] && conn[2]!=conn[0])
6389             std::swap(conn[2],conn[3]);
6390           //not(conn[2]==conn[1] && conn[3]!=conn[1] && conn[3]!=conn[0])
6391           if(conn[2]!=conn[1] || conn[3]==conn[1] || conn[3]==conn[0])
6392             {
6393               std::ostringstream oss; oss << "DataArrayInt::sortEachPairToMakeALinkedList : In the tuple #" << i << " something is invalid !";
6394               throw INTERP_KERNEL::Exception(oss.str().c_str());
6395             }
6396         }
6397       else
6398         {
6399           if(conn[0]==conn[1] || conn[2]==conn[3])
6400             throw INTERP_KERNEL::Exception("DataArrayInt::sortEachPairToMakeALinkedList : In the 2 first tuples presence of a pair filled with same ids !");
6401           int tmp[4];
6402           std::set<int> s;
6403           s.insert(conn,conn+4);
6404           if(s.size()!=3)
6405             throw INTERP_KERNEL::Exception("DataArrayInt::sortEachPairToMakeALinkedList : This can't be considered as a linked list regarding 2 first tuples !");
6406           if(std::count(conn,conn+4,conn[0])==2)
6407             {
6408               tmp[0]=conn[1];
6409               tmp[1]=conn[0];
6410               tmp[2]=conn[0];
6411               if(conn[2]==conn[0])
6412                 { tmp[3]=conn[3]; }
6413               else
6414                 { tmp[3]=conn[2];}
6415               std::copy(tmp,tmp+4,conn);
6416             }
6417           else
6418             {//here we are sure to have (std::count(conn,conn+4,conn[1])==2)
6419               if(conn[1]==conn[3])
6420                 std::swap(conn[2],conn[3]);
6421             }
6422         }
6423     }
6424 }
6425
6426 /*!
6427  * \a this is expected to be a correctly linked list of pairs.
6428  * 
6429  * \sa DataArrayInt::sortEachPairToMakeALinkedList
6430  */
6431 MCAuto<DataArrayInt> DataArrayInt::fromLinkedListOfPairToList() const
6432 {
6433   checkAllocated();
6434   checkNbOfComps(2,"DataArrayInt::fromLinkedListOfPairToList : this is expected to have 2 components");
6435   int nbTuples(getNumberOfTuples());
6436   if(nbTuples<1)
6437     throw INTERP_KERNEL::Exception("DataArrayInt::fromLinkedListOfPairToList : no tuples in this ! Not a linked list !");
6438   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbTuples+1,1);
6439   const int *thisPtr(begin());
6440   int *retPtr(ret->getPointer());
6441   retPtr[0]=thisPtr[0];
6442   for(int i=0;i<nbTuples;i++)
6443     {
6444       retPtr[i+1]=thisPtr[2*i+1];
6445       if(i<nbTuples-1)
6446         if(thisPtr[2*i+1]!=thisPtr[2*(i+1)+0])
6447           {
6448             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 ?";
6449             throw INTERP_KERNEL::Exception(oss.str());
6450           }
6451     }
6452   return ret;
6453 }
6454
6455 /*!
6456  * This method returns all different values found in \a this. This method throws if \a this has not been allocated.
6457  * But the number of components can be different from one.
6458  * \return a newly allocated array (that should be dealt by the caller) containing different values in \a this.
6459  */
6460 DataArrayInt *DataArrayInt::getDifferentValues() const
6461 {
6462   checkAllocated();
6463   std::set<int> ret;
6464   ret.insert(begin(),end());
6465   MCAuto<DataArrayInt> ret2=DataArrayInt::New(); ret2->alloc((int)ret.size(),1);
6466   std::copy(ret.begin(),ret.end(),ret2->getPointer());
6467   return ret2.retn();
6468 }
6469
6470 /*!
6471  * This method is a refinement of DataArrayInt::getDifferentValues because it returns not only different values in \a this but also, for each of
6472  * them it tells which tuple id have this id.
6473  * This method works only on arrays with one component (if it is not the case call DataArrayInt::rearrange(1) ).
6474  * This method returns two arrays having same size.
6475  * 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.
6476  * 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]]
6477  */
6478 std::vector<DataArrayInt *> DataArrayInt::partitionByDifferentValues(std::vector<int>& differentIds) const
6479 {
6480   checkAllocated();
6481   if(getNumberOfComponents()!=1)
6482     throw INTERP_KERNEL::Exception("DataArrayInt::partitionByDifferentValues : this should have only one component !");
6483   int id=0;
6484   std::map<int,int> m,m2,m3;
6485   for(const int *w=begin();w!=end();w++)
6486     m[*w]++;
6487   differentIds.resize(m.size());
6488   std::vector<DataArrayInt *> ret(m.size());
6489   std::vector<int *> retPtr(m.size());
6490   for(std::map<int,int>::const_iterator it=m.begin();it!=m.end();it++,id++)
6491     {
6492       m2[(*it).first]=id;
6493       ret[id]=DataArrayInt::New();
6494       ret[id]->alloc((*it).second,1);
6495       retPtr[id]=ret[id]->getPointer();
6496       differentIds[id]=(*it).first;
6497     }
6498   id=0;
6499   for(const int *w=begin();w!=end();w++,id++)
6500     {
6501       retPtr[m2[*w]][m3[*w]++]=id;
6502     }
6503   return ret;
6504 }
6505
6506 /*!
6507  * This method split ids in [0, \c this->getNumberOfTuples() ) using \a this array as a field of weight (>=0 each).
6508  * The aim of this method is to return a set of \a nbOfSlices chunk of contiguous ids as balanced as possible.
6509  *
6510  * \param [in] nbOfSlices - number of slices expected.
6511  * \return - a vector having a size equal to \a nbOfSlices giving the start (included) and the stop (excluded) of each chunks.
6512  * 
6513  * \sa DataArray::GetSlice
6514  * \throw If \a this is not allocated or not with exactly one component.
6515  * \throw If an element in \a this if < 0.
6516  */
6517 std::vector< std::pair<int,int> > DataArrayInt::splitInBalancedSlices(int nbOfSlices) const
6518 {
6519   if(!isAllocated() || getNumberOfComponents()!=1)
6520     throw INTERP_KERNEL::Exception("DataArrayInt::splitInBalancedSlices : this array should have number of components equal to one and must be allocated !");
6521   if(nbOfSlices<=0)
6522     throw INTERP_KERNEL::Exception("DataArrayInt::splitInBalancedSlices : number of slices must be >= 1 !");
6523   int sum(accumulate(0)),nbOfTuples(getNumberOfTuples());
6524   int sumPerSlc(sum/nbOfSlices),pos(0);
6525   const int *w(begin());
6526   std::vector< std::pair<int,int> > ret(nbOfSlices);
6527   for(int i=0;i<nbOfSlices;i++)
6528     {
6529       std::pair<int,int> p(pos,-1);
6530       int locSum(0);
6531       while(locSum<sumPerSlc && pos<nbOfTuples) { pos++; locSum+=*w++; }
6532       if(i!=nbOfSlices-1)
6533         p.second=pos;
6534       else
6535         p.second=nbOfTuples;
6536       ret[i]=p;
6537     }
6538   return ret;
6539 }
6540
6541 /*!
6542  * Returns a new DataArrayInt that is a modulus of two given arrays. There are 3
6543  * valid cases.
6544  * 1.  The arrays have same number of tuples and components. Then each value of
6545  *   the result array (_a_) is a division of the corresponding values of \a a1 and
6546  *   \a a2, i.e.: _a_ [ i, j ] = _a1_ [ i, j ] % _a2_ [ i, j ].
6547  * 2.  The arrays have same number of tuples and one array, say _a2_, has one
6548  *   component. Then
6549  *   _a_ [ i, j ] = _a1_ [ i, j ] % _a2_ [ i, 0 ].
6550  * 3.  The arrays have same number of components and one array, say _a2_, has one
6551  *   tuple. Then
6552  *   _a_ [ i, j ] = _a1_ [ i, j ] % _a2_ [ 0, j ].
6553  *
6554  * Info on components is copied either from the first array (in the first case) or from
6555  * the array with maximal number of elements (getNbOfElems()).
6556  *  \warning No check of division by zero is performed!
6557  *  \param [in] a1 - a dividend array.
6558  *  \param [in] a2 - a divisor array.
6559  *  \return DataArrayInt * - the new instance of DataArrayInt.
6560  *          The caller is to delete this result array using decrRef() as it is no more
6561  *          needed.
6562  *  \throw If either \a a1 or \a a2 is NULL.
6563  *  \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples() and
6564  *         \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents() and
6565  *         none of them has number of tuples or components equal to 1.
6566  */
6567 DataArrayInt *DataArrayInt::Modulus(const DataArrayInt *a1, const DataArrayInt *a2)
6568 {
6569   if(!a1 || !a2)
6570     throw INTERP_KERNEL::Exception("DataArrayInt::Modulus : input DataArrayInt instance is NULL !");
6571   int nbOfTuple1=a1->getNumberOfTuples();
6572   int nbOfTuple2=a2->getNumberOfTuples();
6573   int nbOfComp1=a1->getNumberOfComponents();
6574   int nbOfComp2=a2->getNumberOfComponents();
6575   if(nbOfTuple2==nbOfTuple1)
6576     {
6577       if(nbOfComp1==nbOfComp2)
6578         {
6579           MCAuto<DataArrayInt> ret=DataArrayInt::New();
6580           ret->alloc(nbOfTuple2,nbOfComp1);
6581           std::transform(a1->begin(),a1->end(),a2->begin(),ret->getPointer(),std::modulus<int>());
6582           ret->copyStringInfoFrom(*a1);
6583           return ret.retn();
6584         }
6585       else if(nbOfComp2==1)
6586         {
6587           MCAuto<DataArrayInt> ret=DataArrayInt::New();
6588           ret->alloc(nbOfTuple1,nbOfComp1);
6589           const int *a2Ptr=a2->getConstPointer();
6590           const int *a1Ptr=a1->getConstPointer();
6591           int *res=ret->getPointer();
6592           for(int i=0;i<nbOfTuple1;i++)
6593             res=std::transform(a1Ptr+i*nbOfComp1,a1Ptr+(i+1)*nbOfComp1,res,std::bind2nd(std::modulus<int>(),a2Ptr[i]));
6594           ret->copyStringInfoFrom(*a1);
6595           return ret.retn();
6596         }
6597       else
6598         {
6599           a1->checkNbOfComps(nbOfComp2,"Nb of components mismatch for array Modulus !");
6600           return 0;
6601         }
6602     }
6603   else if(nbOfTuple2==1)
6604     {
6605       a1->checkNbOfComps(nbOfComp2,"Nb of components mismatch for array Modulus !");
6606       MCAuto<DataArrayInt> ret=DataArrayInt::New();
6607       ret->alloc(nbOfTuple1,nbOfComp1);
6608       const int *a1ptr=a1->getConstPointer(),*a2ptr=a2->getConstPointer();
6609       int *pt=ret->getPointer();
6610       for(int i=0;i<nbOfTuple1;i++)
6611         pt=std::transform(a1ptr+i*nbOfComp1,a1ptr+(i+1)*nbOfComp1,a2ptr,pt,std::modulus<int>());
6612       ret->copyStringInfoFrom(*a1);
6613       return ret.retn();
6614     }
6615   else
6616     {
6617       a1->checkNbOfTuples(nbOfTuple2,"Nb of tuples mismatch for array Modulus !");//will always throw an exception
6618       return 0;
6619     }
6620 }
6621
6622 /*!
6623  * Modify \a this array so that each value becomes a modulus of division of this value by
6624  * a value of another DataArrayInt. There are 3 valid cases.
6625  * 1.  The arrays have same number of tuples and components. Then each value of
6626  *    \a this array is divided by the corresponding value of \a other one, i.e.:
6627  *   _a_ [ i, j ] %= _other_ [ i, j ].
6628  * 2.  The arrays have same number of tuples and \a other array has one component. Then
6629  *   _a_ [ i, j ] %= _other_ [ i, 0 ].
6630  * 3.  The arrays have same number of components and \a other array has one tuple. Then
6631  *   _a_ [ i, j ] %= _a2_ [ 0, j ].
6632  *
6633  *  \warning No check of division by zero is performed!
6634  *  \param [in] other - a divisor array.
6635  *  \throw If \a other is NULL.
6636  *  \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples() and
6637  *         \a this->getNumberOfComponents() != \a other->getNumberOfComponents() and
6638  *         \a other has number of both tuples and components not equal to 1.
6639  */
6640 void DataArrayInt::modulusEqual(const DataArrayInt *other)
6641 {
6642   if(!other)
6643     throw INTERP_KERNEL::Exception("DataArrayInt::modulusEqual : input DataArrayInt instance is NULL !");
6644   const char *msg="Nb of tuples mismatch for DataArrayInt::modulusEqual !";
6645   checkAllocated(); other->checkAllocated();
6646   int nbOfTuple=getNumberOfTuples();
6647   int nbOfTuple2=other->getNumberOfTuples();
6648   int nbOfComp=getNumberOfComponents();
6649   int nbOfComp2=other->getNumberOfComponents();
6650   if(nbOfTuple==nbOfTuple2)
6651     {
6652       if(nbOfComp==nbOfComp2)
6653         {
6654           std::transform(begin(),end(),other->begin(),getPointer(),std::modulus<int>());
6655         }
6656       else if(nbOfComp2==1)
6657         {
6658           if(nbOfComp2==nbOfComp)
6659             {
6660               int *ptr=getPointer();
6661               const int *ptrc=other->getConstPointer();
6662               for(int i=0;i<nbOfTuple;i++)
6663                 std::transform(ptr+i*nbOfComp,ptr+(i+1)*nbOfComp,ptr+i*nbOfComp,std::bind2nd(std::modulus<int>(),*ptrc++));
6664             }
6665           else
6666             throw INTERP_KERNEL::Exception(msg);
6667         }
6668       else
6669         throw INTERP_KERNEL::Exception(msg);
6670     }
6671   else if(nbOfTuple2==1)
6672     {
6673       int *ptr=getPointer();
6674       const int *ptrc=other->getConstPointer();
6675       for(int i=0;i<nbOfTuple;i++)
6676         std::transform(ptr+i*nbOfComp,ptr+(i+1)*nbOfComp,ptrc,ptr+i*nbOfComp,std::modulus<int>());
6677     }
6678   else
6679     throw INTERP_KERNEL::Exception(msg);
6680   declareAsNew();
6681 }
6682
6683 /*!
6684  * Returns a new DataArrayInt that is the result of pow of two given arrays. There are 3
6685  * valid cases.
6686  *
6687  *  \param [in] a1 - an array to pow up.
6688  *  \param [in] a2 - another array to sum up.
6689  *  \return DataArrayInt * - the new instance of DataArrayInt.
6690  *          The caller is to delete this result array using decrRef() as it is no more
6691  *          needed.
6692  *  \throw If either \a a1 or \a a2 is NULL.
6693  *  \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples()
6694  *  \throw If \a a1->getNumberOfComponents() != 1 or \a a2->getNumberOfComponents() != 1.
6695  *  \throw If there is a negative value in \a a2.
6696  */
6697 DataArrayInt *DataArrayInt::Pow(const DataArrayInt *a1, const DataArrayInt *a2)
6698 {
6699   if(!a1 || !a2)
6700     throw INTERP_KERNEL::Exception("DataArrayInt::Pow : at least one of input instances is null !");
6701   int nbOfTuple=a1->getNumberOfTuples();
6702   int nbOfTuple2=a2->getNumberOfTuples();
6703   int nbOfComp=a1->getNumberOfComponents();
6704   int nbOfComp2=a2->getNumberOfComponents();
6705   if(nbOfTuple!=nbOfTuple2)
6706     throw INTERP_KERNEL::Exception("DataArrayInt::Pow : number of tuples mismatches !");
6707   if(nbOfComp!=1 || nbOfComp2!=1)
6708     throw INTERP_KERNEL::Exception("DataArrayInt::Pow : number of components of both arrays must be equal to 1 !");
6709   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfTuple,1);
6710   const int *ptr1(a1->begin()),*ptr2(a2->begin());
6711   int *ptr=ret->getPointer();
6712   for(int i=0;i<nbOfTuple;i++,ptr1++,ptr2++,ptr++)
6713     {
6714       if(*ptr2>=0)
6715         {
6716           int tmp=1;
6717           for(int j=0;j<*ptr2;j++)
6718             tmp*=*ptr1;
6719           *ptr=tmp;
6720         }
6721       else
6722         {
6723           std::ostringstream oss; oss << "DataArrayInt::Pow : on tuple #" << i << " of a2 value is < 0 (" << *ptr2 << ") !";
6724           throw INTERP_KERNEL::Exception(oss.str().c_str());
6725         }
6726     }
6727   return ret.retn();
6728 }
6729
6730 /*!
6731  * Apply pow on values of another DataArrayInt to values of \a this one.
6732  *
6733  *  \param [in] other - an array to pow to \a this one.
6734  *  \throw If \a other is NULL.
6735  *  \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples()
6736  *  \throw If \a this->getNumberOfComponents() != 1 or \a other->getNumberOfComponents() != 1
6737  *  \throw If there is a negative value in \a other.
6738  */
6739 void DataArrayInt::powEqual(const DataArrayInt *other)
6740 {
6741   if(!other)
6742     throw INTERP_KERNEL::Exception("DataArrayInt::powEqual : input instance is null !");
6743   int nbOfTuple=getNumberOfTuples();
6744   int nbOfTuple2=other->getNumberOfTuples();
6745   int nbOfComp=getNumberOfComponents();
6746   int nbOfComp2=other->getNumberOfComponents();
6747   if(nbOfTuple!=nbOfTuple2)
6748     throw INTERP_KERNEL::Exception("DataArrayInt::powEqual : number of tuples mismatches !");
6749   if(nbOfComp!=1 || nbOfComp2!=1)
6750     throw INTERP_KERNEL::Exception("DataArrayInt::powEqual : number of components of both arrays must be equal to 1 !");
6751   int *ptr=getPointer();
6752   const int *ptrc=other->begin();
6753   for(int i=0;i<nbOfTuple;i++,ptrc++,ptr++)
6754     {
6755       if(*ptrc>=0)
6756         {
6757           int tmp=1;
6758           for(int j=0;j<*ptrc;j++)
6759             tmp*=*ptr;
6760           *ptr=tmp;
6761         }
6762       else
6763         {
6764           std::ostringstream oss; oss << "DataArrayInt::powEqual : on tuple #" << i << " of other value is < 0 (" << *ptrc << ") !";
6765           throw INTERP_KERNEL::Exception(oss.str().c_str());
6766         }
6767     }
6768   declareAsNew();
6769 }
6770
6771 /*!
6772  * Returns a C array which is a renumbering map in "Old to New" mode for the input array.
6773  * This map, if applied to \a start array, would make it sorted. For example, if
6774  * \a start array contents are [9,10,0,6,4,11,3,7] then the contents of the result array is
6775  * [5,6,0,3,2,7,1,4].
6776  *  \param [in] start - pointer to the first element of the array for which the
6777  *         permutation map is computed.
6778  *  \param [in] end - pointer specifying the end of the array \a start, so that
6779  *         the last value of \a start is \a end[ -1 ].
6780  *  \return int * - the result permutation array that the caller is to delete as it is no
6781  *         more needed.
6782  *  \throw If there are equal values in the input array.
6783  */
6784 int *DataArrayInt::CheckAndPreparePermutation(const int *start, const int *end)
6785 {
6786   std::size_t sz=std::distance(start,end);
6787   int *ret=(int *)malloc(sz*sizeof(int));
6788   int *work=new int[sz];
6789   std::copy(start,end,work);
6790   std::sort(work,work+sz);
6791   if(std::unique(work,work+sz)!=work+sz)
6792     {
6793       delete [] work;
6794       free(ret);
6795       throw INTERP_KERNEL::Exception("Some elements are equals in the specified array !");
6796     }
6797   std::map<int,int> m;
6798   for(int *workPt=work;workPt!=work+sz;workPt++)
6799     m[*workPt]=(int)std::distance(work,workPt);
6800   int *iter2=ret;
6801   for(const int *iter=start;iter!=end;iter++,iter2++)
6802     *iter2=m[*iter];
6803   delete [] work;
6804   return ret;
6805 }
6806
6807 /*!
6808  * Returns a new DataArrayInt containing an arithmetic progression
6809  * that is equal to the sequence returned by Python \c range(\a begin,\a  end,\a  step )
6810  * function.
6811  *  \param [in] begin - the start value of the result sequence.
6812  *  \param [in] end - limiting value, so that every value of the result array is less than
6813  *              \a end.
6814  *  \param [in] step - specifies the increment or decrement.
6815  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
6816  *          array using decrRef() as it is no more needed.
6817  *  \throw If \a step == 0.
6818  *  \throw If \a end < \a begin && \a step > 0.
6819  *  \throw If \a end > \a begin && \a step < 0.
6820  */
6821 DataArrayInt *DataArrayInt::Range(int begin, int end, int step)
6822 {
6823   int nbOfTuples=GetNumberOfItemGivenBESRelative(begin,end,step,"DataArrayInt::Range");
6824   MCAuto<DataArrayInt> ret=DataArrayInt::New();
6825   ret->alloc(nbOfTuples,1);
6826   int *ptr=ret->getPointer();
6827   if(step>0)
6828     {
6829       for(int i=begin;i<end;i+=step,ptr++)
6830         *ptr=i;
6831     }
6832   else
6833     {
6834       for(int i=begin;i>end;i+=step,ptr++)
6835         *ptr=i;
6836     }
6837   return ret.retn();
6838 }
6839
6840 /*!
6841  * Useless method for end user. Only for MPI/Corba/File serialsation for multi arrays class.
6842  * Server side.
6843  */
6844 void DataArrayInt::getTinySerializationIntInformation(std::vector<int>& tinyInfo) const
6845 {
6846   tinyInfo.resize(2);
6847   if(isAllocated())
6848     {
6849       tinyInfo[0]=getNumberOfTuples();
6850       tinyInfo[1]=getNumberOfComponents();
6851     }
6852   else
6853     {
6854       tinyInfo[0]=-1;
6855       tinyInfo[1]=-1;
6856     }
6857 }
6858
6859 /*!
6860  * Useless method for end user. Only for MPI/Corba/File serialsation for multi arrays class.
6861  * Server side.
6862  */
6863 void DataArrayInt::getTinySerializationStrInformation(std::vector<std::string>& tinyInfo) const
6864 {
6865   if(isAllocated())
6866     {
6867       int nbOfCompo=getNumberOfComponents();
6868       tinyInfo.resize(nbOfCompo+1);
6869       tinyInfo[0]=getName();
6870       for(int i=0;i<nbOfCompo;i++)
6871         tinyInfo[i+1]=getInfoOnComponent(i);
6872     }
6873   else
6874     {
6875       tinyInfo.resize(1);
6876       tinyInfo[0]=getName();
6877     }
6878 }
6879
6880 /*!
6881  * Useless method for end user. Only for MPI/Corba/File serialsation for multi arrays class.
6882  * This method returns if a feeding is needed.
6883  */
6884 bool DataArrayInt::resizeForUnserialization(const std::vector<int>& tinyInfoI)
6885 {
6886   int nbOfTuple=tinyInfoI[0];
6887   int nbOfComp=tinyInfoI[1];
6888   if(nbOfTuple!=-1 || nbOfComp!=-1)
6889     {
6890       alloc(nbOfTuple,nbOfComp);
6891       return true;
6892     }
6893   return false;
6894 }
6895
6896 /*!
6897  * Useless method for end user. Only for MPI/Corba/File serialsation for multi arrays class.
6898  * This method returns if a feeding is needed.
6899  */
6900 void DataArrayInt::finishUnserialization(const std::vector<int>& tinyInfoI, const std::vector<std::string>& tinyInfoS)
6901 {
6902   setName(tinyInfoS[0]);
6903   if(isAllocated())
6904     {
6905       int nbOfCompo=tinyInfoI[1];
6906       for(int i=0;i<nbOfCompo;i++)
6907         setInfoOnComponent(i,tinyInfoS[i+1]);
6908     }
6909 }
6910
6911 DataArrayIntIterator::DataArrayIntIterator(DataArrayInt *da):DataArrayIterator<int>(da)
6912 {
6913 }
6914
6915 DataArrayInt32Tuple::DataArrayInt32Tuple(int *pt, int nbOfComp):DataArrayTuple<int>(pt,nbOfComp)
6916 {
6917 }
6918
6919 std::string DataArrayIntTuple::repr() const
6920 {
6921   std::ostringstream oss; oss << "(";
6922   for(int i=0;i<_nb_of_compo-1;i++)
6923     oss << _pt[i] << ", ";
6924   oss << _pt[_nb_of_compo-1] << ")";
6925   return oss.str();
6926 }
6927
6928 int DataArrayIntTuple::intValue() const
6929 {
6930   return this->zeValue();
6931 }
6932
6933 /*!
6934  * This method returns a newly allocated instance the caller should dealed with by a MEDCoupling::DataArrayInt::decrRef.
6935  * This method performs \b no copy of data. The content is only referenced using MEDCoupling::DataArrayInt::useArray with ownership set to \b false.
6936  * 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
6937  * \b nbOfCompo=1 and \bnbOfTuples==this->_nb_of_elem.
6938  */
6939 DataArrayInt *DataArrayIntTuple::buildDAInt(int nbOfTuples, int nbOfCompo) const
6940 {
6941   return this->buildDA(nbOfTuples,nbOfCompo);
6942 }