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