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