1 // Copyright (C) 2007-2013 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // Author : Anthony Geay (CEA/DEN)
21 #ifndef __PARAMEDMEM_MEDCOUPLINGMEMARRAY_TXX__
22 #define __PARAMEDMEM_MEDCOUPLINGMEMARRAY_TXX__
24 #include "MEDCouplingMemArray.hxx"
25 #include "NormalizedUnstructuredMesh.hxx"
26 #include "InterpKernelException.hxx"
27 #include "InterpolationUtils.hxx"
36 void MEDCouplingPointer<T>::setInternal(T *pointer)
43 void MEDCouplingPointer<T>::setExternal(const T *pointer)
50 MemArray<T>::MemArray(const MemArray<T>& other):_nb_of_elem(0),_nb_of_elem_alloc(0),_ownership(false),_dealloc(0),_param_for_deallocator(0)
52 if(!other._pointer.isNull())
54 _nb_of_elem_alloc=other._nb_of_elem;
55 T *pointer=(T*)malloc(_nb_of_elem_alloc*sizeof(T));
56 std::copy(other._pointer.getConstPointer(),other._pointer.getConstPointer()+other._nb_of_elem,pointer);
57 useArray(pointer,true,C_DEALLOC,other._nb_of_elem);
62 void MemArray<T>::useArray(const T *array, bool ownership, DeallocType type, std::size_t nbOfElem)
65 _nb_of_elem_alloc=nbOfElem;
68 _pointer.setInternal(const_cast<T *>(array));
70 _pointer.setExternal(array);
72 _dealloc=BuildFromType(type);
76 void MemArray<T>::useExternalArrayWithRWAccess(const T *array, std::size_t nbOfElem)
79 _nb_of_elem_alloc=nbOfElem;
81 _pointer.setInternal(const_cast<T *>(array));
83 _dealloc=CPPDeallocator;
87 void MemArray<T>::writeOnPlace(std::size_t id, T element0, const T *others, std::size_t sizeOfOthers)
89 if(id+sizeOfOthers>=_nb_of_elem_alloc)
90 reserve(2*_nb_of_elem+sizeOfOthers+1);
91 T *pointer=_pointer.getPointer();
93 std::copy(others,others+sizeOfOthers,pointer+id+1);
94 _nb_of_elem=std::max<std::size_t>(_nb_of_elem,id+sizeOfOthers+1);
98 template<class InputIterator>
99 void MemArray<T>::insertAtTheEnd(InputIterator first, InputIterator last)
101 T *pointer=_pointer.getPointer();
104 if(_nb_of_elem>=_nb_of_elem_alloc)
106 reserve(_nb_of_elem_alloc>0?2*_nb_of_elem_alloc:1);
107 pointer=_pointer.getPointer();
109 pointer[_nb_of_elem++]=*first++;
114 void MemArray<T>::pushBack(T elem) throw(INTERP_KERNEL::Exception)
116 if(_nb_of_elem>=_nb_of_elem_alloc)
117 reserve(_nb_of_elem_alloc>0?2*_nb_of_elem_alloc:1);
119 pt[_nb_of_elem++]=elem;
123 T MemArray<T>::popBack() throw(INTERP_KERNEL::Exception)
127 const T *pt=getConstPointer();
128 return pt[--_nb_of_elem];
130 throw INTERP_KERNEL::Exception("MemArray::popBack : nothing to pop in array !");
134 void MemArray<T>::pack() const
137 (const_cast<MemArray<T> * >(this))->reserve(_nb_of_elem);
141 bool MemArray<T>::isEqual(const MemArray<T>& other, T prec, std::string& reason) const
143 std::ostringstream oss; oss.precision(15);
144 if(_nb_of_elem!=other._nb_of_elem)
146 oss << "Number of elements in coarse data of DataArray mismatch : this=" << _nb_of_elem << " other=" << other._nb_of_elem;
150 const T *pt1=_pointer.getConstPointer();
151 const T *pt2=other._pointer.getConstPointer();
156 oss << "coarse data pointer is defined for only one DataArray instance !";
162 for(std::size_t i=0;i<_nb_of_elem;i++)
163 if(pt1[i]-pt2[i]<-prec || (pt1[i]-pt2[i])>prec)
165 oss << "The content of data differs at pos #" << i << " of coarse data ! this[i]=" << pt1[i] << " other[i]=" << pt2[i];
173 * \param [in] sl is typically the number of components
174 * \return True if a not null pointer is present, False if not.
177 bool MemArray<T>::reprHeader(int sl, std::ostream& stream) const
179 stream << "Number of tuples : ";
180 if(!_pointer.isNull())
183 stream << _nb_of_elem/sl << std::endl << "Internal memory facts : " << _nb_of_elem << "/" << _nb_of_elem_alloc;
185 stream << "Empty Data";
190 stream << "Data content :\n";
191 bool ret=!_pointer.isNull();
193 stream << "No data !\n";
198 * \param [in] sl is typically the number of components
201 void MemArray<T>::repr(int sl, std::ostream& stream) const
203 if(reprHeader(sl,stream))
205 const T *data=getConstPointer();
206 if(_nb_of_elem!=0 && sl!=0)
208 std::size_t nbOfTuples=_nb_of_elem/std::abs(sl);
209 for(std::size_t i=0;i<nbOfTuples;i++)
211 stream << "Tuple #" << i << " : ";
212 std::copy(data,data+sl,std::ostream_iterator<T>(stream," "));
218 stream << "Empty Data\n";
223 * \param [in] sl is typically the number of components
226 void MemArray<T>::reprZip(int sl, std::ostream& stream) const
228 stream << "Number of tuples : ";
229 if(!_pointer.isNull())
232 stream << _nb_of_elem/sl;
234 stream << "Empty Data";
239 stream << "Data content : ";
240 const T *data=getConstPointer();
241 if(!_pointer.isNull())
243 if(_nb_of_elem!=0 && sl!=0)
245 std::size_t nbOfTuples=_nb_of_elem/std::abs(sl);
246 for(std::size_t i=0;i<nbOfTuples;i++)
249 std::copy(data,data+sl,std::ostream_iterator<T>(stream," "));
256 stream << "Empty Data\n";
259 stream << "No data !\n";
263 void MemArray<T>::fillWithValue(const T& val)
265 T *pt=_pointer.getPointer();
266 std::fill(pt,pt+_nb_of_elem,val);
270 T *MemArray<T>::fromNoInterlace(int nbOfComp) const
273 throw INTERP_KERNEL::Exception("MemArray<T>::fromNoInterlace : number of components must be > 0 !");
274 const T *pt=_pointer.getConstPointer();
275 std::size_t nbOfTuples=_nb_of_elem/nbOfComp;
276 T *ret=(T*)malloc(_nb_of_elem*sizeof(T));
278 for(std::size_t i=0;i<nbOfTuples;i++)
279 for(int j=0;j<nbOfComp;j++,w++)
280 *w=pt[j*nbOfTuples+i];
285 T *MemArray<T>::toNoInterlace(int nbOfComp) const
288 throw INTERP_KERNEL::Exception("MemArray<T>::toNoInterlace : number of components must be > 0 !");
289 const T *pt=_pointer.getConstPointer();
290 std::size_t nbOfTuples=_nb_of_elem/nbOfComp;
291 T *ret=(T*)malloc(_nb_of_elem*sizeof(T));
293 for(int i=0;i<nbOfComp;i++)
294 for(std::size_t j=0;j<nbOfTuples;j++,w++)
300 void MemArray<T>::sort(bool asc)
302 T *pt=_pointer.getPointer();
304 std::sort(pt,pt+_nb_of_elem);
307 typename std::reverse_iterator<T *> it1(pt+_nb_of_elem);
308 typename std::reverse_iterator<T *> it2(pt);
314 void MemArray<T>::reverse(int nbOfComp)
317 throw INTERP_KERNEL::Exception("MemArray<T>::reverse : only supported with 'this' array with ONE or more than ONE component !");
318 T *pt=_pointer.getPointer();
321 std::reverse(pt,pt+_nb_of_elem);
326 T *pt2=pt+_nb_of_elem-nbOfComp;
327 std::size_t nbOfTuples=_nb_of_elem/nbOfComp;
328 for(std::size_t i=0;i<nbOfTuples/2;i++,pt+=nbOfComp,pt2-=nbOfComp)
330 for(int j=0;j<nbOfComp;j++)
331 std::swap(pt[j],pt2[j]);
337 void MemArray<T>::alloc(std::size_t nbOfElements) throw(INTERP_KERNEL::Exception)
341 throw INTERP_KERNEL::Exception("MemArray::alloc : request for negative length of data !");
342 _nb_of_elem=nbOfElements;
343 _nb_of_elem_alloc=nbOfElements;
344 _pointer.setInternal((T*)malloc(_nb_of_elem_alloc*sizeof(T)));
346 _dealloc=CDeallocator;
350 * This method performs systematically an allocation of \a newNbOfElements elements in \a this.
351 * \a _nb_of_elem and \a _nb_of_elem_alloc will \b NOT be systematically equal (contrary to MemArray<T>::reAlloc method.
352 * So after the call of this method \a _nb_of_elem will be equal tostd::min<std::size_t>(_nb_of_elem,newNbOfElements) and \a _nb_of_elem_alloc equal to
353 * \a newNbOfElements. This method is typically used to perform a pushBack to avoid systematic allocations-copy-deallocation.
354 * So after the call of this method the accessible content is perfectly set.
356 * So this method should not be confused with MemArray<T>::reserve that is close to MemArray<T>::reAlloc but not same.
359 void MemArray<T>::reserve(std::size_t newNbOfElements) throw(INTERP_KERNEL::Exception)
361 if(newNbOfElements<0)
362 throw INTERP_KERNEL::Exception("MemArray::reAlloc : request for negative length of data !");
363 if(_nb_of_elem_alloc==newNbOfElements)
365 T *pointer=(T*)malloc(newNbOfElements*sizeof(T));
366 std::copy(_pointer.getConstPointer(),_pointer.getConstPointer()+std::min<std::size_t>(_nb_of_elem,newNbOfElements),pointer);
368 destroyPointer(const_cast<T *>(_pointer.getConstPointer()),_dealloc,_param_for_deallocator);//Do not use getPointer because in case of _external
369 _pointer.setInternal(pointer);
370 _nb_of_elem=std::min<std::size_t>(_nb_of_elem,newNbOfElements);
371 _nb_of_elem_alloc=newNbOfElements;
373 _dealloc=CDeallocator;
374 _param_for_deallocator=0;
378 * This method performs systematically an allocation of \a newNbOfElements elements in \a this.
379 * \a _nb_of_elem and \a _nb_of_elem_alloc will be equal even if only std::min<std::size_t>(_nb_of_elem,newNbOfElements) come from the .
380 * The remaing part of the new allocated chunk are available but not set previouly !
382 * So this method should not be confused with MemArray<T>::reserve that is close to MemArray<T>::reAlloc but not same.
385 void MemArray<T>::reAlloc(std::size_t newNbOfElements) throw(INTERP_KERNEL::Exception)
387 if(newNbOfElements<0)
388 throw INTERP_KERNEL::Exception("MemArray::reAlloc : request for negative length of data !");
389 if(_nb_of_elem==newNbOfElements)
391 T *pointer=(T*)malloc(newNbOfElements*sizeof(T));
392 std::copy(_pointer.getConstPointer(),_pointer.getConstPointer()+std::min<std::size_t>(_nb_of_elem,newNbOfElements),pointer);
394 destroyPointer(const_cast<T *>(_pointer.getConstPointer()),_dealloc,_param_for_deallocator);//Do not use getPointer because in case of _external
395 _pointer.setInternal(pointer);
396 _nb_of_elem=newNbOfElements;
397 _nb_of_elem_alloc=newNbOfElements;
399 _dealloc=CDeallocator;
400 _param_for_deallocator=0;
404 void MemArray<T>::CPPDeallocator(void *pt, void *param)
406 delete [] reinterpret_cast<T*>(pt);
410 void MemArray<T>::CDeallocator(void *pt, void *param)
416 typename MemArray<T>::Deallocator MemArray<T>::BuildFromType(DeallocType type) throw(INTERP_KERNEL::Exception)
421 return CPPDeallocator;
425 throw INTERP_KERNEL::Exception("Invalid deallocation requested ! Unrecognized enum DeallocType !");
430 void MemArray<T>::destroyPointer(T *pt, typename MemArray<T>::Deallocator dealloc, void *param)
437 void MemArray<T>::destroy()
440 destroyPointer(const_cast<T *>(_pointer.getConstPointer()),_dealloc,_param_for_deallocator);//Do not use getPointer because in case of _external
444 _param_for_deallocator=NULL;
448 MemArray<T> &MemArray<T>::operator=(const MemArray<T>& other)
450 alloc(other._nb_of_elem);
451 std::copy(other._pointer.getConstPointer(),other._pointer.getConstPointer()+_nb_of_elem,_pointer.getPointer());