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