// Copyright (C) 2007-2014 CEA/DEN, EDF R&D // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // // Author : Anthony Geay (CEA/DEN) #ifndef __PARAMEDMEM_MEDCOUPLINGMEMARRAY_TXX__ #define __PARAMEDMEM_MEDCOUPLINGMEMARRAY_TXX__ #include "MEDCouplingMemArray.hxx" #include "NormalizedUnstructuredMesh.hxx" #include "InterpKernelException.hxx" #include "InterpolationUtils.hxx" #include #include #include namespace ParaMEDMEM { template void MEDCouplingPointer::setInternal(T *pointer) { _internal=pointer; _external=0; } template void MEDCouplingPointer::setExternal(const T *pointer) { _external=pointer; _internal=0; } template MemArray::MemArray(const MemArray& other):_nb_of_elem(0),_nb_of_elem_alloc(0),_ownership(false),_dealloc(0),_param_for_deallocator(0) { if(!other._pointer.isNull()) { _nb_of_elem_alloc=other._nb_of_elem; T *pointer=(T*)malloc(_nb_of_elem_alloc*sizeof(T)); std::copy(other._pointer.getConstPointer(),other._pointer.getConstPointer()+other._nb_of_elem,pointer); useArray(pointer,true,C_DEALLOC,other._nb_of_elem); } } template void MemArray::useArray(const T *array, bool ownership, DeallocType type, std::size_t nbOfElem) { destroy(); _nb_of_elem=nbOfElem; _nb_of_elem_alloc=nbOfElem; if(ownership) _pointer.setInternal(const_cast(array)); else _pointer.setExternal(array); _ownership=ownership; _dealloc=BuildFromType(type); } template void MemArray::useExternalArrayWithRWAccess(const T *array, std::size_t nbOfElem) { destroy(); _nb_of_elem=nbOfElem; _nb_of_elem_alloc=nbOfElem; _pointer.setInternal(const_cast(array)); _ownership=false; _dealloc=CPPDeallocator; } template void MemArray::writeOnPlace(std::size_t id, T element0, const T *others, std::size_t sizeOfOthers) { if(id+sizeOfOthers>=_nb_of_elem_alloc) reserve(2*_nb_of_elem+sizeOfOthers+1); T *pointer=_pointer.getPointer(); pointer[id]=element0; std::copy(others,others+sizeOfOthers,pointer+id+1); _nb_of_elem=std::max(_nb_of_elem,id+sizeOfOthers+1); } template template void MemArray::insertAtTheEnd(InputIterator first, InputIterator last) { T *pointer=_pointer.getPointer(); while(first!=last) { if(_nb_of_elem>=_nb_of_elem_alloc) { reserve(_nb_of_elem_alloc>0?2*_nb_of_elem_alloc:1); pointer=_pointer.getPointer(); } pointer[_nb_of_elem++]=*first++; } } template void MemArray::pushBack(T elem) { if(_nb_of_elem>=_nb_of_elem_alloc) reserve(_nb_of_elem_alloc>0?2*_nb_of_elem_alloc:1); T *pt=getPointer(); pt[_nb_of_elem++]=elem; } template T MemArray::popBack() { if(_nb_of_elem>0) { const T *pt=getConstPointer(); return pt[--_nb_of_elem]; } throw INTERP_KERNEL::Exception("MemArray::popBack : nothing to pop in array !"); } template void MemArray::pack() const { (const_cast * >(this))->reserve(_nb_of_elem); } template bool MemArray::isEqual(const MemArray& other, T prec, std::string& reason) const { std::ostringstream oss; oss.precision(15); if(_nb_of_elem!=other._nb_of_elem) { oss << "Number of elements in coarse data of DataArray mismatch : this=" << _nb_of_elem << " other=" << other._nb_of_elem; reason=oss.str(); return false; } const T *pt1=_pointer.getConstPointer(); const T *pt2=other._pointer.getConstPointer(); if(pt1==0 && pt2==0) return true; if(pt1==0 || pt2==0) { oss << "coarse data pointer is defined for only one DataArray instance !"; reason=oss.str(); return false; } if(pt1==pt2) return true; for(std::size_t i=0;i<_nb_of_elem;i++) if(pt1[i]-pt2[i]<-prec || (pt1[i]-pt2[i])>prec) { oss << "The content of data differs at pos #" << i << " of coarse data ! this[i]=" << pt1[i] << " other[i]=" << pt2[i]; reason=oss.str(); return false; } return true; } /*! * \param [in] sl is typically the number of components * \return True if a not null pointer is present, False if not. */ template bool MemArray::reprHeader(int sl, std::ostream& stream) const { stream << "Number of tuples : "; if(!_pointer.isNull()) { if(sl!=0) stream << _nb_of_elem/sl << std::endl << "Internal memory facts : " << _nb_of_elem << "/" << _nb_of_elem_alloc; else stream << "Empty Data"; } else stream << "No data"; stream << "\n"; stream << "Data content :\n"; bool ret=!_pointer.isNull(); if(!ret) stream << "No data !\n"; return ret; } /*! * \param [in] sl is typically the number of components */ template void MemArray::repr(int sl, std::ostream& stream) const { if(reprHeader(sl,stream)) { const T *data=getConstPointer(); if(_nb_of_elem!=0 && sl!=0) { std::size_t nbOfTuples=_nb_of_elem/std::abs(sl); for(std::size_t i=0;i(stream," ")); stream << "\n"; data+=sl; } } else stream << "Empty Data\n"; } } /*! * \param [in] sl is typically the number of components */ template void MemArray::reprZip(int sl, std::ostream& stream) const { stream << "Number of tuples : "; if(!_pointer.isNull()) { if(sl!=0) stream << _nb_of_elem/sl; else stream << "Empty Data"; } else stream << "No data"; stream << "\n"; stream << "Data content : "; const T *data=getConstPointer(); if(!_pointer.isNull()) { if(_nb_of_elem!=0 && sl!=0) { std::size_t nbOfTuples=_nb_of_elem/std::abs(sl); for(std::size_t i=0;i(stream," ")); stream << "| "; data+=sl; } stream << "\n"; } else stream << "Empty Data\n"; } else stream << "No data !\n"; } template void MemArray::fillWithValue(const T& val) { T *pt=_pointer.getPointer(); std::fill(pt,pt+_nb_of_elem,val); } template T *MemArray::fromNoInterlace(int nbOfComp) const { if(nbOfComp<1) throw INTERP_KERNEL::Exception("MemArray::fromNoInterlace : number of components must be > 0 !"); const T *pt=_pointer.getConstPointer(); std::size_t nbOfTuples=_nb_of_elem/nbOfComp; T *ret=(T*)malloc(_nb_of_elem*sizeof(T)); T *w=ret; for(std::size_t i=0;i T *MemArray::toNoInterlace(int nbOfComp) const { if(nbOfComp<1) throw INTERP_KERNEL::Exception("MemArray::toNoInterlace : number of components must be > 0 !"); const T *pt=_pointer.getConstPointer(); std::size_t nbOfTuples=_nb_of_elem/nbOfComp; T *ret=(T*)malloc(_nb_of_elem*sizeof(T)); T *w=ret; for(int i=0;i void MemArray::sort(bool asc) { T *pt=_pointer.getPointer(); if(asc) std::sort(pt,pt+_nb_of_elem); else { typename std::reverse_iterator it1(pt+_nb_of_elem); typename std::reverse_iterator it2(pt); std::sort(it1,it2); } } template void MemArray::reverse(int nbOfComp) { if(nbOfComp<1) throw INTERP_KERNEL::Exception("MemArray::reverse : only supported with 'this' array with ONE or more than ONE component !"); T *pt=_pointer.getPointer(); if(nbOfComp==1) { std::reverse(pt,pt+_nb_of_elem); return ; } else { T *pt2=pt+_nb_of_elem-nbOfComp; std::size_t nbOfTuples=_nb_of_elem/nbOfComp; for(std::size_t i=0;i void MemArray::alloc(std::size_t nbOfElements) { destroy(); _nb_of_elem=nbOfElements; _nb_of_elem_alloc=nbOfElements; _pointer.setInternal((T*)malloc(_nb_of_elem_alloc*sizeof(T))); _ownership=true; _dealloc=CDeallocator; } /*! * This method performs systematically an allocation of \a newNbOfElements elements in \a this. * \a _nb_of_elem and \a _nb_of_elem_alloc will \b NOT be systematically equal (contrary to MemArray::reAlloc method. * So after the call of this method \a _nb_of_elem will be equal tostd::min(_nb_of_elem,newNbOfElements) and \a _nb_of_elem_alloc equal to * \a newNbOfElements. This method is typically used to perform a pushBack to avoid systematic allocations-copy-deallocation. * So after the call of this method the accessible content is perfectly set. * * So this method should not be confused with MemArray::reserve that is close to MemArray::reAlloc but not same. */ template void MemArray::reserve(std::size_t newNbOfElements) { if(_nb_of_elem_alloc==newNbOfElements) return ; T *pointer=(T*)malloc(newNbOfElements*sizeof(T)); std::copy(_pointer.getConstPointer(),_pointer.getConstPointer()+std::min(_nb_of_elem,newNbOfElements),pointer); if(_ownership) DestroyPointer(const_cast(_pointer.getConstPointer()),_dealloc,_param_for_deallocator);//Do not use getPointer because in case of _external _pointer.setInternal(pointer); _nb_of_elem=std::min(_nb_of_elem,newNbOfElements); _nb_of_elem_alloc=newNbOfElements; _ownership=true; _dealloc=CDeallocator; _param_for_deallocator=0; } /*! * This method performs systematically an allocation of \a newNbOfElements elements in \a this. * \a _nb_of_elem and \a _nb_of_elem_alloc will be equal even if only std::min(_nb_of_elem,newNbOfElements) come from the . * The remaing part of the new allocated chunk are available but not set previouly ! * * So this method should not be confused with MemArray::reserve that is close to MemArray::reAlloc but not same. */ template void MemArray::reAlloc(std::size_t newNbOfElements) { if(_nb_of_elem==newNbOfElements) return ; T *pointer=(T*)malloc(newNbOfElements*sizeof(T)); std::copy(_pointer.getConstPointer(),_pointer.getConstPointer()+std::min(_nb_of_elem,newNbOfElements),pointer); if(_ownership) DestroyPointer(const_cast(_pointer.getConstPointer()),_dealloc,_param_for_deallocator);//Do not use getPointer because in case of _external _pointer.setInternal(pointer); _nb_of_elem=newNbOfElements; _nb_of_elem_alloc=newNbOfElements; _ownership=true; _dealloc=CDeallocator; _param_for_deallocator=0; } template void MemArray::CPPDeallocator(void *pt, void *param) { delete [] reinterpret_cast(pt); } template void MemArray::CDeallocator(void *pt, void *param) { free(pt); } template typename MemArray::Deallocator MemArray::BuildFromType(DeallocType type) { switch(type) { case CPP_DEALLOC: return CPPDeallocator; case C_DEALLOC: return CDeallocator; default: throw INTERP_KERNEL::Exception("Invalid deallocation requested ! Unrecognized enum DeallocType !"); } } template void MemArray::DestroyPointer(T *pt, typename MemArray::Deallocator dealloc, void *param) { if(dealloc) dealloc(pt,param); } template void MemArray::destroy() { if(_ownership) DestroyPointer(const_cast(_pointer.getConstPointer()),_dealloc,_param_for_deallocator);//Do not use getPointer because in case of _external _pointer.null(); _ownership=false; _dealloc=NULL; _param_for_deallocator=NULL; _nb_of_elem=0; _nb_of_elem_alloc=0; } template MemArray &MemArray::operator=(const MemArray& other) { alloc(other._nb_of_elem); std::copy(other._pointer.getConstPointer(),other._pointer.getConstPointer()+_nb_of_elem,_pointer.getPointer()); return *this; } } #endif