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