Salome HOME
Windows porting
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingPartDefinition.cxx
1 // Copyright (C) 2007-2016  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (EDF R&D)
20
21 #include "MEDCouplingPartDefinition.hxx"
22
23 #include <functional>
24 #include <sstream>
25
26 using namespace MEDCoupling;
27
28 PartDefinition *PartDefinition::New(int start, int stop, int step)
29 {
30   return SlicePartDefinition::New(start,stop,step);
31 }
32
33 PartDefinition *PartDefinition::New(DataArrayInt *listOfIds)
34 {
35   return DataArrayPartDefinition::New(listOfIds);
36 }
37
38 PartDefinition *PartDefinition::Unserialize(std::vector<int>& tinyInt, std::vector< MCAuto<DataArrayInt> >& bigArraysI)
39 {
40   if(tinyInt.empty())
41     {
42       MCAuto<PartDefinition> ret(DataArrayPartDefinition::New(bigArraysI.back()));
43       bigArraysI.pop_back();
44       return ret.retn();
45     }
46   else if(tinyInt.size()==3)
47     {
48       MCAuto<PartDefinition> ret(SlicePartDefinition::New(tinyInt[0],tinyInt[1],tinyInt[2]));
49       tinyInt.erase(tinyInt.begin(),tinyInt.begin()+3);
50       return ret.retn();
51     }
52   else
53     throw INTERP_KERNEL::Exception("PartDefinition::Unserialize");
54 }
55
56 PartDefinition::~PartDefinition()
57 {
58 }
59
60 DataArrayPartDefinition *DataArrayPartDefinition::New(DataArrayInt *listOfIds)
61 {
62   return new DataArrayPartDefinition(listOfIds);
63 }
64
65 bool DataArrayPartDefinition::isEqual(const PartDefinition *other, std::string& what) const
66 {
67   if(!other)
68     {
69       what="DataArrayPartDefinition::isEqual : other is null, this is not null !";
70       return false;
71     }
72   const DataArrayPartDefinition *otherC(dynamic_cast<const DataArrayPartDefinition *>(other));
73   if(!otherC)
74     {
75       what="DataArrayPartDefinition::isEqual : other is not DataArrayPartDefinition !";
76       return false;
77     }
78   const DataArrayInt *arr0(_arr),*arr1(otherC->_arr);
79   if(!arr0 && !arr1)
80     return true;
81   if((arr0 && !arr1) || (!arr0 && arr1))
82     {
83       what="DataArrayPartDefinition::isEqual : array is not defined both in other and this !";
84       return false;
85     }
86   std::string what1;
87   bool ret(arr0->isEqualIfNotWhy(*arr1,what1));
88   if(!ret)
89     {
90       what=std::string("DataArrayPartDefinition::isEqual : arrays are not equal :\n")+what1;
91       return false;
92     }
93   return true;
94 }
95
96 DataArrayPartDefinition *DataArrayPartDefinition::deepCopy() const
97 {
98   const DataArrayInt *arr(_arr);
99   if(!arr)
100     throw INTERP_KERNEL::Exception("DataArrayPartDefinition::deepCopy : array is null !");
101   return DataArrayPartDefinition::New(const_cast<DataArrayInt *>(arr));
102 }
103
104 int DataArrayPartDefinition::getNumberOfElems() const
105 {
106   checkInternalArrayOK();
107   return _arr->getNumberOfTuples();
108 }
109
110 PartDefinition *DataArrayPartDefinition::operator+(const PartDefinition& other) const
111 {
112   const PartDefinition *otherPt(&other);
113   if(!otherPt)
114     throw INTERP_KERNEL::Exception("DataArrayPartDefinition::operator+ : NULL input !");
115   const DataArrayPartDefinition *other1(dynamic_cast<const DataArrayPartDefinition *>(otherPt));
116   if(other1)
117     return add1(other1);
118   const SlicePartDefinition *other2(dynamic_cast<const SlicePartDefinition *>(otherPt));
119   if(other2)
120     return add2(other2);
121   throw INTERP_KERNEL::Exception("DataArrayPartDefinition::operator+ : unrecognized type in input !");
122 }
123
124 std::string DataArrayPartDefinition::getRepr() const
125 {
126   std::ostringstream oss; oss << "DataArray Part : ";
127   const DataArrayInt *arr(_arr);
128   if(arr)
129     arr->reprQuickOverview(oss);
130   else
131     oss << "No Data !";
132   return oss.str();
133 }
134
135 /*!
136  * This method operates FoG where F is \a this and G is \a other.
137  * Example : if \a other is SlicePart(4,14,1) and if \a this is DataArrayPartDefinition([0,1,2,3,6,7,8,9]) -> DataArrayPartDefinition([4,5,6,7,11,12,13]) will be returned
138  */
139 PartDefinition *DataArrayPartDefinition::composeWith(const PartDefinition *other) const
140 {
141   if(!other)
142     throw INTERP_KERNEL::Exception("DataArrayPartDefinition::composeWith : input PartDef must be not NULL !");
143   checkConsistencyLight();
144   other->checkConsistencyLight();
145   const SlicePartDefinition *spd(dynamic_cast<const SlicePartDefinition *>(other));
146   if(spd)
147     {//special case for optim
148       int a(0),b(0),c(0);
149       spd->getSlice(a,b,c);
150       if(c==1)
151         {
152           MCAuto<DataArrayInt> arr(DataArrayInt::New());
153           arr->alloc(_arr->getNumberOfTuples(),1);
154           std::transform(_arr->begin(),_arr->end(),arr->getPointer(),std::bind2nd(std::plus<int>(),a));
155           return DataArrayPartDefinition::New(arr);
156         }
157     }
158   //
159   MCAuto<DataArrayInt> arr1(other->toDAI());
160   MCAuto<DataArrayInt> arr2(arr1->selectByTupleIdSafe(_arr->begin(),_arr->end()));
161   return DataArrayPartDefinition::New(arr2);
162 }
163
164 void DataArrayPartDefinition::checkConsistencyLight() const
165 {
166   CheckInternalArrayOK(_arr);
167 }
168
169 /*!
170  * This method tries to simplify \a this if possible.
171  * 
172  * \return a new reference (equal to this) to be decrRefed.
173  */
174 PartDefinition *DataArrayPartDefinition::tryToSimplify() const
175 {
176   checkConsistencyLight();
177   int a(0),b(0),c(0);
178   if(_arr->isRange(a,b,c))
179     {
180       return SlicePartDefinition::New(a,b,c);
181     }
182   else
183     {
184       PartDefinition *ret(const_cast<DataArrayPartDefinition *>(this));
185       ret->incrRef();
186       return ret;
187     }
188 }
189
190 void DataArrayPartDefinition::serialize(std::vector<int>& tinyInt, std::vector< MCAuto<DataArrayInt> >& bigArraysI) const
191 {
192   bigArraysI.push_back(_arr);
193 }
194
195 DataArrayInt *DataArrayPartDefinition::toDAI() const
196 {
197   checkInternalArrayOK();
198   const DataArrayInt *arr(_arr);
199   DataArrayInt *arr2(const_cast<DataArrayInt *>(arr));
200   arr2->incrRef();
201   return arr2;
202 }
203
204 DataArrayPartDefinition::DataArrayPartDefinition(DataArrayInt *listOfIds)
205 {
206   CheckInternalArrayOK(listOfIds);
207   _arr=listOfIds;
208   _arr->incrRef();
209 }
210
211 void DataArrayPartDefinition::checkInternalArrayOK() const
212 {
213   CheckInternalArrayOK(_arr);
214 }
215
216 void DataArrayPartDefinition::CheckInternalArrayOK(const DataArrayInt *listOfIds)
217 {
218   if(!listOfIds || !listOfIds->isAllocated() || listOfIds->getNumberOfComponents()!=1)
219     throw INTERP_KERNEL::Exception("DataArrayPartDefinition::CheckInternalArrayOK : Input list must be not null allocated and with one components !");
220 }
221
222 void DataArrayPartDefinition::updateTime() const
223 {
224   if((const DataArrayInt *)_arr)
225     updateTimeWith(*_arr);
226 }
227
228 std::size_t DataArrayPartDefinition::getHeapMemorySizeWithoutChildren() const
229 {
230   return sizeof(DataArrayPartDefinition);
231 }
232
233 std::vector<const BigMemoryObject *> DataArrayPartDefinition::getDirectChildrenWithNull() const
234 {
235   std::vector<const BigMemoryObject *> ret(1,(const DataArrayInt *)_arr);
236   return ret;
237 }
238
239 DataArrayPartDefinition *DataArrayPartDefinition::add1(const DataArrayPartDefinition *other) const
240 {
241   MCAuto<DataArrayInt> a1(toDAI()),a2(other->toDAI());
242   MCAuto<DataArrayInt> a3(DataArrayInt::Aggregate(a1,a2,0));
243   a3->sort();
244   return DataArrayPartDefinition::New(a3);
245 }
246
247 DataArrayPartDefinition *DataArrayPartDefinition::add2(const SlicePartDefinition *other) const
248 {
249   MCAuto<DataArrayInt> a1(toDAI()),a2(other->toDAI());
250   MCAuto<DataArrayInt> a3(DataArrayInt::Aggregate(a1,a2,0));
251   a3->sort();
252   return DataArrayPartDefinition::New(a3);
253 }
254
255 DataArrayPartDefinition::~DataArrayPartDefinition()
256 {
257 }
258
259 SlicePartDefinition *SlicePartDefinition::New(int start, int stop, int step)
260 {
261   return new SlicePartDefinition(start,stop,step);
262 }
263
264 bool SlicePartDefinition::isEqual(const PartDefinition *other, std::string& what) const
265 {
266   if(!other)
267     {
268       what="SlicePartDefinition::isEqual : other is null, this is not null !";
269       return false;
270     }
271   const SlicePartDefinition *otherC(dynamic_cast<const SlicePartDefinition *>(other));
272   if(!otherC)
273     {
274       what="SlicePartDefinition::isEqual : other is not SlicePartDefinition !";
275       return false;
276     }
277   bool ret((_start==otherC->_start) && (_stop==otherC->_stop) && (_step==otherC->_step));
278   if(!ret)
279     {
280       what="SlicePartDefinition::isEqual : values are not the same !";
281       return false;
282     }
283   return true;
284 }
285
286 SlicePartDefinition *SlicePartDefinition::deepCopy() const
287 {
288   return SlicePartDefinition::New(_start,_stop,_step);
289 }
290
291 DataArrayInt *SlicePartDefinition::toDAI() const
292 {
293   return DataArrayInt::Range(_start,_stop,_step);
294 }
295
296 int SlicePartDefinition::getNumberOfElems() const
297 {
298   return DataArray::GetNumberOfItemGivenBES(_start,_stop,_step,"SlicePartDefinition::getNumberOfElems");
299 }
300
301 PartDefinition *SlicePartDefinition::operator+(const PartDefinition& other) const
302 {
303   const PartDefinition *otherPt(&other);
304   if(!otherPt)
305     throw INTERP_KERNEL::Exception("DataArrayPartDefinition::operator+ : NULL input !");
306   const DataArrayPartDefinition *other1(dynamic_cast<const DataArrayPartDefinition *>(otherPt));
307   if(other1)
308     return add1(other1);
309   const SlicePartDefinition *other2(dynamic_cast<const SlicePartDefinition *>(otherPt));
310   if(other2)
311     return add2(other2);
312   throw INTERP_KERNEL::Exception("SlicePartDefinition::operator+ : unrecognized type in input !");
313 }
314
315 /*!
316  * This method operates FoG where F is \a this and G is \a other.
317  * Example : if \a this is SlicePart(4,6,1) and if \a other is DataArrayPartDefinition([12,13,17,18,22,28,34,44]) -> DataArrayPartDefinition([22,28]) will be returned
318  */
319 PartDefinition *SlicePartDefinition::composeWith(const PartDefinition *other) const
320 {
321   if(!other)
322     throw INTERP_KERNEL::Exception("SlicePartDefinition::composeWith : input PartDef must be not NULL !");
323   checkConsistencyLight();
324   other->checkConsistencyLight();
325   MCAuto<DataArrayInt> arr(other->toDAI());
326   MCAuto<DataArrayInt> arr1(arr->selectByTupleIdSafeSlice(_start,_stop,_step));
327   return DataArrayPartDefinition::New(arr1);
328 }
329
330 /*!
331  * Do nothing it is not a bug.
332  */
333 void SlicePartDefinition::checkConsistencyLight() const
334 {
335 }
336
337 /*!
338  * Return \a this (because it cannot be simplified)
339  * 
340  * \return a new reference (equal to this) to be decrRefed.
341  */
342 PartDefinition *SlicePartDefinition::tryToSimplify() const
343 {
344   PartDefinition *ret(const_cast<SlicePartDefinition *>(this));
345   ret->incrRef();
346   return ret;
347 }
348
349 void SlicePartDefinition::serialize(std::vector<int>& tinyInt, std::vector< MCAuto<DataArrayInt> >& bigArraysI) const
350 {
351   tinyInt.push_back(_start);
352   tinyInt.push_back(_stop);
353   tinyInt.push_back(_step);
354 }
355
356 std::string SlicePartDefinition::getRepr() const
357 {
358   std::ostringstream oss;
359   oss << "Slice is defined with : start=" << _start << " stop=" << _stop << " step=" << _step;
360   return oss.str();
361 }
362
363 int SlicePartDefinition::getEffectiveStop() const
364 {
365   int nbElems(DataArray::GetNumberOfItemGivenBES(_start,_stop,_step,"SlicePartDefinition::getEffectiveStop"));
366   return _start+nbElems*_step;
367 }
368
369 void SlicePartDefinition::getSlice(int& start, int& stop, int& step) const
370 {
371   start=_start;
372   stop=_stop;
373   step=_step;
374 }
375
376 SlicePartDefinition::SlicePartDefinition(int start, int stop, int step):_start(start),_stop(stop),_step(step)
377 {
378 }
379
380 /*!
381  * No child ! It is the leaf ! So no implementation.
382  */
383 void SlicePartDefinition::updateTime() const
384 {
385 }
386
387 std::size_t SlicePartDefinition::getHeapMemorySizeWithoutChildren() const
388 {
389   return sizeof(SlicePartDefinition);
390 }
391
392 std::vector<const BigMemoryObject *> SlicePartDefinition::getDirectChildrenWithNull() const
393 {
394   return std::vector<const BigMemoryObject *>();
395 }
396
397 DataArrayPartDefinition *SlicePartDefinition::add1(const DataArrayPartDefinition *other) const
398 {
399   MCAuto<DataArrayInt> a1(toDAI()),a2(other->toDAI());
400   MCAuto<DataArrayInt> a3(DataArrayInt::Aggregate(a1,a2,0));
401   a3->sort();
402   return DataArrayPartDefinition::New(a3);
403 }
404
405 PartDefinition *SlicePartDefinition::add2(const SlicePartDefinition *other) const
406 {
407   if(_step==other->_step && getEffectiveStop()==other->_start)
408     {
409       return SlicePartDefinition::New(_start,other->_stop,_step);
410     }
411   else
412     {
413       MCAuto<DataArrayInt> a1(toDAI()),a2(other->toDAI());
414       MCAuto<DataArrayInt> a3(DataArrayInt::Aggregate(a1,a2,0));
415       a3->sort();
416       return DataArrayPartDefinition::New(a3);
417     }
418 }
419
420 SlicePartDefinition::~SlicePartDefinition()
421 {
422 }