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