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