X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FMEDCoupling%2FMEDCouplingMemArray.txx;h=5df4f7150b71637dd40bcf3af923036533ed8d9b;hb=b7e277ad50223814bc479c5bd64cf12abe8fc959;hp=fa5fac7a0c7578b0368277b63816ad7a5c0ea7fb;hpb=1e36a6710aab710674e20fbd89f6a9a8f238c023;p=tools%2Fmedcoupling.git diff --git a/src/MEDCoupling/MEDCouplingMemArray.txx b/src/MEDCoupling/MEDCouplingMemArray.txx index fa5fac7a0..5df4f7150 100644 --- a/src/MEDCoupling/MEDCouplingMemArray.txx +++ b/src/MEDCoupling/MEDCouplingMemArray.txx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2015 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 @@ -25,6 +25,9 @@ #include "NormalizedUnstructuredMesh.hxx" #include "InterpKernelException.hxx" #include "InterpolationUtils.hxx" +#include "MEDCouplingPartDefinition.hxx" +#include "InterpKernelAutoPtr.hxx" +#include "MCAuto.hxx" #include #include @@ -94,22 +97,6 @@ namespace MEDCoupling _nb_of_elem=std::max(_nb_of_elem,id+sizeOfOthers+1); } - template - template - void MemArray::insertAtTheEnd(InputIterator first, InputIterator last) - { - T *pointer=_pointer.getPointer(); - while(first!=last) - { - if(_nb_of_elem>=_nb_of_elem_alloc) - { - reserve(_nb_of_elem_alloc>0?2*_nb_of_elem_alloc:1); - pointer=_pointer.getPointer(); - } - pointer[_nb_of_elem++]=*first++; - } - } - template void MemArray::pushBack(T elem) { @@ -490,6 +477,1781 @@ namespace MEDCoupling std::copy(other._pointer.getConstPointer(),other._pointer.getConstPointer()+_nb_of_elem,_pointer.getPointer()); return *this; } + + ////////////////////////////////// + + 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