Salome HOME
Merge branch 'V9_5_BR'
[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 /*!
329  * Returns 2 SkyLineArrays with same number of packs than \a this.
330  * Each pack in \a this is split in 2 parts using \a threshold parameter as cut point.
331  * \a left part contains ids in \a this pack strictly lower than \a threshold
332  * \a right part contains ids in \a this pack greater or equal to \a threshold
333  */
334 void MEDCouplingSkyLineArray::thresholdPerPack(mcIdType threshold, MCAuto<MEDCouplingSkyLineArray>& left, MCAuto<MEDCouplingSkyLineArray>& right) const
335 {
336   mcIdType nbPacks(this->getNumberOf());
337   MCAuto<DataArrayIdType> lCount(DataArrayIdType::New()); lCount->alloc(nbPacks,1); lCount->fillWithZero();
338   mcIdType *lCountPtr(lCount->getPointerSilent());
339   const mcIdType *valuesPtr(this->_values->begin()),*indexPtr(this->_index->begin());
340   for(mcIdType i = 0 ; i < nbPacks ; ++i, ++lCountPtr)
341   {
342     *lCountPtr = ToIdType(std::count_if(valuesPtr+indexPtr[i],valuesPtr+indexPtr[i+1],[threshold](mcIdType elt) { return elt<threshold; }));
343   }
344   MCAuto<DataArrayIdType> sizeOfPacks(this->_index->deltaShiftIndex());
345   sizeOfPacks->substractEqual(lCount);
346   mcIdType leftNbOfVal(lCount->accumulate(std::size_t(0))),rightNbOfVal(sizeOfPacks->accumulate(std::size_t(0)));
347   lCount->computeOffsetsFull(); sizeOfPacks->computeOffsetsFull();
348   MCAuto<DataArrayIdType> leftValues(DataArrayIdType::New()); leftValues->alloc(leftNbOfVal,1);
349   MCAuto<DataArrayIdType> rightValues(DataArrayIdType::New()); rightValues->alloc(rightNbOfVal,1);
350   mcIdType *rvPtr(rightValues->getPointerSilent()),*lvPtr(leftValues->getPointerSilent());
351   for(mcIdType i = 0 ; i < nbPacks ; ++i)
352   {
353     std::for_each(valuesPtr+indexPtr[i],valuesPtr+indexPtr[i+1],[threshold,&rvPtr,&lvPtr](mcIdType elt) { if(elt<threshold) { *lvPtr++ = elt; } else { *rvPtr++ = elt; } });
354   }
355   left = MEDCouplingSkyLineArray::New(lCount,leftValues); right = MEDCouplingSkyLineArray::New(sizeOfPacks,rightValues);
356 }
357
358 MEDCouplingSkyLineArray *MEDCouplingSkyLineArray::groupPacks(const DataArrayIdType *indexedPacks) const
359 {
360   indexedPacks->checkAllocated();
361   if( indexedPacks->getNumberOfComponents() != 1 )
362     throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::groupPacks : number of components must be 1 !");
363   std::size_t nbTuples(indexedPacks->getNumberOfTuples());
364   if( nbTuples == 0 )
365     throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::groupPacks : number of tuples must be > 0 !");
366   const DataArrayIdType *index(this->getIndexArray());
367   MCAuto<DataArrayIdType> partIndex(index->selectByTupleIdSafe(indexedPacks->begin(),indexedPacks->end()));
368   MCAuto<MEDCouplingSkyLineArray> ret(MEDCouplingSkyLineArray::New(partIndex,this->getValuesArray()));
369   return ret.retn();
370 }
371
372 MEDCouplingSkyLineArray *MEDCouplingSkyLineArray::uniqueNotSortedByPack() const
373 {
374   mcIdType nbPacks(this->getNumberOf());
375   MCAuto<DataArrayIdType> retIndex(DataArrayIdType::New()); retIndex->alloc(nbPacks+1,1);
376   const mcIdType *valuesPtr(this->_values->begin()),*indexPtr(this->_index->begin());
377   mcIdType *retIndexPtr(retIndex->getPointer()); *retIndexPtr = 0;
378   for(mcIdType i = 0 ; i < nbPacks ; ++i, ++retIndexPtr)
379   {
380     std::set<mcIdType> s(valuesPtr+indexPtr[i],valuesPtr+indexPtr[i+1]);
381     retIndexPtr[1] = retIndexPtr[0] + ToIdType(s.size());
382   }
383   MCAuto<DataArrayIdType> retValues(DataArrayIdType::New()); retValues->alloc(retIndex->back(),1);
384   mcIdType *retValuesPtr(retValues->getPointer());
385   for(mcIdType i = 0 ; i < nbPacks ; ++i)
386   {
387     std::set<mcIdType> s(valuesPtr+indexPtr[i],valuesPtr+indexPtr[i+1]);
388     retValuesPtr = std::copy(s.begin(),s.end(),retValuesPtr);
389   }
390   MCAuto<MEDCouplingSkyLineArray> ret(MEDCouplingSkyLineArray::New(retIndex,retValues));
391   return ret.retn();
392 }
393 /*!
394  * Take as input skylinearrays containing the same number of packs ( \a this->getNumberOf ).
395  * For each packs, this method aggregates corresponding pack in \a sks.
396  * 
397  * \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.
398  * \return a newly allocated skyline array that is the aggregated packs of inputs
399  */
400 MEDCouplingSkyLineArray *MEDCouplingSkyLineArray::AggregatePacks(const std::vector<const MEDCouplingSkyLineArray *>& sks)
401 {
402   std::vector<const MEDCouplingSkyLineArray *>sksEff;
403   mcIdType nbOfPacks(std::numeric_limits<mcIdType>::max());
404   constexpr char MSG[]="MEDCouplingSkyLineArray::AggregatePacks : ";
405   for(auto sk : sks)
406   {
407     if(sk)
408     {
409       mcIdType curNbPacks(sk->getNumberOf());
410       if(sksEff.empty())
411         nbOfPacks = curNbPacks;
412       if(nbOfPacks != curNbPacks)
413       {
414         std::ostringstream oss; oss << MSG << "first not null input ska has " << nbOfPacks << " whereas there is presence of ska with " << curNbPacks << " !";
415         throw INTERP_KERNEL::Exception(oss.str());
416       }
417       sksEff.push_back(sk);
418     }
419   }
420   if(sksEff.empty())
421   {
422     std::ostringstream oss; oss << MSG << "input vector contains no not nullptr elements !";
423     throw INTERP_KERNEL::Exception(oss.str());
424   }
425   //
426   MCAuto<DataArrayIdType> index(DataArrayIdType::New()); index->alloc(nbOfPacks+1,1);
427   mcIdType *indexPtr(index->getPointer()); *indexPtr=0;
428   std::vector<const mcIdType *> indicesIn(SkyLineArrayIndexIterator(0,&sksEff),SkyLineArrayIndexIterator(sksEff.size(),&sksEff));
429   for( mcIdType packId = 0 ; packId < nbOfPacks ; ++packId, ++indexPtr )
430   {
431     mcIdType nbOfAggPacks(0);
432     std::for_each(indicesIn.begin(),indicesIn.end(),[packId,&nbOfAggPacks](const mcIdType *elt) { nbOfAggPacks+=elt[packId+1]-elt[packId]; });
433     indexPtr[1] = indexPtr[0] + nbOfAggPacks;
434   }
435   mcIdType nbOfTuplesOut(index->back());
436   MCAuto<DataArrayIdType> values(DataArrayIdType::New()); values->alloc(nbOfTuplesOut,1);
437   mcIdType *valuesPtr(values->getPointer());
438   // let's go to populate values array
439   std::vector<const mcIdType *> valuesIn(SkyLineArrayValuesIterator(0,&sksEff),SkyLineArrayValuesIterator(sksEff.size(),&sksEff));
440   for( mcIdType packId = 0 ; packId < nbOfPacks ; ++packId )
441   {
442     std::size_t pos(0);
443     std::for_each(valuesIn.begin(),valuesIn.end(),[packId,&indicesIn,&valuesPtr,&pos](const mcIdType *elt)
444     { valuesPtr=std::copy(elt+indicesIn[pos][packId],elt+indicesIn[pos][packId+1],valuesPtr); ++pos; }
445     );
446   }
447   //
448   MCAuto<MEDCouplingSkyLineArray> ret(MEDCouplingSkyLineArray::New(index,values));
449   return ret.retn();
450 }
451
452 /**
453  * For a 2- or 3-level SkyLine array, return a copy of the absolute pack with given identifier.
454  */
455 void MEDCouplingSkyLineArray::getSimplePackSafe(const mcIdType absolutePackId, std::vector<mcIdType> & pack) const
456 {
457   if(absolutePackId < 0 || absolutePackId >= _index->getNbOfElems())
458     throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::getPackSafe: invalid index!");
459   const mcIdType * iP(_index->begin()), *vP(_values->begin());
460   mcIdType sz = iP[absolutePackId+1]-iP[absolutePackId];
461   pack.resize(sz);
462   std::copy(vP+iP[absolutePackId], vP+iP[absolutePackId+1],pack.begin());
463 }
464
465 /**
466  * Same as getPackSafe, but directly returns a pointer to the internal data with the size of the pack.
467  */
468 const mcIdType * MEDCouplingSkyLineArray::getSimplePackSafePtr(const mcIdType absolutePackId, mcIdType & packSize) const
469 {
470   if(absolutePackId < 0 || absolutePackId >= _index->getNbOfElems())
471     throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::getPackSafe: invalid index!");
472   const mcIdType * iP(_index->begin()), *vP(_values->begin());
473   packSize = iP[absolutePackId+1]-iP[absolutePackId];
474   return vP+iP[absolutePackId];
475 }
476
477
478 /**!
479  * For each given super-pack ID, provide the sub-index of the first matching pack. If no matching pack is found for the
480  * given super-pack -1 is returned.
481  * \param[in] superPackIndices the list of super-packs that should be inspected
482  * \param[in] packBg the pack that the function is looking for in each of the provided super-pack
483  * \param[in] packEnd the pack that the function is looking for in each of the provided super-pack
484  * \param[out] a vector of mcIdType, having the same size as superPackIndices and containing for each inspected super-pack
485  * the index of the first matching pack, or -1 if none found.
486  */
487 void MEDCouplingSkyLineArray::findPackIds(const std::vector<mcIdType> & superPackIndices,
488                                           const mcIdType *packBg, const mcIdType *packEnd,
489                                           std::vector<mcIdType>& out) const
490 {
491   using namespace std;
492
493   checkSuperIndex("findPackIds");
494
495   mcIdType packSz = ToIdType(std::distance(packBg, packEnd));
496   if (!packSz)
497     throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::findPackIds: void pack!");
498
499   out.resize(superPackIndices.size());
500   mcIdType i = 0;
501   const mcIdType * siP(_super_index->begin()), * iP(_index->begin()), *vP(_values->begin());
502   for(vector<mcIdType>::const_iterator it=superPackIndices.begin(); it!=superPackIndices.end(); ++it, i++)
503     {
504       out[i] = -1;
505       const mcIdType sPackIdx = *it;
506       // for each pack
507       for (mcIdType idx=siP[sPackIdx], j=0; idx < siP[sPackIdx+1]; idx++, j++)
508         {
509           if (packSz == (iP[idx+1] - iP[idx]))
510             if (equal(&vP[iP[idx]], &vP[iP[idx+1]], packBg))
511               {
512                 out[i] = j;
513                 break;
514               }
515         }
516     }
517 }
518
519 /**!
520  * Delete pack number 'idx' in super-pack number 'superIdx'.
521  * \param[in] superIdx is the super-pack number
522  * \param[in] idx is the pack index inside the super-pack 'superIdx'.
523  */
524 void MEDCouplingSkyLineArray::deletePack(const mcIdType superIdx, const mcIdType idx)
525 {
526   checkSuperIndex("deletePack");
527   validSuperIndexAndIndex("deletePack", superIdx, idx);
528
529   mcIdType * vP = _values->getPointer();
530   mcIdType * siP(_super_index->getPointer()), *iP(_index->getPointer());
531   const mcIdType start = iP[siP[superIdx]+idx], end = iP[siP[superIdx]+idx+1];
532   // _values
533   std::copy(vP+end, vP+_values->getNbOfElems(), vP+start);
534   _values->reAlloc(_values->getNbOfElems() - (end-start));
535
536   // _index
537   mcIdType nt = _index->getNbOfElems();
538   std::copy(iP+siP[superIdx]+idx+1, iP+nt, iP+siP[superIdx]+idx);
539   _index->reAlloc(nt-1); iP = _index->getPointer();  // better not forget this ...
540   for(mcIdType ii = siP[superIdx]+idx; ii < nt-1; ii++)
541     iP[ii] -= (end-start);
542
543   // _super_index
544   for(mcIdType ii = superIdx+1; ii < _super_index->getNbOfElems(); ii++)
545     (siP[ii])--;
546 }
547
548 void MEDCouplingSkyLineArray::deleteSimplePack(const mcIdType idx)
549 {
550   validIndex("deleteSimplePack", idx);
551   
552   mcIdType* iP(_index->getPointer());
553   const mcIdType start(iP[idx]), end(iP[idx+1]);
554
555   // _values
556   mcIdType initValSz=_values->getNbOfElems();
557   mcIdType deltaSz( start-end );  // should be negative
558   mcIdType *vP(_values->getPointer());
559   if (deltaSz < 0)
560     {
561       std::copy(vP+end, vP+initValSz, vP+start);
562       _values->reAlloc(initValSz+deltaSz);
563     }
564   else
565     throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::deleteSimplePack");
566   // _index
567   mcIdType nt=_index->getNbOfElems();
568   std::copy(iP+idx+1, iP+nt, iP+idx);
569   for(mcIdType ii = idx; ii < nt-1; ii++)
570     iP[ii] += deltaSz;
571   _index->reAlloc(nt-1);
572 }
573
574 void MEDCouplingSkyLineArray::replaceSimplePacks(const DataArrayIdType* idx, const std::vector<const DataArrayIdType*>& packs)
575 {    
576   if (idx->empty())
577     return;
578     
579   for (const mcIdType * id = idx->begin(); id != idx->end(); id++)
580     validIndex("deleteSimplePacks", *id);
581     
582   if (idx->getNbOfElems() != ToIdType( packs.size()))
583     throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::deleteSimplePacks: size of list of pack is incorrect");
584     
585   // copy _index, _values into a deque<set<mcIdType>>
586   std::deque< std::set<mcIdType> > valuesByIdx;
587   mcIdType* vP(_values->getPointer());
588   mcIdType* iP(_index->getPointer());
589   mcIdType nt = _index->getNbOfElems();
590   for (mcIdType ii = 0; ii < nt-1; ii++)
591     valuesByIdx.push_back(std::set<mcIdType>(vP+iP[ii], vP+iP[ii+1]));
592     
593   // modify the deque<set<mcIdType>> according to idx and packs
594   mcIdType ii(0);
595   for (const mcIdType *id = idx->begin(); id != idx->end(); id++)
596     {
597       valuesByIdx[*id] = std::set<mcIdType>(packs[ii]->begin(), packs[ii]->end());
598       ii++;
599     }
600   // copy back the deque<set<mcIdType>> into _index, _values
601   mcIdType valSz(0);
602   *iP = 0;
603   for (std::deque< std::set<mcIdType> >::const_iterator values=valuesByIdx.begin();values!=valuesByIdx.end();values++)
604     {
605       valSz += ToIdType((*values).size());
606       *(++iP) = valSz;
607     }
608   _values->reAlloc(valSz);
609   iP = _index->getPointer();
610   vP = _values->getPointer();
611   for (auto values : valuesByIdx)
612     {
613       std::copy(values.begin(), values.end(), vP+(*iP));
614       iP++;
615     }
616 }
617
618 void MEDCouplingSkyLineArray::deleteSimplePacks(const DataArrayIdType* idx)
619 {    
620   for (auto id = idx->begin(); id != idx->end(); id++)
621     validIndex("deleteSimplePacks", *id);
622   
623   std::set<mcIdType> packsToDelete(idx->begin(), idx->end());
624     
625   // _values
626   mcIdType* iP(_index->getPointer());
627   mcIdType initValSz = _values->getNbOfElems();
628   mcIdType *vP(_values->getPointer());
629   mcIdType end_prec(0),start_prec(0);
630   for(std::set<mcIdType>::const_iterator ii=packsToDelete.begin();ii!=packsToDelete.end();ii++)
631     {
632       mcIdType start = iP[*ii];
633       if (end_prec != 0)
634         std::copy(vP+end_prec, vP+start, vP+start_prec);
635       start_prec += start-end_prec;
636       end_prec = iP[*ii+1];
637     }
638   if (end_prec != 0)
639     std::copy(vP+end_prec, vP+initValSz, vP+start_prec);
640   _values->reAlloc(initValSz-(end_prec-start_prec));
641     
642   // _index
643   mcIdType nt = _index->getNbOfElems();
644   mcIdType offset = 0;
645   end_prec = 0;
646   start_prec = 0;
647   mcIdType deleted = 0;
648   for(std::set<mcIdType>::const_iterator ii=packsToDelete.begin();ii!=packsToDelete.end();ii++)
649     {
650       if (end_prec != 0)
651         {
652           std::copy(iP+end_prec, iP+*ii, iP+start_prec);
653           for (mcIdType i=start_prec; i<*ii; i++)
654             iP[i] -= offset;
655         }
656       offset += iP[*ii+1] - iP[*ii];
657       start_prec = *ii-deleted;
658       end_prec = *ii+1;
659       deleted += 1;
660     }
661   if (end_prec != 0)
662     {
663       std::copy(iP+end_prec, iP+nt, iP+start_prec);
664       for (mcIdType i=start_prec; i<nt; i++)
665         iP[i] -= offset;
666     }
667   _index->reAlloc(nt-deleted);
668 }
669
670 /**!
671  * 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.
672  */
673 void MEDCouplingSkyLineArray::pushBackPack(const mcIdType superIdx, const mcIdType * packBg, const mcIdType * packEnd)
674 {
675   using namespace std;
676
677   checkSuperIndex("pushBackPack");
678   validSuperIndex("pushBackPack", superIdx);
679
680   mcIdType *siP(_super_index->getPointer()), *iP(_index->getPointer());
681   const mcIdType sz(ToIdType(distance(packBg, packEnd)));
682
683   // _values
684   _values->reAlloc(_values->getNbOfElems()+sz);
685   mcIdType * vPE(_values->getPointer()+_values->getNbOfElems());
686   mcIdType *vP(_values->getPointer());
687   copy(vP+iP[siP[superIdx+1]], vPE-sz, vP+iP[siP[superIdx+1]]+sz);
688   // insert pack
689   copy(packBg, packEnd, vP+iP[siP[superIdx+1]]);
690
691   // _index
692   mcIdType nt = ToIdType(_index->getNbOfElems());
693   _index->reAlloc(nt+1); iP = _index->getPointer();
694   copy(iP+siP[superIdx+1]+1, iP+nt, iP+siP[superIdx+1]+2);
695   iP[siP[superIdx+1]+1] = iP[siP[superIdx+1]] + sz;
696   for(mcIdType ii = siP[superIdx+1]+2; ii < nt+1; ii++)
697     iP[ii] += sz;
698
699   // _super_index
700   for(mcIdType ii = superIdx+1; ii < _super_index->getNbOfElems(); ii++)
701     (siP[ii])++;
702 }
703
704 /**
705  * Replace pack with absolute index 'idx' with the provided new pack. Function can be used either
706  * for 2-level SkyLine or 3-level SkyLine.
707  */
708 void MEDCouplingSkyLineArray::replaceSimplePack(const mcIdType idx, const mcIdType * packBg, const mcIdType * packEnd)
709 {
710   validIndex("replaceSimplePack", idx);
711
712   mcIdType * iP(_index->getPointer());
713   mcIdType newSz = ToIdType(std::distance(packBg, packEnd));
714   const mcIdType start = iP[idx], end = iP[idx+1];
715
716   // _values
717   mcIdType initValSz = _values->getNbOfElems();
718   mcIdType deltaSz = newSz-(end-start);  // can be negative
719   if (deltaSz)
720     {
721       if (deltaSz > 0)
722         _values->reAlloc(initValSz+deltaSz);
723       mcIdType *vP(_values->getPointer());
724       std::copy(vP+end, vP+initValSz, vP+end+deltaSz);
725       if (deltaSz < 0)
726         _values->reAlloc(initValSz+deltaSz);
727     }
728
729   // copy new pack
730   std::copy(packBg, packEnd, _values->getPointer()+start);
731
732   // _index
733   for(mcIdType ii = idx+1; ii < _index->getNbOfElems(); ii++)
734     iP[ii] += deltaSz;
735 }
736
737 /**
738  * Replace pack with super index 'superIdx' and index 'idx' with the provided new pack.
739  * Function can be used only for 3-level SkyLine.
740  */
741 void MEDCouplingSkyLineArray::replacePack(const mcIdType superIdx, const mcIdType idx, const mcIdType *packBg, const mcIdType *packEnd)
742 {
743   checkSuperIndex("replacePack");
744   validSuperIndexAndIndex("replacePack", superIdx, idx);
745
746   mcIdType * siP(_super_index->getPointer()), *iP(_index->getPointer());
747   mcIdType newSz = ToIdType(std::distance(packBg, packEnd));
748   const mcIdType start = iP[siP[superIdx]+idx], end = iP[siP[superIdx]+idx+1];
749
750   // _values
751   mcIdType initValSz = _values->getNbOfElems();
752   mcIdType deltaSz = newSz-(end-start);  // can be negative
753   if (deltaSz)
754     {
755       if (deltaSz > 0)
756         _values->reAlloc(initValSz+deltaSz);
757       mcIdType *vP(_values->getPointer());
758       std::copy(vP+end, vP+initValSz, vP+end+deltaSz);
759       if (deltaSz < 0)
760         _values->reAlloc(initValSz+deltaSz);
761     }
762
763   // copy new pack
764   std::copy(packBg, packEnd, _values->getPointer()+start);
765
766   // _index
767   for(mcIdType ii = siP[superIdx]+idx+1; ii < _index->getNbOfElems(); ii++)
768     iP[ii] += deltaSz;
769 }