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