Salome HOME
211e39df79c8e5501b445cb6c54ebf1cb2f0089c
[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  * Creates a new one-dimensional DataArrayInt of the same size as \a this and a given
4486  * one-dimensional arrays that must be of the same length. The result array describes
4487  * correspondence between \a this and \a other arrays, so that 
4488  * <em> other.getIJ(i,0) == this->getIJ(ret->getIJ(i),0)</em>. If such a permutation is
4489  * not possible because some element in \a other is not in \a this, an exception is thrown.
4490  *  \param [in] other - an array to compute permutation to.
4491  *  \return DataArrayInt * - a new instance of DataArrayInt, which is a permutation array
4492  * from \a this to \a other. The caller is to delete this array using decrRef() as it is
4493  * no more needed.
4494  *  \throw If \a this->getNumberOfComponents() != 1.
4495  *  \throw If \a other->getNumberOfComponents() != 1.
4496  *  \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples().
4497  *  \throw If \a other includes a value which is not in \a this array.
4498  * 
4499  *  \if ENABLE_EXAMPLES
4500  *  \ref cpp_mcdataarrayint_buildpermutationarr "Here is a C++ example".
4501  *
4502  *  \ref py_mcdataarrayint_buildpermutationarr "Here is a Python example".
4503  *  \endif
4504  */
4505 DataArrayInt *DataArrayInt::buildPermutationArr(const DataArrayInt& other) const
4506 {
4507   checkAllocated();
4508   if(getNumberOfComponents()!=1 || other.getNumberOfComponents()!=1)
4509     throw INTERP_KERNEL::Exception("DataArrayInt::buildPermutationArr : 'this' and 'other' have to have exactly ONE component !");
4510   int nbTuple=getNumberOfTuples();
4511   other.checkAllocated();
4512   if(nbTuple!=other.getNumberOfTuples())
4513     throw INTERP_KERNEL::Exception("DataArrayInt::buildPermutationArr : 'this' and 'other' must have the same number of tuple !");
4514   MCAuto<DataArrayInt> ret=DataArrayInt::New();
4515   ret->alloc(nbTuple,1);
4516   ret->fillWithValue(-1);
4517   const int *pt=getConstPointer();
4518   std::map<int,int> mm;
4519   for(int i=0;i<nbTuple;i++)
4520     mm[pt[i]]=i;
4521   pt=other.getConstPointer();
4522   int *retToFill=ret->getPointer();
4523   for(int i=0;i<nbTuple;i++)
4524     {
4525       std::map<int,int>::const_iterator it=mm.find(pt[i]);
4526       if(it==mm.end())
4527         {
4528           std::ostringstream oss; oss << "DataArrayInt::buildPermutationArr : Arrays mismatch : element (" << pt[i] << ") in 'other' not findable in 'this' !";
4529           throw INTERP_KERNEL::Exception(oss.str().c_str());
4530         }
4531       retToFill[i]=(*it).second;
4532     }
4533   return ret.retn();
4534 }
4535
4536 /*!
4537  * Elements of \a partOfThis are expected to be included in \a this.
4538  * The returned array \a ret is so that this[ret]==partOfThis
4539  *
4540  * 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]
4541  * the return array will contain [3,2,5,7].
4542  *
4543  * \a this is expected to be a 1 compo allocated array.
4544  * \param [in] partOfThis - A 1 compo allocated array
4545  * \return - A newly allocated array to be dealed by caller having the same number of tuples than \a partOfThis.
4546  * \throw if two same element is present twice in \a this
4547  * \throw if an element in \a partOfThis is \b NOT in \a this.
4548  */
4549 DataArrayInt *DataArrayInt::indicesOfSubPart(const DataArrayInt& partOfThis) const
4550 {
4551   if(getNumberOfComponents()!=1 || partOfThis.getNumberOfComponents()!=1)
4552     throw INTERP_KERNEL::Exception("DataArrayInt::indicesOfSubPart : this and input array must be one component array !");
4553   checkAllocated(); partOfThis.checkAllocated();
4554   int thisNbTuples(getNumberOfTuples()),nbTuples(partOfThis.getNumberOfTuples());
4555   const int *thisPt(begin()),*pt(partOfThis.begin());
4556   MCAuto<DataArrayInt> ret(DataArrayInt::New());
4557   ret->alloc(nbTuples,1);
4558   int *retPt(ret->getPointer());
4559   std::map<int,int> m;
4560   for(int i=0;i<thisNbTuples;i++,thisPt++)
4561     m[*thisPt]=i;
4562   if(m.size()!=thisNbTuples)
4563     throw INTERP_KERNEL::Exception("DataArrayInt::indicesOfSubPart : some elements appears more than once !");
4564   for(int i=0;i<nbTuples;i++,retPt++,pt++)
4565     {
4566       std::map<int,int>::const_iterator it(m.find(*pt));
4567       if(it!=m.end())
4568         *retPt=(*it).second;
4569       else
4570         {
4571           std::ostringstream oss; oss << "DataArrayInt::indicesOfSubPart : At pos #" << i << " of input array value is " << *pt << " not in this !";
4572           throw INTERP_KERNEL::Exception(oss.str());
4573         }
4574     }
4575   return ret.retn();
4576 }
4577
4578 /*!
4579  * Returns a new DataArrayInt containing a renumbering map in "Old to New" mode.
4580  * This map, if applied to \a this array, would make it sorted. For example, if
4581  * \a this array contents are [9,10,0,6,4,11,3,7] then the contents of the result array
4582  * are [5,6,0,3,2,7,1,4]; if this result array (\a res) is used as an argument in call
4583  * \a this->renumber(\a res) then the returned array contains [0,3,4,6,7,9,10,11].
4584  * This method is useful for renumbering (in MED file for example). For more info
4585  * on renumbering see \ref numbering.
4586  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
4587  *          array using decrRef() as it is no more needed.
4588  *  \throw If \a this is not allocated.
4589  *  \throw If \a this->getNumberOfComponents() != 1.
4590  *  \throw If there are equal values in \a this array.
4591  */
4592 DataArrayInt *DataArrayInt::checkAndPreparePermutation() const
4593 {
4594   checkAllocated();
4595   if(getNumberOfComponents()!=1)
4596     throw INTERP_KERNEL::Exception("DataArrayInt::checkAndPreparePermutation : number of components must == 1 !");
4597   int nbTuples=getNumberOfTuples();
4598   const int *pt=getConstPointer();
4599   int *pt2=CheckAndPreparePermutation(pt,pt+nbTuples);
4600   DataArrayInt *ret=DataArrayInt::New();
4601   ret->useArray(pt2,true,C_DEALLOC,nbTuples,1);
4602   return ret;
4603 }
4604
4605 /*!
4606  * 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
4607  * input array \a ids2.
4608  * \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.
4609  * 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
4610  * inversely.
4611  * In case of success (no throw) : \c ids1->renumber(ret)->isEqual(ids2) where \a ret is the return of this method.
4612  *
4613  * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
4614  *          array using decrRef() as it is no more needed.
4615  * \throw If either ids1 or ids2 is null not allocated or not with one components.
4616  * 
4617  */
4618 DataArrayInt *DataArrayInt::FindPermutationFromFirstToSecond(const DataArrayInt *ids1, const DataArrayInt *ids2)
4619 {
4620   if(!ids1 || !ids2)
4621     throw INTERP_KERNEL::Exception("DataArrayInt::FindPermutationFromFirstToSecond : the two input arrays must be not null !");
4622   if(!ids1->isAllocated() || !ids2->isAllocated())
4623     throw INTERP_KERNEL::Exception("DataArrayInt::FindPermutationFromFirstToSecond : the two input arrays must be allocated !");
4624   if(ids1->getNumberOfComponents()!=1 || ids2->getNumberOfComponents()!=1)
4625     throw INTERP_KERNEL::Exception("DataArrayInt::FindPermutationFromFirstToSecond : the two input arrays have exactly one component !");
4626   if(ids1->getNumberOfTuples()!=ids2->getNumberOfTuples())
4627     {
4628       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 !";
4629       throw INTERP_KERNEL::Exception(oss.str().c_str());
4630     }
4631   MCAuto<DataArrayInt> p1(ids1->deepCopy());
4632   MCAuto<DataArrayInt> p2(ids2->deepCopy());
4633   p1->sort(true); p2->sort(true);
4634   if(!p1->isEqualWithoutConsideringStr(*p2))
4635     throw INTERP_KERNEL::Exception("DataArrayInt::FindPermutationFromFirstToSecond : the two arrays are not lying on same ids ! Impossible to find a permutation between the 2 arrays !");
4636   p1=ids1->checkAndPreparePermutation();
4637   p2=ids2->checkAndPreparePermutation();
4638   p2=p2->invertArrayO2N2N2O(p2->getNumberOfTuples());
4639   p2=p2->selectByTupleIdSafe(p1->begin(),p1->end());
4640   return p2.retn();
4641 }
4642
4643 /*!
4644  * Returns two arrays describing a surjective mapping from \a this set of values (\a A)
4645  * onto a set of values of size \a targetNb (\a B). The surjective function is 
4646  * \a B[ \a A[ i ]] = i. That is to say that for each \a id in [0,\a targetNb), where \a
4647  * targetNb < \a this->getNumberOfTuples(), there exists at least one tupleId (\a tid) so
4648  * that <em> this->getIJ( tid, 0 ) == id</em>. <br>
4649  * The first of out arrays returns indices of elements of \a this array, grouped by their
4650  * place in the set \a B. The second out array is the index of the first one; it shows how
4651  * many elements of \a A are mapped into each element of \a B. <br>
4652  * For more info on
4653  * mapping and its usage in renumbering see \ref numbering. <br>
4654  * \b Example:
4655  * - \a this: [0,3,2,3,2,2,1,2]
4656  * - \a targetNb: 4
4657  * - \a arr:  [0,  6,  2,4,5,7,  1,3]
4658  * - \a arrI: [0,1,2,6,8]
4659  *
4660  * This result means: <br>
4661  * the element of \a B 0 encounters within \a A once (\a arrI[ 0+1 ] - \a arrI[ 0 ]) and
4662  * its index within \a A is 0 ( \a arr[ 0:1 ] == \a arr[ \a arrI[ 0 ] : \a arrI[ 0+1 ]]);<br>
4663  * the element of \a B 2 encounters within \a A 4 times (\a arrI[ 2+1 ] - \a arrI[ 2 ]) and
4664  * its indices within \a A are [2,4,5,7] ( \a arr[ 2:6 ] == \a arr[ \a arrI[ 2 ] : 
4665  * \a arrI[ 2+1 ]]); <br> etc.
4666  *  \param [in] targetNb - the size of the set \a B. \a targetNb must be equal or more
4667  *         than the maximal value of \a A.
4668  *  \param [out] arr - a new instance of DataArrayInt returning indices of
4669  *         elements of \a this, grouped by their place in the set \a B. The caller is to delete
4670  *         this array using decrRef() as it is no more needed.
4671  *  \param [out] arrI - a new instance of DataArrayInt returning size of groups of equal
4672  *         elements of \a this. The caller is to delete this array using decrRef() as it
4673  *         is no more needed.
4674  *  \throw If \a this is not allocated.
4675  *  \throw If \a this->getNumberOfComponents() != 1.
4676  *  \throw If any value in \a this is more or equal to \a targetNb.
4677  */
4678 void DataArrayInt::changeSurjectiveFormat(int targetNb, DataArrayInt *&arr, DataArrayInt *&arrI) const
4679 {
4680   checkAllocated();
4681   if(getNumberOfComponents()!=1)
4682     throw INTERP_KERNEL::Exception("DataArrayInt::changeSurjectiveFormat : number of components must == 1 !");
4683   int nbOfTuples=getNumberOfTuples();
4684   MCAuto<DataArrayInt> ret(DataArrayInt::New());
4685   MCAuto<DataArrayInt> retI(DataArrayInt::New());
4686   retI->alloc(targetNb+1,1);
4687   const int *input=getConstPointer();
4688   std::vector< std::vector<int> > tmp(targetNb);
4689   for(int i=0;i<nbOfTuples;i++)
4690     {
4691       int tmp2=input[i];
4692       if(tmp2>=0 && tmp2<targetNb)
4693         tmp[tmp2].push_back(i);
4694       else
4695         {
4696           std::ostringstream oss; oss << "DataArrayInt::changeSurjectiveFormat : At pos " << i << " presence of element " << tmp2 << " ! should be in [0," << targetNb << ") !";
4697           throw INTERP_KERNEL::Exception(oss.str().c_str());
4698         }
4699     }
4700   int *retIPtr=retI->getPointer();
4701   *retIPtr=0;
4702   for(std::vector< std::vector<int> >::const_iterator it1=tmp.begin();it1!=tmp.end();it1++,retIPtr++)
4703     retIPtr[1]=retIPtr[0]+(int)((*it1).size());
4704   if(nbOfTuples!=retI->getIJ(targetNb,0))
4705     throw INTERP_KERNEL::Exception("DataArrayInt::changeSurjectiveFormat : big problem should never happen !");
4706   ret->alloc(nbOfTuples,1);
4707   int *retPtr=ret->getPointer();
4708   for(std::vector< std::vector<int> >::const_iterator it1=tmp.begin();it1!=tmp.end();it1++)
4709     retPtr=std::copy((*it1).begin(),(*it1).end(),retPtr);
4710   arr=ret.retn();
4711   arrI=retI.retn();
4712 }
4713
4714
4715 /*!
4716  * Returns a new DataArrayInt containing a renumbering map in "Old to New" mode computed
4717  * from a zip representation of a surjective format (returned e.g. by
4718  * \ref MEDCoupling::DataArrayDouble::findCommonTuples() "DataArrayDouble::findCommonTuples()"
4719  * for example). The result array minimizes the permutation. <br>
4720  * For more info on renumbering see \ref numbering. <br>
4721  * \b Example: <br>
4722  * - \a nbOfOldTuples: 10 
4723  * - \a arr          : [0,3, 5,7,9]
4724  * - \a arrIBg       : [0,2,5]
4725  * - \a newNbOfTuples: 7
4726  * - result array    : [0,1,2,0,3,4,5,4,6,4]
4727  *
4728  *  \param [in] nbOfOldTuples - number of tuples in the initial array \a arr.
4729  *  \param [in] arr - the array of tuple indices grouped by \a arrIBg array.
4730  *  \param [in] arrIBg - the array dividing all indices stored in \a arr into groups of
4731  *         (indices of) equal values. Its every element (except the last one) points to
4732  *         the first element of a group of equal values.
4733  *  \param [in] arrIEnd - specifies the end of \a arrIBg, so that the last element of \a
4734  *          arrIBg is \a arrIEnd[ -1 ].
4735  *  \param [out] newNbOfTuples - number of tuples after surjection application.
4736  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
4737  *          array using decrRef() as it is no more needed.
4738  *  \throw If any value of \a arr breaks condition ( 0 <= \a arr[ i ] < \a nbOfOldTuples ).
4739  */
4740 DataArrayInt *DataArrayInt::ConvertIndexArrayToO2N(int nbOfOldTuples, const int *arr, const int *arrIBg, const int *arrIEnd, int &newNbOfTuples)
4741 {
4742   MCAuto<DataArrayInt> ret=DataArrayInt::New();
4743   ret->alloc(nbOfOldTuples,1);
4744   int *pt=ret->getPointer();
4745   std::fill(pt,pt+nbOfOldTuples,-1);
4746   int nbOfGrps=((int)std::distance(arrIBg,arrIEnd))-1;
4747   const int *cIPtr=arrIBg;
4748   for(int i=0;i<nbOfGrps;i++)
4749     pt[arr[cIPtr[i]]]=-(i+2);
4750   int newNb=0;
4751   for(int iNode=0;iNode<nbOfOldTuples;iNode++)
4752     {
4753       if(pt[iNode]<0)
4754         {
4755           if(pt[iNode]==-1)
4756             pt[iNode]=newNb++;
4757           else
4758             {
4759               int grpId=-(pt[iNode]+2);
4760               for(int j=cIPtr[grpId];j<cIPtr[grpId+1];j++)
4761                 {
4762                   if(arr[j]>=0 && arr[j]<nbOfOldTuples)
4763                     pt[arr[j]]=newNb;
4764                   else
4765                     {
4766                       std::ostringstream oss; oss << "DataArrayInt::ConvertIndexArrayToO2N : With element #" << j << " value is " << arr[j] << " should be in [0," << nbOfOldTuples << ") !";
4767                       throw INTERP_KERNEL::Exception(oss.str().c_str());
4768                     }
4769                 }
4770               newNb++;
4771             }
4772         }
4773     }
4774   newNbOfTuples=newNb;
4775   return ret.retn();
4776 }
4777
4778 /*!
4779  * Returns a new DataArrayInt containing a renumbering map in "New to Old" mode,
4780  * which if applied to \a this array would make it sorted ascendingly.
4781  * For more info on renumbering see \ref numbering. <br>
4782  * \b Example: <br>
4783  * - \a this: [2,0,1,1,0,1,2,0,1,1,0,0]
4784  * - result: [10,0,5,6,1,7,11,2,8,9,3,4]
4785  * - after applying result to \a this: [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2] 
4786  *
4787  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
4788  *          array using decrRef() as it is no more needed.
4789  *  \throw If \a this is not allocated.
4790  *  \throw If \a this->getNumberOfComponents() != 1.
4791  */
4792 DataArrayInt *DataArrayInt::buildPermArrPerLevel() const
4793 {
4794   checkAllocated();
4795   if(getNumberOfComponents()!=1)
4796     throw INTERP_KERNEL::Exception("DataArrayInt::buildPermArrPerLevel : number of components must == 1 !");
4797   int nbOfTuples=getNumberOfTuples();
4798   const int *pt=getConstPointer();
4799   std::map<int,int> m;
4800   MCAuto<DataArrayInt> ret=DataArrayInt::New();
4801   ret->alloc(nbOfTuples,1);
4802   int *opt=ret->getPointer();
4803   for(int i=0;i<nbOfTuples;i++,pt++,opt++)
4804     {
4805       int val=*pt;
4806       std::map<int,int>::iterator it=m.find(val);
4807       if(it!=m.end())
4808         {
4809           *opt=(*it).second;
4810           (*it).second++;
4811         }
4812       else
4813         {
4814           *opt=0;
4815           m.insert(std::pair<int,int>(val,1));
4816         }
4817     }
4818   int sum=0;
4819   for(std::map<int,int>::iterator it=m.begin();it!=m.end();it++)
4820     {
4821       int vt=(*it).second;
4822       (*it).second=sum;
4823       sum+=vt;
4824     }
4825   pt=getConstPointer();
4826   opt=ret->getPointer();
4827   for(int i=0;i<nbOfTuples;i++,pt++,opt++)
4828     *opt+=m[*pt];
4829   //
4830   return ret.retn();
4831 }
4832
4833 /*!
4834  * Checks if \a this array has the given size, and if its contents is equal to an array filled with
4835  * iota(). This method is particularly useful for DataArrayInt instances that represent
4836  * a renumbering array, to check if there is a real need in renumbering.
4837  * This method checks than \a this can be considered as an identity mapping
4838  * of a set having \a sizeExpected elements into itself.
4839  *
4840  *  \param [in] sizeExpected - The number of elements expected.
4841  *  \return bool - \a true if \a this array contents == \a range( \a this->getNumberOfTuples())
4842  *  \throw If \a this is not allocated.
4843  *  \throw If \a this->getNumberOfComponents() != 1.
4844  */
4845 bool DataArrayInt::isIota(int sizeExpected) const
4846 {
4847   checkAllocated();
4848   if(getNumberOfComponents()!=1)
4849     return false;
4850   int nbOfTuples(getNumberOfTuples());
4851   if(nbOfTuples!=sizeExpected)
4852     return false;
4853   const int *pt=getConstPointer();
4854   for(int i=0;i<nbOfTuples;i++,pt++)
4855     if(*pt!=i)
4856       return false;
4857   return true;
4858 }
4859
4860 /*!
4861  * Checks if all values in \a this array are equal to \a val.
4862  *  \param [in] val - value to check equality of array values to.
4863  *  \return bool - \a true if all values are \a val.
4864  *  \throw If \a this is not allocated.
4865  *  \throw If \a this->getNumberOfComponents() != 1
4866  *  \sa DataArrayInt::checkUniformAndGuess
4867  */
4868 bool DataArrayInt::isUniform(int val) const
4869 {
4870   checkAllocated();
4871   if(getNumberOfComponents()!=1)
4872     throw INTERP_KERNEL::Exception("DataArrayInt::isUniform : must be applied on DataArrayInt with only one component, you can call 'rearrange' method before !");
4873   const int *w(begin()),*end2(end());
4874   for(;w!=end2;w++)
4875     if(*w!=val)
4876       return false;
4877   return true;
4878 }
4879
4880 /*!
4881  * This method checks that \a this is uniform. If not and exception will be thrown.
4882  * In case of uniformity the corresponding value is returned.
4883  *
4884  * \return int - the unique value contained in this
4885  * \throw If \a this is not allocated.
4886  * \throw If \a this->getNumberOfComponents() != 1
4887  * \throw If \a this is not uniform.
4888  * \sa DataArrayInt::isUniform
4889  */
4890 int DataArrayInt::checkUniformAndGuess() const
4891 {
4892   checkAllocated();
4893   if(getNumberOfComponents()!=1)
4894     throw INTERP_KERNEL::Exception("DataArrayInt::checkUniformAndGuess : must be applied on DataArrayInt with only one component, you can call 'rearrange' method before !");
4895   if(empty())
4896     throw INTERP_KERNEL::Exception("DataArrayInt::checkUniformAndGuess : this is empty !");
4897   const int *w(begin()),*end2(end());
4898   int ret(*w);
4899   for(;w!=end2;w++)
4900     if(*w!=ret)
4901       throw INTERP_KERNEL::Exception("DataArrayInt::checkUniformAndGuess : this is not uniform !");
4902   return ret;
4903 }
4904
4905 /*!
4906  * Checks if all values in \a this array are unique.
4907  *  \return bool - \a true if condition above is true
4908  *  \throw If \a this is not allocated.
4909  *  \throw If \a this->getNumberOfComponents() != 1
4910  */
4911 bool DataArrayInt::hasUniqueValues() const
4912 {
4913   checkAllocated();
4914   if(getNumberOfComponents()!=1)
4915     throw INTERP_KERNEL::Exception("DataArrayInt::hasOnlyUniqueValues: must be applied on DataArrayInt with only one component, you can call 'rearrange' method before !");
4916   int nbOfTuples(getNumberOfTuples());
4917   std::set<int> s(begin(),end());  // in C++11, should use unordered_set (O(1) complexity)
4918   if (s.size() != nbOfTuples)
4919     return false;
4920   return true;
4921 }
4922
4923 /*!
4924  * Copy all components in a specified order from another DataArrayInt.
4925  * The specified components become the first ones in \a this array.
4926  * Both numerical and textual data is copied. The number of tuples in \a this and
4927  * the other array can be different.
4928  *  \param [in] a - the array to copy data from.
4929  *  \param [in] compoIds - sequence of zero based indices of components, data of which is
4930  *              to be copied.
4931  *  \throw If \a a is NULL.
4932  *  \throw If \a compoIds.size() != \a a->getNumberOfComponents().
4933  *  \throw If \a compoIds[i] < 0 or \a compoIds[i] > \a this->getNumberOfComponents().
4934  *
4935  *  \if ENABLE_EXAMPLES
4936  *  \ref py_mcdataarrayint_setselectedcomponents "Here is a Python example".
4937  *  \endif
4938  */
4939 void DataArrayInt::setSelectedComponents(const DataArrayInt *a, const std::vector<int>& compoIds)
4940 {
4941   if(!a)
4942     throw INTERP_KERNEL::Exception("DataArrayInt::setSelectedComponents : input DataArrayInt is NULL !");
4943   checkAllocated();
4944   a->checkAllocated();
4945   copyPartOfStringInfoFrom2(compoIds,*a);
4946   std::size_t partOfCompoSz=compoIds.size();
4947   int nbOfCompo=getNumberOfComponents();
4948   int nbOfTuples=std::min(getNumberOfTuples(),a->getNumberOfTuples());
4949   const int *ac=a->getConstPointer();
4950   int *nc=getPointer();
4951   for(int i=0;i<nbOfTuples;i++)
4952     for(std::size_t j=0;j<partOfCompoSz;j++,ac++)
4953       nc[nbOfCompo*i+compoIds[j]]=*ac;
4954 }
4955
4956 DataArrayIntIterator *DataArrayInt::iterator()
4957 {
4958   return new DataArrayIntIterator(this);
4959 }
4960
4961 /*!
4962  * Creates a new DataArrayInt containing IDs (indices) of tuples holding value equal to a
4963  * given one. The ids are sorted in the ascending order.
4964  *  \param [in] val - the value to find within \a this.
4965  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
4966  *          array using decrRef() as it is no more needed.
4967  *  \throw If \a this is not allocated.
4968  *  \throw If \a this->getNumberOfComponents() != 1.
4969  *  \sa DataArrayInt::findIdsEqualTuple
4970  */
4971 DataArrayInt *DataArrayInt::findIdsEqual(int val) const
4972 {
4973   checkAllocated();
4974   if(getNumberOfComponents()!=1)
4975     throw INTERP_KERNEL::Exception("DataArrayInt::findIdsEqual : the array must have only one component, you can call 'rearrange' method before !");
4976   const int *cptr(getConstPointer());
4977   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
4978   int nbOfTuples=getNumberOfTuples();
4979   for(int i=0;i<nbOfTuples;i++,cptr++)
4980     if(*cptr==val)
4981       ret->pushBackSilent(i);
4982   return ret.retn();
4983 }
4984
4985 /*!
4986  * Creates a new DataArrayInt containing IDs (indices) of tuples holding value \b not
4987  * equal to a given one. 
4988  *  \param [in] val - the value to ignore within \a this.
4989  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
4990  *          array using decrRef() as it is no more needed.
4991  *  \throw If \a this is not allocated.
4992  *  \throw If \a this->getNumberOfComponents() != 1.
4993  */
4994 DataArrayInt *DataArrayInt::findIdsNotEqual(int val) const
4995 {
4996   checkAllocated();
4997   if(getNumberOfComponents()!=1)
4998     throw INTERP_KERNEL::Exception("DataArrayInt::findIdsNotEqual : the array must have only one component, you can call 'rearrange' method before !");
4999   const int *cptr(getConstPointer());
5000   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
5001   int nbOfTuples=getNumberOfTuples();
5002   for(int i=0;i<nbOfTuples;i++,cptr++)
5003     if(*cptr!=val)
5004       ret->pushBackSilent(i);
5005   return ret.retn();
5006 }
5007
5008 /*!
5009  * Creates a new DataArrayInt containing IDs (indices) of tuples holding tuple equal to those defined by [ \a tupleBg , \a tupleEnd )
5010  * This method is an extension of  DataArrayInt::findIdsEqual method.
5011  *
5012  *  \param [in] tupleBg - the begin (included) of the input tuple to find within \a this.
5013  *  \param [in] tupleEnd - the end (excluded) of the input tuple to find within \a this.
5014  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
5015  *          array using decrRef() as it is no more needed.
5016  *  \throw If \a this is not allocated.
5017  *  \throw If \a this->getNumberOfComponents() != std::distance(tupleBg,tupleEnd).
5018  * \throw If \a this->getNumberOfComponents() is equal to 0.
5019  * \sa DataArrayInt::findIdsEqual
5020  */
5021 DataArrayInt *DataArrayInt::findIdsEqualTuple(const int *tupleBg, const int *tupleEnd) const
5022 {
5023   std::size_t nbOfCompoExp(std::distance(tupleBg,tupleEnd));
5024   checkAllocated();
5025   if(getNumberOfComponents()!=(int)nbOfCompoExp)
5026     {
5027       std::ostringstream oss; oss << "DataArrayInt::findIdsEqualTuple : mismatch of number of components. Input tuple has " << nbOfCompoExp << " whereas this array has " << getNumberOfComponents() << " components !";
5028       throw INTERP_KERNEL::Exception(oss.str().c_str());
5029     }
5030   if(nbOfCompoExp==0)
5031     throw INTERP_KERNEL::Exception("DataArrayInt::findIdsEqualTuple : number of components should be > 0 !");
5032   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
5033   const int *bg(begin()),*end2(end()),*work(begin());
5034   while(work!=end2)
5035     {
5036       work=std::search(work,end2,tupleBg,tupleEnd);
5037       if(work!=end2)
5038         {
5039           std::size_t pos(std::distance(bg,work));
5040           if(pos%nbOfCompoExp==0)
5041             ret->pushBackSilent(pos/nbOfCompoExp);
5042           work++;
5043         }
5044     }
5045   return ret.retn();
5046 }
5047
5048 /*!
5049  * Assigns \a newValue to all elements holding \a oldValue within \a this
5050  * one-dimensional array.
5051  *  \param [in] oldValue - the value to replace.
5052  *  \param [in] newValue - the value to assign.
5053  *  \return int - number of replacements performed.
5054  *  \throw If \a this is not allocated.
5055  *  \throw If \a this->getNumberOfComponents() != 1.
5056  */
5057 int DataArrayInt::changeValue(int oldValue, int newValue)
5058 {
5059   checkAllocated();
5060   if(getNumberOfComponents()!=1)
5061     throw INTERP_KERNEL::Exception("DataArrayInt::changeValue : the array must have only one component, you can call 'rearrange' method before !");
5062   if(oldValue==newValue)
5063     return 0;
5064   int *start(getPointer()),*end2(start+getNbOfElems());
5065   int ret(0);
5066   for(int *val=start;val!=end2;val++)
5067     {
5068       if(*val==oldValue)
5069         {
5070           *val=newValue;
5071           ret++;
5072         }
5073     }
5074   if(ret>0)
5075     declareAsNew();
5076   return ret;
5077 }
5078
5079 /*!
5080  * Creates a new DataArrayInt containing IDs (indices) of tuples holding value equal to
5081  * one of given values.
5082  *  \param [in] valsBg - an array of values to find within \a this array.
5083  *  \param [in] valsEnd - specifies the end of the array \a valsBg, so that
5084  *              the last value of \a valsBg is \a valsEnd[ -1 ].
5085  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
5086  *          array using decrRef() as it is no more needed.
5087  *  \throw If \a this->getNumberOfComponents() != 1.
5088  */
5089 DataArrayInt *DataArrayInt::findIdsEqualList(const int *valsBg, const int *valsEnd) const
5090 {
5091   if(getNumberOfComponents()!=1)
5092     throw INTERP_KERNEL::Exception("DataArrayInt::findIdsEqualList : the array must have only one component, you can call 'rearrange' method before !");
5093   std::set<int> vals2(valsBg,valsEnd);
5094   const int *cptr(getConstPointer());
5095   std::vector<int> res;
5096   int nbOfTuples(getNumberOfTuples());
5097   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
5098   for(int i=0;i<nbOfTuples;i++,cptr++)
5099     if(vals2.find(*cptr)!=vals2.end())
5100       ret->pushBackSilent(i);
5101   return ret.retn();
5102 }
5103
5104 /*!
5105  * Creates a new DataArrayInt containing IDs (indices) of tuples holding values \b not
5106  * equal to any of given values.
5107  *  \param [in] valsBg - an array of values to ignore within \a this array.
5108  *  \param [in] valsEnd - specifies the end of the array \a valsBg, so that
5109  *              the last value of \a valsBg is \a valsEnd[ -1 ].
5110  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
5111  *          array using decrRef() as it is no more needed.
5112  *  \throw If \a this->getNumberOfComponents() != 1.
5113  */
5114 DataArrayInt *DataArrayInt::findIdsNotEqualList(const int *valsBg, const int *valsEnd) const
5115 {
5116   if(getNumberOfComponents()!=1)
5117     throw INTERP_KERNEL::Exception("DataArrayInt::findIdsNotEqualList : the array must have only one component, you can call 'rearrange' method before !");
5118   std::set<int> vals2(valsBg,valsEnd);
5119   const int *cptr=getConstPointer();
5120   std::vector<int> res;
5121   int nbOfTuples=getNumberOfTuples();
5122   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
5123   for(int i=0;i<nbOfTuples;i++,cptr++)
5124     if(vals2.find(*cptr)==vals2.end())
5125       ret->pushBackSilent(i);
5126   return ret.retn();
5127 }
5128
5129 /*!
5130  * This method is an extension of DataArrayInt::findIdFirstEqual method because this method works for DataArrayInt with
5131  * any number of components excepted 0 (an INTERP_KERNEL::Exception is thrown in this case).
5132  * This method searches in \b this is there is a tuple that matched the input parameter \b tupl.
5133  * If any the tuple id is returned. If not -1 is returned.
5134  * 
5135  * This method throws an INTERP_KERNEL::Exception if the number of components in \b this mismatches with the size of
5136  * the input vector. An INTERP_KERNEL::Exception is thrown too if \b this is not allocated.
5137  *
5138  * \return tuple id where \b tupl is. -1 if no such tuple exists in \b this.
5139  * \sa DataArrayInt::findIdSequence, DataArrayInt::presenceOfTuple.
5140  */
5141 int DataArrayInt::findIdFirstEqualTuple(const std::vector<int>& tupl) const
5142 {
5143   checkAllocated();
5144   int nbOfCompo=getNumberOfComponents();
5145   if(nbOfCompo==0)
5146     throw INTERP_KERNEL::Exception("DataArrayInt::findIdFirstEqualTuple : 0 components in 'this' !");
5147   if(nbOfCompo!=(int)tupl.size())
5148     {
5149       std::ostringstream oss; oss << "DataArrayInt::findIdFirstEqualTuple : 'this' contains " << nbOfCompo << " components and searching for a tuple of length " << tupl.size() << " !";
5150       throw INTERP_KERNEL::Exception(oss.str().c_str());
5151     }
5152   const int *cptr=getConstPointer();
5153   std::size_t nbOfVals=getNbOfElems();
5154   for(const int *work=cptr;work!=cptr+nbOfVals;)
5155     {
5156       work=std::search(work,cptr+nbOfVals,tupl.begin(),tupl.end());
5157       if(work!=cptr+nbOfVals)
5158         {
5159           if(std::distance(cptr,work)%nbOfCompo!=0)
5160             work++;
5161           else
5162             return std::distance(cptr,work)/nbOfCompo;
5163         }
5164     }
5165   return -1;
5166 }
5167
5168 /*!
5169  * This method searches the sequence specified in input parameter \b vals in \b this.
5170  * This works only for DataArrayInt having number of components equal to one (if not an INTERP_KERNEL::Exception will be thrown).
5171  * This method differs from DataArrayInt::findIdFirstEqualTuple in that the position is internal raw data is not considered here contrary to DataArrayInt::findIdFirstEqualTuple.
5172  * \sa DataArrayInt::findIdFirstEqualTuple
5173  */
5174 int DataArrayInt::findIdSequence(const std::vector<int>& vals) const
5175 {
5176   checkAllocated();
5177   int nbOfCompo=getNumberOfComponents();
5178   if(nbOfCompo!=1)
5179     throw INTERP_KERNEL::Exception("DataArrayInt::findIdSequence : works only for DataArrayInt instance with one component !");
5180   const int *cptr=getConstPointer();
5181   std::size_t nbOfVals=getNbOfElems();
5182   const int *loc=std::search(cptr,cptr+nbOfVals,vals.begin(),vals.end());
5183   if(loc!=cptr+nbOfVals)
5184     return std::distance(cptr,loc);
5185   return -1;
5186 }
5187
5188 /*!
5189  * This method expects to be called when number of components of this is equal to one.
5190  * This method returns the tuple id, if it exists, of the first tuple equal to \b value.
5191  * If not any tuple contains \b value -1 is returned.
5192  * \sa DataArrayInt::presenceOfValue
5193  */
5194 int DataArrayInt::findIdFirstEqual(int value) const
5195 {
5196   checkAllocated();
5197   if(getNumberOfComponents()!=1)
5198     throw INTERP_KERNEL::Exception("DataArrayInt::presenceOfValue : the array must have only one component, you can call 'rearrange' method before !");
5199   const int *cptr=getConstPointer();
5200   int nbOfTuples=getNumberOfTuples();
5201   const int *ret=std::find(cptr,cptr+nbOfTuples,value);
5202   if(ret!=cptr+nbOfTuples)
5203     return std::distance(cptr,ret);
5204   return -1;
5205 }
5206
5207 /*!
5208  * This method expects to be called when number of components of this is equal to one.
5209  * This method returns the tuple id, if it exists, of the first tuple so that the value is contained in \b vals.
5210  * If not any tuple contains one of the values contained in 'vals' -1 is returned.
5211  * \sa DataArrayInt::presenceOfValue
5212  */
5213 int DataArrayInt::findIdFirstEqual(const std::vector<int>& vals) const
5214 {
5215   checkAllocated();
5216   if(getNumberOfComponents()!=1)
5217     throw INTERP_KERNEL::Exception("DataArrayInt::presenceOfValue : the array must have only one component, you can call 'rearrange' method before !");
5218   std::set<int> vals2(vals.begin(),vals.end());
5219   const int *cptr=getConstPointer();
5220   int nbOfTuples=getNumberOfTuples();
5221   for(const int *w=cptr;w!=cptr+nbOfTuples;w++)
5222     if(vals2.find(*w)!=vals2.end())
5223       return std::distance(cptr,w);
5224   return -1;
5225 }
5226
5227 /*!
5228  * This method returns the number of values in \a this that are equals to input parameter \a value.
5229  * This method only works for single component array.
5230  *
5231  * \return a value in [ 0, \c this->getNumberOfTuples() )
5232  *
5233  * \throw If \a this is not allocated
5234  *
5235  */
5236 int DataArrayInt::count(int value) const
5237 {
5238   int ret=0;
5239   checkAllocated();
5240   if(getNumberOfComponents()!=1)
5241     throw INTERP_KERNEL::Exception("DataArrayInt::count : must be applied on DataArrayInt with only one component, you can call 'rearrange' method before !");
5242   const int *vals=begin();
5243   int nbOfTuples=getNumberOfTuples();
5244   for(int i=0;i<nbOfTuples;i++,vals++)
5245     if(*vals==value)
5246       ret++;
5247   return ret;
5248 }
5249
5250 /*!
5251  * This method is an extension of DataArrayInt::presenceOfValue method because this method works for DataArrayInt with
5252  * any number of components excepted 0 (an INTERP_KERNEL::Exception is thrown in this case).
5253  * This method searches in \b this is there is a tuple that matched the input parameter \b tupl.
5254  * This method throws an INTERP_KERNEL::Exception if the number of components in \b this mismatches with the size of
5255  * the input vector. An INTERP_KERNEL::Exception is thrown too if \b this is not allocated.
5256  * \sa DataArrayInt::findIdFirstEqualTuple
5257  */
5258 bool DataArrayInt::presenceOfTuple(const std::vector<int>& tupl) const
5259 {
5260   return findIdFirstEqualTuple(tupl)!=-1;
5261 }
5262
5263
5264 /*!
5265  * Returns \a true if a given value is present within \a this one-dimensional array.
5266  *  \param [in] value - the value to find within \a this array.
5267  *  \return bool - \a true in case if \a value is present within \a this array.
5268  *  \throw If \a this is not allocated.
5269  *  \throw If \a this->getNumberOfComponents() != 1.
5270  *  \sa findIdFirstEqual()
5271  */
5272 bool DataArrayInt::presenceOfValue(int value) const
5273 {
5274   return findIdFirstEqual(value)!=-1;
5275 }
5276
5277 /*!
5278  * This method expects to be called when number of components of this is equal to one.
5279  * This method returns true if it exists a tuple so that the value is contained in \b vals.
5280  * If not any tuple contains one of the values contained in 'vals' false is returned.
5281  * \sa DataArrayInt::findIdFirstEqual
5282  */
5283 bool DataArrayInt::presenceOfValue(const std::vector<int>& vals) const
5284 {
5285   return findIdFirstEqual(vals)!=-1;
5286 }
5287
5288 /*!
5289  * Accumulates values of each component of \a this array.
5290  *  \param [out] res - an array of length \a this->getNumberOfComponents(), allocated 
5291  *         by the caller, that is filled by this method with sum value for each
5292  *         component.
5293  *  \throw If \a this is not allocated.
5294  */
5295 void DataArrayInt::accumulate(int *res) const
5296 {
5297   checkAllocated();
5298   const int *ptr=getConstPointer();
5299   int nbTuple=getNumberOfTuples();
5300   int nbComps=getNumberOfComponents();
5301   std::fill(res,res+nbComps,0);
5302   for(int i=0;i<nbTuple;i++)
5303     std::transform(ptr+i*nbComps,ptr+(i+1)*nbComps,res,res,std::plus<int>());
5304 }
5305
5306 int DataArrayInt::accumulate(int compId) const
5307 {
5308   checkAllocated();
5309   const int *ptr=getConstPointer();
5310   int nbTuple=getNumberOfTuples();
5311   int nbComps=getNumberOfComponents();
5312   if(compId<0 || compId>=nbComps)
5313     throw INTERP_KERNEL::Exception("DataArrayInt::accumulate : Invalid compId specified : No such nb of components !");
5314   int ret=0;
5315   for(int i=0;i<nbTuple;i++)
5316     ret+=ptr[i*nbComps+compId];
5317   return ret;
5318 }
5319
5320 /*!
5321  * This method accumulate using addition tuples in \a this using input index array [ \a bgOfIndex, \a endOfIndex ).
5322  * The returned array will have same number of components than \a this and number of tuples equal to
5323  * \c std::distance(bgOfIndex,endOfIndex) \b minus \b one.
5324  *
5325  * The input index array is expected to be ascendingly sorted in which the all referenced ids should be in [0, \c this->getNumberOfTuples).
5326  *
5327  * \param [in] bgOfIndex - begin (included) of the input index array.
5328  * \param [in] endOfIndex - end (excluded) of the input index array.
5329  * \return DataArrayInt * - the new instance having the same number of components than \a this.
5330  * 
5331  * \throw If bgOfIndex or end is NULL.
5332  * \throw If input index array is not ascendingly sorted.
5333  * \throw If there is an id in [ \a bgOfIndex, \a endOfIndex ) not in [0, \c this->getNumberOfTuples).
5334  * \throw If std::distance(bgOfIndex,endOfIndex)==0.
5335  */
5336 DataArrayInt *DataArrayInt::accumulatePerChunck(const int *bgOfIndex, const int *endOfIndex) const
5337 {
5338   if(!bgOfIndex || !endOfIndex)
5339     throw INTERP_KERNEL::Exception("DataArrayInt::accumulatePerChunck : input pointer NULL !");
5340   checkAllocated();
5341   int nbCompo=getNumberOfComponents();
5342   int nbOfTuples=getNumberOfTuples();
5343   int sz=(int)std::distance(bgOfIndex,endOfIndex);
5344   if(sz<1)
5345     throw INTERP_KERNEL::Exception("DataArrayInt::accumulatePerChunck : invalid size of input index array !");
5346   sz--;
5347   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(sz,nbCompo);
5348   const int *w=bgOfIndex;
5349   if(*w<0 || *w>=nbOfTuples)
5350     throw INTERP_KERNEL::Exception("DataArrayInt::accumulatePerChunck : The first element of the input index not in [0,nbOfTuples) !");
5351   const int *srcPt=begin()+(*w)*nbCompo;
5352   int *tmp=ret->getPointer();
5353   for(int i=0;i<sz;i++,tmp+=nbCompo,w++)
5354     {
5355       std::fill(tmp,tmp+nbCompo,0);
5356       if(w[1]>=w[0])
5357         {
5358           for(int j=w[0];j<w[1];j++,srcPt+=nbCompo)
5359             {
5360               if(j>=0 && j<nbOfTuples)
5361                 std::transform(srcPt,srcPt+nbCompo,tmp,tmp,std::plus<int>());
5362               else
5363                 {
5364                   std::ostringstream oss; oss << "DataArrayInt::accumulatePerChunck : At rank #" << i << " the input index array points to id " << j << " should be in [0," << nbOfTuples << ") !";
5365                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5366                 }
5367             }
5368         }
5369       else
5370         {
5371           std::ostringstream oss; oss << "DataArrayInt::accumulatePerChunck : At rank #" << i << " the input index array is not in ascendingly sorted.";
5372           throw INTERP_KERNEL::Exception(oss.str().c_str());
5373         }
5374     }
5375   ret->copyStringInfoFrom(*this);
5376   return ret.retn();
5377 }
5378
5379 /*!
5380  * Returns a new DataArrayInt by concatenating two given arrays, so that (1) the number
5381  * of tuples in the result array is <em> a1->getNumberOfTuples() + a2->getNumberOfTuples() -
5382  * offsetA2</em> and (2)
5383  * the number of component in the result array is same as that of each of given arrays.
5384  * First \a offsetA2 tuples of \a a2 are skipped and thus are missing from the result array.
5385  * Info on components is copied from the first of the given arrays. Number of components
5386  * in the given arrays must be the same.
5387  *  \param [in] a1 - an array to include in the result array.
5388  *  \param [in] a2 - another array to include in the result array.
5389  *  \param [in] offsetA2 - number of tuples of \a a2 to skip.
5390  *  \return DataArrayInt * - the new instance of DataArrayInt.
5391  *          The caller is to delete this result array using decrRef() as it is no more
5392  *          needed.
5393  *  \throw If either \a a1 or \a a2 is NULL.
5394  *  \throw If \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents().
5395  */
5396 DataArrayInt *DataArrayInt::Aggregate(const DataArrayInt *a1, const DataArrayInt *a2, int offsetA2)
5397 {
5398   if(!a1 || !a2)
5399     throw INTERP_KERNEL::Exception("DataArrayInt::Aggregate : input DataArrayInt instance is NULL !");
5400   int nbOfComp=a1->getNumberOfComponents();
5401   if(nbOfComp!=a2->getNumberOfComponents())
5402     throw INTERP_KERNEL::Exception("Nb of components mismatch for array Aggregation !");
5403   int nbOfTuple1=a1->getNumberOfTuples();
5404   int nbOfTuple2=a2->getNumberOfTuples();
5405   DataArrayInt *ret=DataArrayInt::New();
5406   ret->alloc(nbOfTuple1+nbOfTuple2-offsetA2,nbOfComp);
5407   int *pt=std::copy(a1->getConstPointer(),a1->getConstPointer()+nbOfTuple1*nbOfComp,ret->getPointer());
5408   std::copy(a2->getConstPointer()+offsetA2*nbOfComp,a2->getConstPointer()+nbOfTuple2*nbOfComp,pt);
5409   ret->copyStringInfoFrom(*a1);
5410   return ret;
5411 }
5412
5413 /*!
5414  * Returns a new DataArrayInt by concatenating all given arrays, so that (1) the number
5415  * of tuples in the result array is a sum of the number of tuples of given arrays and (2)
5416  * the number of component in the result array is same as that of each of given arrays.
5417  * Info on components is copied from the first of the given arrays. Number of components
5418  * in the given arrays must be  the same.
5419  * If the number of non null of elements in \a arr is equal to one the returned object is a copy of it
5420  * not the object itself.
5421  *  \param [in] arr - a sequence of arrays to include in the result array.
5422  *  \return DataArrayInt * - the new instance of DataArrayInt.
5423  *          The caller is to delete this result array using decrRef() as it is no more
5424  *          needed.
5425  *  \throw If all arrays within \a arr are NULL.
5426  *  \throw If getNumberOfComponents() of arrays within \a arr.
5427  */
5428 DataArrayInt *DataArrayInt::Aggregate(const std::vector<const DataArrayInt *>& arr)
5429 {
5430   std::vector<const DataArrayInt *> a;
5431   for(std::vector<const DataArrayInt *>::const_iterator it4=arr.begin();it4!=arr.end();it4++)
5432     if(*it4)
5433       a.push_back(*it4);
5434   if(a.empty())
5435     throw INTERP_KERNEL::Exception("DataArrayInt::Aggregate : input list must be NON EMPTY !");
5436   std::vector<const DataArrayInt *>::const_iterator it=a.begin();
5437   int nbOfComp=(*it)->getNumberOfComponents();
5438   int nbt=(*it++)->getNumberOfTuples();
5439   for(int i=1;it!=a.end();it++,i++)
5440     {
5441       if((*it)->getNumberOfComponents()!=nbOfComp)
5442         throw INTERP_KERNEL::Exception("DataArrayInt::Aggregate : Nb of components mismatch for array aggregation !");
5443       nbt+=(*it)->getNumberOfTuples();
5444     }
5445   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5446   ret->alloc(nbt,nbOfComp);
5447   int *pt=ret->getPointer();
5448   for(it=a.begin();it!=a.end();it++)
5449     pt=std::copy((*it)->getConstPointer(),(*it)->getConstPointer()+(*it)->getNbOfElems(),pt);
5450   ret->copyStringInfoFrom(*(a[0]));
5451   return ret.retn();
5452 }
5453
5454 /*!
5455  * This method takes as input a list of DataArrayInt instances \a arrs that represent each a packed index arrays.
5456  * A packed index array is an allocated array with one component, and at least one tuple. The first element
5457  * of each array in \a arrs must be 0. Each array in \a arrs is expected to be increasingly monotonic.
5458  * 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.
5459  * 
5460  * \return DataArrayInt * - a new object to be managed by the caller.
5461  */
5462 DataArrayInt *DataArrayInt::AggregateIndexes(const std::vector<const DataArrayInt *>& arrs)
5463 {
5464   int retSz=1;
5465   for(std::vector<const DataArrayInt *>::const_iterator it4=arrs.begin();it4!=arrs.end();it4++)
5466     {
5467       if(*it4)
5468         {
5469           (*it4)->checkAllocated();
5470           if((*it4)->getNumberOfComponents()!=1)
5471             {
5472               std::ostringstream oss; oss << "DataArrayInt::AggregateIndexes : presence of a DataArrayInt instance with nb of compo != 1 at pos " << std::distance(arrs.begin(),it4) << " !";
5473               throw INTERP_KERNEL::Exception(oss.str().c_str());
5474             }
5475           int nbTupl=(*it4)->getNumberOfTuples();
5476           if(nbTupl<1)
5477             {
5478               std::ostringstream oss; oss << "DataArrayInt::AggregateIndexes : presence of a DataArrayInt instance with nb of tuples < 1 at pos " << std::distance(arrs.begin(),it4) << " !";
5479               throw INTERP_KERNEL::Exception(oss.str().c_str());
5480             }
5481           if((*it4)->front()!=0)
5482             {
5483               std::ostringstream oss; oss << "DataArrayInt::AggregateIndexes : presence of a DataArrayInt instance with front value != 0 at pos " << std::distance(arrs.begin(),it4) << " !";
5484               throw INTERP_KERNEL::Exception(oss.str().c_str());
5485             }
5486           retSz+=nbTupl-1;
5487         }
5488       else
5489         {
5490           std::ostringstream oss; oss << "DataArrayInt::AggregateIndexes : presence of a null instance at pos " << std::distance(arrs.begin(),it4) << " !";
5491           throw INTERP_KERNEL::Exception(oss.str().c_str());
5492         }
5493     }
5494   if(arrs.empty())
5495     throw INTERP_KERNEL::Exception("DataArrayInt::AggregateIndexes : input list must be NON EMPTY !");
5496   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5497   ret->alloc(retSz,1);
5498   int *pt=ret->getPointer(); *pt++=0;
5499   for(std::vector<const DataArrayInt *>::const_iterator it=arrs.begin();it!=arrs.end();it++)
5500     pt=std::transform((*it)->begin()+1,(*it)->end(),pt,std::bind2nd(std::plus<int>(),pt[-1]));
5501   ret->copyStringInfoFrom(*(arrs[0]));
5502   return ret.retn();
5503 }
5504
5505 /*!
5506  * Returns in a single walk in \a this the min value and the max value in \a this.
5507  * \a this is expected to be single component array.
5508  *
5509  * \param [out] minValue - the min value in \a this.
5510  * \param [out] maxValue - the max value in \a this.
5511  *
5512  * \sa getMinValueInArray, getMinValue, getMaxValueInArray, getMaxValue
5513  */
5514 void DataArrayInt::getMinMaxValues(int& minValue, int& maxValue) const
5515 {
5516   checkAllocated();
5517   if(getNumberOfComponents()!=1)
5518     throw INTERP_KERNEL::Exception("DataArrayInt::getMinMaxValues : must be applied on DataArrayInt with only one component !");
5519   int nbTuples(getNumberOfTuples());
5520   const int *pt(begin());
5521   minValue=std::numeric_limits<int>::max(); maxValue=-std::numeric_limits<int>::max();
5522   for(int i=0;i<nbTuples;i++,pt++)
5523     {
5524       if(*pt<minValue)
5525         minValue=*pt;
5526       if(*pt>maxValue)
5527         maxValue=*pt;
5528     }
5529 }
5530
5531 /*!
5532  * Modify all elements of \a this array, so that
5533  * an element _x_ becomes \f$ numerator / x \f$.
5534  *  \warning If an exception is thrown because of presence of 0 element in \a this 
5535  *           array, all elements processed before detection of the zero element remain
5536  *           modified.
5537  *  \param [in] numerator - the numerator used to modify array elements.
5538  *  \throw If \a this is not allocated.
5539  *  \throw If there is an element equal to 0 in \a this array.
5540  */
5541 void DataArrayInt::applyInv(int numerator)
5542 {
5543   checkAllocated();
5544   int *ptr=getPointer();
5545   std::size_t nbOfElems=getNbOfElems();
5546   for(std::size_t i=0;i<nbOfElems;i++,ptr++)
5547     {
5548       if(*ptr!=0)
5549         {
5550           *ptr=numerator/(*ptr);
5551         }
5552       else
5553         {
5554           std::ostringstream oss; oss << "DataArrayInt::applyInv : presence of null value in tuple #" << i/getNumberOfComponents() << " component #" << i%getNumberOfComponents();
5555           oss << " !";
5556           throw INTERP_KERNEL::Exception(oss.str().c_str());
5557         }
5558     }
5559   declareAsNew();
5560 }
5561
5562 /*!
5563  * Modify all elements of \a this array, so that
5564  * an element _x_ becomes \f$ x / val \f$.
5565  *  \param [in] val - the denominator used to modify array elements.
5566  *  \throw If \a this is not allocated.
5567  *  \throw If \a val == 0.
5568  */
5569 void DataArrayInt::applyDivideBy(int val)
5570 {
5571   if(val==0)
5572     throw INTERP_KERNEL::Exception("DataArrayInt::applyDivideBy : Trying to divide by 0 !");
5573   checkAllocated();
5574   int *ptr=getPointer();
5575   std::size_t nbOfElems=getNbOfElems();
5576   std::transform(ptr,ptr+nbOfElems,ptr,std::bind2nd(std::divides<int>(),val));
5577   declareAsNew();
5578 }
5579
5580 /*!
5581  * Modify all elements of \a this array, so that
5582  * an element _x_ becomes  <em> x % val </em>.
5583  *  \param [in] val - the divisor used to modify array elements.
5584  *  \throw If \a this is not allocated.
5585  *  \throw If \a val <= 0.
5586  */
5587 void DataArrayInt::applyModulus(int val)
5588 {
5589   if(val<=0)
5590     throw INTERP_KERNEL::Exception("DataArrayInt::applyDivideBy : Trying to operate modulus on value <= 0 !");
5591   checkAllocated();
5592   int *ptr=getPointer();
5593   std::size_t nbOfElems=getNbOfElems();
5594   std::transform(ptr,ptr+nbOfElems,ptr,std::bind2nd(std::modulus<int>(),val));
5595   declareAsNew();
5596 }
5597
5598 /*!
5599  * This method works only on data array with one component.
5600  * This method returns a newly allocated array storing stored ascendantly tuple ids in \b this so that
5601  * this[*id] in [\b vmin,\b vmax)
5602  * 
5603  * \param [in] vmin begin of range. This value is included in range (included).
5604  * \param [in] vmax end of range. This value is \b not included in range (excluded).
5605  * \return a newly allocated data array that the caller should deal with.
5606  *
5607  * \sa DataArrayInt::findIdsNotInRange , DataArrayInt::findIdsStricltyNegative
5608  */
5609 DataArrayInt *DataArrayInt::findIdsInRange(int vmin, int vmax) const
5610 {
5611   InRange<int> ir(vmin,vmax);
5612   MCAuto<DataArrayInt> ret(findIdsAdv(ir));
5613   return ret.retn();
5614 }
5615
5616 /*!
5617  * This method works only on data array with one component.
5618  * This method returns a newly allocated array storing stored ascendantly tuple ids in \b this so that
5619  * this[*id] \b not in [\b vmin,\b vmax)
5620  * 
5621  * \param [in] vmin begin of range. This value is \b not included in range (excluded).
5622  * \param [in] vmax end of range. This value is included in range (included).
5623  * \return a newly allocated data array that the caller should deal with.
5624  * 
5625  * \sa DataArrayInt::findIdsInRange , DataArrayInt::findIdsStricltyNegative
5626  */
5627 DataArrayInt *DataArrayInt::findIdsNotInRange(int vmin, int vmax) const
5628 {
5629   NotInRange<int> nir(vmin,vmax);
5630   MCAuto<DataArrayInt> ret(findIdsAdv(nir));
5631   return ret.retn();
5632 }
5633
5634 /*!
5635  * This method works only on data array with one component.
5636  * 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.
5637  * 
5638  * \param [in] vmin begin of range. This value is included in range (included).
5639  * \param [in] vmax end of range. This value is \b not included in range (excluded).
5640  * \return if all ids in \a this are so that (*this)[i]==i for all i in [ 0, \c this->getNumberOfTuples() ). */
5641 bool DataArrayInt::checkAllIdsInRange(int vmin, int vmax) const
5642 {
5643   checkAllocated();
5644   if(getNumberOfComponents()!=1)
5645     throw INTERP_KERNEL::Exception("DataArrayInt::checkAllIdsInRange : this must have exactly one component !");
5646   int nbOfTuples=getNumberOfTuples();
5647   bool ret=true;
5648   const int *cptr=getConstPointer();
5649   for(int i=0;i<nbOfTuples;i++,cptr++)
5650     {
5651       if(*cptr>=vmin && *cptr<vmax)
5652         { ret=ret && *cptr==i; }
5653       else
5654         {
5655           std::ostringstream oss; oss << "DataArrayInt::checkAllIdsInRange : tuple #" << i << " has value " << *cptr << " should be in [" << vmin << "," << vmax << ") !";
5656           throw INTERP_KERNEL::Exception(oss.str().c_str());
5657         }
5658     }
5659   return ret;
5660 }
5661
5662 /*!
5663  * Modify all elements of \a this array, so that
5664  * an element _x_ becomes <em> val % x </em>.
5665  *  \warning If an exception is thrown because of presence of an element <= 0 in \a this 
5666  *           array, all elements processed before detection of the zero element remain
5667  *           modified.
5668  *  \param [in] val - the divident used to modify array elements.
5669  *  \throw If \a this is not allocated.
5670  *  \throw If there is an element equal to or less than 0 in \a this array.
5671  */
5672 void DataArrayInt::applyRModulus(int val)
5673 {
5674   checkAllocated();
5675   int *ptr=getPointer();
5676   std::size_t nbOfElems=getNbOfElems();
5677   for(std::size_t i=0;i<nbOfElems;i++,ptr++)
5678     {
5679       if(*ptr>0)
5680         {
5681           *ptr=val%(*ptr);
5682         }
5683       else
5684         {
5685           std::ostringstream oss; oss << "DataArrayInt::applyRModulus : presence of value <=0 in tuple #" << i/getNumberOfComponents() << " component #" << i%getNumberOfComponents();
5686           oss << " !";
5687           throw INTERP_KERNEL::Exception(oss.str().c_str());
5688         }
5689     }
5690   declareAsNew();
5691 }
5692
5693 /*!
5694  * Modify all elements of \a this array, so that
5695  * an element _x_ becomes <em> val ^ x </em>.
5696  *  \param [in] val - the value used to apply pow on all array elements.
5697  *  \throw If \a this is not allocated.
5698  *  \throw If \a val < 0.
5699  */
5700 void DataArrayInt::applyPow(int val)
5701 {
5702   checkAllocated();
5703   if(val<0)
5704     throw INTERP_KERNEL::Exception("DataArrayInt::applyPow : input pow in < 0 !");
5705   int *ptr=getPointer();
5706   std::size_t nbOfElems=getNbOfElems();
5707   if(val==0)
5708     {
5709       std::fill(ptr,ptr+nbOfElems,1);
5710       return ;
5711     }
5712   for(std::size_t i=0;i<nbOfElems;i++,ptr++)
5713     {
5714       int tmp=1;
5715       for(int j=0;j<val;j++)
5716         tmp*=*ptr;
5717       *ptr=tmp;
5718     }
5719   declareAsNew();
5720 }
5721
5722 /*!
5723  * Modify all elements of \a this array, so that
5724  * an element _x_ becomes \f$ val ^ x \f$.
5725  *  \param [in] val - the value used to apply pow on all array elements.
5726  *  \throw If \a this is not allocated.
5727  *  \throw If there is an element < 0 in \a this array.
5728  *  \warning If an exception is thrown because of presence of 0 element in \a this 
5729  *           array, all elements processed before detection of the zero element remain
5730  *           modified.
5731  */
5732 void DataArrayInt::applyRPow(int val)
5733 {
5734   checkAllocated();
5735   int *ptr=getPointer();
5736   std::size_t nbOfElems=getNbOfElems();
5737   for(std::size_t i=0;i<nbOfElems;i++,ptr++)
5738     {
5739       if(*ptr>=0)
5740         {
5741           int tmp=1;
5742           for(int j=0;j<*ptr;j++)
5743             tmp*=val;
5744           *ptr=tmp;
5745         }
5746       else
5747         {
5748           std::ostringstream oss; oss << "DataArrayInt::applyRPow : presence of negative value in tuple #" << i/getNumberOfComponents() << " component #" << i%getNumberOfComponents();
5749           oss << " !";
5750           throw INTERP_KERNEL::Exception(oss.str().c_str());
5751         }
5752     }
5753   declareAsNew();
5754 }
5755
5756 /*!
5757  * Returns a new DataArrayInt which is a minimal partition of elements of \a groups.
5758  * The i-th item of the result array is an ID of a set of elements belonging to a
5759  * unique set of groups, which the i-th element is a part of. This set of elements
5760  * belonging to a unique set of groups is called \a family, so the result array contains
5761  * IDs of families each element belongs to.
5762  *
5763  * \b Example: if we have two groups of elements: \a group1 [0,4] and \a group2 [ 0,1,2 ],
5764  * then there are 3 families:
5765  * - \a family1 (with ID 1) contains element [0] belonging to ( \a group1 + \a group2 ),
5766  * - \a family2 (with ID 2) contains elements [4] belonging to ( \a group1 ),
5767  * - \a family3 (with ID 3) contains element [1,2] belonging to ( \a group2 ), <br>
5768  * and the result array contains IDs of families [ 1,3,3,0,2 ]. <br> Note a family ID 0 which
5769  * stands for the element #3 which is in none of groups.
5770  *
5771  *  \param [in] groups - sequence of groups of element IDs.
5772  *  \param [in] newNb - total number of elements; it must be more than max ID of element
5773  *         in \a groups.
5774  *  \param [out] fidsOfGroups - IDs of families the elements of each group belong to.
5775  *  \return DataArrayInt * - a new instance of DataArrayInt containing IDs of families
5776  *         each element with ID from range [0, \a newNb ) belongs to. The caller is to
5777  *         delete this array using decrRef() as it is no more needed.
5778  *  \throw If any element ID in \a groups violates condition ( 0 <= ID < \a newNb ).
5779  */
5780 DataArrayInt *DataArrayInt::MakePartition(const std::vector<const DataArrayInt *>& groups, int newNb, std::vector< std::vector<int> >& fidsOfGroups)
5781 {
5782   std::vector<const DataArrayInt *> groups2;
5783   for(std::vector<const DataArrayInt *>::const_iterator it4=groups.begin();it4!=groups.end();it4++)
5784     if(*it4)
5785       groups2.push_back(*it4);
5786   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5787   ret->alloc(newNb,1);
5788   int *retPtr=ret->getPointer();
5789   std::fill(retPtr,retPtr+newNb,0);
5790   int fid=1;
5791   for(std::vector<const DataArrayInt *>::const_iterator iter=groups2.begin();iter!=groups2.end();iter++)
5792     {
5793       const int *ptr=(*iter)->getConstPointer();
5794       std::size_t nbOfElem=(*iter)->getNbOfElems();
5795       int sfid=fid;
5796       for(int j=0;j<sfid;j++)
5797         {
5798           bool found=false;
5799           for(std::size_t i=0;i<nbOfElem;i++)
5800             {
5801               if(ptr[i]>=0 && ptr[i]<newNb)
5802                 {
5803                   if(retPtr[ptr[i]]==j)
5804                     {
5805                       retPtr[ptr[i]]=fid;
5806                       found=true;
5807                     }
5808                 }
5809               else
5810                 {
5811                   std::ostringstream oss; oss << "DataArrayInt::MakePartition : In group \"" << (*iter)->getName() << "\" in tuple #" << i << " value = " << ptr[i] << " ! Should be in [0," << newNb;
5812                   oss << ") !";
5813                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5814                 }
5815             }
5816           if(found)
5817             fid++;
5818         }
5819     }
5820   fidsOfGroups.clear();
5821   fidsOfGroups.resize(groups2.size());
5822   int grId=0;
5823   for(std::vector<const DataArrayInt *>::const_iterator iter=groups2.begin();iter!=groups2.end();iter++,grId++)
5824     {
5825       std::set<int> tmp;
5826       const int *ptr=(*iter)->getConstPointer();
5827       std::size_t nbOfElem=(*iter)->getNbOfElems();
5828       for(const int *p=ptr;p!=ptr+nbOfElem;p++)
5829         tmp.insert(retPtr[*p]);
5830       fidsOfGroups[grId].insert(fidsOfGroups[grId].end(),tmp.begin(),tmp.end());
5831     }
5832   return ret.retn();
5833 }
5834
5835 /*!
5836  * Returns a new DataArrayInt which contains all elements of given one-dimensional
5837  * arrays. The result array does not contain any duplicates and its values
5838  * are sorted in ascending order.
5839  *  \param [in] arr - sequence of DataArrayInt's to unite.
5840  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
5841  *         array using decrRef() as it is no more needed.
5842  *  \throw If any \a arr[i] is not allocated.
5843  *  \throw If \a arr[i]->getNumberOfComponents() != 1.
5844  */
5845 DataArrayInt *DataArrayInt::BuildUnion(const std::vector<const DataArrayInt *>& arr)
5846 {
5847   std::vector<const DataArrayInt *> a;
5848   for(std::vector<const DataArrayInt *>::const_iterator it4=arr.begin();it4!=arr.end();it4++)
5849     if(*it4)
5850       a.push_back(*it4);
5851   for(std::vector<const DataArrayInt *>::const_iterator it=a.begin();it!=a.end();it++)
5852     {
5853       (*it)->checkAllocated();
5854       if((*it)->getNumberOfComponents()!=1)
5855         throw INTERP_KERNEL::Exception("DataArrayInt::BuildUnion : only single component allowed !");
5856     }
5857   //
5858   std::set<int> r;
5859   for(std::vector<const DataArrayInt *>::const_iterator it=a.begin();it!=a.end();it++)
5860     {
5861       const int *pt=(*it)->getConstPointer();
5862       int nbOfTuples=(*it)->getNumberOfTuples();
5863       r.insert(pt,pt+nbOfTuples);
5864     }
5865   DataArrayInt *ret=DataArrayInt::New();
5866   ret->alloc((int)r.size(),1);
5867   std::copy(r.begin(),r.end(),ret->getPointer());
5868   return ret;
5869 }
5870
5871 /*!
5872  * Returns a new DataArrayInt which contains elements present in each of given one-dimensional
5873  * arrays. The result array does not contain any duplicates and its values
5874  * are sorted in ascending order.
5875  *  \param [in] arr - sequence of DataArrayInt's to intersect.
5876  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
5877  *         array using decrRef() as it is no more needed.
5878  *  \throw If any \a arr[i] is not allocated.
5879  *  \throw If \a arr[i]->getNumberOfComponents() != 1.
5880  */
5881 DataArrayInt *DataArrayInt::BuildIntersection(const std::vector<const DataArrayInt *>& arr)
5882 {
5883   std::vector<const DataArrayInt *> a;
5884   for(std::vector<const DataArrayInt *>::const_iterator it4=arr.begin();it4!=arr.end();it4++)
5885     if(*it4)
5886       a.push_back(*it4);
5887   for(std::vector<const DataArrayInt *>::const_iterator it=a.begin();it!=a.end();it++)
5888     {
5889       (*it)->checkAllocated();
5890       if((*it)->getNumberOfComponents()!=1)
5891         throw INTERP_KERNEL::Exception("DataArrayInt::BuildIntersection : only single component allowed !");
5892     }
5893   //
5894   std::set<int> r;
5895   for(std::vector<const DataArrayInt *>::const_iterator it=a.begin();it!=a.end();it++)
5896     {
5897       const int *pt=(*it)->getConstPointer();
5898       int nbOfTuples=(*it)->getNumberOfTuples();
5899       std::set<int> s1(pt,pt+nbOfTuples);
5900       if(it!=a.begin())
5901         {
5902           std::set<int> r2;
5903           std::set_intersection(r.begin(),r.end(),s1.begin(),s1.end(),inserter(r2,r2.end()));
5904           r=r2;
5905         }
5906       else
5907         r=s1;
5908     }
5909   DataArrayInt *ret(DataArrayInt::New());
5910   ret->alloc((int)r.size(),1);
5911   std::copy(r.begin(),r.end(),ret->getPointer());
5912   return ret;
5913 }
5914
5915 /// @cond INTERNAL
5916 namespace MEDCouplingImpl
5917 {
5918   class OpSwitchedOn
5919   {
5920   public:
5921     OpSwitchedOn(int *pt):_pt(pt),_cnt(0) { }
5922     void operator()(const bool& b) { if(b) *_pt++=_cnt; _cnt++; }
5923   private:
5924     int *_pt;
5925     int _cnt;
5926   };
5927
5928   class OpSwitchedOff
5929   {
5930   public:
5931     OpSwitchedOff(int *pt):_pt(pt),_cnt(0) { }
5932     void operator()(const bool& b) { if(!b) *_pt++=_cnt; _cnt++; }
5933   private:
5934     int *_pt;
5935     int _cnt;
5936   };
5937 }
5938 /// @endcond
5939
5940 /*!
5941  * This method returns the list of ids in ascending mode so that v[id]==true.
5942  */
5943 DataArrayInt *DataArrayInt::BuildListOfSwitchedOn(const std::vector<bool>& v)
5944 {
5945   int sz((int)std::count(v.begin(),v.end(),true));
5946   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(sz,1);
5947   std::for_each(v.begin(),v.end(),MEDCouplingImpl::OpSwitchedOn(ret->getPointer()));
5948   return ret.retn();
5949 }
5950
5951 /*!
5952  * This method returns the list of ids in ascending mode so that v[id]==false.
5953  */
5954 DataArrayInt *DataArrayInt::BuildListOfSwitchedOff(const std::vector<bool>& v)
5955 {
5956   int sz((int)std::count(v.begin(),v.end(),false));
5957   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(sz,1);
5958   std::for_each(v.begin(),v.end(),MEDCouplingImpl::OpSwitchedOff(ret->getPointer()));
5959   return ret.retn();
5960 }
5961
5962 /*!
5963  * This method allows to put a vector of vector of integer into a more compact data stucture (skyline). 
5964  * This method is not available into python because no available optimized data structure available to map std::vector< std::vector<int> >.
5965  *
5966  * \param [in] v the input data structure to be translate into skyline format.
5967  * \param [out] data the first element of the skyline format. The user is expected to deal with newly allocated array.
5968  * \param [out] dataIndex the second element of the skyline format.
5969  */
5970 void DataArrayInt::PutIntoToSkylineFrmt(const std::vector< std::vector<int> >& v, DataArrayInt *& data, DataArrayInt *& dataIndex)
5971 {
5972   int sz((int)v.size());
5973   MCAuto<DataArrayInt> ret0(DataArrayInt::New()),ret1(DataArrayInt::New());
5974   ret1->alloc(sz+1,1);
5975   int *pt(ret1->getPointer()); *pt=0;
5976   for(int i=0;i<sz;i++,pt++)
5977     pt[1]=pt[0]+(int)v[i].size();
5978   ret0->alloc(ret1->back(),1);
5979   pt=ret0->getPointer();
5980   for(int i=0;i<sz;i++)
5981     pt=std::copy(v[i].begin(),v[i].end(),pt);
5982   data=ret0.retn(); dataIndex=ret1.retn();
5983 }
5984
5985 /*!
5986  * Returns a new DataArrayInt which contains a complement of elements of \a this
5987  * one-dimensional array. I.e. the result array contains all elements from the range [0,
5988  * \a nbOfElement) not present in \a this array.
5989  *  \param [in] nbOfElement - maximal size of the result array.
5990  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
5991  *         array using decrRef() as it is no more needed.
5992  *  \throw If \a this is not allocated.
5993  *  \throw If \a this->getNumberOfComponents() != 1.
5994  *  \throw If any element \a x of \a this array violates condition ( 0 <= \a x < \a
5995  *         nbOfElement ).
5996  */
5997 DataArrayInt *DataArrayInt::buildComplement(int nbOfElement) const
5998 {
5999   checkAllocated();
6000   if(getNumberOfComponents()!=1)
6001     throw INTERP_KERNEL::Exception("DataArrayInt::buildComplement : only single component allowed !");
6002   std::vector<bool> tmp(nbOfElement);
6003   const int *pt=getConstPointer();
6004   int nbOfTuples=getNumberOfTuples();
6005   for(const int *w=pt;w!=pt+nbOfTuples;w++)
6006     if(*w>=0 && *w<nbOfElement)
6007       tmp[*w]=true;
6008     else
6009       throw INTERP_KERNEL::Exception("DataArrayInt::buildComplement : an element is not in valid range : [0,nbOfElement) !");
6010   int nbOfRetVal=(int)std::count(tmp.begin(),tmp.end(),false);
6011   DataArrayInt *ret=DataArrayInt::New();
6012   ret->alloc(nbOfRetVal,1);
6013   int j=0;
6014   int *retPtr=ret->getPointer();
6015   for(int i=0;i<nbOfElement;i++)
6016     if(!tmp[i])
6017       retPtr[j++]=i;
6018   return ret;
6019 }
6020
6021 /*!
6022  * Returns a new DataArrayInt containing elements of \a this one-dimensional missing
6023  * from an \a other one-dimensional array.
6024  *  \param [in] other - a DataArrayInt containing elements not to include in the result array.
6025  *  \return DataArrayInt * - a new instance of DataArrayInt with one component. The
6026  *         caller is to delete this array using decrRef() as it is no more needed.
6027  *  \throw If \a other is NULL.
6028  *  \throw If \a other is not allocated.
6029  *  \throw If \a other->getNumberOfComponents() != 1.
6030  *  \throw If \a this is not allocated.
6031  *  \throw If \a this->getNumberOfComponents() != 1.
6032  *  \sa DataArrayInt::buildSubstractionOptimized()
6033  */
6034 DataArrayInt *DataArrayInt::buildSubstraction(const DataArrayInt *other) const
6035 {
6036   if(!other)
6037     throw INTERP_KERNEL::Exception("DataArrayInt::buildSubstraction : DataArrayInt pointer in input is NULL !");
6038   checkAllocated();
6039   other->checkAllocated();
6040   if(getNumberOfComponents()!=1)
6041     throw INTERP_KERNEL::Exception("DataArrayInt::buildSubstraction : only single component allowed !");
6042   if(other->getNumberOfComponents()!=1)
6043     throw INTERP_KERNEL::Exception("DataArrayInt::buildSubstraction : only single component allowed for other type !");
6044   const int *pt=getConstPointer();
6045   int nbOfTuples=getNumberOfTuples();
6046   std::set<int> s1(pt,pt+nbOfTuples);
6047   pt=other->getConstPointer();
6048   nbOfTuples=other->getNumberOfTuples();
6049   std::set<int> s2(pt,pt+nbOfTuples);
6050   std::vector<int> r;
6051   std::set_difference(s1.begin(),s1.end(),s2.begin(),s2.end(),std::back_insert_iterator< std::vector<int> >(r));
6052   DataArrayInt *ret=DataArrayInt::New();
6053   ret->alloc((int)r.size(),1);
6054   std::copy(r.begin(),r.end(),ret->getPointer());
6055   return ret;
6056 }
6057
6058 /*!
6059  * \a this is expected to have one component and to be sorted ascendingly (as for \a other).
6060  * \a other is expected to be a part of \a this. If not DataArrayInt::buildSubstraction should be called instead.
6061  * 
6062  * \param [in] other an array with one component and expected to be sorted ascendingly.
6063  * \ret list of ids in \a this but not in \a other.
6064  * \sa DataArrayInt::buildSubstraction
6065  */
6066 DataArrayInt *DataArrayInt::buildSubstractionOptimized(const DataArrayInt *other) const
6067 {
6068   static const char *MSG="DataArrayInt::buildSubstractionOptimized : only single component allowed !";
6069   if(!other) throw INTERP_KERNEL::Exception("DataArrayInt::buildSubstractionOptimized : NULL input array !");
6070   checkAllocated(); other->checkAllocated();
6071   if(getNumberOfComponents()!=1) throw INTERP_KERNEL::Exception(MSG);
6072   if(other->getNumberOfComponents()!=1) throw INTERP_KERNEL::Exception(MSG);
6073   const int *pt1Bg(begin()),*pt1End(end()),*pt2Bg(other->begin()),*pt2End(other->end());
6074   const int *work1(pt1Bg),*work2(pt2Bg);
6075   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6076   for(;work1!=pt1End;work1++)
6077     {
6078       if(work2!=pt2End && *work1==*work2)
6079         work2++;
6080       else
6081         ret->pushBackSilent(*work1);
6082     }
6083   return ret.retn();
6084 }
6085
6086
6087 /*!
6088  * Returns a new DataArrayInt which contains all elements of \a this and a given
6089  * one-dimensional arrays. The result array does not contain any duplicates
6090  * and its values are sorted in ascending order.
6091  *  \param [in] other - an array to unite with \a this one.
6092  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
6093  *         array using decrRef() as it is no more needed.
6094  *  \throw If \a this or \a other is not allocated.
6095  *  \throw If \a this->getNumberOfComponents() != 1.
6096  *  \throw If \a other->getNumberOfComponents() != 1.
6097  */
6098 DataArrayInt *DataArrayInt::buildUnion(const DataArrayInt *other) const
6099 {
6100   std::vector<const DataArrayInt *>arrs(2);
6101   arrs[0]=this; arrs[1]=other;
6102   return BuildUnion(arrs);
6103 }
6104
6105
6106 /*!
6107  * Returns a new DataArrayInt which contains elements present in both \a this and a given
6108  * one-dimensional arrays. The result array does not contain any duplicates
6109  * and its values are sorted in ascending order.
6110  *  \param [in] other - an array to intersect with \a this one.
6111  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
6112  *         array using decrRef() as it is no more needed.
6113  *  \throw If \a this or \a other is not allocated.
6114  *  \throw If \a this->getNumberOfComponents() != 1.
6115  *  \throw If \a other->getNumberOfComponents() != 1.
6116  */
6117 DataArrayInt *DataArrayInt::buildIntersection(const DataArrayInt *other) const
6118 {
6119   std::vector<const DataArrayInt *>arrs(2);
6120   arrs[0]=this; arrs[1]=other;
6121   return BuildIntersection(arrs);
6122 }
6123
6124 /*!
6125  * This method can be applied on allocated with one component DataArrayInt instance.
6126  * This method is typically relevant for sorted arrays. All consecutive duplicated items in \a this will appear only once in returned DataArrayInt instance.
6127  * 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]
6128  * 
6129  * \return a newly allocated array that contain the result of the unique operation applied on \a this.
6130  * \throw if \a this is not allocated or if \a this has not exactly one component.
6131  * \sa DataArrayInt::buildUniqueNotSorted
6132  */
6133 DataArrayInt *DataArrayInt::buildUnique() const
6134 {
6135   checkAllocated();
6136   if(getNumberOfComponents()!=1)
6137     throw INTERP_KERNEL::Exception("DataArrayInt::buildUnique : only single component allowed !");
6138   int nbOfTuples=getNumberOfTuples();
6139   MCAuto<DataArrayInt> tmp=deepCopy();
6140   int *data=tmp->getPointer();
6141   int *last=std::unique(data,data+nbOfTuples);
6142   MCAuto<DataArrayInt> ret=DataArrayInt::New();
6143   ret->alloc(std::distance(data,last),1);
6144   std::copy(data,last,ret->getPointer());
6145   return ret.retn();
6146 }
6147
6148 /*!
6149  * This method can be applied on allocated with one component DataArrayInt instance.
6150  * This method keep elements only once by keeping the same order in \a this that is not expected to be sorted.
6151  *
6152  * \return a newly allocated array that contain the result of the unique operation applied on \a this.
6153  *
6154  * \throw if \a this is not allocated or if \a this has not exactly one component.
6155  *
6156  * \sa DataArrayInt::buildUnique
6157  */
6158 DataArrayInt *DataArrayInt::buildUniqueNotSorted() const
6159 {
6160   checkAllocated();
6161     if(getNumberOfComponents()!=1)
6162       throw INTERP_KERNEL::Exception("DataArrayInt::buildUniqueNotSorted : only single component allowed !");
6163   int minVal,maxVal;
6164   getMinMaxValues(minVal,maxVal);
6165   std::vector<bool> b(maxVal-minVal+1,false);
6166   const int *ptBg(begin()),*endBg(end());
6167   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6168   for(const int *pt=ptBg;pt!=endBg;pt++)
6169     {
6170       if(!b[*pt-minVal])
6171         {
6172           ret->pushBackSilent(*pt);
6173           b[*pt-minVal]=true;
6174         }
6175     }
6176   ret->copyStringInfoFrom(*this);
6177   return ret.retn();
6178 }
6179
6180 /*!
6181  * Returns a new DataArrayInt which contains size of every of groups described by \a this
6182  * "index" array. Such "index" array is returned for example by 
6183  * \ref MEDCoupling::MEDCouplingUMesh::buildDescendingConnectivity
6184  * "MEDCouplingUMesh::buildDescendingConnectivity" and
6185  * \ref MEDCoupling::MEDCouplingUMesh::getNodalConnectivityIndex
6186  * "MEDCouplingUMesh::getNodalConnectivityIndex" etc.
6187  * This method preforms the reverse operation of DataArrayInt::computeOffsetsFull.
6188  *  \return DataArrayInt * - a new instance of DataArrayInt, whose number of tuples
6189  *          equals to \a this->getNumberOfComponents() - 1, and number of components is 1.
6190  *          The caller is to delete this array using decrRef() as it is no more needed. 
6191  *  \throw If \a this is not allocated.
6192  *  \throw If \a this->getNumberOfComponents() != 1.
6193  *  \throw If \a this->getNumberOfTuples() < 2.
6194  *
6195  *  \b Example: <br> 
6196  *         - this contains [1,3,6,7,7,9,15]
6197  *         - result array contains [2,3,1,0,2,6],
6198  *          where 2 = 3 - 1, 3 = 6 - 3, 1 = 7 - 6 etc.
6199  *
6200  * \sa DataArrayInt::computeOffsetsFull
6201  */
6202 DataArrayInt *DataArrayInt::deltaShiftIndex() const
6203 {
6204   checkAllocated();
6205   if(getNumberOfComponents()!=1)
6206     throw INTERP_KERNEL::Exception("DataArrayInt::deltaShiftIndex : only single component allowed !");
6207   int nbOfTuples=getNumberOfTuples();
6208   if(nbOfTuples<2)
6209     throw INTERP_KERNEL::Exception("DataArrayInt::deltaShiftIndex : 1 tuple at least must be present in 'this' !");
6210   const int *ptr=getConstPointer();
6211   DataArrayInt *ret=DataArrayInt::New();
6212   ret->alloc(nbOfTuples-1,1);
6213   int *out=ret->getPointer();
6214   std::transform(ptr+1,ptr+nbOfTuples,ptr,out,std::minus<int>());
6215   return ret;
6216 }
6217
6218 /*!
6219  * Modifies \a this one-dimensional array so that value of each element \a x
6220  * of \a this array (\a a) is computed as \f$ x_i = \sum_{j=0}^{i-1} a[ j ] \f$.
6221  * Or: for each i>0 new[i]=new[i-1]+old[i-1] for i==0 new[i]=0. Number of tuples
6222  * and components remains the same.<br>
6223  * This method is useful for allToAllV in MPI with contiguous policy. This method
6224  * differs from computeOffsetsFull() in that the number of tuples is \b not changed by
6225  * this one.
6226  *  \throw If \a this is not allocated.
6227  *  \throw If \a this->getNumberOfComponents() != 1.
6228  *
6229  *  \b Example: <br>
6230  *          - Before \a this contains [3,5,1,2,0,8]
6231  *          - After \a this contains  [0,3,8,9,11,11]<br>
6232  *          Note that the last element 19 = 11 + 8 is missing because size of \a this
6233  *          array is retained and thus there is no space to store the last element.
6234  */
6235 void DataArrayInt::computeOffsets()
6236 {
6237   checkAllocated();
6238   if(getNumberOfComponents()!=1)
6239     throw INTERP_KERNEL::Exception("DataArrayInt::computeOffsets : only single component allowed !");
6240   int nbOfTuples=getNumberOfTuples();
6241   if(nbOfTuples==0)
6242     return ;
6243   int *work=getPointer();
6244   int tmp=work[0];
6245   work[0]=0;
6246   for(int i=1;i<nbOfTuples;i++)
6247     {
6248       int tmp2=work[i];
6249       work[i]=work[i-1]+tmp;
6250       tmp=tmp2;
6251     }
6252   declareAsNew();
6253 }
6254
6255
6256 /*!
6257  * Modifies \a this one-dimensional array so that value of each element \a x
6258  * of \a this array (\a a) is computed as \f$ x_i = \sum_{j=0}^{i-1} a[ j ] \f$.
6259  * Or: for each i>0 new[i]=new[i-1]+old[i-1] for i==0 new[i]=0. Number
6260  * components remains the same and number of tuples is inceamented by one.<br>
6261  * This method is useful for allToAllV in MPI with contiguous policy. This method
6262  * differs from computeOffsets() in that the number of tuples is changed by this one.
6263  * This method preforms the reverse operation of DataArrayInt::deltaShiftIndex.
6264  *  \throw If \a this is not allocated.
6265  *  \throw If \a this->getNumberOfComponents() != 1.
6266  *
6267  *  \b Example: <br>
6268  *          - Before \a this contains [3,5,1,2,0,8]
6269  *          - After \a this contains  [0,3,8,9,11,11,19]<br>
6270  * \sa DataArrayInt::deltaShiftIndex
6271  */
6272 void DataArrayInt::computeOffsetsFull()
6273 {
6274   checkAllocated();
6275   if(getNumberOfComponents()!=1)
6276     throw INTERP_KERNEL::Exception("DataArrayInt::computeOffsetsFull : only single component allowed !");
6277   int nbOfTuples=getNumberOfTuples();
6278   int *ret=(int *)malloc((nbOfTuples+1)*sizeof(int));
6279   const int *work=getConstPointer();
6280   ret[0]=0;
6281   for(int i=0;i<nbOfTuples;i++)
6282     ret[i+1]=work[i]+ret[i];
6283   useArray(ret,true,C_DEALLOC,nbOfTuples+1,1);
6284   declareAsNew();
6285 }
6286
6287 /*!
6288  * Returns two new DataArrayInt instances whose contents is computed from that of \a this and \a listOfIds arrays as follows.
6289  * \a this is expected to be an offset format ( as returned by DataArrayInt::computeOffsetsFull ) that is to say with one component
6290  * and ** sorted strictly increasingly **. \a listOfIds is expected to be sorted ascendingly (not strictly needed for \a listOfIds).
6291  * This methods searches in \a this, considered as a set of contiguous \c this->getNumberOfComponents() ranges, all ids in \a listOfIds
6292  * filling completely one of the ranges in \a this.
6293  *
6294  * \param [in] listOfIds a list of ids that has to be sorted ascendingly.
6295  * \param [out] rangeIdsFetched the range ids fetched
6296  * \param [out] idsInInputListThatFetch contains the list of ids in \a listOfIds that are \b fully included in a range in \a this. So
6297  *              \a idsInInputListThatFetch is a part of input \a listOfIds.
6298  *
6299  * \sa DataArrayInt::computeOffsetsFull
6300  *
6301  *  \b Example: <br>
6302  *          - \a this : [0,3,7,9,15,18]
6303  *          - \a listOfIds contains  [0,1,2,3,7,8,15,16,17]
6304  *          - \a rangeIdsFetched result array: [0,2,4]
6305  *          - \a idsInInputListThatFetch result array: [0,1,2,7,8,15,16,17]
6306  * In this example id 3 in input \a listOfIds is alone so it do not appear in output \a idsInInputListThatFetch.
6307  * <br>
6308  */
6309 void DataArrayInt::findIdsRangesInListOfIds(const DataArrayInt *listOfIds, DataArrayInt *& rangeIdsFetched, DataArrayInt *& idsInInputListThatFetch) const
6310 {
6311   if(!listOfIds)
6312     throw INTERP_KERNEL::Exception("DataArrayInt::findIdsRangesInListOfIds : input list of ids is null !");
6313   listOfIds->checkAllocated(); checkAllocated();
6314   if(listOfIds->getNumberOfComponents()!=1)
6315     throw INTERP_KERNEL::Exception("DataArrayInt::findIdsRangesInListOfIds : input list of ids must have exactly one component !");
6316   if(getNumberOfComponents()!=1)
6317     throw INTERP_KERNEL::Exception("DataArrayInt::findIdsRangesInListOfIds : this must have exactly one component !");
6318   MCAuto<DataArrayInt> ret0=DataArrayInt::New(); ret0->alloc(0,1);
6319   MCAuto<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(0,1);
6320   const int *tupEnd(listOfIds->end()),*offBg(begin()),*offEnd(end()-1);
6321   const int *tupPtr(listOfIds->begin()),*offPtr(offBg);
6322   while(tupPtr!=tupEnd && offPtr!=offEnd)
6323     {
6324       if(*tupPtr==*offPtr)
6325         {
6326           int i=offPtr[0];
6327           while(i<offPtr[1] && *tupPtr==i && tupPtr!=tupEnd) { i++; tupPtr++; }
6328           if(i==offPtr[1])
6329             {
6330               ret0->pushBackSilent((int)std::distance(offBg,offPtr));
6331               ret1->pushBackValsSilent(tupPtr-(offPtr[1]-offPtr[0]),tupPtr);
6332               offPtr++;
6333             }
6334         }
6335       else
6336         { if(*tupPtr<*offPtr) tupPtr++; else offPtr++; }
6337     }
6338   rangeIdsFetched=ret0.retn();
6339   idsInInputListThatFetch=ret1.retn();
6340 }
6341
6342 /*!
6343  * Returns a new DataArrayInt whose contents is computed from that of \a this and \a
6344  * offsets arrays as follows. \a offsets is a one-dimensional array considered as an
6345  * "index" array of a "iota" array, thus, whose each element gives an index of a group
6346  * beginning within the "iota" array. And \a this is a one-dimensional array
6347  * considered as a selector of groups described by \a offsets to include into the result array.
6348  *  \throw If \a offsets is NULL.
6349  *  \throw If \a offsets is not allocated.
6350  *  \throw If \a offsets->getNumberOfComponents() != 1.
6351  *  \throw If \a offsets is not monotonically increasing.
6352  *  \throw If \a this is not allocated.
6353  *  \throw If \a this->getNumberOfComponents() != 1.
6354  *  \throw If any element of \a this is not a valid index for \a offsets array.
6355  *
6356  *  \b Example: <br>
6357  *          - \a this: [0,2,3]
6358  *          - \a offsets: [0,3,6,10,14,20]
6359  *          - result array: [0,1,2,6,7,8,9,10,11,12,13] == <br>
6360  *            \c range(0,3) + \c range(6,10) + \c range(10,14) ==<br>
6361  *            \c range( \a offsets[ \a this[0] ], offsets[ \a this[0]+1 ]) + 
6362  *            \c range( \a offsets[ \a this[1] ], offsets[ \a this[1]+1 ]) + 
6363  *            \c range( \a offsets[ \a this[2] ], offsets[ \a this[2]+1 ])
6364  */
6365 DataArrayInt *DataArrayInt::buildExplicitArrByRanges(const DataArrayInt *offsets) const
6366 {
6367   if(!offsets)
6368     throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrByRanges : DataArrayInt pointer in input is NULL !");
6369   checkAllocated();
6370   if(getNumberOfComponents()!=1)
6371     throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrByRanges : only single component allowed !");
6372   offsets->checkAllocated();
6373   if(offsets->getNumberOfComponents()!=1)
6374     throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrByRanges : input array should have only single component !");
6375   int othNbTuples=offsets->getNumberOfTuples()-1;
6376   int nbOfTuples=getNumberOfTuples();
6377   int retNbOftuples=0;
6378   const int *work=getConstPointer();
6379   const int *offPtr=offsets->getConstPointer();
6380   for(int i=0;i<nbOfTuples;i++)
6381     {
6382       int val=work[i];
6383       if(val>=0 && val<othNbTuples)
6384         {
6385           int delta=offPtr[val+1]-offPtr[val];
6386           if(delta>=0)
6387             retNbOftuples+=delta;
6388           else
6389             {
6390               std::ostringstream oss; oss << "DataArrayInt::buildExplicitArrByRanges : Tuple #" << val << " of offset array has a delta < 0 !";
6391               throw INTERP_KERNEL::Exception(oss.str().c_str());
6392             }
6393         }
6394       else
6395         {
6396           std::ostringstream oss; oss << "DataArrayInt::buildExplicitArrByRanges : Tuple #" << i << " in this contains " << val;
6397           oss << " whereas offsets array is of size " << othNbTuples+1 << " !";
6398           throw INTERP_KERNEL::Exception(oss.str().c_str());
6399         }
6400     }
6401   MCAuto<DataArrayInt> ret=DataArrayInt::New();
6402   ret->alloc(retNbOftuples,1);
6403   int *retPtr=ret->getPointer();
6404   for(int i=0;i<nbOfTuples;i++)
6405     {
6406       int val=work[i];
6407       int start=offPtr[val];
6408       int off=offPtr[val+1]-start;
6409       for(int j=0;j<off;j++,retPtr++)
6410         *retPtr=start+j;
6411     }
6412   return ret.retn();
6413 }
6414
6415 /*!
6416  * Returns a new DataArrayInt whose contents is computed using \a this that must be a 
6417  * scaled array (monotonically increasing).
6418 from that of \a this and \a
6419  * offsets arrays as follows. \a offsets is a one-dimensional array considered as an
6420  * "index" array of a "iota" array, thus, whose each element gives an index of a group
6421  * beginning within the "iota" array. And \a this is a one-dimensional array
6422  * considered as a selector of groups described by \a offsets to include into the result array.
6423  *  \throw If \a  is NULL.
6424  *  \throw If \a this is not allocated.
6425  *  \throw If \a this->getNumberOfComponents() != 1.
6426  *  \throw If \a this->getNumberOfTuples() == 0.
6427  *  \throw If \a this is not monotonically increasing.
6428  *  \throw If any element of ids in ( \a bg \a stop \a step ) points outside the scale in \a this.
6429  *
6430  *  \b Example: <br>
6431  *          - \a bg , \a stop and \a step : (0,5,2)
6432  *          - \a this: [0,3,6,10,14,20]
6433  *          - result array: [0,0,0, 2,2,2,2, 4,4,4,4,4,4] == <br>
6434  */
6435 DataArrayInt *DataArrayInt::buildExplicitArrOfSliceOnScaledArr(int bg, int stop, int step) const
6436 {
6437   if(!isAllocated())
6438     throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrOfSliceOnScaledArr : not allocated array !");
6439   if(getNumberOfComponents()!=1)
6440     throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrOfSliceOnScaledArr : number of components is expected to be equal to one !");
6441   int nbOfTuples(getNumberOfTuples());
6442   if(nbOfTuples==0)
6443     throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrOfSliceOnScaledArr : number of tuples must be != 0 !");
6444   const int *ids(begin());
6445   int nbOfEltsInSlc(GetNumberOfItemGivenBESRelative(bg,stop,step,"DataArrayInt::buildExplicitArrOfSliceOnScaledArr")),sz(0),pos(bg);
6446   for(int i=0;i<nbOfEltsInSlc;i++,pos+=step)
6447     {
6448       if(pos>=0 && pos<nbOfTuples-1)
6449         {
6450           int delta(ids[pos+1]-ids[pos]);
6451           sz+=delta;
6452           if(delta<0)
6453             {
6454               std::ostringstream oss; oss << "DataArrayInt::buildExplicitArrOfSliceOnScaledArr : At pos #" << i << " of input slice, value is " << pos << " and at this pos this is not monotonically increasing !";
6455               throw INTERP_KERNEL::Exception(oss.str().c_str());
6456             }          
6457         }
6458       else
6459         {
6460           std::ostringstream oss; oss << "DataArrayInt::buildExplicitArrOfSliceOnScaledArr : At pos #" << i << " of input slice, value is " << pos << " should be in [0," << nbOfTuples-1 << ") !";  
6461           throw INTERP_KERNEL::Exception(oss.str().c_str());
6462         }
6463     }
6464   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(sz,1);
6465   int *retPtr(ret->getPointer());
6466   pos=bg;
6467   for(int i=0;i<nbOfEltsInSlc;i++,pos+=step)
6468     {
6469       int delta(ids[pos+1]-ids[pos]);
6470       for(int j=0;j<delta;j++,retPtr++)
6471         *retPtr=pos;
6472     }
6473   return ret.retn();
6474 }
6475
6476 /*!
6477  * 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.
6478  * 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
6479  * in tuple **i** of returned DataArrayInt.
6480  * If ranges overlapped (in theory it should not) this method do not detect it and always returns the first range.
6481  *
6482  * 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)]
6483  * The return DataArrayInt will contain : **[0,4,1,2,2,3]**
6484  * 
6485  * \param [in] ranges typically come from output of MEDCouplingUMesh::ComputeRangesFromTypeDistribution. Each range is specified like this : 1st component is
6486  *             for lower value included and 2nd component is the upper value of corresponding range **excluded**.
6487  * \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
6488  *        is thrown if no ranges in \a ranges contains value in \a this.
6489  * 
6490  * \sa DataArrayInt::findIdInRangeForEachTuple
6491  */
6492 DataArrayInt *DataArrayInt::findRangeIdForEachTuple(const DataArrayInt *ranges) const
6493 {
6494   if(!ranges)
6495     throw INTERP_KERNEL::Exception("DataArrayInt::findRangeIdForEachTuple : null input pointer !");
6496   if(ranges->getNumberOfComponents()!=2)
6497     throw INTERP_KERNEL::Exception("DataArrayInt::findRangeIdForEachTuple : input DataArrayInt instance should have 2 components !");
6498   checkAllocated();
6499   if(getNumberOfComponents()!=1)
6500     throw INTERP_KERNEL::Exception("DataArrayInt::findRangeIdForEachTuple : this should have only one component !");
6501   int nbTuples=getNumberOfTuples();
6502   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbTuples,1);
6503   int nbOfRanges=ranges->getNumberOfTuples();
6504   const int *rangesPtr=ranges->getConstPointer();
6505   int *retPtr=ret->getPointer();
6506   const int *inPtr=getConstPointer();
6507   for(int i=0;i<nbTuples;i++,retPtr++)
6508     {
6509       int val=inPtr[i];
6510       bool found=false;
6511       for(int j=0;j<nbOfRanges && !found;j++)
6512         if(val>=rangesPtr[2*j] && val<rangesPtr[2*j+1])
6513           { *retPtr=j; found=true; }
6514       if(found)
6515         continue;
6516       else
6517         {
6518           std::ostringstream oss; oss << "DataArrayInt::findRangeIdForEachTuple : tuple #" << i << " not found by any ranges !";
6519           throw INTERP_KERNEL::Exception(oss.str().c_str());
6520         }
6521     }
6522   return ret.retn();
6523 }
6524
6525 /*!
6526  * 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.
6527  * 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
6528  * in tuple **i** of returned DataArrayInt.
6529  * If ranges overlapped (in theory it should not) this method do not detect it and always returns the sub position of the first range.
6530  *
6531  * 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)]
6532  * The return DataArrayInt will contain : **[1,2,4,0,2,2]**
6533  * This method is often called in pair with DataArrayInt::findRangeIdForEachTuple method.
6534  * 
6535  * \param [in] ranges typically come from output of MEDCouplingUMesh::ComputeRangesFromTypeDistribution. Each range is specified like this : 1st component is
6536  *             for lower value included and 2nd component is the upper value of corresponding range **excluded**.
6537  * \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
6538  *        is thrown if no ranges in \a ranges contains value in \a this.
6539  * \sa DataArrayInt::findRangeIdForEachTuple
6540  */
6541 DataArrayInt *DataArrayInt::findIdInRangeForEachTuple(const DataArrayInt *ranges) const
6542 {
6543   if(!ranges)
6544     throw INTERP_KERNEL::Exception("DataArrayInt::findIdInRangeForEachTuple : null input pointer !");
6545   if(ranges->getNumberOfComponents()!=2)
6546     throw INTERP_KERNEL::Exception("DataArrayInt::findIdInRangeForEachTuple : input DataArrayInt instance should have 2 components !");
6547   checkAllocated();
6548   if(getNumberOfComponents()!=1)
6549     throw INTERP_KERNEL::Exception("DataArrayInt::findIdInRangeForEachTuple : this should have only one component !");
6550   int nbTuples=getNumberOfTuples();
6551   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbTuples,1);
6552   int nbOfRanges=ranges->getNumberOfTuples();
6553   const int *rangesPtr=ranges->getConstPointer();
6554   int *retPtr=ret->getPointer();
6555   const int *inPtr=getConstPointer();
6556   for(int i=0;i<nbTuples;i++,retPtr++)
6557     {
6558       int val=inPtr[i];
6559       bool found=false;
6560       for(int j=0;j<nbOfRanges && !found;j++)
6561         if(val>=rangesPtr[2*j] && val<rangesPtr[2*j+1])
6562           { *retPtr=val-rangesPtr[2*j]; found=true; }
6563       if(found)
6564         continue;
6565       else
6566         {
6567           std::ostringstream oss; oss << "DataArrayInt::findIdInRangeForEachTuple : tuple #" << i << " not found by any ranges !";
6568           throw INTERP_KERNEL::Exception(oss.str().c_str());
6569         }
6570     }
6571   return ret.retn();
6572 }
6573
6574 /*!
6575  * \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).
6576  * 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).
6577  * 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 !
6578  * If this method has correctly worked, \a this will be able to be considered as a linked list.
6579  * This method does nothing if number of tuples is lower of equal to 1.
6580  *
6581  * This method is useful for users having an unstructured mesh having only SEG2 to rearrange internaly the connectibity without any coordinates consideration.
6582  *
6583  * \sa MEDCouplingUMesh::orderConsecutiveCells1D, DataArrayInt::fromLinkedListOfPairToList
6584  */
6585 void DataArrayInt::sortEachPairToMakeALinkedList()
6586 {
6587   checkAllocated();
6588   if(getNumberOfComponents()!=2)
6589     throw INTERP_KERNEL::Exception("DataArrayInt::sortEachPairToMakeALinkedList : Only works on DataArrayInt instance with nb of components equal to 2 !");
6590   int nbOfTuples(getNumberOfTuples());
6591   if(nbOfTuples<=1)
6592     return ;
6593   int *conn(getPointer());
6594   for(int i=1;i<nbOfTuples;i++,conn+=2)
6595     {
6596       if(i>1)
6597         {
6598           if(conn[2]==conn[3])
6599             {
6600               std::ostringstream oss; oss << "DataArrayInt::sortEachPairToMakeALinkedList : In the tuple #" << i << " presence of a pair filled with same ids !";
6601               throw INTERP_KERNEL::Exception(oss.str().c_str());
6602             }
6603           if(conn[2]!=conn[1] && conn[3]==conn[1] && conn[2]!=conn[0])
6604             std::swap(conn[2],conn[3]);
6605           //not(conn[2]==conn[1] && conn[3]!=conn[1] && conn[3]!=conn[0])
6606           if(conn[2]!=conn[1] || conn[3]==conn[1] || conn[3]==conn[0])
6607             {
6608               std::ostringstream oss; oss << "DataArrayInt::sortEachPairToMakeALinkedList : In the tuple #" << i << " something is invalid !";
6609               throw INTERP_KERNEL::Exception(oss.str().c_str());
6610             }
6611         }
6612       else
6613         {
6614           if(conn[0]==conn[1] || conn[2]==conn[3])
6615             throw INTERP_KERNEL::Exception("DataArrayInt::sortEachPairToMakeALinkedList : In the 2 first tuples presence of a pair filled with same ids !");
6616           int tmp[4];
6617           std::set<int> s;
6618           s.insert(conn,conn+4);
6619           if(s.size()!=3)
6620             throw INTERP_KERNEL::Exception("DataArrayInt::sortEachPairToMakeALinkedList : This can't be considered as a linked list regarding 2 first tuples !");
6621           if(std::count(conn,conn+4,conn[0])==2)
6622             {
6623               tmp[0]=conn[1];
6624               tmp[1]=conn[0];
6625               tmp[2]=conn[0];
6626               if(conn[2]==conn[0])
6627                 { tmp[3]=conn[3]; }
6628               else
6629                 { tmp[3]=conn[2];}
6630               std::copy(tmp,tmp+4,conn);
6631             }
6632           else
6633             {//here we are sure to have (std::count(conn,conn+4,conn[1])==2)
6634               if(conn[1]==conn[3])
6635                 std::swap(conn[2],conn[3]);
6636             }
6637         }
6638     }
6639 }
6640
6641 /*!
6642  * \a this is expected to be a correctly linked list of pairs.
6643  * 
6644  * \sa DataArrayInt::sortEachPairToMakeALinkedList
6645  */
6646 MCAuto<DataArrayInt> DataArrayInt::fromLinkedListOfPairToList() const
6647 {
6648   checkAllocated();
6649   checkNbOfComps(2,"DataArrayInt::fromLinkedListOfPairToList : this is expected to have 2 components");
6650   int nbTuples(getNumberOfTuples());
6651   if(nbTuples<1)
6652     throw INTERP_KERNEL::Exception("DataArrayInt::fromLinkedListOfPairToList : no tuples in this ! Not a linked list !");
6653   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbTuples+1,1);
6654   const int *thisPtr(begin());
6655   int *retPtr(ret->getPointer());
6656   retPtr[0]=thisPtr[0];
6657   for(int i=0;i<nbTuples;i++)
6658     {
6659       retPtr[i+1]=thisPtr[2*i+1];
6660       if(i<nbTuples-1)
6661         if(thisPtr[2*i+1]!=thisPtr[2*(i+1)+0])
6662           {
6663             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 ?";
6664             throw INTERP_KERNEL::Exception(oss.str());
6665           }
6666     }
6667   return ret;
6668 }
6669
6670 /*!
6671  * This method returns all different values found in \a this. This method throws if \a this has not been allocated.
6672  * But the number of components can be different from one.
6673  * \return a newly allocated array (that should be dealt by the caller) containing different values in \a this.
6674  */
6675 DataArrayInt *DataArrayInt::getDifferentValues() const
6676 {
6677   checkAllocated();
6678   std::set<int> ret;
6679   ret.insert(begin(),end());
6680   MCAuto<DataArrayInt> ret2=DataArrayInt::New(); ret2->alloc((int)ret.size(),1);
6681   std::copy(ret.begin(),ret.end(),ret2->getPointer());
6682   return ret2.retn();
6683 }
6684
6685 /*!
6686  * This method is a refinement of DataArrayInt::getDifferentValues because it returns not only different values in \a this but also, for each of
6687  * them it tells which tuple id have this id.
6688  * This method works only on arrays with one component (if it is not the case call DataArrayInt::rearrange(1) ).
6689  * This method returns two arrays having same size.
6690  * 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.
6691  * 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]]
6692  */
6693 std::vector<DataArrayInt *> DataArrayInt::partitionByDifferentValues(std::vector<int>& differentIds) const
6694 {
6695   checkAllocated();
6696   if(getNumberOfComponents()!=1)
6697     throw INTERP_KERNEL::Exception("DataArrayInt::partitionByDifferentValues : this should have only one component !");
6698   int id=0;
6699   std::map<int,int> m,m2,m3;
6700   for(const int *w=begin();w!=end();w++)
6701     m[*w]++;
6702   differentIds.resize(m.size());
6703   std::vector<DataArrayInt *> ret(m.size());
6704   std::vector<int *> retPtr(m.size());
6705   for(std::map<int,int>::const_iterator it=m.begin();it!=m.end();it++,id++)
6706     {
6707       m2[(*it).first]=id;
6708       ret[id]=DataArrayInt::New();
6709       ret[id]->alloc((*it).second,1);
6710       retPtr[id]=ret[id]->getPointer();
6711       differentIds[id]=(*it).first;
6712     }
6713   id=0;
6714   for(const int *w=begin();w!=end();w++,id++)
6715     {
6716       retPtr[m2[*w]][m3[*w]++]=id;
6717     }
6718   return ret;
6719 }
6720
6721 /*!
6722  * This method split ids in [0, \c this->getNumberOfTuples() ) using \a this array as a field of weight (>=0 each).
6723  * The aim of this method is to return a set of \a nbOfSlices chunk of contiguous ids as balanced as possible.
6724  *
6725  * \param [in] nbOfSlices - number of slices expected.
6726  * \return - a vector having a size equal to \a nbOfSlices giving the start (included) and the stop (excluded) of each chunks.
6727  * 
6728  * \sa DataArray::GetSlice
6729  * \throw If \a this is not allocated or not with exactly one component.
6730  * \throw If an element in \a this if < 0.
6731  */
6732 std::vector< std::pair<int,int> > DataArrayInt::splitInBalancedSlices(int nbOfSlices) const
6733 {
6734   if(!isAllocated() || getNumberOfComponents()!=1)
6735     throw INTERP_KERNEL::Exception("DataArrayInt::splitInBalancedSlices : this array should have number of components equal to one and must be allocated !");
6736   if(nbOfSlices<=0)
6737     throw INTERP_KERNEL::Exception("DataArrayInt::splitInBalancedSlices : number of slices must be >= 1 !");
6738   int sum(accumulate(0)),nbOfTuples(getNumberOfTuples());
6739   int sumPerSlc(sum/nbOfSlices),pos(0);
6740   const int *w(begin());
6741   std::vector< std::pair<int,int> > ret(nbOfSlices);
6742   for(int i=0;i<nbOfSlices;i++)
6743     {
6744       std::pair<int,int> p(pos,-1);
6745       int locSum(0);
6746       while(locSum<sumPerSlc && pos<nbOfTuples) { pos++; locSum+=*w++; }
6747       if(i!=nbOfSlices-1)
6748         p.second=pos;
6749       else
6750         p.second=nbOfTuples;
6751       ret[i]=p;
6752     }
6753   return ret;
6754 }
6755
6756 /*!
6757  * Returns a new DataArrayInt that is a modulus of two given arrays. There are 3
6758  * valid cases.
6759  * 1.  The arrays have same number of tuples and components. Then each value of
6760  *   the result array (_a_) is a division of the corresponding values of \a a1 and
6761  *   \a a2, i.e.: _a_ [ i, j ] = _a1_ [ i, j ] % _a2_ [ i, j ].
6762  * 2.  The arrays have same number of tuples and one array, say _a2_, has one
6763  *   component. Then
6764  *   _a_ [ i, j ] = _a1_ [ i, j ] % _a2_ [ i, 0 ].
6765  * 3.  The arrays have same number of components and one array, say _a2_, has one
6766  *   tuple. Then
6767  *   _a_ [ i, j ] = _a1_ [ i, j ] % _a2_ [ 0, j ].
6768  *
6769  * Info on components is copied either from the first array (in the first case) or from
6770  * the array with maximal number of elements (getNbOfElems()).
6771  *  \warning No check of division by zero is performed!
6772  *  \param [in] a1 - a dividend array.
6773  *  \param [in] a2 - a divisor array.
6774  *  \return DataArrayInt * - the new instance of DataArrayInt.
6775  *          The caller is to delete this result array using decrRef() as it is no more
6776  *          needed.
6777  *  \throw If either \a a1 or \a a2 is NULL.
6778  *  \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples() and
6779  *         \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents() and
6780  *         none of them has number of tuples or components equal to 1.
6781  */
6782 DataArrayInt *DataArrayInt::Modulus(const DataArrayInt *a1, const DataArrayInt *a2)
6783 {
6784   if(!a1 || !a2)
6785     throw INTERP_KERNEL::Exception("DataArrayInt::Modulus : input DataArrayInt instance is NULL !");
6786   int nbOfTuple1=a1->getNumberOfTuples();
6787   int nbOfTuple2=a2->getNumberOfTuples();
6788   int nbOfComp1=a1->getNumberOfComponents();
6789   int nbOfComp2=a2->getNumberOfComponents();
6790   if(nbOfTuple2==nbOfTuple1)
6791     {
6792       if(nbOfComp1==nbOfComp2)
6793         {
6794           MCAuto<DataArrayInt> ret=DataArrayInt::New();
6795           ret->alloc(nbOfTuple2,nbOfComp1);
6796           std::transform(a1->begin(),a1->end(),a2->begin(),ret->getPointer(),std::modulus<int>());
6797           ret->copyStringInfoFrom(*a1);
6798           return ret.retn();
6799         }
6800       else if(nbOfComp2==1)
6801         {
6802           MCAuto<DataArrayInt> ret=DataArrayInt::New();
6803           ret->alloc(nbOfTuple1,nbOfComp1);
6804           const int *a2Ptr=a2->getConstPointer();
6805           const int *a1Ptr=a1->getConstPointer();
6806           int *res=ret->getPointer();
6807           for(int i=0;i<nbOfTuple1;i++)
6808             res=std::transform(a1Ptr+i*nbOfComp1,a1Ptr+(i+1)*nbOfComp1,res,std::bind2nd(std::modulus<int>(),a2Ptr[i]));
6809           ret->copyStringInfoFrom(*a1);
6810           return ret.retn();
6811         }
6812       else
6813         {
6814           a1->checkNbOfComps(nbOfComp2,"Nb of components mismatch for array Modulus !");
6815           return 0;
6816         }
6817     }
6818   else if(nbOfTuple2==1)
6819     {
6820       a1->checkNbOfComps(nbOfComp2,"Nb of components mismatch for array Modulus !");
6821       MCAuto<DataArrayInt> ret=DataArrayInt::New();
6822       ret->alloc(nbOfTuple1,nbOfComp1);
6823       const int *a1ptr=a1->getConstPointer(),*a2ptr=a2->getConstPointer();
6824       int *pt=ret->getPointer();
6825       for(int i=0;i<nbOfTuple1;i++)
6826         pt=std::transform(a1ptr+i*nbOfComp1,a1ptr+(i+1)*nbOfComp1,a2ptr,pt,std::modulus<int>());
6827       ret->copyStringInfoFrom(*a1);
6828       return ret.retn();
6829     }
6830   else
6831     {
6832       a1->checkNbOfTuples(nbOfTuple2,"Nb of tuples mismatch for array Modulus !");//will always throw an exception
6833       return 0;
6834     }
6835 }
6836
6837 /*!
6838  * Modify \a this array so that each value becomes a modulus of division of this value by
6839  * a value of another DataArrayInt. There are 3 valid cases.
6840  * 1.  The arrays have same number of tuples and components. Then each value of
6841  *    \a this array is divided by the corresponding value of \a other one, i.e.:
6842  *   _a_ [ i, j ] %= _other_ [ i, j ].
6843  * 2.  The arrays have same number of tuples and \a other array has one component. Then
6844  *   _a_ [ i, j ] %= _other_ [ i, 0 ].
6845  * 3.  The arrays have same number of components and \a other array has one tuple. Then
6846  *   _a_ [ i, j ] %= _a2_ [ 0, j ].
6847  *
6848  *  \warning No check of division by zero is performed!
6849  *  \param [in] other - a divisor array.
6850  *  \throw If \a other is NULL.
6851  *  \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples() and
6852  *         \a this->getNumberOfComponents() != \a other->getNumberOfComponents() and
6853  *         \a other has number of both tuples and components not equal to 1.
6854  */
6855 void DataArrayInt::modulusEqual(const DataArrayInt *other)
6856 {
6857   if(!other)
6858     throw INTERP_KERNEL::Exception("DataArrayInt::modulusEqual : input DataArrayInt instance is NULL !");
6859   const char *msg="Nb of tuples mismatch for DataArrayInt::modulusEqual !";
6860   checkAllocated(); other->checkAllocated();
6861   int nbOfTuple=getNumberOfTuples();
6862   int nbOfTuple2=other->getNumberOfTuples();
6863   int nbOfComp=getNumberOfComponents();
6864   int nbOfComp2=other->getNumberOfComponents();
6865   if(nbOfTuple==nbOfTuple2)
6866     {
6867       if(nbOfComp==nbOfComp2)
6868         {
6869           std::transform(begin(),end(),other->begin(),getPointer(),std::modulus<int>());
6870         }
6871       else if(nbOfComp2==1)
6872         {
6873           if(nbOfComp2==nbOfComp)
6874             {
6875               int *ptr=getPointer();
6876               const int *ptrc=other->getConstPointer();
6877               for(int i=0;i<nbOfTuple;i++)
6878                 std::transform(ptr+i*nbOfComp,ptr+(i+1)*nbOfComp,ptr+i*nbOfComp,std::bind2nd(std::modulus<int>(),*ptrc++));
6879             }
6880           else
6881             throw INTERP_KERNEL::Exception(msg);
6882         }
6883       else
6884         throw INTERP_KERNEL::Exception(msg);
6885     }
6886   else if(nbOfTuple2==1)
6887     {
6888       int *ptr=getPointer();
6889       const int *ptrc=other->getConstPointer();
6890       for(int i=0;i<nbOfTuple;i++)
6891         std::transform(ptr+i*nbOfComp,ptr+(i+1)*nbOfComp,ptrc,ptr+i*nbOfComp,std::modulus<int>());
6892     }
6893   else
6894     throw INTERP_KERNEL::Exception(msg);
6895   declareAsNew();
6896 }
6897
6898 /*!
6899  * Returns a new DataArrayInt that is the result of pow of two given arrays. There are 3
6900  * valid cases.
6901  *
6902  *  \param [in] a1 - an array to pow up.
6903  *  \param [in] a2 - another array to sum up.
6904  *  \return DataArrayInt * - the new instance of DataArrayInt.
6905  *          The caller is to delete this result array using decrRef() as it is no more
6906  *          needed.
6907  *  \throw If either \a a1 or \a a2 is NULL.
6908  *  \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples()
6909  *  \throw If \a a1->getNumberOfComponents() != 1 or \a a2->getNumberOfComponents() != 1.
6910  *  \throw If there is a negative value in \a a2.
6911  */
6912 DataArrayInt *DataArrayInt::Pow(const DataArrayInt *a1, const DataArrayInt *a2)
6913 {
6914   if(!a1 || !a2)
6915     throw INTERP_KERNEL::Exception("DataArrayInt::Pow : at least one of input instances is null !");
6916   int nbOfTuple=a1->getNumberOfTuples();
6917   int nbOfTuple2=a2->getNumberOfTuples();
6918   int nbOfComp=a1->getNumberOfComponents();
6919   int nbOfComp2=a2->getNumberOfComponents();
6920   if(nbOfTuple!=nbOfTuple2)
6921     throw INTERP_KERNEL::Exception("DataArrayInt::Pow : number of tuples mismatches !");
6922   if(nbOfComp!=1 || nbOfComp2!=1)
6923     throw INTERP_KERNEL::Exception("DataArrayInt::Pow : number of components of both arrays must be equal to 1 !");
6924   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfTuple,1);
6925   const int *ptr1(a1->begin()),*ptr2(a2->begin());
6926   int *ptr=ret->getPointer();
6927   for(int i=0;i<nbOfTuple;i++,ptr1++,ptr2++,ptr++)
6928     {
6929       if(*ptr2>=0)
6930         {
6931           int tmp=1;
6932           for(int j=0;j<*ptr2;j++)
6933             tmp*=*ptr1;
6934           *ptr=tmp;
6935         }
6936       else
6937         {
6938           std::ostringstream oss; oss << "DataArrayInt::Pow : on tuple #" << i << " of a2 value is < 0 (" << *ptr2 << ") !";
6939           throw INTERP_KERNEL::Exception(oss.str().c_str());
6940         }
6941     }
6942   return ret.retn();
6943 }
6944
6945 /*!
6946  * Apply pow on values of another DataArrayInt to values of \a this one.
6947  *
6948  *  \param [in] other - an array to pow to \a this one.
6949  *  \throw If \a other is NULL.
6950  *  \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples()
6951  *  \throw If \a this->getNumberOfComponents() != 1 or \a other->getNumberOfComponents() != 1
6952  *  \throw If there is a negative value in \a other.
6953  */
6954 void DataArrayInt::powEqual(const DataArrayInt *other)
6955 {
6956   if(!other)
6957     throw INTERP_KERNEL::Exception("DataArrayInt::powEqual : input instance is null !");
6958   int nbOfTuple=getNumberOfTuples();
6959   int nbOfTuple2=other->getNumberOfTuples();
6960   int nbOfComp=getNumberOfComponents();
6961   int nbOfComp2=other->getNumberOfComponents();
6962   if(nbOfTuple!=nbOfTuple2)
6963     throw INTERP_KERNEL::Exception("DataArrayInt::powEqual : number of tuples mismatches !");
6964   if(nbOfComp!=1 || nbOfComp2!=1)
6965     throw INTERP_KERNEL::Exception("DataArrayInt::powEqual : number of components of both arrays must be equal to 1 !");
6966   int *ptr=getPointer();
6967   const int *ptrc=other->begin();
6968   for(int i=0;i<nbOfTuple;i++,ptrc++,ptr++)
6969     {
6970       if(*ptrc>=0)
6971         {
6972           int tmp=1;
6973           for(int j=0;j<*ptrc;j++)
6974             tmp*=*ptr;
6975           *ptr=tmp;
6976         }
6977       else
6978         {
6979           std::ostringstream oss; oss << "DataArrayInt::powEqual : on tuple #" << i << " of other value is < 0 (" << *ptrc << ") !";
6980           throw INTERP_KERNEL::Exception(oss.str().c_str());
6981         }
6982     }
6983   declareAsNew();
6984 }
6985
6986 /*!
6987  * Returns a C array which is a renumbering map in "Old to New" mode for the input array.
6988  * This map, if applied to \a start array, would make it sorted. For example, if
6989  * \a start array contents are [9,10,0,6,4,11,3,7] then the contents of the result array is
6990  * [5,6,0,3,2,7,1,4].
6991  *  \param [in] start - pointer to the first element of the array for which the
6992  *         permutation map is computed.
6993  *  \param [in] end - pointer specifying the end of the array \a start, so that
6994  *         the last value of \a start is \a end[ -1 ].
6995  *  \return int * - the result permutation array that the caller is to delete as it is no
6996  *         more needed.
6997  *  \throw If there are equal values in the input array.
6998  */
6999 int *DataArrayInt::CheckAndPreparePermutation(const int *start, const int *end)
7000 {
7001   std::size_t sz=std::distance(start,end);
7002   int *ret=(int *)malloc(sz*sizeof(int));
7003   int *work=new int[sz];
7004   std::copy(start,end,work);
7005   std::sort(work,work+sz);
7006   if(std::unique(work,work+sz)!=work+sz)
7007     {
7008       delete [] work;
7009       free(ret);
7010       throw INTERP_KERNEL::Exception("Some elements are equals in the specified array !");
7011     }
7012   std::map<int,int> m;
7013   for(int *workPt=work;workPt!=work+sz;workPt++)
7014     m[*workPt]=(int)std::distance(work,workPt);
7015   int *iter2=ret;
7016   for(const int *iter=start;iter!=end;iter++,iter2++)
7017     *iter2=m[*iter];
7018   delete [] work;
7019   return ret;
7020 }
7021
7022 /*!
7023  * Returns a new DataArrayInt containing an arithmetic progression
7024  * that is equal to the sequence returned by Python \c range(\a begin,\a  end,\a  step )
7025  * function.
7026  *  \param [in] begin - the start value of the result sequence.
7027  *  \param [in] end - limiting value, so that every value of the result array is less than
7028  *              \a end.
7029  *  \param [in] step - specifies the increment or decrement.
7030  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
7031  *          array using decrRef() as it is no more needed.
7032  *  \throw If \a step == 0.
7033  *  \throw If \a end < \a begin && \a step > 0.
7034  *  \throw If \a end > \a begin && \a step < 0.
7035  */
7036 DataArrayInt *DataArrayInt::Range(int begin, int end, int step)
7037 {
7038   int nbOfTuples=GetNumberOfItemGivenBESRelative(begin,end,step,"DataArrayInt::Range");
7039   MCAuto<DataArrayInt> ret=DataArrayInt::New();
7040   ret->alloc(nbOfTuples,1);
7041   int *ptr=ret->getPointer();
7042   if(step>0)
7043     {
7044       for(int i=begin;i<end;i+=step,ptr++)
7045         *ptr=i;
7046     }
7047   else
7048     {
7049       for(int i=begin;i>end;i+=step,ptr++)
7050         *ptr=i;
7051     }
7052   return ret.retn();
7053 }
7054
7055 /*!
7056  * Useless method for end user. Only for MPI/Corba/File serialsation for multi arrays class.
7057  * Server side.
7058  */
7059 void DataArrayInt::getTinySerializationIntInformation(std::vector<int>& tinyInfo) const
7060 {
7061   tinyInfo.resize(2);
7062   if(isAllocated())
7063     {
7064       tinyInfo[0]=getNumberOfTuples();
7065       tinyInfo[1]=getNumberOfComponents();
7066     }
7067   else
7068     {
7069       tinyInfo[0]=-1;
7070       tinyInfo[1]=-1;
7071     }
7072 }
7073
7074 /*!
7075  * Useless method for end user. Only for MPI/Corba/File serialsation for multi arrays class.
7076  * Server side.
7077  */
7078 void DataArrayInt::getTinySerializationStrInformation(std::vector<std::string>& tinyInfo) const
7079 {
7080   if(isAllocated())
7081     {
7082       int nbOfCompo=getNumberOfComponents();
7083       tinyInfo.resize(nbOfCompo+1);
7084       tinyInfo[0]=getName();
7085       for(int i=0;i<nbOfCompo;i++)
7086         tinyInfo[i+1]=getInfoOnComponent(i);
7087     }
7088   else
7089     {
7090       tinyInfo.resize(1);
7091       tinyInfo[0]=getName();
7092     }
7093 }
7094
7095 /*!
7096  * Useless method for end user. Only for MPI/Corba/File serialsation for multi arrays class.
7097  * This method returns if a feeding is needed.
7098  */
7099 bool DataArrayInt::resizeForUnserialization(const std::vector<int>& tinyInfoI)
7100 {
7101   int nbOfTuple=tinyInfoI[0];
7102   int nbOfComp=tinyInfoI[1];
7103   if(nbOfTuple!=-1 || nbOfComp!=-1)
7104     {
7105       alloc(nbOfTuple,nbOfComp);
7106       return true;
7107     }
7108   return false;
7109 }
7110
7111 /*!
7112  * Useless method for end user. Only for MPI/Corba/File serialsation for multi arrays class.
7113  * This method returns if a feeding is needed.
7114  */
7115 void DataArrayInt::finishUnserialization(const std::vector<int>& tinyInfoI, const std::vector<std::string>& tinyInfoS)
7116 {
7117   setName(tinyInfoS[0]);
7118   if(isAllocated())
7119     {
7120       int nbOfCompo=tinyInfoI[1];
7121       for(int i=0;i<nbOfCompo;i++)
7122         setInfoOnComponent(i,tinyInfoS[i+1]);
7123     }
7124 }
7125
7126 DataArrayIntIterator::DataArrayIntIterator(DataArrayInt *da):DataArrayIterator<int>(da)
7127 {
7128 }
7129
7130 DataArrayInt32Tuple::DataArrayInt32Tuple(int *pt, int nbOfComp):DataArrayTuple<int>(pt,nbOfComp)
7131 {
7132 }
7133
7134 std::string DataArrayIntTuple::repr() const
7135 {
7136   std::ostringstream oss; oss << "(";
7137   for(int i=0;i<_nb_of_compo-1;i++)
7138     oss << _pt[i] << ", ";
7139   oss << _pt[_nb_of_compo-1] << ")";
7140   return oss.str();
7141 }
7142
7143 int DataArrayIntTuple::intValue() const
7144 {
7145   return this->zeValue();
7146 }
7147
7148 /*!
7149  * This method returns a newly allocated instance the caller should dealed with by a MEDCoupling::DataArrayInt::decrRef.
7150  * This method performs \b no copy of data. The content is only referenced using MEDCoupling::DataArrayInt::useArray with ownership set to \b false.
7151  * 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
7152  * \b nbOfCompo=1 and \bnbOfTuples==this->_nb_of_elem.
7153  */
7154 DataArrayInt *DataArrayIntTuple::buildDAInt(int nbOfTuples, int nbOfCompo) const
7155 {
7156   return this->buildDA(nbOfTuples,nbOfCompo);
7157 }