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