X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FMEDCoupling%2FMEDCouplingMemArray.txx;h=941326a87b3a26b7a52341cddaba9a9abc3f5c16;hb=bc69ae91f0e6c8e5043650f26897a8a0ac2056fb;hp=39030643deffd907e9d8cd34c3ea5b0963671ad3;hpb=de8da643a7f441fb2154818cde04b7b24ca76bb4;p=tools%2Fmedcoupling.git diff --git a/src/MEDCoupling/MEDCouplingMemArray.txx b/src/MEDCoupling/MEDCouplingMemArray.txx index 39030643d..941326a87 100644 --- a/src/MEDCoupling/MEDCouplingMemArray.txx +++ b/src/MEDCoupling/MEDCouplingMemArray.txx @@ -1,9 +1,9 @@ -// Copyright (C) 2007-2013 CEA/DEN, EDF R&D +// Copyright (C) 2007-2016 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. +// 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 @@ -25,12 +25,16 @@ #include "NormalizedUnstructuredMesh.hxx" #include "InterpKernelException.hxx" #include "InterpolationUtils.hxx" +#include "MEDCouplingPartDefinition.hxx" +#include "InterpKernelAutoPtr.hxx" +#include "MCAuto.hxx" #include #include +#include #include -namespace ParaMEDMEM +namespace MEDCoupling { template void MEDCouplingPointer::setInternal(T *pointer) @@ -61,9 +65,9 @@ namespace ParaMEDMEM 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; - destroy(); if(ownership) _pointer.setInternal(const_cast(array)); else @@ -75,14 +79,14 @@ namespace ParaMEDMEM template void MemArray::useExternalArrayWithRWAccess(const T *array, std::size_t nbOfElem) { + destroy(); _nb_of_elem=nbOfElem; _nb_of_elem_alloc=nbOfElem; - destroy(); _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) { @@ -93,34 +97,18 @@ namespace ParaMEDMEM 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 || _nb_of_elem==0) - { - 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) throw(INTERP_KERNEL::Exception) + 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() throw(INTERP_KERNEL::Exception) + T MemArray::popBack() { if(_nb_of_elem>0) { @@ -129,12 +117,11 @@ namespace ParaMEDMEM } throw INTERP_KERNEL::Exception("MemArray::popBack : nothing to pop in array !"); } - + template void MemArray::pack() const { - if(_nb_of_elem>=0) - (const_cast * >(this))->reserve(_nb_of_elem); + (const_cast * >(this))->reserve(_nb_of_elem); } template @@ -181,7 +168,7 @@ namespace ParaMEDMEM { if(sl!=0) stream << _nb_of_elem/sl << std::endl << "Internal memory facts : " << _nb_of_elem << "/" << _nb_of_elem_alloc; - else + else stream << "Empty Data"; } else @@ -193,7 +180,7 @@ namespace ParaMEDMEM stream << "No data !\n"; return ret; } - + /*! * \param [in] sl is typically the number of components */ @@ -218,7 +205,7 @@ namespace ParaMEDMEM stream << "Empty Data\n"; } } - + /*! * \param [in] sl is typically the number of components */ @@ -258,14 +245,58 @@ namespace ParaMEDMEM else stream << "No data !\n"; } - + + /*! + * \param [in] sl is typically the number of components + */ + template + void MemArray::reprNotTooLong(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); + if(nbOfTuples<=1000) + { + for(std::size_t i=0;i(stream," ")); + stream << "\n"; + data+=sl; + } + } + else + {// too much tuples -> print the 3 first tuples and 3 last. + stream << "Tuple #0 : "; + std::copy(data,data+sl,std::ostream_iterator(stream," ")); stream << "\n"; + stream << "Tuple #1 : "; + std::copy(data+sl,data+2*sl,std::ostream_iterator(stream," ")); stream << "\n"; + stream << "Tuple #2 : "; + std::copy(data+2*sl,data+3*sl,std::ostream_iterator(stream," ")); stream << "\n"; + stream << "...\n"; + stream << "Tuple #" << nbOfTuples-3 << " : "; + std::copy(data+(nbOfTuples-3)*sl,data+(nbOfTuples-2)*sl,std::ostream_iterator(stream," ")); stream << "\n"; + stream << "Tuple #" << nbOfTuples-2 << " : "; + std::copy(data+(nbOfTuples-2)*sl,data+(nbOfTuples-1)*sl,std::ostream_iterator(stream," ")); stream << "\n"; + stream << "Tuple #" << nbOfTuples-1 << " : "; + std::copy(data+(nbOfTuples-1)*sl,data+nbOfTuples*sl,std::ostream_iterator(stream," ")); stream << "\n"; + } + } + else + stream << "Empty 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 { @@ -280,7 +311,7 @@ namespace ParaMEDMEM *w=pt[j*nbOfTuples+i]; return ret; } - + template T *MemArray::toNoInterlace(int nbOfComp) const { @@ -334,11 +365,9 @@ namespace ParaMEDMEM } template - void MemArray::alloc(std::size_t nbOfElements) throw(INTERP_KERNEL::Exception) + void MemArray::alloc(std::size_t nbOfElements) { destroy(); - if(nbOfElements<0) - throw INTERP_KERNEL::Exception("MemArray::alloc : request for negative length of data !"); _nb_of_elem=nbOfElements; _nb_of_elem_alloc=nbOfElements; _pointer.setInternal((T*)malloc(_nb_of_elem_alloc*sizeof(T))); @@ -356,16 +385,14 @@ namespace ParaMEDMEM * 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) throw(INTERP_KERNEL::Exception) + void MemArray::reserve(std::size_t newNbOfElements) { - if(newNbOfElements<0) - throw INTERP_KERNEL::Exception("MemArray::reAlloc : request for negative length of data !"); 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 + 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; @@ -382,16 +409,14 @@ namespace ParaMEDMEM * 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) throw(INTERP_KERNEL::Exception) + void MemArray::reAlloc(std::size_t newNbOfElements) { - if(newNbOfElements<0) - throw INTERP_KERNEL::Exception("MemArray::reAlloc : request for negative length of data !"); 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 + 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; @@ -413,21 +438,21 @@ namespace ParaMEDMEM } template - typename MemArray::Deallocator MemArray::BuildFromType(DeallocType type) throw(INTERP_KERNEL::Exception) + 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) + void MemArray::DestroyPointer(T *pt, typename MemArray::Deallocator dealloc, void *param) { if(dealloc) dealloc(pt,param); @@ -437,13 +462,15 @@ namespace ParaMEDMEM void MemArray::destroy() { if(_ownership) - destroyPointer(const_cast(_pointer.getConstPointer()),_dealloc,_param_for_deallocator);//Do not use getPointer because in case of _external + 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) { @@ -451,6 +478,2777 @@ namespace ParaMEDMEM std::copy(other._pointer.getConstPointer(),other._pointer.getConstPointer()+_nb_of_elem,_pointer.getPointer()); return *this; } + + ////////////////////////////////// + + template + DataArrayIterator::DataArrayIterator(typename Traits::ArrayType *da):_da(da),_tuple_id(0),_nb_comp(0),_nb_tuple(0) + { + if(_da) + { + _da->incrRef(); + if(_da->isAllocated()) + { + _nb_comp=da->getNumberOfComponents(); + _nb_tuple=da->getNumberOfTuples(); + _pt=da->getPointer(); + } + } + } + + template + DataArrayIterator::~DataArrayIterator() + { + if(_da) + _da->decrRef(); + } + + template + typename Traits::ArrayTuple *DataArrayIterator::nextt() + { + if(_tuple_id<_nb_tuple) + { + _tuple_id++; + typename Traits::ArrayTuple *ret=new typename Traits::ArrayTuple(_pt,_nb_comp); + _pt+=_nb_comp; + return ret; + } + else + return 0; + } + + ////////////////////////////////// + + template + DataArrayTuple::DataArrayTuple(T *pt, int nbOfComp):_pt(pt),_nb_of_compo(nbOfComp) + { + } + + template + T DataArrayTuple::zeValue() const + { + if(_nb_of_compo==1) + return *_pt; + throw INTERP_KERNEL::Exception("DataArrayTuple::zeValue : DataArrayTuple instance has not exactly 1 component -> Not possible to convert it into a single value !"); + } + + template + typename Traits::ArrayType *DataArrayTuple::buildDA(int nbOfTuples, int nbOfCompo) const + { + if((_nb_of_compo==nbOfCompo && nbOfTuples==1) || (_nb_of_compo==nbOfTuples && nbOfCompo==1)) + { + typename Traits::ArrayType *ret=Traits::ArrayType::New(); + ret->useExternalArrayWithRWAccess(_pt,nbOfTuples,nbOfCompo); + return ret; + } + else + { + std::ostringstream oss; oss << "DataArrayTuple::buildDA : unable to build a requested DataArrayDouble instance with nbofTuple=" << nbOfTuples << " and nbOfCompo=" << nbOfCompo; + oss << ".\nBecause the number of elements in this is " << _nb_of_compo << " !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + + ////////////////////////////////// + + template + MCAuto< typename Traits::ArrayTypeCh > DataArrayTemplate::NewFromStdVector(const typename std::vector& v) + { + std::size_t sz(v.size()); + MCAuto< typename Traits::ArrayTypeCh > ret(Traits::ArrayTypeCh::New()); + ret->alloc(sz,1); + T *pt(ret->getPointer()); + std::copy(v.begin(),v.end(),pt); + return ret; + } + + template + std::vector< MCAuto< typename Traits::ArrayTypeCh > > DataArrayTemplate::explodeComponents() const + { + checkAllocated(); + std::size_t sz(getNumberOfComponents()); + int nbTuples(getNumberOfTuples()); + std::string name(getName()); + std::vector compNames(getInfoOnComponents()); + std::vector< MCAuto< typename Traits::ArrayTypeCh > > ret(sz); + const T *thisPt(begin()); + for(std::size_t i=0;i::ArrayTypeCh > part(Traits::ArrayTypeCh::New()); + part->alloc(nbTuples,1); + part->setName(name); + part->setInfoOnComponent(0,compNames[i]); + T *otherPt(part->getPointer()); + for(int j=0;j + std::size_t DataArrayTemplate::getHeapMemorySizeWithoutChildren() const + { + std::size_t sz(_mem.getNbOfElemAllocated()); + sz*=sizeof(T); + return DataArray::getHeapMemorySizeWithoutChildren()+sz; + } + + /*! + * Allocates the raw data in memory. If the memory was already allocated, then it is + * freed and re-allocated. See an example of this method use + * \ref MEDCouplingArraySteps1WC "here". + * \param [in] nbOfTuple - number of tuples of data to allocate. + * \param [in] nbOfCompo - number of components of data to allocate. + * \throw If \a nbOfTuple < 0 or \a nbOfCompo < 0. + */ + template + void DataArrayTemplate::alloc(std::size_t nbOfTuple, std::size_t nbOfCompo) + { + _info_on_compo.resize(nbOfCompo); + _mem.alloc(nbOfCompo*nbOfTuple); + declareAsNew(); + } + + /*! + * Sets a C array to be used as raw data of \a this. The previously set info + * of components is retained and re-sized. + * For more info see \ref MEDCouplingArraySteps1. + * \param [in] array - the C array to be used as raw data of \a this. + * \param [in] ownership - if \a true, \a array will be deallocated at destruction of \a this. + * \param [in] type - specifies how to deallocate \a array. If \a type == MEDCoupling::CPP_DEALLOC, + * \c delete [] \c array; will be called. If \a type == MEDCoupling::C_DEALLOC, + * \c free(\c array ) will be called. + * \param [in] nbOfTuple - new number of tuples in \a this. + * \param [in] nbOfCompo - new number of components in \a this. + */ + template + void DataArrayTemplate::useArray(const T *array, bool ownership, DeallocType type, int nbOfTuple, int nbOfCompo) + { + _info_on_compo.resize(nbOfCompo); + _mem.useArray(array,ownership,type,(std::size_t)nbOfTuple*nbOfCompo); + declareAsNew(); + } + + template + void DataArrayTemplate::useExternalArrayWithRWAccess(const T *array, int nbOfTuple, int nbOfCompo) + { + _info_on_compo.resize(nbOfCompo); + _mem.useExternalArrayWithRWAccess(array,(std::size_t)nbOfTuple*nbOfCompo); + declareAsNew(); + } + + /*! + * Returns a value located at specified tuple and component. + * This method is equivalent to DataArrayTemplate::getIJ() except that validity of + * parameters is checked. So this method is safe but expensive if used to go through + * all values of \a this. + * \param [in] tupleId - index of tuple of interest. + * \param [in] compoId - index of component of interest. + * \return double - value located by \a tupleId and \a compoId. + * \throw If \a this is not allocated. + * \throw If condition ( 0 <= tupleId < this->getNumberOfTuples() ) is violated. + * \throw If condition ( 0 <= compoId < this->getNumberOfComponents() ) is violated. + */ + template + T DataArrayTemplate::getIJSafe(int tupleId, int compoId) const + { + checkAllocated(); + if(tupleId<0 || tupleId>=getNumberOfTuples()) + { + std::ostringstream oss; oss << Traits::ArrayTypeName << "::getIJSafe : request for tupleId " << tupleId << " should be in [0," << getNumberOfTuples() << ") !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + if(compoId<0 || compoId>=getNumberOfComponents()) + { + std::ostringstream oss; oss << Traits::ArrayTypeName << "::getIJSafe : request for compoId " << compoId << " should be in [0," << getNumberOfComponents() << ") !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + return _mem[tupleId*_info_on_compo.size()+compoId]; + } + + /*! + * This method \b do \b not modify content of \a this. It only modify its memory footprint if the allocated memory is to high regarding real data to store. + * + * \sa DataArray::getHeapMemorySizeWithoutChildren, DataArrayTemplate::reserve + */ + template + void DataArrayTemplate::pack() const + { + _mem.pack(); + } + + /*! + * Checks if raw data is allocated. Read more on the raw data + * in \ref MEDCouplingArrayBasicsTuplesAndCompo "DataArrays infos" for more information. + * \return bool - \a true if the raw data is allocated, \a false else. + */ + template + bool DataArrayTemplate::isAllocated() const + { + return getConstPointer()!=0; + } + + /*! + * Checks if raw data is allocated and throws an exception if it is not the case. + * \throw If the raw data is not allocated. + */ + template + void DataArrayTemplate::checkAllocated() const + { + if(!isAllocated()) + { + std::ostringstream oss; oss << Traits::ArrayTypeName << "::checkAllocated : Array is defined but not allocated ! Call alloc or setValues method first !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + + /*! + * This method desallocated \a this without modification of informations relative to the components. + * After call of this method, DataArrayDouble::isAllocated will return false. + * If \a this is already not allocated, \a this is let unchanged. + */ + template + void DataArrayTemplate::desallocate() + { + _mem.destroy(); + } + + /*! + * This method reserve nbOfElems elements in memory ( nbOfElems*8 bytes ) \b without impacting the number of tuples in \a this. + * If \a this has already been allocated, this method checks that \a this has only one component. If not an INTERP_KERNEL::Exception will be thrown. + * If \a this has not already been allocated, number of components is set to one. + * This method allows to reduce number of reallocations on invokation of DataArrayDouble::pushBackSilent and DataArrayDouble::pushBackValsSilent on \a this. + * + * \sa DataArrayDouble::pack, DataArrayDouble::pushBackSilent, DataArrayDouble::pushBackValsSilent + */ + template + void DataArrayTemplate::reserve(std::size_t nbOfElems) + { + int nbCompo(getNumberOfComponents()); + if(nbCompo==1) + { + _mem.reserve(nbOfElems); + } + else if(nbCompo==0) + { + _mem.reserve(nbOfElems); + _info_on_compo.resize(1); + } + else + { + std::ostringstream oss; oss << Traits::ArrayTypeName << "::reserve : not available for DataArrayDouble with number of components different than 1 !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + + /*! + * This method adds at the end of \a this the single value \a val. This method do \b not update its time label to avoid useless incrementation + * of counter. So the caller is expected to call TimeLabel::declareAsNew on \a this at the end of the push session. + * + * \param [in] val the value to be added in \a this + * \throw If \a this has already been allocated with number of components different from one. + * \sa DataArrayDouble::pushBackValsSilent + */ + template + void DataArrayTemplate::pushBackSilent(T val) + { + int nbCompo(getNumberOfComponents()); + if(nbCompo==1) + _mem.pushBack(val); + else if(nbCompo==0) + { + _info_on_compo.resize(1); + _mem.pushBack(val); + } + else + { + std::ostringstream oss; oss << Traits::ArrayTypeName << "::pushBackSilent : not available for DataArrayDouble with number of components different than 1 !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + + /*! + * This method adds at the end of \a this a serie of values [\c valsBg,\c valsEnd). This method do \b not update its time label to avoid useless incrementation + * of counter. So the caller is expected to call TimeLabel::declareAsNew on \a this at the end of the push session. + * + * \param [in] valsBg - an array of values to push at the end of \c this. + * \param [in] valsEnd - specifies the end of the array \a valsBg, so that + * the last value of \a valsBg is \a valsEnd[ -1 ]. + * \throw If \a this has already been allocated with number of components different from one. + * \sa DataArrayDouble::pushBackSilent + */ + template + void DataArrayTemplate::pushBackValsSilent(const T *valsBg, const T *valsEnd) + { + int nbCompo(getNumberOfComponents()); + if(nbCompo==1) + _mem.insertAtTheEnd(valsBg,valsEnd); + else if(nbCompo==0) + { + _info_on_compo.resize(1); + _mem.insertAtTheEnd(valsBg,valsEnd); + } + else + { + std::ostringstream oss; oss << Traits::ArrayTypeName << "::pushBackValsSilent : not available for DataArrayDouble with number of components different than 1 !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + + /*! + * This method returns silently ( without updating time label in \a this ) the last value, if any and suppress it. + * \throw If \a this is already empty. + * \throw If \a this has number of components different from one. + */ + template + T DataArrayTemplate::popBackSilent() + { + if(getNumberOfComponents()==1) + return _mem.popBack(); + else + { + std::ostringstream oss; oss << Traits::ArrayTypeName << "::popBackSilent : not available for DataArrayDouble with number of components different than 1 !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + + /*! + * Allocates the raw data in memory. If exactly same memory as needed already + * allocated, it is not re-allocated. + * \param [in] nbOfTuple - number of tuples of data to allocate. + * \param [in] nbOfCompo - number of components of data to allocate. + * \throw If \a nbOfTuple < 0 or \a nbOfCompo < 0. + */ + template + void DataArrayTemplate::allocIfNecessary(int nbOfTuple, int nbOfCompo) + { + if(isAllocated()) + { + if(nbOfTuple!=getNumberOfTuples() || nbOfCompo!=getNumberOfComponents()) + alloc(nbOfTuple,nbOfCompo); + } + else + alloc(nbOfTuple,nbOfCompo); + } + + /*! + * Checks the number of tuples. + * \return bool - \a true if getNumberOfTuples() == 0, \a false else. + * \throw If \a this is not allocated. + */ + template + bool DataArrayTemplate::empty() const + { + checkAllocated(); + return getNumberOfTuples()==0; + } + + /*! + * Copies all the data from another DataArrayDouble. For more info see + * \ref MEDCouplingArrayBasicsCopyDeepAssign. + * \param [in] other - another instance of DataArrayDouble to copy data from. + * \throw If the \a other is not allocated. + */ + template + void DataArrayTemplate::deepCopyFrom(const DataArrayTemplate& other) + { + other.checkAllocated(); + int nbOfTuples(other.getNumberOfTuples()),nbOfComp(other.getNumberOfComponents()); + allocIfNecessary(nbOfTuples,nbOfComp); + std::size_t nbOfElems((std::size_t)nbOfTuples*nbOfComp); + T *pt(getPointer()); + const T *ptI(other.begin()); + for(std::size_t i=0;igetNumberOfComponents() < 1. + * \throw If \a this is not allocated. + */ + template + void DataArrayTemplate::reverse() + { + checkAllocated(); + _mem.reverse(getNumberOfComponents()); + declareAsNew(); + } + + /*! + * Assign \a val to all values in \a this array. To know more on filling arrays see + * \ref MEDCouplingArrayFill. + * \param [in] val - the value to fill with. + * \throw If \a this is not allocated. + */ + template + void DataArrayTemplate::fillWithValue(T val) + { + checkAllocated(); + _mem.fillWithValue(val); + declareAsNew(); + } + + /*! + * Changes number of tuples in the array. If the new number of tuples is smaller + * than the current number the array is truncated, otherwise the array is extended. + * \param [in] nbOfTuples - new number of tuples. + * \throw If \a this is not allocated. + * \throw If \a nbOfTuples is negative. + */ + template + void DataArrayTemplate::reAlloc(std::size_t nbOfTuples) + { + checkAllocated(); + _mem.reAlloc(getNumberOfComponents()*nbOfTuples); + declareAsNew(); + } + + /*! + * Permutes values of \a this array as required by \a old2New array. The values are + * permuted so that \c new[ \a old2New[ i ]] = \c old[ i ]. Number of tuples remains + * the same as in \c this one. + * If a permutation reduction is needed, subArray() or selectByTupleId() should be used. + * For more info on renumbering see \ref numbering. + * \param [in] old2New - C array of length equal to \a this->getNumberOfTuples() + * giving a new position for i-th old value. + */ + template + void DataArrayTemplate::renumberInPlace(const int *old2New) + { + checkAllocated(); + int nbTuples(getNumberOfTuples()),nbOfCompo(getNumberOfComponents()); + T *tmp(new T[nbTuples*nbOfCompo]); + const T *iptr(begin()); + for(int i=0;i=0 && v::ArrayTypeName << "::renumberInPlace : At place #" << i << " value is " << v << " ! Should be in [0," << nbTuples << ") !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + std::copy(tmp,tmp+nbTuples*nbOfCompo,getPointer()); + delete [] tmp; + declareAsNew(); + } + + + /*! + * Permutes values of \a this array as required by \a new2Old array. The values are + * permuted so that \c new[ i ] = \c old[ \a new2Old[ i ]]. Number of tuples remains + * the same as in \c this one. + * For more info on renumbering see \ref numbering. + * \param [in] new2Old - C array of length equal to \a this->getNumberOfTuples() + * giving a previous position of i-th new value. + * \return DataArrayDouble * - the new instance of DataArrayDouble that the caller + * is to delete using decrRef() as it is no more needed. + */ + template + void DataArrayTemplate::renumberInPlaceR(const int *new2Old) + { + checkAllocated(); + int nbTuples(getNumberOfTuples()),nbOfCompo(getNumberOfComponents()); + T *tmp(new T[nbTuples*nbOfCompo]); + const T *iptr(begin()); + for(int i=0;i=0 && v::ArrayTypeName << "::renumberInPlaceR : At place #" << i << " value is " << v << " ! Should be in [0," << nbTuples << ") !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + std::copy(tmp,tmp+nbTuples*nbOfCompo,getPointer()); + delete [] tmp; + declareAsNew(); + } + + /*! + * Sorts values of the array. + * \param [in] asc - \a true means ascending order, \a false, descending. + * \throw If \a this is not allocated. + * \throw If \a this->getNumberOfComponents() != 1. + */ + template + void DataArrayTemplate::sort(bool asc) + { + checkAllocated(); + if(getNumberOfComponents()!=1) + { + std::ostringstream oss; oss << Traits::ArrayTypeName << "::sort : only supported with 'this' array with ONE component !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + _mem.sort(asc); + declareAsNew(); + } + + /*! + * Returns a copy of \a this array with values permuted as required by \a old2New array. + * The values are permuted so that \c new[ \a old2New[ i ]] = \c old[ i ]. + * Number of tuples in the result array remains the same as in \c this one. + * If a permutation reduction is needed, renumberAndReduce() should be used. + * For more info on renumbering see \ref numbering. + * \param [in] old2New - C array of length equal to \a this->getNumberOfTuples() + * giving a new position for i-th old value. + * \return DataArrayDouble * - the new instance of DataArrayDouble that the caller + * is to delete using decrRef() as it is no more needed. + * \throw If \a this is not allocated. + */ + template + typename Traits::ArrayType *DataArrayTemplate::renumber(const int *old2New) const + { + checkAllocated(); + int nbTuples(getNumberOfTuples()),nbOfCompo(getNumberOfComponents()); + MCAuto ret0(buildNewEmptyInstance()); + MCAuto< typename Traits::ArrayType > ret(DynamicCastSafe::ArrayType>(ret0)); + ret->alloc(nbTuples,nbOfCompo); + ret->copyStringInfoFrom(*this); + const T *iptr(begin()); + T *optr(ret->getPointer()); + for(int i=0;icopyStringInfoFrom(*this); + return ret.retn(); + } + + /*! + * Returns a copy of \a this array with values permuted as required by \a new2Old array. + * The values are permuted so that \c new[ i ] = \c old[ \a new2Old[ i ]]. Number of + * tuples in the result array remains the same as in \c this one. + * If a permutation reduction is needed, subArray() or selectByTupleId() should be used. + * For more info on renumbering see \ref numbering. + * \param [in] new2Old - C array of length equal to \a this->getNumberOfTuples() + * giving a previous position of i-th new value. + * \return DataArrayDouble * - the new instance of DataArrayDouble that the caller + * is to delete using decrRef() as it is no more needed. + */ + template + typename Traits::ArrayType *DataArrayTemplate::renumberR(const int *new2Old) const + { + checkAllocated(); + int nbTuples(getNumberOfTuples()),nbOfCompo(getNumberOfComponents()); + MCAuto ret0(buildNewEmptyInstance()); + MCAuto< typename Traits::ArrayType > ret(DynamicCastSafe::ArrayType>(ret0)); + ret->alloc(nbTuples,nbOfCompo); + ret->copyStringInfoFrom(*this); + const T *iptr(getConstPointer()); + T *optr(ret->getPointer()); + for(int i=0;icopyStringInfoFrom(*this); + return ret.retn(); + } + + /*! + * Returns a shorten and permuted copy of \a this array. The new DataArrayDouble is + * of size \a newNbOfTuple and it's values are permuted as required by \a old2New array. + * The values are permuted so that \c new[ \a old2New[ i ]] = \c old[ i ] for all + * \a old2New[ i ] >= 0. In other words every i-th tuple in \a this array, for which + * \a old2New[ i ] is negative, is missing from the result array. + * For more info on renumbering see \ref numbering. + * \param [in] old2New - C array of length equal to \a this->getNumberOfTuples() + * giving a new position for i-th old tuple and giving negative position for + * for i-th old tuple that should be omitted. + * \return DataArrayDouble * - the new instance of DataArrayDouble that the caller + * is to delete using decrRef() as it is no more needed. + */ + template + typename Traits::ArrayType *DataArrayTemplate::renumberAndReduce(const int *old2New, int newNbOfTuple) const + { + checkAllocated(); + int nbTuples(getNumberOfTuples()),nbOfCompo(getNumberOfComponents()); + MCAuto ret0(buildNewEmptyInstance()); + MCAuto< typename Traits::ArrayType > ret(DynamicCastSafe::ArrayType>(ret0)); + ret->alloc(newNbOfTuple,nbOfCompo); + const T *iptr=getConstPointer(); + T *optr=ret->getPointer(); + for(int i=0;i=0) + std::copy(iptr+i*nbOfCompo,iptr+(i+1)*nbOfCompo,optr+w*nbOfCompo); + } + ret->copyStringInfoFrom(*this); + return ret.retn(); + } + + /*! + * Returns a shorten and permuted copy of \a this array. The new DataArrayDouble is + * of size \a new2OldEnd - \a new2OldBg and it's values are permuted as required by + * \a new2OldBg array. + * The values are permuted so that \c new[ i ] = \c old[ \a new2OldBg[ i ]]. + * This method is equivalent to renumberAndReduce() except that convention in input is + * \c new2old and \b not \c old2new. + * For more info on renumbering see \ref numbering. + * \param [in] new2OldBg - pointer to the beginning of a permutation array that gives a + * tuple index in \a this array to fill the i-th tuple in the new array. + * \param [in] new2OldEnd - specifies the end of the permutation array that starts at + * \a new2OldBg, so that pointer to a tuple index (\a pi) varies as this: + * \a new2OldBg <= \a pi < \a new2OldEnd. + * \return DataArrayDouble * - the new instance of DataArrayDouble that the caller + * is to delete using decrRef() as it is no more needed. + */ + template + typename Traits::ArrayType *DataArrayTemplate::mySelectByTupleId(const int *new2OldBg, const int *new2OldEnd) const + { + checkAllocated(); + MCAuto ret0(buildNewEmptyInstance()); + MCAuto< typename Traits::ArrayType > ret(DynamicCastSafe::ArrayType>(ret0)); + int nbComp(getNumberOfComponents()); + ret->alloc((int)std::distance(new2OldBg,new2OldEnd),nbComp); + ret->copyStringInfoFrom(*this); + T *pt(ret->getPointer()); + const T *srcPt(getConstPointer()); + int i(0); + for(const int *w=new2OldBg;w!=new2OldEnd;w++,i++) + std::copy(srcPt+(*w)*nbComp,srcPt+((*w)+1)*nbComp,pt+i*nbComp); + ret->copyStringInfoFrom(*this); + return ret.retn(); + } + + template + typename Traits::ArrayType *DataArrayTemplate::mySelectByTupleId(const DataArrayInt& di) const + { + return DataArrayTemplate::mySelectByTupleId(di.begin(),di.end()); + } + + template + MCAuto::ArrayTypeCh> DataArrayTemplate::selectPartDef(const PartDefinition *pd) const + { + if(!pd) + throw INTERP_KERNEL::Exception("DataArrayTemplate::selectPartDef : null input pointer !"); + MCAuto::ArrayTypeCh> ret(Traits::ArrayTypeCh::New()); + const SlicePartDefinition *spd(dynamic_cast(pd)); + if(spd) + { + int a,b,c; + spd->getSlice(a,b,c); + if(a==0 && b==getNumberOfTuples() && c==1) + { + DataArrayTemplate *directRet(const_cast *>(this)); + directRet->incrRef(); + MCAuto > ret(directRet); + return DynamicCastSafe,typename Traits::ArrayTypeCh>(ret); + } + else + { + MCAuto ret(selectByTupleIdSafeSlice(a,b,c)); + return DynamicCastSafe::ArrayTypeCh>(ret); + } + } + const DataArrayPartDefinition *dpd(dynamic_cast(pd)); + if(dpd) + { + MCAuto arr(dpd->toDAI()); + MCAuto ret(selectByTupleIdSafe(arr->begin(),arr->end())); + return DynamicCastSafe::ArrayTypeCh>(ret); + + } + throw INTERP_KERNEL::Exception("DataArrayTemplate::selectPartDef : unrecognized part def !"); + } + + /*! + * Returns a shorten and permuted copy of \a this array. The new DataArrayDouble is + * of size \a new2OldEnd - \a new2OldBg and it's values are permuted as required by + * \a new2OldBg array. + * The values are permuted so that \c new[ i ] = \c old[ \a new2OldBg[ i ]]. + * This method is equivalent to renumberAndReduce() except that convention in input is + * \c new2old and \b not \c old2new. + * This method is equivalent to selectByTupleId() except that it prevents coping data + * from behind the end of \a this array. + * For more info on renumbering see \ref numbering. + * \param [in] new2OldBg - pointer to the beginning of a permutation array that gives a + * tuple index in \a this array to fill the i-th tuple in the new array. + * \param [in] new2OldEnd - specifies the end of the permutation array that starts at + * \a new2OldBg, so that pointer to a tuple index (\a pi) varies as this: + * \a new2OldBg <= \a pi < \a new2OldEnd. + * \return DataArrayDouble * - the new instance of DataArrayDouble that the caller + * is to delete using decrRef() as it is no more needed. + * \throw If \a new2OldEnd - \a new2OldBg > \a this->getNumberOfTuples(). + */ + template + typename Traits::ArrayType *DataArrayTemplate::mySelectByTupleIdSafe(const int *new2OldBg, const int *new2OldEnd) const + { + checkAllocated(); + MCAuto ret0(buildNewEmptyInstance()); + MCAuto< typename Traits::ArrayType > ret(DynamicCastSafe::ArrayType>(ret0)); + int nbComp(getNumberOfComponents()),oldNbOfTuples(getNumberOfTuples()); + ret->alloc((int)std::distance(new2OldBg,new2OldEnd),nbComp); + ret->copyStringInfoFrom(*this); + T *pt(ret->getPointer()); + const T *srcPt(getConstPointer()); + int i(0); + for(const int *w=new2OldBg;w!=new2OldEnd;w++,i++) + if(*w>=0 && *w::ArrayTypeName << "::selectByTupleIdSafe : some ids has been detected to be out of [0,this->getNumberOfTuples) !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + ret->copyStringInfoFrom(*this); + return ret.retn(); + } + + /*! + * Changes the number of components within \a this array so that its raw data **does + * not** change, instead splitting this data into tuples changes. + * \warning This method erases all (name and unit) component info set before! + * \param [in] newNbOfComp - number of components for \a this array to have. + * \throw If \a this is not allocated + * \throw If getNbOfElems() % \a newNbOfCompo != 0. + * \throw If \a newNbOfCompo is lower than 1. + * \throw If the rearrange method would lead to a number of tuples higher than 2147483647 (maximal capacity of int32 !). + * \warning This method erases all (name and unit) component info set before! + */ + template + void DataArrayTemplate::rearrange(int newNbOfCompo) + { + checkAllocated(); + if(newNbOfCompo<1) + { + std::ostringstream oss; oss << Traits::ArrayTypeName << "::rearrange : input newNbOfCompo must be > 0 !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + std::size_t nbOfElems=getNbOfElems(); + if(nbOfElems%newNbOfCompo!=0) + { + std::ostringstream oss; oss << Traits::ArrayTypeName << "::rearrange : nbOfElems%newNbOfCompo!=0 !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + if(nbOfElems/newNbOfCompo>(std::size_t)std::numeric_limits::max()) + { + std::ostringstream oss; oss << Traits::ArrayTypeName << "::rearrange : the rearrangement leads to too high number of tuples (> 2147483647) !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + _info_on_compo.clear(); + _info_on_compo.resize(newNbOfCompo); + declareAsNew(); + } + + /*! + * Changes the number of components within \a this array to be equal to its number + * of tuples, and inversely its number of tuples to become equal to its number of + * components. So that its raw data **does not** change, instead splitting this + * data into tuples changes. + * \warning This method erases all (name and unit) component info set before! + * \warning Do not confuse this method with fromNoInterlace() and toNoInterlace()! + * \throw If \a this is not allocated. + * \sa rearrange() + */ + template + void DataArrayTemplate::transpose() + { + checkAllocated(); + int nbOfTuples(getNumberOfTuples()); + rearrange(nbOfTuples); + } + + /*! + * Returns a shorten or extended copy of \a this array. If \a newNbOfComp is less + * than \a this->getNumberOfComponents() then the result array is shorten as each tuple + * is truncated to have \a newNbOfComp components, keeping first components. If \a + * newNbOfComp is more than \a this->getNumberOfComponents() then the result array is + * expanded as each tuple is populated with \a dftValue to have \a newNbOfComp + * components. + * \param [in] newNbOfComp - number of components for the new array to have. + * \param [in] dftValue - value assigned to new values added to the new array. + * \return DataArrayDouble * - the new instance of DataArrayDouble that the caller + * is to delete using decrRef() as it is no more needed. + * \throw If \a this is not allocated. + */ + template + typename Traits::ArrayType *DataArrayTemplate::changeNbOfComponents(int newNbOfComp, T dftValue) const + { + checkAllocated(); + MCAuto ret0(buildNewEmptyInstance()); + MCAuto< typename Traits::ArrayType > ret(DynamicCastSafe::ArrayType>(ret0)); + ret->alloc(getNumberOfTuples(),newNbOfComp); + const T *oldc(getConstPointer()); + T *nc(ret->getPointer()); + int nbOfTuples(getNumberOfTuples()),oldNbOfComp(getNumberOfComponents()); + int dim(std::min(oldNbOfComp,newNbOfComp)); + for(int i=0;isetName(getName()); + for(int i=0;isetInfoOnComponent(i,getInfoOnComponent(i)); + ret->setName(getName()); + return ret.retn(); + } + + /*! + * Returns a copy of \a this array composed of selected components. + * The new DataArrayDouble has the same number of tuples but includes components + * specified by \a compoIds parameter. So that getNbOfElems() of the result array + * can be either less, same or more than \a this->getNbOfElems(). + * \param [in] compoIds - sequence of zero based indices of components to include + * into the new array. + * \return DataArrayDouble * - the new instance of DataArrayDouble that the caller + * is to delete using decrRef() as it is no more needed. + * \throw If \a this is not allocated. + * \throw If a component index (\a i) is not valid: + * \a i < 0 || \a i >= \a this->getNumberOfComponents(). + * + * \if ENABLE_EXAMPLES + * \ref py_mcdataarraydouble_KeepSelectedComponents "Here is a Python example". + * \endif + */ + template + typename Traits::ArrayType *DataArrayTemplate::myKeepSelectedComponents(const std::vector& compoIds) const + { + checkAllocated(); + MCAuto ret0(buildNewEmptyInstance()); + MCAuto< typename Traits::ArrayType > ret(DynamicCastSafe::ArrayType>(ret0)); + std::size_t newNbOfCompo(compoIds.size()); + int oldNbOfCompo(getNumberOfComponents()); + for(std::vector::const_iterator it=compoIds.begin();it!=compoIds.end();it++) + if((*it)<0 || (*it)>=oldNbOfCompo) + { + std::ostringstream oss; oss << Traits::ArrayTypeName << "::keepSelectedComponents : invalid requested component : " << *it << " whereas it should be in [0," << oldNbOfCompo << ") !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + int nbOfTuples(getNumberOfTuples()); + ret->alloc(nbOfTuples,(int)newNbOfCompo); + ret->copyPartOfStringInfoFrom(*this,compoIds); + const T *oldc(getConstPointer()); + T *nc(ret->getPointer()); + for(int i=0;i \a this->getNumberOfTuples(). + * \throw If \a tupleIdEnd != -1 && \a tupleIdEnd < \a this->getNumberOfTuples(). + * \sa DataArrayDouble::selectByTupleIdSafeSlice + */ + template + typename Traits::ArrayType *DataArrayTemplate::subArray(int tupleIdBg, int tupleIdEnd) const + { + checkAllocated(); + int nbt(getNumberOfTuples()); + if(tupleIdBg<0) + { + std::ostringstream oss; oss << Traits::ArrayTypeName << "::subArray : The tupleIdBg parameter must be greater than 0 !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + if(tupleIdBg>nbt) + { + std::ostringstream oss; oss << Traits::ArrayTypeName << ":subArray : The tupleIdBg parameter is greater than number of tuples !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + int trueEnd=tupleIdEnd; + if(tupleIdEnd!=-1) + { + if(tupleIdEnd>nbt) + { + std::ostringstream oss; oss << Traits::ArrayTypeName << ":subArray : The tupleIdBg parameter is greater than number of tuples !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + else + trueEnd=nbt; + int nbComp(getNumberOfComponents()); + MCAuto ret0(buildNewEmptyInstance()); + MCAuto< typename Traits::ArrayType > ret(DynamicCastSafe::ArrayType>(ret0)); + ret->alloc(trueEnd-tupleIdBg,nbComp); + ret->copyStringInfoFrom(*this); + std::copy(getConstPointer()+tupleIdBg*nbComp,getConstPointer()+trueEnd*nbComp,ret->getPointer()); + return ret.retn(); + } + + /*! + * Returns a shorten copy of \a this array. The new DataArrayDouble contains every + * (\a bg + \c i * \a step)-th tuple of \a this array located before the \a end2-th + * tuple. Indices of the selected tuples are the same as ones returned by the Python + * command \c range( \a bg, \a end2, \a step ). + * This method is equivalent to selectByTupleIdSafe() except that the input array is + * not constructed explicitly. + * For more info on renumbering see \ref numbering. + * \param [in] bg - index of the first tuple to copy from \a this array. + * \param [in] end2 - index of the tuple before which the tuples to copy are located. + * \param [in] step - index increment to get index of the next tuple to copy. + * \return DataArrayDouble * - the new instance of DataArrayDouble that the caller + * is to delete using decrRef() as it is no more needed. + * \sa DataArrayDouble::subArray. + */ + template + typename Traits::ArrayType *DataArrayTemplate::mySelectByTupleIdSafeSlice(int bg, int end2, int step) const + { + checkAllocated(); + MCAuto ret0(buildNewEmptyInstance()); + MCAuto< typename Traits::ArrayType > ret(DynamicCastSafe::ArrayType>(ret0)); + int nbComp(getNumberOfComponents()); + std::ostringstream oss; oss << Traits::ArrayTypeName << "::selectByTupleIdSafeSlice : "; + int newNbOfTuples(GetNumberOfItemGivenBESRelative(bg,end2,step,oss.str())); + ret->alloc(newNbOfTuples,nbComp); + T *pt(ret->getPointer()); + const T *srcPt(getConstPointer()+bg*nbComp); + for(int i=0;icopyStringInfoFrom(*this); + return ret.retn(); + } + + /*! + * Copy all values from another DataArrayDouble into specified tuples and components + * of \a this array. Textual data is not copied. + * The tree parameters defining set of indices of tuples and components are similar to + * the tree parameters of the Python function \c range(\c start,\c stop,\c step). + * \param [in] a - the array to copy values from. + * \param [in] bgTuples - index of the first tuple of \a this array to assign values to. + * \param [in] endTuples - index of the tuple before which the tuples to assign to + * are located. + * \param [in] stepTuples - index increment to get index of the next tuple to assign to. + * \param [in] bgComp - index of the first component of \a this array to assign values to. + * \param [in] endComp - index of the component before which the components to assign + * to are located. + * \param [in] stepComp - index increment to get index of the next component to assign to. + * \param [in] strictCompoCompare - if \a true (by default), then \a a->getNumberOfComponents() + * must be equal to the number of columns to assign to, else an + * exception is thrown; if \a false, then it is only required that \a + * a->getNbOfElems() equals to number of values to assign to (this condition + * must be respected even if \a strictCompoCompare is \a true). The number of + * values to assign to is given by following Python expression: + * \a nbTargetValues = + * \c len(\c range(\a bgTuples,\a endTuples,\a stepTuples)) * + * \c len(\c range(\a bgComp,\a endComp,\a stepComp)). + * \throw If \a a is NULL. + * \throw If \a a is not allocated. + * \throw If \a this is not allocated. + * \throw If parameters specifying tuples and components to assign to do not give a + * non-empty range of increasing indices. + * \throw If \a a->getNbOfElems() != \a nbTargetValues. + * \throw If \a strictCompoCompare == \a true && \a a->getNumberOfComponents() != + * \c len(\c range(\a bgComp,\a endComp,\a stepComp)). + * + * \if ENABLE_EXAMPLES + * \ref py_mcdataarraydouble_setpartofvalues1 "Here is a Python example". + * \endif + */ + template + void DataArrayTemplate::setPartOfValues1(const typename Traits::ArrayType *a, int bgTuples, int endTuples, int stepTuples, int bgComp, int endComp, int stepComp, bool strictCompoCompare) + { + if(!a) + { + std::ostringstream oss; oss << Traits::ArrayTypeName << "::setPartOfValues1 : input DataArrayDouble is NULL !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + const char msg[]="DataArrayTemplate::setPartOfValues1"; + checkAllocated(); + a->checkAllocated(); + int newNbOfTuples(DataArray::GetNumberOfItemGivenBES(bgTuples,endTuples,stepTuples,msg)); + int newNbOfComp(DataArray::GetNumberOfItemGivenBES(bgComp,endComp,stepComp,msg)); + int nbComp(getNumberOfComponents()),nbOfTuples(getNumberOfTuples()); + DataArray::CheckValueInRangeEx(nbOfTuples,bgTuples,endTuples,"invalid tuple value"); + DataArray::CheckValueInRangeEx(nbComp,bgComp,endComp,"invalid component value"); + bool assignTech(true); + if(a->getNbOfElems()==(std::size_t)newNbOfTuples*newNbOfComp) + { + if(strictCompoCompare) + a->checkNbOfTuplesAndComp(newNbOfTuples,newNbOfComp,msg); + } + else + { + a->checkNbOfTuplesAndComp(1,newNbOfComp,msg); + assignTech=false; + } + const T *srcPt(a->getConstPointer()); + T *pt(getPointer()+bgTuples*nbComp+bgComp); + if(assignTech) + { + for(int i=0;i + void DataArrayTemplate::setPartOfValuesSimple1(T a, int bgTuples, int endTuples, int stepTuples, int bgComp, int endComp, int stepComp) + { + const char msg[]="DataArrayTemplate::setPartOfValuesSimple1"; + checkAllocated(); + int newNbOfTuples(DataArray::GetNumberOfItemGivenBES(bgTuples,endTuples,stepTuples,msg)); + int newNbOfComp(DataArray::GetNumberOfItemGivenBES(bgComp,endComp,stepComp,msg)); + int nbComp(getNumberOfComponents()),nbOfTuples(getNumberOfTuples()); + DataArray::CheckValueInRangeEx(nbOfTuples,bgTuples,endTuples,"invalid tuple value"); + DataArray::CheckValueInRangeEx(nbComp,bgComp,endComp,"invalid component value"); + T *pt=getPointer()+bgTuples*nbComp+bgComp; + for(int i=0;igetNbOfElems() equals to number of values to assign to, then every value + * of \a a is assigned to its own location within \a this array. + * - If \a a includes one tuple, then all values of \a a are assigned to the specified + * components of every specified tuple of \a this array. In this mode it is required + * that \a a->getNumberOfComponents() equals to the number of specified components. + * + * \param [in] a - the array to copy values from. + * \param [in] bgTuples - pointer to an array of tuple indices of \a this array to + * assign values of \a a to. + * \param [in] endTuples - specifies the end of the array \a bgTuples, so that + * pointer to a tuple index (pi) varies as this: + * \a bgTuples <= \a pi < \a endTuples. + * \param [in] bgComp - pointer to an array of component indices of \a this array to + * assign values of \a a to. + * \param [in] endComp - specifies the end of the array \a bgTuples, so that + * pointer to a component index (pi) varies as this: + * \a bgComp <= \a pi < \a endComp. + * \param [in] strictCompoCompare - this parameter is checked only if the + * *mode of usage* is the first; if it is \a true (default), + * then \a a->getNumberOfComponents() must be equal + * to the number of specified columns, else this is not required. + * \throw If \a a is NULL. + * \throw If \a a is not allocated. + * \throw If \a this is not allocated. + * \throw If any index of tuple/component given by bgTuples / bgComp is + * out of a valid range for \a this array. + * \throw In the first *mode of usage*, if strictCompoCompare == true and + * if a->getNumberOfComponents() != (endComp - bgComp) . + * \throw In the second *mode of usage*, if \a a->getNumberOfTuples() != 1 or + * a->getNumberOfComponents() != (endComp - bgComp). + * + * \if ENABLE_EXAMPLES + * \ref py_mcdataarraydouble_setpartofvalues2 "Here is a Python example". + * \endif + */ + template + void DataArrayTemplate::setPartOfValues2(const typename Traits::ArrayType *a, const int *bgTuples, const int *endTuples, const int *bgComp, const int *endComp, bool strictCompoCompare) + { + if(!a) + throw INTERP_KERNEL::Exception("DataArrayDouble::setPartOfValues2 : input DataArrayDouble is NULL !"); + const char msg[]="DataArrayTemplate::setPartOfValues2"; + checkAllocated(); + a->checkAllocated(); + int nbComp(getNumberOfComponents()),nbOfTuples(getNumberOfTuples()); + for(const int *z=bgComp;z!=endComp;z++) + DataArray::CheckValueInRange(nbComp,*z,"invalid component id"); + int newNbOfTuples((int)std::distance(bgTuples,endTuples)); + int newNbOfComp((int)std::distance(bgComp,endComp)); + bool assignTech(true); + if(a->getNbOfElems()==(std::size_t)newNbOfTuples*newNbOfComp) + { + if(strictCompoCompare) + a->checkNbOfTuplesAndComp(newNbOfTuples,newNbOfComp,msg); + } + else + { + a->checkNbOfTuplesAndComp(1,newNbOfComp,msg); + assignTech=false; + } + T *pt(getPointer()); + const T *srcPt(a->getConstPointer()); + if(assignTech) + { + for(const int *w=bgTuples;w!=endTuples;w++) + { + DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id"); + for(const int *z=bgComp;z!=endComp;z++,srcPt++) + { + pt[(std::size_t)(*w)*nbComp+(*z)]=*srcPt; + } + } + } + else + { + for(const int *w=bgTuples;w!=endTuples;w++) + { + const T *srcPt2=srcPt; + DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id"); + for(const int *z=bgComp;z!=endComp;z++,srcPt2++) + { + pt[(std::size_t)(*w)*nbComp+(*z)]=*srcPt2; + } + } + } + } + + /*! + * Assign a given value to values at specified tuples and components of \a this array. + * The tuples and components to assign to are defined by C arrays of indices. + * \param [in] a - the value to assign. + * \param [in] bgTuples - pointer to an array of tuple indices of \a this array to + * assign \a a to. + * \param [in] endTuples - specifies the end of the array \a bgTuples, so that + * pointer to a tuple index (\a pi) varies as this: + * \a bgTuples <= \a pi < \a endTuples. + * \param [in] bgComp - pointer to an array of component indices of \a this array to + * assign \a a to. + * \param [in] endComp - specifies the end of the array \a bgTuples, so that + * pointer to a component index (\a pi) varies as this: + * \a bgComp <= \a pi < \a endComp. + * \throw If \a this is not allocated. + * \throw If any index of tuple/component given by bgTuples / bgComp is + * out of a valid range for \a this array. + * + * \if ENABLE_EXAMPLES + * \ref py_mcdataarraydouble_setpartofvaluessimple2 "Here is a Python example". + * \endif + */ + template + void DataArrayTemplate::setPartOfValuesSimple2(T a, const int *bgTuples, const int *endTuples, const int *bgComp, const int *endComp) + { + checkAllocated(); + int nbComp(getNumberOfComponents()),nbOfTuples(getNumberOfTuples()); + for(const int *z=bgComp;z!=endComp;z++) + DataArray::CheckValueInRange(nbComp,*z,"invalid component id"); + T *pt(getPointer()); + for(const int *w=bgTuples;w!=endTuples;w++) + for(const int *z=bgComp;z!=endComp;z++) + { + DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id"); + pt[(std::size_t)(*w)*nbComp+(*z)]=a; + } + } + + /*! + * Copy all values from another DataArrayDouble (\a a) into specified tuples and + * components of \a this array. Textual data is not copied. + * The tuples to assign to are defined by a C array of indices. + * The components to assign to are defined by three values similar to parameters of + * the Python function \c range(\c start,\c stop,\c step). + * There are two *modes of usage*: + * - If \a a->getNbOfElems() equals to number of values to assign to, then every value + * of \a a is assigned to its own location within \a this array. + * - If \a a includes one tuple, then all values of \a a are assigned to the specified + * components of every specified tuple of \a this array. In this mode it is required + * that \a a->getNumberOfComponents() equals to the number of specified components. + * + * \param [in] a - the array to copy values from. + * \param [in] bgTuples - pointer to an array of tuple indices of \a this array to + * assign values of \a a to. + * \param [in] endTuples - specifies the end of the array \a bgTuples, so that + * pointer to a tuple index (pi) varies as this: + * \a bgTuples <= \a pi < \a endTuples. + * \param [in] bgComp - index of the first component of \a this array to assign to. + * \param [in] endComp - index of the component before which the components to assign + * to are located. + * \param [in] stepComp - index increment to get index of the next component to assign to. + * \param [in] strictCompoCompare - this parameter is checked only in the first + * *mode of usage*; if \a strictCompoCompare is \a true (default), + * then \a a->getNumberOfComponents() must be equal + * to the number of specified columns, else this is not required. + * \throw If \a a is NULL. + * \throw If \a a is not allocated. + * \throw If \a this is not allocated. + * \throw If any index of tuple given by \a bgTuples is out of a valid range for + * \a this array. + * \throw In the first *mode of usage*, if strictCompoCompare == true and + * if a->getNumberOfComponents() is unequal to the number of components + * defined by (bgComp,endComp,stepComp). + * \throw In the second *mode of usage*, if \a a->getNumberOfTuples() != 1 or + * a->getNumberOfComponents() is unequal to the number of components + * defined by (bgComp,endComp,stepComp). + * \throw If parameters specifying components to assign to, do not give a + * non-empty range of increasing indices or indices are out of a valid range + * for \c this array. + * + * \if ENABLE_EXAMPLES + * \ref py_mcdataarraydouble_setpartofvalues3 "Here is a Python example". + * \endif + */ + template + void DataArrayTemplate::setPartOfValues3(const typename Traits::ArrayType *a, const int *bgTuples, const int *endTuples, int bgComp, int endComp, int stepComp, bool strictCompoCompare) + { + if(!a) + throw INTERP_KERNEL::Exception("DataArrayTemplate::setPartOfValues3 : input DataArrayDouble is NULL !"); + const char msg[]="DataArrayTemplate::setPartOfValues3"; + checkAllocated(); + a->checkAllocated(); + int newNbOfComp=DataArray::GetNumberOfItemGivenBES(bgComp,endComp,stepComp,msg); + int nbComp=getNumberOfComponents(); + int nbOfTuples=getNumberOfTuples(); + DataArray::CheckValueInRangeEx(nbComp,bgComp,endComp,"invalid component value"); + int newNbOfTuples=(int)std::distance(bgTuples,endTuples); + bool assignTech=true; + if(a->getNbOfElems()==(std::size_t)newNbOfTuples*newNbOfComp) + { + if(strictCompoCompare) + a->checkNbOfTuplesAndComp(newNbOfTuples,newNbOfComp,msg); + } + else + { + a->checkNbOfTuplesAndComp(1,newNbOfComp,msg); + assignTech=false; + } + T *pt(getPointer()+bgComp); + const T *srcPt(a->getConstPointer()); + if(assignTech) + { + for(const int *w=bgTuples;w!=endTuples;w++) + for(int j=0;j(pi) varies as this: + * \a bgTuples <= \a pi < \a endTuples. + * \param [in] bgComp - index of the first component of \a this array to assign to. + * \param [in] endComp - index of the component before which the components to assign + * to are located. + * \param [in] stepComp - index increment to get index of the next component to assign to. + * \throw If \a this is not allocated. + * \throw If any index of tuple given by \a bgTuples is out of a valid range for + * \a this array. + * \throw If parameters specifying components to assign to, do not give a + * non-empty range of increasing indices or indices are out of a valid range + * for \c this array. + * + * \if ENABLE_EXAMPLES + * \ref py_mcdataarraydouble_setpartofvaluessimple3 "Here is a Python example". + * \endif + */ + template + void DataArrayTemplate::setPartOfValuesSimple3(T a, const int *bgTuples, const int *endTuples, int bgComp, int endComp, int stepComp) + { + const char msg[]="DataArrayTemplate::setPartOfValuesSimple3"; + checkAllocated(); + int newNbOfComp(DataArray::GetNumberOfItemGivenBES(bgComp,endComp,stepComp,msg)); + int nbComp(getNumberOfComponents()),nbOfTuples(getNumberOfTuples()); + DataArray::CheckValueInRangeEx(nbComp,bgComp,endComp,"invalid component value"); + T *pt(getPointer()+bgComp); + for(const int *w=bgTuples;w!=endTuples;w++) + for(int j=0;jgetNumberOfComponents() + * must be equal to the number of columns to assign to, else an + * exception is thrown; if \a false, then it is only required that \a + * a->getNbOfElems() equals to number of values to assign to (this condition + * must be respected even if \a strictCompoCompare is \a true). The number of + * values to assign to is given by following Python expression: + * \a nbTargetValues = + * \c len(\c range(\a bgTuples,\a endTuples,\a stepTuples)) * + * \c len(\c range(\a bgComp,\a endComp,\a stepComp)). + * \throw If \a a is NULL. + * \throw If \a a is not allocated. + * \throw If \a this is not allocated. + * \throw If parameters specifying tuples and components to assign to do not give a + * non-empty range of increasing indices. + * \throw If \a a->getNbOfElems() != \a nbTargetValues. + * \throw If \a strictCompoCompare == \a true && \a a->getNumberOfComponents() != + * \c len(\c range(\a bgComp,\a endComp,\a stepComp)). + * + */ + template + void DataArrayTemplate::setPartOfValues4(const typename Traits::ArrayType *a, int bgTuples, int endTuples, int stepTuples, const int *bgComp, const int *endComp, bool strictCompoCompare) + {if(!a) + throw INTERP_KERNEL::Exception("DataArrayTemplate::setPartOfValues4 : input DataArrayTemplate is NULL !"); + const char msg[]="DataArrayTemplate::setPartOfValues4"; + checkAllocated(); + a->checkAllocated(); + int newNbOfTuples(DataArray::GetNumberOfItemGivenBES(bgTuples,endTuples,stepTuples,msg)); + int newNbOfComp((int)std::distance(bgComp,endComp)); + int nbComp(getNumberOfComponents()); + for(const int *z=bgComp;z!=endComp;z++) + DataArray::CheckValueInRange(nbComp,*z,"invalid component id"); + int nbOfTuples(getNumberOfTuples()); + DataArray::CheckValueInRangeEx(nbOfTuples,bgTuples,endTuples,"invalid tuple value"); + bool assignTech(true); + if(a->getNbOfElems()==(std::size_t)newNbOfTuples*newNbOfComp) + { + if(strictCompoCompare) + a->checkNbOfTuplesAndComp(newNbOfTuples,newNbOfComp,msg); + } + else + { + a->checkNbOfTuplesAndComp(1,newNbOfComp,msg); + assignTech=false; + } + const T *srcPt(a->getConstPointer()); + T *pt(getPointer()+bgTuples*nbComp); + if(assignTech) + { + for(int i=0;i + void DataArrayTemplate::setPartOfValuesSimple4(T a, int bgTuples, int endTuples, int stepTuples, const int *bgComp, const int *endComp) + { + const char msg[]="DataArrayTemplate::setPartOfValuesSimple4"; + checkAllocated(); + int newNbOfTuples(DataArray::GetNumberOfItemGivenBES(bgTuples,endTuples,stepTuples,msg)); + int nbComp(getNumberOfComponents()); + for(const int *z=bgComp;z!=endComp;z++) + DataArray::CheckValueInRange(nbComp,*z,"invalid component id"); + int nbOfTuples(getNumberOfTuples()); + DataArray::CheckValueInRangeEx(nbOfTuples,bgTuples,endTuples,"invalid tuple value"); + T *pt=getPointer()+bgTuples*nbComp; + for(int i=0;ithis->getNumberOfComponents() != a->getNumberOfComponents(). + * \throw If \a tuplesSelec->getNumberOfComponents() != 2. + * \throw If any tuple index given by \a tuplesSelec is out of a valid range for + * the corresponding (\a this or \a a) array. + */ + template + void DataArrayTemplate::setPartOfValuesAdv(const typename Traits::ArrayType *a, const DataArrayInt *tuplesSelec) + { + if(!a || !tuplesSelec) + throw INTERP_KERNEL::Exception("DataArrayTemplate::setPartOfValuesAdv : input DataArrayTemplate is NULL !"); + checkAllocated(); + a->checkAllocated(); + tuplesSelec->checkAllocated(); + int nbOfComp=getNumberOfComponents(); + if(nbOfComp!=a->getNumberOfComponents()) + throw INTERP_KERNEL::Exception("DataArrayTemplate::setPartOfValuesAdv : This and a do not have the same number of components !"); + if(tuplesSelec->getNumberOfComponents()!=2) + throw INTERP_KERNEL::Exception("DataArrayTemplate::setPartOfValuesAdv : Expecting to have a tuple selector DataArrayInt instance with exactly 2 components !"); + int thisNt(getNumberOfTuples()); + int aNt(a->getNumberOfTuples()); + T *valsToSet(getPointer()); + const T *valsSrc(a->getConstPointer()); + for(const int *tuple=tuplesSelec->begin();tuple!=tuplesSelec->end();tuple+=2) + { + if(tuple[1]>=0 && tuple[1]=0 && tuple[0]begin(),tuple)/2; + oss << " of 'tuplesSelec' request of tuple id #" << tuple[0] << " in 'this' ! It should be in [0," << thisNt << ") !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + else + { + std::ostringstream oss; oss << "DataArrayTemplate::setPartOfValuesAdv : Tuple #" << std::distance(tuplesSelec->begin(),tuple)/2; + oss << " of 'tuplesSelec' request of tuple id #" << tuple[1] << " in 'a' ! It should be in [0," << aNt << ") !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + } + + /*! + * Copy some tuples from another DataArrayDouble (\a aBase) into contiguous tuples + * of \a this array. Textual data is not copied. Both arrays must have equal number of + * components. + * The tuples to assign to are defined by index of the first tuple, and + * their number is defined by \a tuplesSelec->getNumberOfTuples(). + * The tuples to copy are defined by values of a DataArrayInt. + * All components of selected tuples are copied. + * \param [in] tupleIdStart - index of the first tuple of \a this array to assign + * values to. + * \param [in] aBase - the array to copy values from. + * \param [in] tuplesSelec - the array specifying tuples of \a a to copy. + * \throw If \a this is not allocated. + * \throw If \a aBase is NULL. + * \throw If \a aBase is not allocated. + * \throw If \a tuplesSelec is NULL. + * \throw If \a tuplesSelec is not allocated. + * \throw If this->getNumberOfComponents() != aBase->getNumberOfComponents(). + * \throw If \a tuplesSelec->getNumberOfComponents() != 1. + * \throw If tupleIdStart + tuplesSelec->getNumberOfTuples() > this->getNumberOfTuples(). + * \throw If any tuple index given by \a tuplesSelec is out of a valid range for + * \a aBase array. + */ + template + void DataArrayTemplate::setContigPartOfSelectedValues(int tupleIdStart, const DataArray *aBase, const DataArrayInt *tuplesSelec) + { + if(!aBase || !tuplesSelec) + throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValues : input DataArray is NULL !"); + const typename Traits::ArrayType *a(dynamic_cast::ArrayType *>(aBase)); + if(!a) + throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValues : input DataArray aBase is not a DataArrayDouble !"); + checkAllocated(); + a->checkAllocated(); + tuplesSelec->checkAllocated(); + int nbOfComp(getNumberOfComponents()); + if(nbOfComp!=a->getNumberOfComponents()) + throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValues : This and a do not have the same number of components !"); + if(tuplesSelec->getNumberOfComponents()!=1) + throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValues : Expecting to have a tuple selector DataArrayInt instance with exactly 1 component !"); + int thisNt(getNumberOfTuples()); + int aNt(a->getNumberOfTuples()); + int nbOfTupleToWrite(tuplesSelec->getNumberOfTuples()); + T *valsToSet(getPointer()+tupleIdStart*nbOfComp); + if(tupleIdStart+nbOfTupleToWrite>thisNt) + throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValues : invalid number range of values to write !"); + const T *valsSrc=a->getConstPointer(); + for(const int *tuple=tuplesSelec->begin();tuple!=tuplesSelec->end();tuple++,valsToSet+=nbOfComp) + { + if(*tuple>=0 && *tuple::ArrayTypeName << "::setContigPartOfSelectedValues : Tuple #" << std::distance(tuplesSelec->begin(),tuple); + oss << " of 'tuplesSelec' request of tuple id #" << *tuple << " in 'a' ! It should be in [0," << aNt << ") !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + } + + /*! + * Copy some tuples from another DataArrayDouble (\a aBase) into contiguous tuples + * of \a this array. Textual data is not copied. Both arrays must have equal number of + * components. + * The tuples to copy are defined by three values similar to parameters of + * the Python function \c range(\c start,\c stop,\c step). + * The tuples to assign to are defined by index of the first tuple, and + * their number is defined by number of tuples to copy. + * All components of selected tuples are copied. + * \param [in] tupleIdStart - index of the first tuple of \a this array to assign + * values to. + * \param [in] aBase - the array to copy values from. + * \param [in] bg - index of the first tuple to copy of the array \a aBase. + * \param [in] end2 - index of the tuple of \a aBase before which the tuples to copy + * are located. + * \param [in] step - index increment to get index of the next tuple to copy. + * \throw If \a this is not allocated. + * \throw If \a aBase is NULL. + * \throw If \a aBase is not allocated. + * \throw If this->getNumberOfComponents() != aBase->getNumberOfComponents(). + * \throw If tupleIdStart + len(range(bg,end2,step)) > this->getNumberOfTuples(). + * \throw If parameters specifying tuples to copy, do not give a + * non-empty range of increasing indices or indices are out of a valid range + * for the array \a aBase. + */ + template + void DataArrayTemplate::setContigPartOfSelectedValuesSlice(int tupleIdStart, const DataArray *aBase, int bg, int end2, int step) + { + if(!aBase) + { + std::ostringstream oss; oss << Traits::ArrayTypeName << "::setContigPartOfSelectedValuesSlice : input DataArray is NULL !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + const typename Traits::ArrayType *a(dynamic_cast::ArrayType *>(aBase)); + if(!a) + throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValuesSlice : input DataArray aBase is not a DataArrayDouble !"); + checkAllocated(); + a->checkAllocated(); + int nbOfComp(getNumberOfComponents()); + const char msg[]="DataArrayDouble::setContigPartOfSelectedValuesSlice"; + int nbOfTupleToWrite(DataArray::GetNumberOfItemGivenBES(bg,end2,step,msg)); + if(nbOfComp!=a->getNumberOfComponents()) + throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValuesSlice : This and a do not have the same number of components !"); + int thisNt(getNumberOfTuples()),aNt(a->getNumberOfTuples()); + T *valsToSet(getPointer()+tupleIdStart*nbOfComp); + if(tupleIdStart+nbOfTupleToWrite>thisNt) + throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValuesSlice : invalid number range of values to write !"); + if(end2>aNt) + throw INTERP_KERNEL::Exception("DataArrayTemplate::setContigPartOfSelectedValuesSlice : invalid range of values to read !"); + const T *valsSrc(a->getConstPointer()+bg*nbOfComp); + for(int i=0;i \a this->getNumberOfTuples(). + * \throw If \a this is not allocated. + */ + template + typename Traits::ArrayType *DataArrayTemplate::mySelectByTupleRanges(const std::vector >& ranges) const + { + checkAllocated(); + int nbOfComp(getNumberOfComponents()),nbOfTuplesThis(getNumberOfTuples()); + if(ranges.empty()) + { + MCAuto ret0(buildNewEmptyInstance()); + MCAuto< typename Traits::ArrayType > ret(DynamicCastSafe::ArrayType>(ret0)); + ret->alloc(0,nbOfComp); + ret->copyStringInfoFrom(*this); + return ret.retn(); + } + int ref(ranges.front().first),nbOfTuples(0); + bool isIncreasing(true); + for(std::vector >::const_iterator it=ranges.begin();it!=ranges.end();it++) + { + if((*it).first<=(*it).second) + { + if((*it).first>=0 && (*it).second<=nbOfTuplesThis) + { + nbOfTuples+=(*it).second-(*it).first; + if(isIncreasing) + isIncreasing=ref<=(*it).first; + ref=(*it).second; + } + else + { + std::ostringstream oss; oss << "DataArrayTemplate::selectByTupleRanges : on range #" << std::distance(ranges.begin(),it); + oss << " (" << (*it).first << "," << (*it).second << ") is greater than number of tuples of this :" << nbOfTuples << " !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + else + { + std::ostringstream oss; oss << "DataArrayTemplate::selectByTupleRanges : on range #" << std::distance(ranges.begin(),it); + oss << " (" << (*it).first << "," << (*it).second << ") end is before begin !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + if(isIncreasing && nbOfTuplesThis==nbOfTuples) + return static_cast::ArrayType *>(deepCopy()); + MCAuto ret0(buildNewEmptyInstance()); + MCAuto< typename Traits::ArrayType > ret(DynamicCastSafe::ArrayType>(ret0)); + ret->alloc(nbOfTuples,nbOfComp); + ret->copyStringInfoFrom(*this); + const T *src(getConstPointer()); + T *work(ret->getPointer()); + for(std::vector >::const_iterator it=ranges.begin();it!=ranges.end();it++) + work=std::copy(src+(*it).first*nbOfComp,src+(*it).second*nbOfComp,work); + return ret.retn(); + } + + /*! + * Returns the first value of \a this. + * \return double - the last value of \a this array. + * \throw If \a this is not allocated. + * \throw If \a this->getNumberOfComponents() != 1. + * \throw If \a this->getNumberOfTuples() < 1. + */ + template + T DataArrayTemplate::front() const + { + checkAllocated(); + if(getNumberOfComponents()!=1) + throw INTERP_KERNEL::Exception("DataArrayTemplate::front : number of components not equal to one !"); + int nbOfTuples(getNumberOfTuples()); + if(nbOfTuples<1) + throw INTERP_KERNEL::Exception("DataArrayTemplate::front : number of tuples must be >= 1 !"); + return *(getConstPointer()); + } + + /*! + * Returns the last value of \a this. + * \return double - the last value of \a this array. + * \throw If \a this is not allocated. + * \throw If \a this->getNumberOfComponents() != 1. + * \throw If \a this->getNumberOfTuples() < 1. + */ + template + T DataArrayTemplate::back() const + { + checkAllocated(); + if(getNumberOfComponents()!=1) + throw INTERP_KERNEL::Exception("DataArrayTemplate::back : number of components not equal to one !"); + int nbOfTuples(getNumberOfTuples()); + if(nbOfTuples<1) + throw INTERP_KERNEL::Exception("DataArrayTemplate::back : number of tuples must be >= 1 !"); + return *(getConstPointer()+nbOfTuples-1); + } + + /*! + * Returns the maximal value and its location within \a this one-dimensional array. + * \param [out] tupleId - index of the tuple holding the maximal value. + * \return double - the maximal value among all values of \a this array. + * \throw If \a this->getNumberOfComponents() != 1 + * \throw If \a this->getNumberOfTuples() < 1 + */ + template + T DataArrayTemplate::getMaxValue(int& tupleId) const + { + checkAllocated(); + if(getNumberOfComponents()!=1) + throw INTERP_KERNEL::Exception("DataArrayDouble::getMaxValue : must be applied on DataArrayDouble with only one component, you can call 'rearrange' method before or call 'getMaxValueInArray' method !"); + int nbOfTuples(getNumberOfTuples()); + if(nbOfTuples<=0) + throw INTERP_KERNEL::Exception("DataArrayDouble::getMaxValue : array exists but number of tuples must be > 0 !"); + const T *vals(getConstPointer()); + const T *loc(std::max_element(vals,vals+nbOfTuples)); + tupleId=(int)std::distance(vals,loc); + return *loc; + } + + /*! + * Returns the maximal value within \a this array that is allowed to have more than + * one component. + * \return double - the maximal value among all values of \a this array. + * \throw If \a this is not allocated. + */ + template + T DataArrayTemplate::getMaxValueInArray() const + { + checkAllocated(); + const T *loc(std::max_element(begin(),end())); + return *loc; + } + + /*! + * Returns the minimal value and its location within \a this one-dimensional array. + * \param [out] tupleId - index of the tuple holding the minimal value. + * \return double - the minimal value among all values of \a this array. + * \throw If \a this->getNumberOfComponents() != 1 + * \throw If \a this->getNumberOfTuples() < 1 + */ + template + T DataArrayTemplate::getMinValue(int& tupleId) const + { + checkAllocated(); + if(getNumberOfComponents()!=1) + throw INTERP_KERNEL::Exception("DataArrayDouble::getMinValue : must be applied on DataArrayDouble with only one component, you can call 'rearrange' method before call 'getMinValueInArray' method !"); + int nbOfTuples(getNumberOfTuples()); + if(nbOfTuples<=0) + throw INTERP_KERNEL::Exception("DataArrayDouble::getMinValue : array exists but number of tuples must be > 0 !"); + const T *vals(getConstPointer()); + const T *loc(std::min_element(vals,vals+nbOfTuples)); + tupleId=(int)std::distance(vals,loc); + return *loc; + } + + /*! + * Returns the minimal value within \a this array that is allowed to have more than + * one component. + * \return double - the minimal value among all values of \a this array. + * \throw If \a this is not allocated. + */ + template + T DataArrayTemplate::getMinValueInArray() const + { + checkAllocated(); + const T *loc=std::min_element(begin(),end()); + return *loc; + } + + template + void DataArrayTemplate::circularPermutation(int nbOfShift) + { + checkAllocated(); + int nbOfCompo(getNumberOfComponents()),nbTuples(getNumberOfTuples()); + int effNbSh(EffectiveCircPerm(nbOfShift,nbTuples)); + if(effNbSh==0) + return ; + T *work(getPointer()); + if(effNbSh buf(new T[effNbSh*nbOfCompo]); + std::copy(work,work+effNbSh*nbOfCompo,(T *)buf); + std::copy(work+effNbSh*nbOfCompo,work+nbTuples*nbOfCompo,work);// ze big shift + std::copy((T *)buf,(T *)buf+effNbSh*nbOfCompo,work+(nbTuples-effNbSh)*nbOfCompo); + } + else + { + typename INTERP_KERNEL::AutoPtr buf(new T[(nbTuples-effNbSh)*nbOfCompo]); + std::copy(work+effNbSh*nbOfCompo,work+nbTuples*nbOfCompo,(T *)buf); + std::copy(work,work+effNbSh*nbOfCompo,work+(nbTuples-effNbSh)*nbOfCompo);// ze big shift + std::copy((T*)buf,(T *)buf+(nbTuples-effNbSh)*nbOfCompo,work); + } + } + + template + void DataArrayTemplate::circularPermutationPerTuple(int nbOfShift) + { + checkAllocated(); + int nbOfCompo(getNumberOfComponents()),nbTuples(getNumberOfTuples()); + int effNbSh(EffectiveCircPerm(nbOfShift,nbOfCompo)); + if(effNbSh==0) + return ; + T *work(getPointer()); + if(effNbSh buf(new T[effNbSh]); + for(int i=0;i buf(new T[nbOfCompo-effNbSh]); + for(int i=0;i sts(nbOfCompo); + for(int i=0;i + void DataArrayTemplate::reversePerTuple() + { + checkAllocated(); + int nbOfCompo(getNumberOfComponents()),nbTuples(getNumberOfTuples()); + if(nbOfCompo<=1) + return ; + T *work(getPointer()); + for(int i=0;i + void DataArrayTemplate::SetArrayIn(typename Traits::ArrayType *newArray, typename Traits::ArrayType* &arrayToSet) + { + if(newArray!=arrayToSet) + { + if(arrayToSet) + arrayToSet->decrRef(); + arrayToSet=newArray; + if(arrayToSet) + arrayToSet->incrRef(); + } + } + + template + template + MCAuto< typename Traits::ArrayType > DataArrayTemplateClassic::convertToOtherTypeOfArr() const + { + this->checkAllocated(); + MCAuto::ArrayType> ret(Traits::ArrayType::New()); + ret->alloc(this->getNumberOfTuples(),this->getNumberOfComponents()); + std::size_t nbOfVals(this->getNbOfElems()); + const T *src(this->begin()); + U *dest(ret->getPointer()); + // to make Visual C++ happy : instead of std::size_t nbOfVals=getNbOfElems(); std::copy(src,src+nbOfVals,dest); + //for(const T *src=this->begin();src!=this->end();src++,dest++) + // *dest=(int)*src; + std::copy(src,src+nbOfVals,dest); + ret->copyStringInfoFrom(*this); + return ret; + } + + /*! + * Creates a new DataArrayDouble and assigns all (textual and numerical) data of \a this + * array to the new one. + * \return DataArrayDouble * - the new instance of DataArrayInt. + */ + template + MCAuto DataArrayTemplateClassic::convertToDblArr() const + { + return convertToOtherTypeOfArr(); + } + + /*! + * Creates a new DataArrayInt and assigns all (textual and numerical) data of \a this + * array to the new one. + * \return DataArrayInt * - the new instance of DataArrayInt. + */ + template + MCAuto DataArrayTemplateClassic::convertToIntArr() const + { + return convertToOtherTypeOfArr(); + } + + /*! + * Creates a new DataArrayFloat and assigns all (textual and numerical) data of \a this + * array to the new one. + * \return DataArrayFloat * - the new instance of DataArrayInt. + */ + template + MCAuto DataArrayTemplateClassic::convertToFloatArr() const + { + return convertToOtherTypeOfArr(); + } + + /*! + * Apply a linear function to a given component of \a this array, so that + * an array element (x) becomes \f$ a * x + b \f$. + * \param [in] a - the first coefficient of the function. + * \param [in] b - the second coefficient of the function. + * \param [in] compoId - the index of component to modify. + * \throw If \a this is not allocated, or \a compoId is not in [0,\c this->getNumberOfComponents() ). + */ + template + void DataArrayTemplateClassic::applyLin(T a, T b, int compoId) + { + this->checkAllocated(); + T *ptr(this->getPointer()+compoId); + int nbOfComp(this->getNumberOfComponents()),nbOfTuple(this->getNumberOfTuples()); + if(compoId<0 || compoId>=nbOfComp) + { + std::ostringstream oss; oss << "DataArrayDouble::applyLin : The compoId requested (" << compoId << ") is not valid ! Must be in [0," << nbOfComp << ") !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + for(int i=0;ideclareAsNew(); + } + + /*! + * Apply a linear function to all elements of \a this array, so that + * an element _x_ becomes \f$ a * x + b \f$. + * \param [in] a - the first coefficient of the function. + * \param [in] b - the second coefficient of the function. + * \throw If \a this is not allocated. + */ + template + void DataArrayTemplateClassic::applyLin(T a, T b) + { + this->checkAllocated(); + T *ptr(this->getPointer()); + std::size_t nbOfElems(this->getNbOfElems()); + for(std::size_t i=0;ideclareAsNew(); + } + + /*! + * Returns a full copy of \a this array except that sign of all elements is reversed. + * \return DataArrayDouble * - the new instance of DataArrayDouble containing the + * same number of tuples and component as \a this array. + * The caller is to delete this result array using decrRef() as it is no more + * needed. + * \throw If \a this is not allocated. + */ + template + typename Traits::ArrayType *DataArrayTemplateClassic::negate() const + { + this->checkAllocated(); + MCAuto::ArrayType> newArr(Traits::ArrayType::New()); + int nbOfTuples(this->getNumberOfTuples()),nbOfComp(this->getNumberOfComponents()); + newArr->alloc(nbOfTuples,nbOfComp); + const T *cptr(this->begin()); + std::transform(cptr,cptr+nbOfTuples*nbOfComp,newArr->getPointer(),std::negate()); + newArr->copyStringInfoFrom(*this); + return newArr.retn(); + } + + template + template + void DataArrayTemplateClassic::somethingEqual(const typename Traits::ArrayType *other) + { + if(!other) + throw INTERP_KERNEL::Exception("DataArray::SomethingEqual : input DataArray instance is NULL !"); + const char *msg="Nb of tuples mismatch for DataArrayDouble::multiplyEqual !"; + this->checkAllocated(); + other->checkAllocated(); + int nbOfTuple(this->getNumberOfTuples()),nbOfTuple2(other->getNumberOfTuples()); + int nbOfComp(this->getNumberOfComponents()),nbOfComp2(other->getNumberOfComponents()); + if(nbOfTuple==nbOfTuple2) + { + if(nbOfComp==nbOfComp2) + { + std::transform(this->begin(),this->end(),other->begin(),this->getPointer(),FCT()); + } + else if(nbOfComp2==1) + { + T *ptr(this->getPointer()); + const T *ptrc(other->begin()); + for(int i=0;igetPointer()); + const T *ptrc(other->begin()); + for(int i=0;ideclareAsNew(); + } + + /*! + * Adds values of another DataArrayDouble to values of \a this one. There are 3 + * valid cases. + * 1. The arrays have same number of tuples and components. Then each value of + * \a other array is added to the corresponding value of \a this array, i.e.: + * _a_ [ i, j ] += _other_ [ i, j ]. + * 2. The arrays have same number of tuples and \a other array has one component. Then + * _a_ [ i, j ] += _other_ [ i, 0 ]. + * 3. The arrays have same number of components and \a other array has one tuple. Then + * _a_ [ i, j ] += _a2_ [ 0, j ]. + * + * \param [in] other - an array to add to \a this one. + * \throw If \a other is NULL. + * \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples() and + * \a this->getNumberOfComponents() != \a other->getNumberOfComponents() and + * \a other has number of both tuples and components not equal to 1. + */ + template + void DataArrayTemplateClassic::addEqual(const typename Traits::ArrayType *other) + { + this->somethingEqual< std::plus >(other); + } + + /*! + * Subtract values of another DataArrayDouble from values of \a this one. There are 3 + * valid cases. + * 1. The arrays have same number of tuples and components. Then each value of + * \a other array is subtracted from the corresponding value of \a this array, i.e.: + * _a_ [ i, j ] -= _other_ [ i, j ]. + * 2. The arrays have same number of tuples and \a other array has one component. Then + * _a_ [ i, j ] -= _other_ [ i, 0 ]. + * 3. The arrays have same number of components and \a other array has one tuple. Then + * _a_ [ i, j ] -= _a2_ [ 0, j ]. + * + * \param [in] other - an array to subtract from \a this one. + * \throw If \a other is NULL. + * \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples() and + * \a this->getNumberOfComponents() != \a other->getNumberOfComponents() and + * \a other has number of both tuples and components not equal to 1. + */ + template + void DataArrayTemplateClassic::substractEqual(const typename Traits::ArrayType *other) + { + this->somethingEqual< std::minus >(other); + } + + /*! + * Multiply values of another DataArrayDouble to values of \a this one. There are 3 + * valid cases. + * 1. The arrays have same number of tuples and components. Then each value of + * \a other array is multiplied to the corresponding value of \a this array, i.e. + * _this_ [ i, j ] *= _other_ [ i, j ]. + * 2. The arrays have same number of tuples and \a other array has one component. Then + * _this_ [ i, j ] *= _other_ [ i, 0 ]. + * 3. The arrays have same number of components and \a other array has one tuple. Then + * _this_ [ i, j ] *= _a2_ [ 0, j ]. + * + * \param [in] other - an array to multiply to \a this one. + * \throw If \a other is NULL. + * \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples() and + * \a this->getNumberOfComponents() != \a other->getNumberOfComponents() and + * \a other has number of both tuples and components not equal to 1. + */ + template + void DataArrayTemplateClassic::multiplyEqual(const typename Traits::ArrayType *other) + { + this->somethingEqual< std::multiplies >(other); + } + + /*! + * Divide values of \a this array by values of another DataArrayDouble. There are 3 + * valid cases. + * 1. The arrays have same number of tuples and components. Then each value of + * \a this array is divided by the corresponding value of \a other one, i.e.: + * _a_ [ i, j ] /= _other_ [ i, j ]. + * 2. The arrays have same number of tuples and \a other array has one component. Then + * _a_ [ i, j ] /= _other_ [ i, 0 ]. + * 3. The arrays have same number of components and \a other array has one tuple. Then + * _a_ [ i, j ] /= _a2_ [ 0, j ]. + * + * \warning No check of division by zero is performed! + * \param [in] other - an array to divide \a this one by. + * \throw If \a other is NULL. + * \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples() and + * \a this->getNumberOfComponents() != \a other->getNumberOfComponents() and + * \a other has number of both tuples and components not equal to 1. + */ + template + void DataArrayTemplateClassic::divideEqual(const typename Traits::ArrayType *other) + { + this->somethingEqual< std::divides >(other); + } + + template + typename Traits::ArrayType *DivSub(const typename Traits::ArrayType *a1, const typename Traits::ArrayType *a2) + { + if(!a1 || !a2) + throw INTERP_KERNEL::Exception("DivSub : input DataArrayDouble instance is NULL !"); + int nbOfTuple1(a1->getNumberOfTuples()),nbOfTuple2(a2->getNumberOfTuples()); + int nbOfComp1(a1->getNumberOfComponents()),nbOfComp2(a2->getNumberOfComponents()); + if(nbOfTuple2==nbOfTuple1) + { + if(nbOfComp1==nbOfComp2) + { + MCAuto::ArrayType> ret(Traits::ArrayType::New()); + ret->alloc(nbOfTuple2,nbOfComp1); + std::transform(a1->begin(),a1->end(),a2->begin(),ret->getPointer(),FCT()); + ret->copyStringInfoFrom(*a1); + return ret.retn(); + } + else if(nbOfComp2==1) + { + MCAuto::ArrayType> ret(Traits::ArrayType::New()); + ret->alloc(nbOfTuple1,nbOfComp1); + const T *a2Ptr(a2->begin()),*a1Ptr(a1->begin()); + T *res(ret->getPointer()); + for(int i=0;icopyStringInfoFrom(*a1); + return ret.retn(); + } + else + { + a1->checkNbOfComps(nbOfComp2,"Nb of components mismatch for array Divide !"); + return 0; + } + } + else if(nbOfTuple2==1) + { + a1->checkNbOfComps(nbOfComp2,"Nb of components mismatch for array Divide !"); + MCAuto::ArrayType> ret(Traits::ArrayType::New()); + ret->alloc(nbOfTuple1,nbOfComp1); + const T *a1ptr=a1->begin(),*a2ptr(a2->begin()); + T *pt(ret->getPointer()); + for(int i=0;icopyStringInfoFrom(*a1); + return ret.retn(); + } + else + { + a1->checkNbOfTuples(nbOfTuple2,"Nb of tuples mismatch for array Divide !");//will always throw an exception + return 0; + } + } + + /*! + * Returns a new DataArrayDouble that is a subtraction of two given arrays. There are 3 + * valid cases. + * 1. The arrays have same number of tuples and components. Then each value of + * the result array (_a_) is a subtraction of the corresponding values of \a a1 and + * \a a2, i.e.: _a_ [ i, j ] = _a1_ [ i, j ] - _a2_ [ i, j ]. + * 2. The arrays have same number of tuples and one array, say _a2_, has one + * component. Then + * _a_ [ i, j ] = _a1_ [ i, j ] - _a2_ [ i, 0 ]. + * 3. The arrays have same number of components and one array, say _a2_, has one + * tuple. Then + * _a_ [ i, j ] = _a1_ [ i, j ] - _a2_ [ 0, j ]. + * + * Info on components is copied either from the first array (in the first case) or from + * the array with maximal number of elements (getNbOfElems()). + * \param [in] a1 - an array to subtract from. + * \param [in] a2 - an array to subtract. + * \return DataArrayDouble * - the new instance of DataArrayDouble. + * The caller is to delete this result array using decrRef() as it is no more + * needed. + * \throw If either \a a1 or \a a2 is NULL. + * \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples() and + * \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents() and + * none of them has number of tuples or components equal to 1. + */ + template + typename Traits::ArrayType *DataArrayTemplateClassic::Substract(const typename Traits::ArrayType *a1, const typename Traits::ArrayType *a2) + { + return DivSub< T,std::minus >(a1,a2); + } + + /*! + * Returns a new DataArrayDouble that is a division of two given arrays. There are 3 + * valid cases. + * 1. The arrays have same number of tuples and components. Then each value of + * the result array (_a_) is a division of the corresponding values of \a a1 and + * \a a2, i.e.: _a_ [ i, j ] = _a1_ [ i, j ] / _a2_ [ i, j ]. + * 2. The arrays have same number of tuples and one array, say _a2_, has one + * component. Then + * _a_ [ i, j ] = _a1_ [ i, j ] / _a2_ [ i, 0 ]. + * 3. The arrays have same number of components and one array, say _a2_, has one + * tuple. Then + * _a_ [ i, j ] = _a1_ [ i, j ] / _a2_ [ 0, j ]. + * + * Info on components is copied either from the first array (in the first case) or from + * the array with maximal number of elements (getNbOfElems()). + * \warning No check of division by zero is performed! + * \param [in] a1 - a numerator array. + * \param [in] a2 - a denominator array. + * \return DataArrayDouble * - the new instance of DataArrayDouble. + * The caller is to delete this result array using decrRef() as it is no more + * needed. + * \throw If either \a a1 or \a a2 is NULL. + * \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples() and + * \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents() and + * none of them has number of tuples or components equal to 1. + */ + template + typename Traits::ArrayType *DataArrayTemplateClassic::Divide(const typename Traits::ArrayType *a1, const typename Traits::ArrayType *a2) + { + return DivSub< T,std::divides >(a1,a2); + } + + template + typename Traits::ArrayType *MulAdd(const typename Traits::ArrayType *a1, const typename Traits::ArrayType *a2) + { + if(!a1 || !a2) + throw INTERP_KERNEL::Exception("DataArrayDouble::MulAdd : input DataArrayDouble instance is NULL !"); + int nbOfTuple(a1->getNumberOfTuples()),nbOfTuple2(a2->getNumberOfTuples()); + int nbOfComp(a1->getNumberOfComponents()),nbOfComp2(a2->getNumberOfComponents()); + MCAuto::ArrayType> ret=0; + if(nbOfTuple==nbOfTuple2) + { + if(nbOfComp==nbOfComp2) + { + ret=Traits::ArrayType::New(); + ret->alloc(nbOfTuple,nbOfComp); + std::transform(a1->begin(),a1->end(),a2->begin(),ret->getPointer(),FCT()); + ret->copyStringInfoFrom(*a1); + } + else + { + int nbOfCompMin,nbOfCompMax; + const typename Traits::ArrayType *aMin, *aMax; + if(nbOfComp>nbOfComp2) + { + nbOfCompMin=nbOfComp2; nbOfCompMax=nbOfComp; + aMin=a2; aMax=a1; + } + else + { + nbOfCompMin=nbOfComp; nbOfCompMax=nbOfComp2; + aMin=a1; aMax=a2; + } + if(nbOfCompMin==1) + { + ret=Traits::ArrayType::New(); + ret->alloc(nbOfTuple,nbOfCompMax); + const T *aMinPtr(aMin->begin()); + const T *aMaxPtr(aMax->begin()); + T *res=ret->getPointer(); + for(int i=0;icopyStringInfoFrom(*aMax); + } + else + throw INTERP_KERNEL::Exception("Nb of components mismatch for array MulAdd !"); + } + } + else if((nbOfTuple==1 && nbOfTuple2>1) || (nbOfTuple>1 && nbOfTuple2==1)) + { + if(nbOfComp==nbOfComp2) + { + int nbOfTupleMax=std::max(nbOfTuple,nbOfTuple2); + const typename Traits::ArrayType *aMin(nbOfTuple>nbOfTuple2?a2:a1); + const typename Traits::ArrayType *aMax(nbOfTuple>nbOfTuple2?a1:a2); + const T *aMinPtr(aMin->begin()),*aMaxPtr(aMax->begin()); + ret=Traits::ArrayType::New(); + ret->alloc(nbOfTupleMax,nbOfComp); + T *res(ret->getPointer()); + for(int i=0;icopyStringInfoFrom(*aMax); + } + else + throw INTERP_KERNEL::Exception("Nb of components mismatch for array MulAdd !"); + } + else + throw INTERP_KERNEL::Exception("Nb of tuples mismatch for array MulAdd !"); + return ret.retn(); + } + + /*! + * Returns a new DataArrayDouble that is a product of two given arrays. There are 3 + * valid cases. + * 1. The arrays have same number of tuples and components. Then each value of + * the result array (_a_) is a product of the corresponding values of \a a1 and + * \a a2, i.e. _a_ [ i, j ] = _a1_ [ i, j ] * _a2_ [ i, j ]. + * 2. The arrays have same number of tuples and one array, say _a2_, has one + * component. Then + * _a_ [ i, j ] = _a1_ [ i, j ] * _a2_ [ i, 0 ]. + * 3. The arrays have same number of components and one array, say _a2_, has one + * tuple. Then + * _a_ [ i, j ] = _a1_ [ i, j ] * _a2_ [ 0, j ]. + * + * Info on components is copied either from the first array (in the first case) or from + * the array with maximal number of elements (getNbOfElems()). + * \param [in] a1 - a factor array. + * \param [in] a2 - another factor array. + * \return DataArrayDouble * - the new instance of DataArrayDouble. + * The caller is to delete this result array using decrRef() as it is no more + * needed. + * \throw If either \a a1 or \a a2 is NULL. + * \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples() and + * \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents() and + * none of them has number of tuples or components equal to 1. + */ + template + typename Traits::ArrayType *DataArrayTemplateClassic::Multiply(const typename Traits::ArrayType *a1, const typename Traits::ArrayType *a2) + { + return MulAdd< T , std::multiplies >(a1,a2); + } + + /*! + * Returns a new DataArrayDouble that is a sum of two given arrays. There are 3 + * valid cases. + * 1. The arrays have same number of tuples and components. Then each value of + * the result array (_a_) is a sum of the corresponding values of \a a1 and \a a2, + * i.e.: _a_ [ i, j ] = _a1_ [ i, j ] + _a2_ [ i, j ]. + * 2. The arrays have same number of tuples and one array, say _a2_, has one + * component. Then + * _a_ [ i, j ] = _a1_ [ i, j ] + _a2_ [ i, 0 ]. + * 3. The arrays have same number of components and one array, say _a2_, has one + * tuple. Then + * _a_ [ i, j ] = _a1_ [ i, j ] + _a2_ [ 0, j ]. + * + * Info on components is copied either from the first array (in the first case) or from + * the array with maximal number of elements (getNbOfElems()). + * \param [in] a1 - an array to sum up. + * \param [in] a2 - another array to sum up. + * \return DataArrayDouble * - the new instance of DataArrayDouble. + * The caller is to delete this result array using decrRef() as it is no more + * needed. + * \throw If either \a a1 or \a a2 is NULL. + * \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples() and + * \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents() and + * none of them has number of tuples or components equal to 1. + */ + template + typename Traits::ArrayType *DataArrayTemplateClassic::Add(const typename Traits::ArrayType *a1, const typename Traits::ArrayType *a2) + { + return MulAdd< T , std::plus >(a1,a2); + } + + /*! + * Returns either a \a deep or \a shallow copy of this array. For more info see + * \ref MEDCouplingArrayBasicsCopyDeep and \ref MEDCouplingArrayBasicsCopyShallow. + * \param [in] dCpy - if \a true, a deep copy is returned, else, a shallow one. + * \return DataArrayDouble * - either a new instance of DataArrayDouble (if \a dCpy + * == \a true) or \a this instance (if \a dCpy == \a false). + */ + template + typename Traits::ArrayType *DataArrayTemplateClassic::PerformCopyOrIncrRef(bool dCpy, const typename Traits::ArrayType& self) + { + if(dCpy) + return self.deepCopy(); + else + { + self.incrRef(); + return const_cast::ArrayType *>(&self); + } + } + + template + struct GreatEqual + { + GreatEqual(T v):_v(v) { } + bool operator()(T v) const { return v>=_v; } + T _v; + }; + + template + struct GreaterThan + { + GreaterThan(T v):_v(v) { } + bool operator()(T v) const { return v>_v; } + T _v; + }; + + template + struct LowerEqual + { + LowerEqual(T v):_v(v) { } + bool operator()(T v) const { return v<=_v; } + T _v; + }; + + template + struct LowerThan + { + LowerThan(T v):_v(v) { } + bool operator()(T v) const { return v<_v; } + T _v; + }; + + template + struct InRange + { + InRange(T a, T b):_a(a),_b(b) { } + bool operator()(T v) const { return v>=_a && v<_b; } + T _a,_b; + }; + +template +struct NotInRange +{ + NotInRange(T a, T b):_a(a),_b(b) { } + bool operator()(T v) const { return v<_a || v>=_b; } + T _a,_b; +}; + + /*! + * This method works only on data array with one component. This method returns a newly allocated array storing stored ascendantly of tuple ids in \a this so that this[id]<0. + * + * \return a newly allocated data array that the caller should deal with. + * \sa DataArrayInt::findIdsInRange + */ + template + DataArrayInt *DataArrayTemplateClassic::findIdsStrictlyNegative() const + { + LowerThan lt((T)0); + MCAuto ret(findIdsAdv(lt)); + return ret.retn(); + } + + template + MCAuto DataArrayTemplateClassic::findIdsGreaterOrEqualTo(T val) const + { + GreatEqual ge(val); + return findIdsAdv(ge); + } + + template + MCAuto DataArrayTemplateClassic::findIdsGreaterThan(T val) const + { + GreaterThan gt(val); + return findIdsAdv(gt); + } + + template + MCAuto DataArrayTemplateClassic::findIdsLowerOrEqualTo(T val) const + { + LowerEqual le(val); + return findIdsAdv(le); + } + + template + MCAuto DataArrayTemplateClassic::findIdsLowerThan(T val) const + { + LowerThan lt(val); + return findIdsAdv(lt); + } + + /*! + * Returns a new DataArrayDouble by aggregating two given arrays, so that (1) the number + * of components in the result array is a sum of the number of components of given arrays + * and (2) the number of tuples in the result array is same as that of each of given + * arrays. In other words the i-th tuple of result array includes all components of + * i-th tuples of all given arrays. + * Number of tuples in the given arrays must be the same. + * \param [in] a1 - an array to include in the result array. + * \param [in] a2 - another array to include in the result array. + * \return DataArrayDouble * - the new instance of DataArrayDouble. + * The caller is to delete this result array using decrRef() as it is no more + * needed. + * \throw If both \a a1 and \a a2 are NULL. + * \throw If any given array is not allocated. + * \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples() + */ + template + typename Traits::ArrayType *DataArrayTemplateClassic::Meld(const typename Traits::ArrayType *a1, const typename Traits::ArrayType *a2) + { + std::vector::ArrayType *> arr(2); + arr[0]=a1; arr[1]=a2; + return Meld(arr); + } + + /*! + * Returns a new DataArrayDouble by aggregating all given arrays, so that (1) the number + * of components in the result array is a sum of the number of components of given arrays + * and (2) the number of tuples in the result array is same as that of each of given + * arrays. In other words the i-th tuple of result array includes all components of + * i-th tuples of all given arrays. + * Number of tuples in the given arrays must be the same. + * \param [in] arr - a sequence of arrays to include in the result array. + * \return DataArrayDouble * - the new instance of DataArrayDouble. + * The caller is to delete this result array using decrRef() as it is no more + * needed. + * \throw If all arrays within \a arr are NULL. + * \throw If any given array is not allocated. + * \throw If getNumberOfTuples() of arrays within \a arr is different. + */ + template + typename Traits::ArrayType *DataArrayTemplateClassic::Meld(const std::vector::ArrayType *>& arr) + { + std::vector::ArrayType *> a; + for(typename std::vector::ArrayType *>::const_iterator it4=arr.begin();it4!=arr.end();it4++) + if(*it4) + a.push_back(*it4); + if(a.empty()) + throw INTERP_KERNEL::Exception("DataArrayDouble::Meld : input list must contain at least one NON EMPTY DataArrayDouble !"); + typename std::vector::ArrayType *>::const_iterator it; + for(it=a.begin();it!=a.end();it++) + (*it)->checkAllocated(); + it=a.begin(); + int nbOfTuples((*it)->getNumberOfTuples()); + std::vector nbc(a.size()); + std::vector pts(a.size()); + nbc[0]=(*it)->getNumberOfComponents(); + pts[0]=(*it++)->getConstPointer(); + for(int i=1;it!=a.end();it++,i++) + { + if(nbOfTuples!=(*it)->getNumberOfTuples()) + throw INTERP_KERNEL::Exception("DataArrayDouble::Meld : mismatch of number of tuples !"); + nbc[i]=(*it)->getNumberOfComponents(); + pts[i]=(*it)->getConstPointer(); + } + int totalNbOfComp=std::accumulate(nbc.begin(),nbc.end(),0); + typename Traits::ArrayType *ret(Traits::ArrayType::New()); + ret->alloc(nbOfTuples,totalNbOfComp); + T *retPtr(ret->getPointer()); + for(int i=0;isetInfoOnComponent(k,a[i]->getInfoOnComponent(j)); + return ret; + } + + /*! + * Returns a new DataArrayDouble holding the same values as \a this array but differently + * arranged in memory. If \a this array holds 2 components of 3 values: + * \f$ x_0,x_1,x_2,y_0,y_1,y_2 \f$, then the result array holds these values arranged + * as follows: \f$ x_0,y_0,x_1,y_1,x_2,y_2 \f$. + * \warning Do not confuse this method with transpose()! + * \return DataArrayDouble * - the new instance of DataArrayDouble that the caller + * is to delete using decrRef() as it is no more needed. + * \throw If \a this is not allocated. + */ + template + typename Traits::ArrayType *DataArrayTemplateClassic::fromNoInterlace() const + { + if(this->_mem.isNull()) + throw INTERP_KERNEL::Exception("DataArrayDouble::fromNoInterlace : Not defined array !"); + T *tab(this->_mem.fromNoInterlace(this->getNumberOfComponents())); + MCAuto::ArrayType> ret(Traits::ArrayType::New()); + ret->useArray(tab,true,C_DEALLOC,this->getNumberOfTuples(),this->getNumberOfComponents()); + return ret.retn(); + } + + /*! + * Returns a new DataArrayDouble holding the same values as \a this array but differently + * arranged in memory. If \a this array holds 2 components of 3 values: + * \f$ x_0,y_0,x_1,y_1,x_2,y_2 \f$, then the result array holds these values arranged + * as follows: \f$ x_0,x_1,x_2,y_0,y_1,y_2 \f$. + * \warning Do not confuse this method with transpose()! + * \return DataArrayDouble * - the new instance of DataArrayDouble that the caller + * is to delete using decrRef() as it is no more needed. + * \throw If \a this is not allocated. + */ + template + typename Traits::ArrayType *DataArrayTemplateClassic::toNoInterlace() const + { + if(this->_mem.isNull()) + throw INTERP_KERNEL::Exception("DataArrayDouble::toNoInterlace : Not defined array !"); + T *tab(this->_mem.toNoInterlace(this->getNumberOfComponents())); + MCAuto::ArrayType> ret(Traits::ArrayType::New()); + ret->useArray(tab,true,C_DEALLOC,this->getNumberOfTuples(),this->getNumberOfComponents()); + return ret.retn(); + } + + /*! + * Appends components of another array to components of \a this one, tuple by tuple. + * So that the number of tuples of \a this array remains the same and the number of + * components increases. + * \param [in] other - the DataArrayDouble to append to \a this one. + * \throw If \a this is not allocated. + * \throw If \a this and \a other arrays have different number of tuples. + * + * \if ENABLE_EXAMPLES + * \ref cpp_mcdataarraydouble_meldwith "Here is a C++ example". + * + * \ref py_mcdataarraydouble_meldwith "Here is a Python example". + * \endif + */ + template + void DataArrayTemplateClassic::meldWith(const typename Traits::ArrayType *other) + { + this->checkAllocated(); + other->checkAllocated(); + int nbOfTuples(this->getNumberOfTuples()); + if(nbOfTuples!=other->getNumberOfTuples()) + throw INTERP_KERNEL::Exception("DataArrayDouble::meldWith : mismatch of number of tuples !"); + int nbOfComp1(this->getNumberOfComponents()),nbOfComp2(other->getNumberOfComponents()); + T *newArr=(T *)malloc((nbOfTuples*(nbOfComp1+nbOfComp2))*sizeof(T)); + T *w=newArr; + const T *inp1(this->begin()),*inp2(other->begin()); + for(int i=0;iuseArray(newArr,true,C_DEALLOC,nbOfTuples,nbOfComp1+nbOfComp2); + std::vector compIds(nbOfComp2); + for(int i=0;icopyPartOfStringInfoFrom2(compIds,*other); + } + + /*! + * + * \param [in] nbTimes specifies the nb of times each tuples in \a this will be duplicated contiguouly in returned DataArrayDouble instance. + * \a nbTimes should be at least equal to 1. + * \return a newly allocated DataArrayDouble having one component and number of tuples equal to \a nbTimes * \c this->getNumberOfTuples. + * \throw if \a this is not allocated or if \a this has not number of components set to one or if \a nbTimes is lower than 1. + */ + template + typename Traits::ArrayType *DataArrayTemplateClassic::duplicateEachTupleNTimes(int nbTimes) const + { + this->checkAllocated(); + if(this->getNumberOfComponents()!=1) + throw INTERP_KERNEL::Exception("DataArrayDouble::duplicateEachTupleNTimes : this should have only one component !"); + if(nbTimes<1) + throw INTERP_KERNEL::Exception("DataArrayDouble::duplicateEachTupleNTimes : nb times should be >= 1 !"); + int nbTuples(this->getNumberOfTuples()); + const T *inPtr(this->begin()); + MCAuto::ArrayType> ret(Traits::ArrayType::New()); ret->alloc(nbTimes*nbTuples,1); + T *retPtr(ret->getPointer()); + for(int i=0;icopyStringInfoFrom(*this); + return ret.retn(); + } + + template + void DataArrayTemplateClassic::aggregate(const typename Traits::ArrayType *other) + { + if(!other) + throw INTERP_KERNEL::Exception("DataArrayDouble::aggregate : null pointer !"); + if(this->getNumberOfComponents()!=other->getNumberOfComponents()) + throw INTERP_KERNEL::Exception("DataArrayDouble::aggregate : mismatch number of components !"); + this->_mem.insertAtTheEnd(other->begin(),other->end()); + } + + /*! + * Converts every value of \a this array to its absolute value. + * \b WARNING this method is non const. If a new DataArrayDouble instance should be built containing the result of abs DataArrayDouble::computeAbs + * should be called instead. + * + * \throw If \a this is not allocated. + * \sa DataArrayDouble::computeAbs + */ + template + void DataArrayTemplateClassic::abs() + { + this->checkAllocated(); + T *ptr(this->getPointer()); + std::size_t nbOfElems(this->getNbOfElems()); + std::transform(ptr,ptr+nbOfElems,ptr,std::ptr_fun(std::abs)); + this->declareAsNew(); + } + + /*! + * This method builds a new instance of \a this object containing the result of std::abs applied of all elements in \a this. + * This method is a const method (that do not change any values in \a this) contrary to DataArrayDouble::abs method. + * + * \return DataArrayDouble * - the new instance of DataArrayDouble containing the + * same number of tuples and component as \a this array. + * The caller is to delete this result array using decrRef() as it is no more + * needed. + * \throw If \a this is not allocated. + * \sa DataArrayDouble::abs + */ + template + typename Traits::ArrayType *DataArrayTemplateClassic::computeAbs() const + { + this->checkAllocated(); + MCAuto::ArrayType> newArr(Traits::ArrayType::New()); + int nbOfTuples(this->getNumberOfTuples()); + int nbOfComp(this->getNumberOfComponents()); + newArr->alloc(nbOfTuples,nbOfComp); + std::transform(this->begin(),this->end(),newArr->getPointer(),std::ptr_fun(std::abs)); + newArr->copyStringInfoFrom(*this); + return newArr.retn(); + } + + /*! + * Returns either a \a deep or \a shallow copy of this array. For more info see + * \ref MEDCouplingArrayBasicsCopyDeep and \ref MEDCouplingArrayBasicsCopyShallow. + * \param [in] dCpy - if \a true, a deep copy is returned, else, a shallow one. + * \return DataArrayDouble * - either a new instance of DataArrayDouble (if \a dCpy + * == \a true) or \a this instance (if \a dCpy == \a false). + */ + template + typename Traits::ArrayType *DataArrayTemplateClassic::performCopyOrIncrRef(bool dCpy) const + { + const typename Traits::ArrayType *thisC(static_cast::ArrayType *>(this)); + return DataArrayTemplateClassic::PerformCopyOrIncrRef(dCpy,*thisC); + } + + /*! + * Checks if all values in \a this array are equal to \a val at precision \a eps. + * \param [in] val - value to check equality of array values to. + * \param [in] eps - precision to check the equality. + * \return bool - \a true if all values are in range (_val_ - _eps_; _val_ + _eps_), + * \a false else. + * \throw If \a this->getNumberOfComponents() != 1 + * \throw If \a this is not allocated. + */ + template + bool DataArrayTemplateFP::isUniform(T val, T eps) const + { + this->checkAllocated(); + if(this->getNumberOfComponents()!=1) + throw INTERP_KERNEL::Exception("DataArrayDouble::isUniform : must be applied on DataArrayDouble with only one component, you can call 'rearrange' method before !"); + int nbOfTuples(this->getNumberOfTuples()); + const T *w(this->begin()),*end2(this->end()); + const T vmin(val-eps),vmax(val+eps); + for(;w!=end2;w++) + if(*wvmax) + return false; + return true; + } + + /*! + * Set all values in \a this array so that the i-th element equals to \a init + i + * (i starts from zero). To know more on filling arrays see \ref MEDCouplingArrayFill. + * \param [in] init - value to assign to the first element of array. + * \throw If \a this->getNumberOfComponents() != 1 + * \throw If \a this is not allocated. + */ + template + void DataArrayTemplateFP::iota(T init) + { + this->checkAllocated(); + if(this->getNumberOfComponents()!=1) + throw INTERP_KERNEL::Exception("DataArrayDouble::iota : works only for arrays with only one component, you can call 'rearrange' method before !"); + T *ptr(this->getPointer()); + int ntuples(this->getNumberOfTuples()); + for(int i=0;ideclareAsNew(); + } } #endif