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