Salome HOME
ParaUMesh.redistributeCells implementation.
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingSkyLineArray.cxx
1 // Copyright (C) 2007-2020  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
20 #include "MEDCouplingSkyLineArray.hxx"
21
22 #include <sstream>
23 #include <deque>
24 #include <set>
25
26 using namespace MEDCoupling;
27
28 MEDCouplingSkyLineArray::MEDCouplingSkyLineArray():
29   _super_index( DataArrayIdType::New() ), _index( DataArrayIdType::New() ), _values( DataArrayIdType::New() )
30 {
31 }
32
33 MEDCouplingSkyLineArray::~MEDCouplingSkyLineArray()
34 {
35 }
36
37 MEDCouplingSkyLineArray* MEDCouplingSkyLineArray::New()
38 {
39   return new MEDCouplingSkyLineArray();
40 }
41
42 MEDCouplingSkyLineArray* MEDCouplingSkyLineArray::New( const std::vector<mcIdType>& index,
43                                                        const std::vector<mcIdType>& value )
44 {
45   MEDCouplingSkyLineArray * ret = new MEDCouplingSkyLineArray();
46   ret->_index->reserve( index.size() );
47   ret->_index->insertAtTheEnd( index.begin(), index.end() );
48   ret->_values->reserve( value.size() );
49   ret->_values->insertAtTheEnd( value.begin(), value.end() );
50   return ret;
51 }
52
53 MEDCouplingSkyLineArray* MEDCouplingSkyLineArray::New( DataArrayIdType* index, DataArrayIdType* value )
54 {
55   MEDCouplingSkyLineArray* ret = new MEDCouplingSkyLineArray();
56   ret->set(index, value);
57   return ret;
58 }
59
60 MEDCouplingSkyLineArray* MEDCouplingSkyLineArray::New( const MEDCouplingSkyLineArray & other )
61 {
62   MEDCouplingSkyLineArray* ret = new MEDCouplingSkyLineArray();
63   ret->_super_index = other._super_index;
64   ret->_index = other._index;
65   ret->_values = other._values;
66   return ret;
67 }
68
69 /**! Build a three level SkyLine array from the dynamic connectivity of a dynamic mesh (i.e. containing only
70  * polyhedrons or polygons).
71  * The input arrays are deep copied, contrary to the other ctors.
72  */
73 MEDCouplingSkyLineArray * MEDCouplingSkyLineArray::BuildFromPolyhedronConn( const DataArrayIdType* c, const DataArrayIdType* cI )
74 {
75   using namespace std;
76
77   MEDCouplingSkyLineArray* ret = new MEDCouplingSkyLineArray();
78
79   const mcIdType * cP(c->begin()), * cIP(cI->begin());
80   mcIdType prev = -1;
81   if (c->getNbOfElems() != *(cI->end()-1))
82     throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::BuildFromDynamicConn: misformatted connectivity (wrong nb of tuples)!");
83   for (mcIdType i=0; i < cI->getNbOfElems(); i++)
84     {
85       mcIdType j = cIP[i];
86       if (cIP[i] < prev)
87         throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::BuildFromDynamicConn: misformatted connectivity (indices not monotonic ascending)!");
88       prev = cIP[i];
89       if (i!=cI->getNbOfElems()-1)
90         if (cP[j] != INTERP_KERNEL::NORM_POLYHED)
91           throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::BuildFromDynamicConn: connectivity containing other types than POLYHED!");
92     }
93
94   vector<mcIdType> superIdx, idx, vals;
95   mcIdType cnt = 0, cnt2 = 0;
96   superIdx.reserve(cI->getNbOfElems());
97   superIdx.push_back(0);
98   idx.push_back(0);
99   vals.resize(c->getNbOfElems()); // too much because of the type and the -1, but still better than push_back().
100   for (mcIdType i=0; i < cI->getNbOfElems()-1; i++)
101     {
102       mcIdType start = cIP[i]+1, end = cIP[i+1];
103       mcIdType * work = vals.data() + cnt;
104       const mcIdType * w = cP+start;
105       const mcIdType * w2 = find(w, cP+end, -1);
106       while (w2 != cP+end)
107         {
108           copy(w, w2, work);
109           mcIdType d = ToIdType(distance(w, w2));
110           cnt += d; work +=d;
111           idx.push_back(cnt); cnt2++;
112           w = w2+1;  // skip the -1
113           w2 = find(w, cP+end, -1);
114         }
115       copy(w, cP+end, work);
116       cnt += ToIdType(distance(w, cP+end));
117       idx.push_back(cnt); cnt2++;
118       superIdx.push_back(cnt2);
119     }
120   ret->_super_index->alloc(superIdx.size(),1);
121   copy(superIdx.begin(), superIdx.end(), ret->_super_index->getPointer());
122   ret->_index->alloc(idx.size(),1);
123   copy(idx.begin(), idx.end(), ret->_index->getPointer());
124   ret->_values->alloc(cnt,1);
125   copy(vals.begin(), vals.begin()+cnt, ret->_values->getPointer());
126
127   return ret;
128 }
129
130 /**
131  * Convert a three-level SkyLineArray into a polyhedral connectivity.
132  * The super-packs are interpreted as cell description, and the packs represent the face connectivity.
133  */
134 void MEDCouplingSkyLineArray::convertToPolyhedronConn( MCAuto<DataArrayIdType>& c,  MCAuto<DataArrayIdType>& cI) const
135 {
136   // TODO: in this case an iterator would be nice
137   using namespace std;
138
139   checkSuperIndex("convertToPolyhedronConn");
140
141   const mcIdType * siP(_super_index->begin()), * iP(_index->begin()), *vP(_values->begin());
142   mcIdType cnt = 0;
143   cI->alloc(_super_index->getNbOfElems(),1);  // same number of super packs as number of cells
144   mcIdType * cIVecP(cI->getPointer());
145   MCAuto <DataArrayIdType> dsi = _index->deltaShiftIndex();
146   mcIdType sz = dsi->accumulate((std::size_t)0) + ToIdType(dsi->getNbOfElems());  // think about it: one slot for the type, -1 at the end of each face of the cell
147   c->alloc(sz, 1);
148   mcIdType * cVecP(c->getPointer());
149
150   for ( mcIdType i=0; i < _super_index->getNbOfElems()-1; i++)
151      {
152        cIVecP[i]= cnt;
153        mcIdType endId = siP[i+1];
154        cVecP[cnt++] = INTERP_KERNEL::NORM_POLYHED;
155        for (mcIdType j=siP[i]; j < endId; j++)
156          {
157            mcIdType startId2 = iP[j], endId2 = iP[j+1];
158            copy(vP+startId2, vP+endId2, cVecP+cnt);
159            cnt += endId2-startId2;
160            if(j != endId-1)
161              cVecP[cnt++] = -1;
162          }
163      }
164   cIVecP[_super_index->getNbOfElems()-1] = cnt;
165 }
166
167 std::size_t MEDCouplingSkyLineArray::getHeapMemorySizeWithoutChildren() const
168 {
169   return _index->getHeapMemorySizeWithoutChildren()+_values->getHeapMemorySizeWithoutChildren()+_super_index->getHeapMemorySizeWithoutChildren();
170 }
171
172 std::vector<const BigMemoryObject *> MEDCouplingSkyLineArray::getDirectChildrenWithNull() const
173 {
174   std::vector<const BigMemoryObject *> ret;
175   ret.push_back(_super_index);
176   ret.push_back(_index);
177   ret.push_back(_values);
178   return ret;
179 }
180
181
182 void MEDCouplingSkyLineArray::set( DataArrayIdType* index, DataArrayIdType* value )
183 {
184   _index=index;
185   _values=value;
186   if ( (DataArrayIdType*)_index ) _index->incrRef();
187   else                            _index = DataArrayIdType::New();
188   if ( (DataArrayIdType*)_values ) _values->incrRef();
189   else                             _values = DataArrayIdType::New();
190 }
191
192 void MEDCouplingSkyLineArray::set3( DataArrayIdType* superIndex, DataArrayIdType* index, DataArrayIdType* value )
193 {
194   _super_index=superIndex;
195   if ( (DataArrayIdType*)_super_index ) _super_index->incrRef();
196   else                                  _super_index = DataArrayIdType::New();
197   set(index, value);
198 }
199
200 DataArrayIdType* MEDCouplingSkyLineArray::getSuperIndexArray() const
201 {
202   return const_cast<MEDCouplingSkyLineArray*>(this)->_super_index;
203 }
204
205
206 DataArrayIdType* MEDCouplingSkyLineArray::getIndexArray() const
207 {
208   return const_cast<MEDCouplingSkyLineArray*>(this)->_index;
209 }
210
211 DataArrayIdType* MEDCouplingSkyLineArray::getValuesArray() const
212 {
213   return const_cast<MEDCouplingSkyLineArray*>(this)->_values;
214 }
215
216 MEDCouplingSkyLineArray *MEDCouplingSkyLineArray::deepCopy() const
217 {
218   MCAuto<DataArrayIdType> indexCpy(this->_index->deepCopy());
219   MCAuto<DataArrayIdType> valuesCpy(this->_values->deepCopy());
220   MCAuto<MEDCouplingSkyLineArray> ret(MEDCouplingSkyLineArray::New(indexCpy,valuesCpy));
221   if(_super_index.isNotNull())
222   {
223     MCAuto<DataArrayIdType> superIndexCpy(this->_super_index->deepCopy());
224     ret->_super_index = superIndexCpy;
225   }
226   return ret.retn();
227 }
228
229 void MEDCouplingSkyLineArray::checkSuperIndex(const std::string& func) const
230 {
231   if (!_super_index->getNbOfElems())
232     {
233       std::ostringstream oss;
234       oss << "MEDCouplingSkyLineArray::"<< func << ": not a three level SkyLineArray! Method is not available for two-level SkyLineArray.";
235       throw INTERP_KERNEL::Exception(oss.str());
236     }
237 }
238
239 void MEDCouplingSkyLineArray::validSuperIndex(const std::string& func, mcIdType superIndex) const
240 {
241   if(superIndex < 0 || superIndex >= _super_index->getNbOfElems())
242     {
243       std::ostringstream oss;
244       oss << "MEDCouplingSkyLineArray::" << func <<  ": invalid super index!";
245       throw INTERP_KERNEL::Exception(oss.str());
246     }
247 }
248
249 void MEDCouplingSkyLineArray::validIndex(const std::string& func, mcIdType idx) const
250 {
251   if(idx < 0 || idx >= _index->getNbOfElems())
252     {
253       std::ostringstream oss;
254       oss << "MEDCouplingSkyLineArray::" << func <<  ": invalid index!";
255       throw INTERP_KERNEL::Exception(oss.str());
256     }
257 }
258
259 void MEDCouplingSkyLineArray::validSuperIndexAndIndex(const std::string& func, mcIdType superIndex, mcIdType index) const
260 {
261   validSuperIndex(func, superIndex);
262   mcIdType idx = _super_index->begin()[superIndex] + index;
263   if(idx < 0 || idx >= _index->getNbOfElems())
264     {
265       std::ostringstream oss;
266       oss << "MEDCouplingSkyLineArray::" << func <<  ": invalid index!";
267       throw INTERP_KERNEL::Exception(oss.str());
268     }
269 }
270
271 std::string MEDCouplingSkyLineArray::simpleRepr() const
272 {
273   std::ostringstream oss;
274   oss << "MEDCouplingSkyLineArray (" << this << ")" << std::endl;
275   MCAuto<DataArrayIdType> super_index = _super_index->deepCopy();
276   if (_super_index->getNbOfElems())
277     oss << "   Nb of super-packs: " << getSuperNumberOf() << std::endl;
278   else
279     {
280       super_index->alloc(2,1);
281       super_index->setIJSilent(0,0,0);
282       super_index->setIJSilent(1,0,_index->getNbOfElems()-1);
283     }
284   oss << "   Nb of packs: " << getNumberOf() << std::endl;
285   oss << "   Nb of values: " << getLength() << std::endl;
286
287   if (_super_index->getNbOfElems())
288     {
289       oss << "   Super-indices:" << std::endl;
290       oss << "   ";
291       const mcIdType * i = _super_index->begin();
292       for ( ; i != _super_index->end(); ++i )
293         oss << *i << " ";
294       oss << std::endl;
295     }
296
297   oss << "   Indices:" << std::endl;
298   oss << "   ";
299   const mcIdType * i = _index->begin();
300   for ( ; i != _index->end(); ++i )
301     oss << *i << " ";
302   oss << std::endl;
303   oss << "   Values:" << std::endl;
304   oss << "     ";
305   const mcIdType * v = _values->begin();
306   mcIdType cnt = 0, cntI = 0;
307   i = _index->begin();
308   for ( const mcIdType * si = super_index->begin()+1; v != _values->end(); ++v, ++cnt )
309     {
310       if ( cnt == *i )
311         {
312           if ( cntI == *si && cnt != 0)
313             {
314               oss << std::endl << "     ";
315               ++si;
316             }
317
318           oss << "| ";
319           ++i; ++cntI;
320         }
321       oss << *v << " ";
322     }
323   oss << std::endl;
324
325   return oss.str();
326 }
327
328 MEDCouplingSkyLineArray *MEDCouplingSkyLineArray::groupPacks(const DataArrayIdType *indexedPacks) const
329 {
330   indexedPacks->checkAllocated();
331   if( indexedPacks->getNumberOfComponents() != 1 )
332     throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::groupPacks : number of components must be 1 !");
333   std::size_t nbTuples(indexedPacks->getNumberOfTuples());
334   if( nbTuples == 0 )
335     throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::groupPacks : number of tuples must be > 0 !");
336   const DataArrayIdType *index(this->getIndexArray());
337   MCAuto<DataArrayIdType> partIndex(index->selectByTupleIdSafe(indexedPacks->begin(),indexedPacks->end()));
338   MCAuto<MEDCouplingSkyLineArray> ret(MEDCouplingSkyLineArray::New(partIndex,this->getValuesArray()));
339   return ret.retn();
340 }
341
342 MEDCouplingSkyLineArray *MEDCouplingSkyLineArray::uniqueNotSortedByPack() const
343 {
344   mcIdType nbPacks(this->getNumberOf());
345   MCAuto<DataArrayIdType> retIndex(DataArrayIdType::New()); retIndex->alloc(nbPacks+1,1);
346   const mcIdType *valuesPtr(this->_values->begin()),*indexPtr(this->_index->begin());
347   mcIdType *retIndexPtr(retIndex->getPointer()); *retIndexPtr = 0;
348   for(mcIdType i = 0 ; i < nbPacks ; ++i, ++retIndexPtr)
349   {
350     std::set<mcIdType> s(valuesPtr+indexPtr[i],valuesPtr+indexPtr[i+1]);
351     retIndexPtr[1] = retIndexPtr[0] + ToIdType(s.size());
352   }
353   MCAuto<DataArrayIdType> retValues(DataArrayIdType::New()); retValues->alloc(retIndex->back(),1);
354   mcIdType *retValuesPtr(retValues->getPointer());
355   for(mcIdType i = 0 ; i < nbPacks ; ++i)
356   {
357     std::set<mcIdType> s(valuesPtr+indexPtr[i],valuesPtr+indexPtr[i+1]);
358     retValuesPtr = std::copy(s.begin(),s.end(),retValuesPtr);
359   }
360   MCAuto<MEDCouplingSkyLineArray> ret(MEDCouplingSkyLineArray::New(retIndex,retValues));
361   return ret.retn();
362 }
363 /*!
364  * Take as input skylinearrays containing the same number of packs ( \a this->getNumberOf ).
365  * For each packs, this method aggregates corresponding pack in \a sks.
366  * 
367  * \throw if either a lenght of not nullptr instances in \a sks is zero or if number of packs of not nullptr instances in \a sks is not the same.
368  * \return a newly allocated skyline array that is the aggregated packs of inputs
369  */
370 MEDCouplingSkyLineArray *MEDCouplingSkyLineArray::AggregatePacks(const std::vector<const MEDCouplingSkyLineArray *>& sks)
371 {
372   std::vector<const MEDCouplingSkyLineArray *>sksEff;
373   mcIdType nbOfPacks(std::numeric_limits<mcIdType>::max());
374   constexpr char MSG[]="MEDCouplingSkyLineArray::AggregatePacks : ";
375   for(auto sk : sks)
376   {
377     if(sk)
378     {
379       mcIdType curNbPacks(sk->getNumberOf());
380       if(sksEff.empty())
381         nbOfPacks = curNbPacks;
382       if(nbOfPacks != curNbPacks)
383       {
384         std::ostringstream oss; oss << MSG << "first not null input ska has " << nbOfPacks << " whereas there is presence of ska with " << curNbPacks << " !";
385         throw INTERP_KERNEL::Exception(oss.str());
386       }
387       sksEff.push_back(sk);
388     }
389   }
390   if(sksEff.empty())
391   {
392     std::ostringstream oss; oss << MSG << "input vector contains no not nullptr elements !";
393     throw INTERP_KERNEL::Exception(oss.str());
394   }
395   //
396   MCAuto<DataArrayIdType> index(DataArrayIdType::New()); index->alloc(nbOfPacks+1,1);
397   mcIdType *indexPtr(index->getPointer()); *indexPtr=0;
398   std::vector<const mcIdType *> indicesIn(SkyLineArrayIndexIterator(0,&sksEff),SkyLineArrayIndexIterator(sksEff.size(),&sksEff));
399   for( mcIdType packId = 0 ; packId < nbOfPacks ; ++packId, ++indexPtr )
400   {
401     mcIdType nbOfAggPacks(0);
402     std::for_each(indicesIn.begin(),indicesIn.end(),[packId,&nbOfAggPacks](const mcIdType *elt) { nbOfAggPacks+=elt[packId+1]-elt[packId]; });
403     indexPtr[1] = indexPtr[0] + nbOfAggPacks;
404   }
405   mcIdType nbOfTuplesOut(index->back());
406   MCAuto<DataArrayIdType> values(DataArrayIdType::New()); values->alloc(nbOfTuplesOut,1);
407   mcIdType *valuesPtr(values->getPointer());
408   // let's go to populate values array
409   std::vector<const mcIdType *> valuesIn(SkyLineArrayValuesIterator(0,&sksEff),SkyLineArrayValuesIterator(sksEff.size(),&sksEff));
410   for( mcIdType packId = 0 ; packId < nbOfPacks ; ++packId )
411   {
412     std::size_t pos(0);
413     std::for_each(valuesIn.begin(),valuesIn.end(),[packId,&indicesIn,&valuesPtr,&pos](const mcIdType *elt)
414     { valuesPtr=std::copy(elt+indicesIn[pos][packId],elt+indicesIn[pos][packId+1],valuesPtr); ++pos; }
415     );
416   }
417   //
418   MCAuto<MEDCouplingSkyLineArray> ret(MEDCouplingSkyLineArray::New(index,values));
419   return ret.retn();
420 }
421
422 /**
423  * For a 2- or 3-level SkyLine array, return a copy of the absolute pack with given identifier.
424  */
425 void MEDCouplingSkyLineArray::getSimplePackSafe(const mcIdType absolutePackId, std::vector<mcIdType> & pack) const
426 {
427   if(absolutePackId < 0 || absolutePackId >= _index->getNbOfElems())
428     throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::getPackSafe: invalid index!");
429   const mcIdType * iP(_index->begin()), *vP(_values->begin());
430   mcIdType sz = iP[absolutePackId+1]-iP[absolutePackId];
431   pack.resize(sz);
432   std::copy(vP+iP[absolutePackId], vP+iP[absolutePackId+1],pack.begin());
433 }
434
435 /**
436  * Same as getPackSafe, but directly returns a pointer to the internal data with the size of the pack.
437  */
438 const mcIdType * MEDCouplingSkyLineArray::getSimplePackSafePtr(const mcIdType absolutePackId, mcIdType & packSize) const
439 {
440   if(absolutePackId < 0 || absolutePackId >= _index->getNbOfElems())
441     throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::getPackSafe: invalid index!");
442   const mcIdType * iP(_index->begin()), *vP(_values->begin());
443   packSize = iP[absolutePackId+1]-iP[absolutePackId];
444   return vP+iP[absolutePackId];
445 }
446
447
448 /**!
449  * For each given super-pack ID, provide the sub-index of the first matching pack. If no matching pack is found for the
450  * given super-pack -1 is returned.
451  * \param[in] superPackIndices the list of super-packs that should be inspected
452  * \param[in] packBg the pack that the function is looking for in each of the provided super-pack
453  * \param[in] packEnd the pack that the function is looking for in each of the provided super-pack
454  * \param[out] a vector of mcIdType, having the same size as superPackIndices and containing for each inspected super-pack
455  * the index of the first matching pack, or -1 if none found.
456  */
457 void MEDCouplingSkyLineArray::findPackIds(const std::vector<mcIdType> & superPackIndices,
458                                           const mcIdType *packBg, const mcIdType *packEnd,
459                                           std::vector<mcIdType>& out) const
460 {
461   using namespace std;
462
463   checkSuperIndex("findPackIds");
464
465   mcIdType packSz = ToIdType(std::distance(packBg, packEnd));
466   if (!packSz)
467     throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::findPackIds: void pack!");
468
469   out.resize(superPackIndices.size());
470   mcIdType i = 0;
471   const mcIdType * siP(_super_index->begin()), * iP(_index->begin()), *vP(_values->begin());
472   for(vector<mcIdType>::const_iterator it=superPackIndices.begin(); it!=superPackIndices.end(); ++it, i++)
473     {
474       out[i] = -1;
475       const mcIdType sPackIdx = *it;
476       // for each pack
477       for (mcIdType idx=siP[sPackIdx], j=0; idx < siP[sPackIdx+1]; idx++, j++)
478         {
479           if (packSz == (iP[idx+1] - iP[idx]))
480             if (equal(&vP[iP[idx]], &vP[iP[idx+1]], packBg))
481               {
482                 out[i] = j;
483                 break;
484               }
485         }
486     }
487 }
488
489 /**!
490  * Delete pack number 'idx' in super-pack number 'superIdx'.
491  * \param[in] superIdx is the super-pack number
492  * \param[in] idx is the pack index inside the super-pack 'superIdx'.
493  */
494 void MEDCouplingSkyLineArray::deletePack(const mcIdType superIdx, const mcIdType idx)
495 {
496   checkSuperIndex("deletePack");
497   validSuperIndexAndIndex("deletePack", superIdx, idx);
498
499   mcIdType * vP = _values->getPointer();
500   mcIdType * siP(_super_index->getPointer()), *iP(_index->getPointer());
501   const mcIdType start = iP[siP[superIdx]+idx], end = iP[siP[superIdx]+idx+1];
502   // _values
503   std::copy(vP+end, vP+_values->getNbOfElems(), vP+start);
504   _values->reAlloc(_values->getNbOfElems() - (end-start));
505
506   // _index
507   mcIdType nt = _index->getNbOfElems();
508   std::copy(iP+siP[superIdx]+idx+1, iP+nt, iP+siP[superIdx]+idx);
509   _index->reAlloc(nt-1); iP = _index->getPointer();  // better not forget this ...
510   for(mcIdType ii = siP[superIdx]+idx; ii < nt-1; ii++)
511     iP[ii] -= (end-start);
512
513   // _super_index
514   for(mcIdType ii = superIdx+1; ii < _super_index->getNbOfElems(); ii++)
515     (siP[ii])--;
516 }
517
518 void MEDCouplingSkyLineArray::deleteSimplePack(const mcIdType idx)
519 {
520   validIndex("deleteSimplePack", idx);
521   
522   mcIdType* iP(_index->getPointer());
523   const mcIdType start(iP[idx]), end(iP[idx+1]);
524
525   // _values
526   mcIdType initValSz=_values->getNbOfElems();
527   mcIdType deltaSz( start-end );  // should be negative
528   mcIdType *vP(_values->getPointer());
529   if (deltaSz < 0)
530     {
531       std::copy(vP+end, vP+initValSz, vP+start);
532       _values->reAlloc(initValSz+deltaSz);
533     }
534   else
535     throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::deleteSimplePack");
536   // _index
537   mcIdType nt=_index->getNbOfElems();
538   std::copy(iP+idx+1, iP+nt, iP+idx);
539   for(mcIdType ii = idx; ii < nt-1; ii++)
540     iP[ii] += deltaSz;
541   _index->reAlloc(nt-1);
542 }
543
544 void MEDCouplingSkyLineArray::replaceSimplePacks(const DataArrayIdType* idx, const std::vector<const DataArrayIdType*>& packs)
545 {    
546   if (idx->empty())
547     return;
548     
549   for (const mcIdType * id = idx->begin(); id != idx->end(); id++)
550     validIndex("deleteSimplePacks", *id);
551     
552   if (idx->getNbOfElems() != ToIdType( packs.size()))
553     throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::deleteSimplePacks: size of list of pack is incorrect");
554     
555   // copy _index, _values into a deque<set<mcIdType>>
556   std::deque< std::set<mcIdType> > valuesByIdx;
557   mcIdType* vP(_values->getPointer());
558   mcIdType* iP(_index->getPointer());
559   mcIdType nt = _index->getNbOfElems();
560   for (mcIdType ii = 0; ii < nt-1; ii++)
561     valuesByIdx.push_back(std::set<mcIdType>(vP+iP[ii], vP+iP[ii+1]));
562     
563   // modify the deque<set<mcIdType>> according to idx and packs
564   mcIdType ii(0);
565   for (const mcIdType *id = idx->begin(); id != idx->end(); id++)
566     {
567       valuesByIdx[*id] = std::set<mcIdType>(packs[ii]->begin(), packs[ii]->end());
568       ii++;
569     }
570   // copy back the deque<set<mcIdType>> into _index, _values
571   mcIdType valSz(0);
572   *iP = 0;
573   for (std::deque< std::set<mcIdType> >::const_iterator values=valuesByIdx.begin();values!=valuesByIdx.end();values++)
574     {
575       valSz += ToIdType((*values).size());
576       *(++iP) = valSz;
577     }
578   _values->reAlloc(valSz);
579   iP = _index->getPointer();
580   vP = _values->getPointer();
581   for (auto values : valuesByIdx)
582     {
583       std::copy(values.begin(), values.end(), vP+(*iP));
584       iP++;
585     }
586 }
587
588 void MEDCouplingSkyLineArray::deleteSimplePacks(const DataArrayIdType* idx)
589 {    
590   for (auto id = idx->begin(); id != idx->end(); id++)
591     validIndex("deleteSimplePacks", *id);
592   
593   std::set<mcIdType> packsToDelete(idx->begin(), idx->end());
594     
595   // _values
596   mcIdType* iP(_index->getPointer());
597   mcIdType initValSz = _values->getNbOfElems();
598   mcIdType *vP(_values->getPointer());
599   mcIdType end_prec(0),start_prec(0);
600   for(std::set<mcIdType>::const_iterator ii=packsToDelete.begin();ii!=packsToDelete.end();ii++)
601     {
602       mcIdType start = iP[*ii];
603       if (end_prec != 0)
604         std::copy(vP+end_prec, vP+start, vP+start_prec);
605       start_prec += start-end_prec;
606       end_prec = iP[*ii+1];
607     }
608   if (end_prec != 0)
609     std::copy(vP+end_prec, vP+initValSz, vP+start_prec);
610   _values->reAlloc(initValSz-(end_prec-start_prec));
611     
612   // _index
613   mcIdType nt = _index->getNbOfElems();
614   mcIdType offset = 0;
615   end_prec = 0;
616   start_prec = 0;
617   mcIdType deleted = 0;
618   for(std::set<mcIdType>::const_iterator ii=packsToDelete.begin();ii!=packsToDelete.end();ii++)
619     {
620       if (end_prec != 0)
621         {
622           std::copy(iP+end_prec, iP+*ii, iP+start_prec);
623           for (mcIdType i=start_prec; i<*ii; i++)
624             iP[i] -= offset;
625         }
626       offset += iP[*ii+1] - iP[*ii];
627       start_prec = *ii-deleted;
628       end_prec = *ii+1;
629       deleted += 1;
630     }
631   if (end_prec != 0)
632     {
633       std::copy(iP+end_prec, iP+nt, iP+start_prec);
634       for (mcIdType i=start_prec; i<nt; i++)
635         iP[i] -= offset;
636     }
637   _index->reAlloc(nt-deleted);
638 }
639
640 /**!
641  * Insert a new pack in super-pack at index 'superIdx'. The pack is inserted at the end of the pack list of the chosen super-pack.
642  */
643 void MEDCouplingSkyLineArray::pushBackPack(const mcIdType superIdx, const mcIdType * packBg, const mcIdType * packEnd)
644 {
645   using namespace std;
646
647   checkSuperIndex("pushBackPack");
648   validSuperIndex("pushBackPack", superIdx);
649
650   mcIdType *siP(_super_index->getPointer()), *iP(_index->getPointer());
651   const mcIdType sz(ToIdType(distance(packBg, packEnd)));
652
653   // _values
654   _values->reAlloc(_values->getNbOfElems()+sz);
655   mcIdType * vPE(_values->getPointer()+_values->getNbOfElems());
656   mcIdType *vP(_values->getPointer());
657   copy(vP+iP[siP[superIdx+1]], vPE-sz, vP+iP[siP[superIdx+1]]+sz);
658   // insert pack
659   copy(packBg, packEnd, vP+iP[siP[superIdx+1]]);
660
661   // _index
662   mcIdType nt = ToIdType(_index->getNbOfElems());
663   _index->reAlloc(nt+1); iP = _index->getPointer();
664   copy(iP+siP[superIdx+1]+1, iP+nt, iP+siP[superIdx+1]+2);
665   iP[siP[superIdx+1]+1] = iP[siP[superIdx+1]] + sz;
666   for(mcIdType ii = siP[superIdx+1]+2; ii < nt+1; ii++)
667     iP[ii] += sz;
668
669   // _super_index
670   for(mcIdType ii = superIdx+1; ii < _super_index->getNbOfElems(); ii++)
671     (siP[ii])++;
672 }
673
674 /**
675  * Replace pack with absolute index 'idx' with the provided new pack. Function can be used either
676  * for 2-level SkyLine or 3-level SkyLine.
677  */
678 void MEDCouplingSkyLineArray::replaceSimplePack(const mcIdType idx, const mcIdType * packBg, const mcIdType * packEnd)
679 {
680   validIndex("replaceSimplePack", idx);
681
682   mcIdType * iP(_index->getPointer());
683   mcIdType newSz = ToIdType(std::distance(packBg, packEnd));
684   const mcIdType start = iP[idx], end = iP[idx+1];
685
686   // _values
687   mcIdType initValSz = _values->getNbOfElems();
688   mcIdType deltaSz = newSz-(end-start);  // can be negative
689   if (deltaSz)
690     {
691       if (deltaSz > 0)
692         _values->reAlloc(initValSz+deltaSz);
693       mcIdType *vP(_values->getPointer());
694       std::copy(vP+end, vP+initValSz, vP+end+deltaSz);
695       if (deltaSz < 0)
696         _values->reAlloc(initValSz+deltaSz);
697     }
698
699   // copy new pack
700   std::copy(packBg, packEnd, _values->getPointer()+start);
701
702   // _index
703   for(mcIdType ii = idx+1; ii < _index->getNbOfElems(); ii++)
704     iP[ii] += deltaSz;
705 }
706
707 /**
708  * Replace pack with super index 'superIdx' and index 'idx' with the provided new pack.
709  * Function can be used only for 3-level SkyLine.
710  */
711 void MEDCouplingSkyLineArray::replacePack(const mcIdType superIdx, const mcIdType idx, const mcIdType *packBg, const mcIdType *packEnd)
712 {
713   checkSuperIndex("replacePack");
714   validSuperIndexAndIndex("replacePack", superIdx, idx);
715
716   mcIdType * siP(_super_index->getPointer()), *iP(_index->getPointer());
717   mcIdType newSz = ToIdType(std::distance(packBg, packEnd));
718   const mcIdType start = iP[siP[superIdx]+idx], end = iP[siP[superIdx]+idx+1];
719
720   // _values
721   mcIdType initValSz = _values->getNbOfElems();
722   mcIdType deltaSz = newSz-(end-start);  // can be negative
723   if (deltaSz)
724     {
725       if (deltaSz > 0)
726         _values->reAlloc(initValSz+deltaSz);
727       mcIdType *vP(_values->getPointer());
728       std::copy(vP+end, vP+initValSz, vP+end+deltaSz);
729       if (deltaSz < 0)
730         _values->reAlloc(initValSz+deltaSz);
731     }
732
733   // copy new pack
734   std::copy(packBg, packEnd, _values->getPointer()+start);
735
736   // _index
737   for(mcIdType ii = siP[superIdx]+idx+1; ii < _index->getNbOfElems(); ii++)
738     iP[ii] += deltaSz;
739 }