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