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