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