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