X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FMEDCoupling%2FMEDCouplingMemArray.txx;h=48ac1c576fb9298c1a6f4e2a055fc949b0f9356f;hb=e7835cba1eb17f50ef4e130c2cb8d0f54bc25083;hp=51edbee9696e234dab9e04d8e10d515f7f0c6f33;hpb=06ac794455d7c9eee11f03dbf1f4082d1def4057;p=tools%2Fmedcoupling.git diff --git a/src/MEDCoupling/MEDCouplingMemArray.txx b/src/MEDCoupling/MEDCouplingMemArray.txx index 51edbee96..48ac1c576 100644 --- a/src/MEDCoupling/MEDCouplingMemArray.txx +++ b/src/MEDCoupling/MEDCouplingMemArray.txx @@ -16,7 +16,7 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // -// Author : Anthony Geay (CEA/DEN) +// Author : Anthony Geay (EDF R&D) #ifndef __PARAMEDMEM_MEDCOUPLINGMEMARRAY_TXX__ #define __PARAMEDMEM_MEDCOUPLINGMEMARRAY_TXX__ @@ -404,7 +404,7 @@ namespace MEDCoupling /*! * This method performs systematically an allocation of \a newNbOfElements elements in \a this. * \a _nb_of_elem and \a _nb_of_elem_alloc will be equal even if only std::min(_nb_of_elem,newNbOfElements) come from the . - * The remaing part of the new allocated chunk are available but not set previouly ! + * The remaining part of the new allocated chunk are available but not set previously ! * * So this method should not be confused with MemArray::reserve that is close to MemArray::reAlloc but not same. */ @@ -704,7 +704,7 @@ namespace MEDCoupling } /*! - * This method desallocated \a this without modification of informations relative to the components. + * This method deallocated \a this without modification of information 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. */ @@ -718,7 +718,7 @@ namespace MEDCoupling * 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. + * This method allows to reduce number of reallocations on invocation of DataArrayDouble::pushBackSilent and DataArrayDouble::pushBackValsSilent on \a this. * * \sa DataArrayDouble::pack, DataArrayDouble::pushBackSilent, DataArrayDouble::pushBackValsSilent */ @@ -769,7 +769,7 @@ namespace MEDCoupling } /*! - * 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 + * This method adds at the end of \a this a series 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. @@ -1132,7 +1132,7 @@ namespace MEDCoupling { int a,b,c; spd->getSlice(a,b,c); - if(a==0 && b==getNumberOfTuples() && c==1) + if(a==0 && b==(int)getNumberOfTuples() && c==1) { DataArrayTemplate *directRet(const_cast *>(this)); directRet->incrRef(); @@ -2185,6 +2185,7 @@ namespace MEDCoupling * \return double - the maximal value among all values of \a this array. * \throw If \a this->getNumberOfComponents() != 1 * \throw If \a this->getNumberOfTuples() < 1 + * \sa getMaxAbsValue, getMinValue */ template T DataArrayTemplate::getMaxValue(int& tupleId) const @@ -2206,6 +2207,7 @@ namespace MEDCoupling * one component. * \return double - the maximal value among all values of \a this array. * \throw If \a this is not allocated. + * \sa getMaxAbsValueInArray, getMinValueInArray */ template T DataArrayTemplate::getMaxValueInArray() const @@ -2215,6 +2217,50 @@ namespace MEDCoupling return *loc; } + /*! + * Returns the maximal absolute value in \a this and the first occurrence location associated to it. + * \return the element in this (positive or negative) having the max abs value in \a this. + * \throw If \a this is not allocated. + * \throw If \a this is non one component array. + * \throw If \a this is empty. + */ + template + T DataArrayTemplate::getMaxAbsValue(std::size_t& tupleId) const + { + checkAllocated(); + if(getNumberOfComponents()!=1) + throw INTERP_KERNEL::Exception("DataArrayDouble::getMaxAbsValue : must be applied on DataArrayDouble with only one component, you can call 'rearrange' method before or call 'getMaxValueInArray' method !"); + std::size_t nbTuples(this->getNumberOfTuples()); + if(nbTuples==0) + throw INTERP_KERNEL::Exception("DataArrayTemplate::getMaxAbsValue : empty array !"); + T ret((T)-1); + tupleId=0; + const T *pt(begin()); + for(std::size_t i=0;iret) + { + ret=cand; + tupleId=i; + } + } + return this->getIJ(tupleId,0); + } + + /*! + * Returns the maximal absolute value in \a this. + * \throw If \a this is not allocated. + * \throw If \a this is non one component array. + * \throw If \a this is empty. + */ + template + T DataArrayTemplate::getMaxAbsValueInArray() const + { + std::size_t dummy; + return getMaxAbsValue(dummy); + } + /*! * Returns the minimal value and its location within \a this one-dimensional array. * \param [out] tupleId - index of the tuple holding the minimal value. @@ -2343,6 +2389,19 @@ namespace MEDCoupling } } + /*! + * Assign zero to all values in \a this array. To know more on filling arrays see + * \ref MEDCouplingArrayFill. + * \throw If \a this is not allocated. + */ + template + void DataArrayTemplate::fillWithZero() + { + fillWithValue((T)0); + } + + ////////////////////////////// + template template MCAuto< typename Traits::ArrayType > DataArrayTemplateClassic::convertToOtherTypeOfArr() const @@ -3002,7 +3061,7 @@ struct NotInRange for(it=a.begin();it!=a.end();it++) (*it)->checkAllocated(); it=a.begin(); - int nbOfTuples((*it)->getNumberOfTuples()); + std::size_t nbOfTuples((*it)->getNumberOfTuples()); std::vector nbc(a.size()); std::vector pts(a.size()); nbc[0]=(*it)->getNumberOfComponents(); @@ -3018,8 +3077,8 @@ struct NotInRange typename Traits::ArrayType *ret(Traits::ArrayType::New()); ret->alloc(nbOfTuples,totalNbOfComp); T *retPtr(ret->getPointer()); - for(int i=0;icheckAllocated(); other->checkAllocated(); - int nbOfTuples(this->getNumberOfTuples()); + std::size_t 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;i::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 + * Computes for each tuple the sum of number of components values in the tuple and return it. + * + * \return DataArrayDouble * - the new instance of DataArrayDouble containing the + * same number of tuples as \a this array and one component. + * The caller is to delete this result array using decrRef() as it is no more + * needed. * \throw If \a this is not allocated. */ template - bool DataArrayTemplateFP::isUniform(T val, T eps) const + typename Traits::ArrayType *DataArrayTemplateClassic::sumPerTuple() 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 !"); - 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; + std::size_t nbOfComp(this->getNumberOfComponents()),nbOfTuple(this->getNumberOfTuples()); + MCAuto::ArrayType> ret(Traits::ArrayType::New()); + ret->alloc(nbOfTuple,1); + const T *src(this->begin()); + T *dest(ret->getPointer()); + for(std::size_t i=0;i - void DataArrayTemplateFP::iota(T init) + void DataArrayTemplateClassic::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;igetNumberOfTuples()); + for(std::size_t i=0;ideclareAsNew(); } + template + struct ImplReprTraits { static void SetPrecision(std::ostream& oss) { } }; + + template<> + struct ImplReprTraits { static void SetPrecision(std::ostream& oss) { oss.precision(17); } }; + + template<> + struct ImplReprTraits { static void SetPrecision(std::ostream& oss) { oss.precision(7); } }; + + template + void DataArrayTemplateClassic::reprStream(std::ostream& stream) const + { + stream << "Name of " << Traits::ReprStr << " array : \"" << this->_name << "\"\n"; + reprWithoutNameStream(stream); + } + + template + void DataArrayTemplateClassic::reprZipStream(std::ostream& stream) const + { + stream << "Name of " << Traits::ReprStr << " array : \"" << this->_name << "\"\n"; + reprZipWithoutNameStream(stream); + } + + template + void DataArrayTemplateClassic::reprNotTooLongStream(std::ostream& stream) const + { + stream << "Name of "<< Traits::ReprStr << " array : \"" << this->_name << "\"\n"; + reprNotTooLongWithoutNameStream(stream); + } + + template + void DataArrayTemplateClassic::reprWithoutNameStream(std::ostream& stream) const + { + DataArray::reprWithoutNameStream(stream); + ImplReprTraits::SetPrecision(stream); + this->_mem.repr(this->getNumberOfComponents(),stream); + } + + template + void DataArrayTemplateClassic::reprZipWithoutNameStream(std::ostream& stream) const + { + DataArray::reprWithoutNameStream(stream); + ImplReprTraits::SetPrecision(stream); + this->_mem.reprZip(this->getNumberOfComponents(),stream); + } + + template + void DataArrayTemplateClassic::reprNotTooLongWithoutNameStream(std::ostream& stream) const + { + DataArray::reprWithoutNameStream(stream); + ImplReprTraits::SetPrecision(stream); + this->_mem.reprNotTooLong(this->getNumberOfComponents(),stream); + } + + /*! + * This method is close to repr method except that when \a this has more than 1000 tuples, all tuples are not + * printed out to avoid to consume too much space in interpretor. + * \sa repr + */ + template + std::string DataArrayTemplateClassic::reprNotTooLong() const + { + std::ostringstream ret; + reprNotTooLongStream(ret); + return ret.str(); + } + + ///////////////////////////////// + + /*! + * 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 !"); + 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; + } + /*! * Equivalent to DataArrayInt::isEqual except that if false the reason of * mismatch is given. @@ -3349,6 +3500,218 @@ struct NotInRange switchOnTupleAlg(val,vec,std::not_equal_to()); } + /*! + * Creates a new one-dimensional DataArrayInt of the same size as \a this and a given + * one-dimensional arrays that must be of the same length. The result array describes + * correspondence between \a this and \a other arrays, so that + * other.getIJ(i,0) == this->getIJ(ret->getIJ(i),0). If such a permutation is + * not possible because some element in \a other is not in \a this, an exception is thrown. + * \param [in] other - an array to compute permutation to. + * \return DataArrayInt * - a new instance of DataArrayInt, which is a permutation array + * from \a this to \a other. The caller is to delete this array using decrRef() as it is + * no more needed. + * \throw If \a this->getNumberOfComponents() != 1. + * \throw If \a other->getNumberOfComponents() != 1. + * \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples(). + * \throw If \a other includes a value which is not in \a this array. + * + * \if ENABLE_EXAMPLES + * \ref cpp_mcdataarrayint_buildpermutationarr "Here is a C++ example". + * + * \ref py_mcdataarrayint_buildpermutationarr "Here is a Python example". + * \endif + */ + template + DataArrayIdType *DataArrayDiscrete::buildPermutationArr(const DataArrayDiscrete& other) const + { + this->checkAllocated(); + if(this->getNumberOfComponents()!=1 || other.getNumberOfComponents()!=1) + throw INTERP_KERNEL::Exception("DataArrayInt::buildPermutationArr : 'this' and 'other' have to have exactly ONE component !"); + std::size_t nbTuple(this->getNumberOfTuples()); + other.checkAllocated(); + if(nbTuple!=other.getNumberOfTuples()) + throw INTERP_KERNEL::Exception("DataArrayInt::buildPermutationArr : 'this' and 'other' must have the same number of tuple !"); + MCAuto ret(DataArrayIdType::New()); + ret->alloc(nbTuple,1); + ret->fillWithValue(-1); + const T *pt(this->begin()); + std::map mm; + for(std::size_t i=0;igetPointer()); + for(std::size_t i=0;i::const_iterator it=mm.find(pt[i]); + if(it==mm.end()) + { + std::ostringstream oss; oss << "DataArrayInt::buildPermutationArr : Arrays mismatch : element (" << pt[i] << ") in 'other' not findable in 'this' !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + retToFill[i]=(*it).second; + } + return ret.retn(); + } + + /*! + * Elements of \a partOfThis are expected to be included in \a this. + * The returned array \a ret is so that this[ret]==partOfThis + * + * For example, if \a this array contents are [9,10,0,6,4,11,3,8] and if \a partOfThis contains [6,0,11,8] + * the return array will contain [3,2,5,7]. + * + * \a this is expected to be a 1 compo allocated array. + * \param [in] partOfThis - A 1 compo allocated array + * \return - A newly allocated array to be dealed by caller having the same number of tuples than \a partOfThis. + * \throw if two same element is present twice in \a this + * \throw if an element in \a partOfThis is \b NOT in \a this. + */ + template + DataArrayIdType *DataArrayDiscrete::indicesOfSubPart(const DataArrayDiscrete& partOfThis) const + { + if(this->getNumberOfComponents()!=1 || partOfThis.getNumberOfComponents()!=1) + throw INTERP_KERNEL::Exception("DataArrayInt::indicesOfSubPart : this and input array must be one component array !"); + this->checkAllocated(); partOfThis.checkAllocated(); + std::size_t thisNbTuples(this->getNumberOfTuples()),nbTuples(partOfThis.getNumberOfTuples()); + const T *thisPt(this->begin()),*pt(partOfThis.begin()); + MCAuto ret(DataArrayIdType::New()); + ret->alloc(nbTuples,1); + T *retPt(ret->getPointer()); + std::map m; + for(std::size_t i=0;i::const_iterator it(m.find(*pt)); + if(it!=m.end()) + *retPt=(*it).second; + else + { + std::ostringstream oss; oss << "DataArrayInt::indicesOfSubPart : At pos #" << i << " of input array value is " << *pt << " not in this !"; + throw INTERP_KERNEL::Exception(oss.str()); + } + } + return ret.retn(); + } + + /*! + * Checks that \a this array is consistently **increasing** or **decreasing** in value. + * If not an exception is thrown. + * \param [in] increasing - if \a true, the array values should be increasing. + * \throw If sequence of values is not strictly monotonic in agreement with \a + * increasing arg. + * \throw If \a this->getNumberOfComponents() != 1. + * \throw If \a this is not allocated. + */ + template + void DataArrayDiscrete::checkMonotonic(bool increasing) const + { + if(!isMonotonic(increasing)) + { + if (increasing) + throw INTERP_KERNEL::Exception("DataArrayInt::checkMonotonic : 'this' is not INCREASING monotonic !"); + else + throw INTERP_KERNEL::Exception("DataArrayInt::checkMonotonic : 'this' is not DECREASING monotonic !"); + } + } + + /*! + * Checks that \a this array is consistently **increasing** or **decreasing** in value. + * \param [in] increasing - if \a true, array values should be increasing. + * \return bool - \a true if values change in accordance with \a increasing arg. + * \throw If \a this->getNumberOfComponents() != 1. + * \throw If \a this is not allocated. + */ + template + bool DataArrayDiscrete::isMonotonic(bool increasing) const + { + this->checkAllocated(); + if(this->getNumberOfComponents()!=1) + throw INTERP_KERNEL::Exception("DataArrayInt::isMonotonic : only supported with 'this' array with ONE component !"); + std::size_t nbOfElements(this->getNumberOfTuples()); + const T *ptr(this->begin()); + if(nbOfElements==0) + return true; + T ref(ptr[0]); + if(increasing) + { + for(std::size_t i=1;i=ref) + ref=ptr[i]; + else + return false; + } + } + else + { + for(std::size_t i=1;i + bool DataArrayDiscrete::isStrictlyMonotonic(bool increasing) const + { + this->checkAllocated(); + if(this->getNumberOfComponents()!=1) + throw INTERP_KERNEL::Exception("DataArrayInt::isStrictlyMonotonic : only supported with 'this' array with ONE component !"); + std::size_t nbOfElements(this->getNumberOfTuples()); + const T *ptr(this->begin()); + if(nbOfElements==0) + return true; + T ref(ptr[0]); + if(increasing) + { + for(std::size_t i=1;iref) + ref=ptr[i]; + else + return false; + } + } + else + { + for(std::size_t i=1;i + void DataArrayDiscrete::checkStrictlyMonotonic(bool increasing) const + { + if(!isStrictlyMonotonic(increasing)) + { + if (increasing) + throw INTERP_KERNEL::Exception("DataArrayInt::checkStrictlyMonotonic : 'this' is not strictly INCREASING monotonic !"); + else + throw INTERP_KERNEL::Exception("DataArrayInt::checkStrictlyMonotonic : 'this' is not strictly DECREASING monotonic !"); + } + } + + //////////////////////////////////// + /*! * This method compares content of input vector \a v and \a this. * If for each id in \a this v[id]==True and for all other ids id2 not in \a this v[id2]==False, true is returned.