X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FMEDCoupling%2FMEDCouplingMemArray.cxx;h=ee514548315a710085ad4ca73fd66512bcc491a8;hb=a25fc7c3173633c8eec4a4db9cda520f947317b7;hp=c54ef2cec1678423d63a669b42e60acc88106a30;hpb=97a70baa6f327efeaf2b65acb2f499cdcff68583;p=tools%2Fmedcoupling.git diff --git a/src/MEDCoupling/MEDCouplingMemArray.cxx b/src/MEDCoupling/MEDCouplingMemArray.cxx index c54ef2cec..ee5145483 100644 --- a/src/MEDCoupling/MEDCouplingMemArray.cxx +++ b/src/MEDCoupling/MEDCouplingMemArray.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2014 CEA/DEN, EDF R&D +// Copyright (C) 2007-2015 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 @@ -120,7 +120,7 @@ std::size_t DataArray::getHeapMemorySizeWithoutChildren() const return sz1+sz2+sz3; } -std::vector DataArray::getDirectChildren() const +std::vector DataArray::getDirectChildrenWithNull() const { return std::vector(); } @@ -1146,7 +1146,9 @@ bool DataArrayDouble::isMonotonic(bool increasing, double eps) const /*! * Returns a textual and human readable representation of \a this instance of * DataArrayDouble. This text is shown when a DataArrayDouble is printed in Python. - * \return std::string - text describing \a this DataArrayDouble. + * \return std::string - text describing \a this DataArrayDouble. + * + * \sa reprNotTooLong, reprZip */ std::string DataArrayDouble::repr() const { @@ -1162,6 +1164,18 @@ std::string DataArrayDouble::reprZip() const return ret.str(); } +/*! + * 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 + */ +std::string DataArrayDouble::reprNotTooLong() const +{ + std::ostringstream ret; + reprNotTooLongStream(ret); + return ret.str(); +} + void DataArrayDouble::writeVTK(std::ostream& ofs, int indent, const std::string& nameInFile, DataArrayByte *byteArr) const { static const char SPACE[4]={' ',' ',' ',' '}; @@ -1169,6 +1183,15 @@ void DataArrayDouble::writeVTK(std::ostream& ofs, int indent, const std::string& std::string idt(indent,' '); ofs.precision(17); ofs << idt << "::const_iterator it=_info_on_compo.begin();it!=_info_on_compo.end();it++) + if(!(*it).empty()) + areAllEmpty=false; + if(!areAllEmpty) + for(std::size_t i=0;i<_info_on_compo.size();i++) + ofs << " ComponentName" << i << "=\"" << _info_on_compo[i] << "\""; + // if(byteArr) { ofs << " format=\"appended\" offset=\"" << byteArr->getNumberOfTuples() << "\">"; @@ -1202,6 +1225,12 @@ void DataArrayDouble::reprZipStream(std::ostream& stream) const reprZipWithoutNameStream(stream); } +void DataArrayDouble::reprNotTooLongStream(std::ostream& stream) const +{ + stream << "Name of double array : \"" << _name << "\"\n"; + reprNotTooLongWithoutNameStream(stream); +} + void DataArrayDouble::reprWithoutNameStream(std::ostream& stream) const { DataArray::reprWithoutNameStream(stream); @@ -1216,6 +1245,13 @@ void DataArrayDouble::reprZipWithoutNameStream(std::ostream& stream) const _mem.reprZip(getNumberOfComponents(),stream); } +void DataArrayDouble::reprNotTooLongWithoutNameStream(std::ostream& stream) const +{ + DataArray::reprWithoutNameStream(stream); + stream.precision(17); + _mem.reprNotTooLong(getNumberOfComponents(),stream); +} + void DataArrayDouble::reprCppStream(const std::string& varName, std::ostream& stream) const { int nbTuples=getNumberOfTuples(),nbComp=getNumberOfComponents(); @@ -1862,7 +1898,7 @@ void DataArrayDouble::transpose() * \ref py_mcdataarraydouble_KeepSelectedComponents "Here is a Python example". * \endif */ -DataArray *DataArrayDouble::keepSelectedComponents(const std::vector& compoIds) const +DataArrayDouble *DataArrayDouble::keepSelectedComponents(const std::vector& compoIds) const { checkAllocated(); MEDCouplingAutoRefCountObjectPtr ret(DataArrayDouble::New()); @@ -4108,7 +4144,7 @@ DataArrayDouble *DataArrayDouble::computeAbs() const } /*! - * Apply a liner function to a given component of \a this array, so that + * 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. @@ -4131,7 +4167,7 @@ void DataArrayDouble::applyLin(double a, double b, int compoId) } /*! - * Apply a liner function to all elements of \a this array, so that + * 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. @@ -4307,6 +4343,8 @@ DataArrayDouble *DataArrayDouble::applyFunc(int nbOfComp, FunctionToEvaluate fun * \param [in] nbOfComp - number of components in the result array. * \param [in] func - the expression defining how to transform a tuple of \a this array. * Supported expressions are described \ref MEDCouplingArrayApplyFuncExpr "here". + * \param [in] isSafe - By default true. If true invalid operation (division by 0. acos of value > 1. ...) leads to a throw of an exception. + * If false the computation is carried on without any notification. When false the evaluation is a little faster. * \return DataArrayDouble * - the new instance of DataArrayDouble containing the * same number of tuples as \a this array and \a nbOfComp components. * The caller is to delete this result array using decrRef() as it is no more @@ -4314,144 +4352,210 @@ DataArrayDouble *DataArrayDouble::applyFunc(int nbOfComp, FunctionToEvaluate fun * \throw If \a this is not allocated. * \throw If computing \a func fails. */ -DataArrayDouble *DataArrayDouble::applyFunc(int nbOfComp, const std::string& func) const +DataArrayDouble *DataArrayDouble::applyFunc(int nbOfComp, const std::string& func, bool isSafe) const { - checkAllocated(); INTERP_KERNEL::ExprParser expr(func); expr.parse(); std::set vars; expr.getTrueSetOfVars(vars); - int oldNbOfComp=getNumberOfComponents(); - if((int)vars.size()>oldNbOfComp) - { - std::ostringstream oss; oss << "The field has " << oldNbOfComp << " components and there are "; - oss << vars.size() << " variables : "; - std::copy(vars.begin(),vars.end(),std::ostream_iterator(oss," ")); - throw INTERP_KERNEL::Exception(oss.str().c_str()); - } std::vector varsV(vars.begin(),vars.end()); - expr.prepareExprEvaluation(varsV,oldNbOfComp,nbOfComp); - // - DataArrayDouble *newArr=DataArrayDouble::New(); - int nbOfTuples=getNumberOfTuples(); - newArr->alloc(nbOfTuples,nbOfComp); - const double *ptr=getConstPointer(); - double *ptrToFill=newArr->getPointer(); - for(int i=0;i(oss,", ")); - oss << ") : Evaluation of function failed !" << e.what(); - newArr->decrRef(); - throw INTERP_KERNEL::Exception(oss.str().c_str()); - } - } - return newArr; + return applyFunc3(nbOfComp,varsV,func,isSafe); } /*! * Returns a new DataArrayDouble created from \a this one by applying a function to every - * tuple of \a this array. Textual data is not copied. + * tuple of \a this array. Textual data is not copied. This method works by tuples (whatever its size). + * If \a this is a one component array, call applyFuncOnThis instead that performs the same work faster. + * * For more info see \ref MEDCouplingArrayApplyFunc0. * \param [in] func - the expression defining how to transform a tuple of \a this array. * Supported expressions are described \ref MEDCouplingArrayApplyFuncExpr "here". + * \param [in] isSafe - By default true. If true invalid operation (division by 0. acos of value > 1. ...) leads to a throw of an exception. + * If false the computation is carried on without any notification. When false the evaluation is a little faster. * \return DataArrayDouble * - the new instance of DataArrayDouble containing the * same number of tuples and components as \a this array. * The caller is to delete this result array using decrRef() as it is no more * needed. + * \sa applyFuncOnThis * \throw If \a this is not allocated. * \throw If computing \a func fails. */ -DataArrayDouble *DataArrayDouble::applyFunc(const std::string& func) const +DataArrayDouble *DataArrayDouble::applyFunc(const std::string& func, bool isSafe) const { + int nbOfComp(getNumberOfComponents()); + if(nbOfComp<=0) + throw INTERP_KERNEL::Exception("DataArrayDouble::applyFunc : output number of component must be > 0 !"); checkAllocated(); + int nbOfTuples(getNumberOfTuples()); + MEDCouplingAutoRefCountObjectPtr newArr(DataArrayDouble::New()); + newArr->alloc(nbOfTuples,nbOfComp); INTERP_KERNEL::ExprParser expr(func); expr.parse(); - expr.prepareExprEvaluationVec(); - // - DataArrayDouble *newArr=DataArrayDouble::New(); - int nbOfTuples=getNumberOfTuples(); - int nbOfComp=getNumberOfComponents(); - newArr->alloc(nbOfTuples,nbOfComp); - const double *ptr=getConstPointer(); - double *ptrToFill=newArr->getPointer(); - for(int i=0;i vars; + expr.getTrueSetOfVars(vars); + if((int)vars.size()>1) { - try - { - expr.evaluateExpr(nbOfComp,ptr+i*nbOfComp,ptrToFill+i*nbOfComp); - } - catch(INTERP_KERNEL::Exception& e) - { - std::ostringstream oss; oss << "For tuple # " << i << " with value ("; - std::copy(ptr+nbOfComp*i,ptr+nbOfComp*(i+1),std::ostream_iterator(oss,", ")); - oss << ") : Evaluation of function failed ! " << e.what(); - newArr->decrRef(); - throw INTERP_KERNEL::Exception(oss.str().c_str()); - } + std::ostringstream oss; oss << "DataArrayDouble::applyFunc : this method works only with at most one var func expression ! If you need to map comps on variables please use applyFunc2 or applyFunc3 instead ! Vars in expr are : "; + std::copy(vars.begin(),vars.end(),std::ostream_iterator(oss," ")); + throw INTERP_KERNEL::Exception(oss.str().c_str()); } - return newArr; + if(vars.empty()) + { + expr.prepareFastEvaluator(); + newArr->rearrange(1); + newArr->fillWithValue(expr.evaluateDouble()); + newArr->rearrange(nbOfComp); + return newArr.retn(); + } + std::vector vars2(vars.begin(),vars.end()); + double buff,*ptrToFill(newArr->getPointer()); + const double *ptr(begin()); + std::vector stck; + expr.prepareExprEvaluationDouble(vars2,1,1,0,&buff,&buff+1); + expr.prepareFastEvaluator(); + if(!isSafe) + { + for(int i=0;igetInfoOnComponent(). - * \throw If computing \a func fails. + * \param [in] isSafe - By default true. If true invalid operation (division by 0. acos of value > 1. ...) leads to a throw of an exception. + * If false the computation is carried on without any notification. When false the evaluation is a little faster. + * + * \sa applyFunc */ -DataArrayDouble *DataArrayDouble::applyFunc2(int nbOfComp, const std::string& func) const +void DataArrayDouble::applyFuncOnThis(const std::string& func, bool isSafe) { + int nbOfComp(getNumberOfComponents()); + if(nbOfComp<=0) + throw INTERP_KERNEL::Exception("DataArrayDouble::applyFuncOnThis : output number of component must be > 0 !"); checkAllocated(); + int nbOfTuples(getNumberOfTuples()); INTERP_KERNEL::ExprParser expr(func); expr.parse(); std::set vars; expr.getTrueSetOfVars(vars); - int oldNbOfComp=getNumberOfComponents(); - if((int)vars.size()>oldNbOfComp) + if((int)vars.size()>1) { - std::ostringstream oss; oss << "The field has " << oldNbOfComp << " components and there are "; - oss << vars.size() << " variables : "; + std::ostringstream oss; oss << "DataArrayDouble::applyFuncOnThis : this method works only with at most one var func expression ! If you need to map comps on variables please use applyFunc2 or applyFunc3 instead ! Vars in expr are : "; std::copy(vars.begin(),vars.end(),std::ostream_iterator(oss," ")); throw INTERP_KERNEL::Exception(oss.str().c_str()); } - expr.prepareExprEvaluation(getVarsOnComponent(),oldNbOfComp,nbOfComp); - // - DataArrayDouble *newArr=DataArrayDouble::New(); - int nbOfTuples=getNumberOfTuples(); - newArr->alloc(nbOfTuples,nbOfComp); - const double *ptr=getConstPointer(); - double *ptrToFill=newArr->getPointer(); - for(int i=0;i(oss,", ")); - oss << ") : Evaluation of function failed !" << e.what(); - newArr->decrRef(); - throw INTERP_KERNEL::Exception(oss.str().c_str()); - } + expr.prepareFastEvaluator(); + std::vector compInfo(getInfoOnComponents()); + rearrange(1); + fillWithValue(expr.evaluateDouble()); + rearrange(nbOfComp); + setInfoOnComponents(compInfo); + return ; + } + std::vector vars2(vars.begin(),vars.end()); + double buff,*ptrToFill(getPointer()); + const double *ptr(begin()); + std::vector stck; + expr.prepareExprEvaluationDouble(vars2,1,1,0,&buff,&buff+1); + expr.prepareFastEvaluator(); + if(!isSafe) + { + for(int i=0;i 1. ...) leads to a throw of an exception. + * If false the computation is carried on without any notification. When false the evaluation is a little faster. + * \return DataArrayDouble * - the new instance of DataArrayDouble containing the + * same number of tuples 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. + * \throw If \a func contains vars that are not in \a this->getInfoOnComponent(). + * \throw If computing \a func fails. + */ +DataArrayDouble *DataArrayDouble::applyFunc2(int nbOfComp, const std::string& func, bool isSafe) const +{ + return applyFunc3(nbOfComp,getVarsOnComponent(),func,isSafe); } /*! @@ -4462,6 +4566,8 @@ DataArrayDouble *DataArrayDouble::applyFunc2(int nbOfComp, const std::string& fu * \param [in] varsOrder - sequence of vars defining their order. * \param [in] func - the expression defining how to transform a tuple of \a this array. * Supported expressions are described \ref MEDCouplingArrayApplyFuncExpr "here". + * \param [in] isSafe - By default true. If true invalid operation (division by 0. acos of value > 1. ...) leads to a throw of an exception. + * If false the computation is carried on without any notification. When false the evaluation is a little faster. * \return DataArrayDouble * - the new instance of DataArrayDouble containing the * same number of tuples as \a this array. * The caller is to delete this result array using decrRef() as it is no more @@ -4470,14 +4576,20 @@ DataArrayDouble *DataArrayDouble::applyFunc2(int nbOfComp, const std::string& fu * \throw If \a func contains vars not in \a varsOrder. * \throw If computing \a func fails. */ -DataArrayDouble *DataArrayDouble::applyFunc3(int nbOfComp, const std::vector& varsOrder, const std::string& func) const +DataArrayDouble *DataArrayDouble::applyFunc3(int nbOfComp, const std::vector& varsOrder, const std::string& func, bool isSafe) const { + if(nbOfComp<=0) + throw INTERP_KERNEL::Exception("DataArrayDouble::applyFunc3 : output number of component must be > 0 !"); + std::vector varsOrder2(varsOrder); + int oldNbOfComp(getNumberOfComponents()); + for(int i=(int)varsOrder.size();i vars; expr.getTrueSetOfVars(vars); - int oldNbOfComp=getNumberOfComponents(); if((int)vars.size()>oldNbOfComp) { std::ostringstream oss; oss << "The field has " << oldNbOfComp << " components and there are "; @@ -4485,29 +4597,49 @@ DataArrayDouble *DataArrayDouble::applyFunc3(int nbOfComp, const std::vector(oss," ")); throw INTERP_KERNEL::Exception(oss.str().c_str()); } - expr.prepareExprEvaluation(varsOrder,oldNbOfComp,nbOfComp); - // - DataArrayDouble *newArr=DataArrayDouble::New(); - int nbOfTuples=getNumberOfTuples(); + MEDCouplingAutoRefCountObjectPtr newArr(DataArrayDouble::New()); newArr->alloc(nbOfTuples,nbOfComp); - const double *ptr=getConstPointer(); - double *ptrToFill=newArr->getPointer(); - for(int i=0;i(oss,", ")); - oss << ") : Evaluation of function failed !" << e.what(); - newArr->decrRef(); - throw INTERP_KERNEL::Exception(oss.str().c_str()); - } + INTERP_KERNEL::AutoPtr buff(new double[oldNbOfComp]); + double *buffPtr(buff),*ptrToFill; + std::vector stck; + for(int iComp=0;iCompgetPointer()+iComp; + if(!isSafe) + { + for(int i=0;i(oss,", ")); + oss << ") : Evaluation of function failed !" << e.what(); + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + } } - return newArr; + return newArr.retn(); } void DataArrayDouble::applyFuncFast32(const std::string& func) @@ -5584,6 +5716,37 @@ void DataArrayDouble::powEqual(const DataArrayDouble *other) declareAsNew(); } +/*! + * This method is \b NOT wrapped into python because it can be useful only for performance reasons in C++ context. + * All values in \a this must be 0. or 1. within eps error. 0 means false, 1 means true. + * If an another value than 0 or 1 appear (within eps precision) an INTERP_KERNEL::Exception will be thrown. + * + * \throw if \a this is not allocated. + * \throw if \a this has not exactly one component. + */ +std::vector DataArrayDouble::toVectorOfBool(double eps) const +{ + checkAllocated(); + if(getNumberOfComponents()!=1) + throw INTERP_KERNEL::Exception("DataArrayDouble::toVectorOfBool : must be applied on single component array !"); + int nbt(getNumberOfTuples()); + std::vector ret(nbt); + const double *pt(begin()); + for(int i=0;igetNumberOfComponents() != 1 * \throw If any value of \a this can't be used as a valid index for * [\a indArrBg, \a indArrEnd). + * + * \sa replaceOneValByInThis */ void DataArrayInt::transformWithIndArr(const int *indArrBg, const int *indArrEnd) { checkAllocated(); if(getNumberOfComponents()!=1) throw INTERP_KERNEL::Exception("Call transformWithIndArr method on DataArrayInt with only one component, you can call 'rearrange' method before !"); - int nbElemsIn=(int)std::distance(indArrBg,indArrEnd); - int nbOfTuples=getNumberOfTuples(); - int *pt=getPointer(); + int nbElemsIn((int)std::distance(indArrBg,indArrEnd)),nbOfTuples(getNumberOfTuples()),*pt(getPointer()); for(int i=0;i=0 && *ptstrt) + { + sttoopp++; + int a(sttoopp-1-strt),tmp(strt); + if(a%(nbTuples-1)!=0) + return false; + stteepp=a/(nbTuples-1); + for(int i=0;i& v) const return w==end2; } +/*! + * This method assumes that \a this has one component and is allocated. This method scans all tuples in \a this and for all tuple equal to \a val + * put True to the corresponding entry in \a vec. + * \a vec is expected to be with the same size than the number of tuples of \a this. + */ +void DataArrayInt::switchOnTupleEqualTo(int val, std::vector& vec) const +{ + checkAllocated(); + if(getNumberOfComponents()!=1) + throw INTERP_KERNEL::Exception("DataArrayInt::switchOnTupleEqualTo : number of components of this should be equal to one !"); + int nbOfTuples(getNumberOfTuples()); + if(nbOfTuples!=(int)vec.size()) + throw INTERP_KERNEL::Exception("DataArrayInt::switchOnTupleEqualTo : number of tuples of this should be equal to size of input vector of bool !"); + const int *pt(begin()); + for(int i=0;igetNumberOfTuples()) * \throw If \a this is not allocated. * \throw If \a this->getNumberOfComponents() != 1. + * \sa isIdentity2 */ bool DataArrayInt::isIdentity() const { checkAllocated(); if(getNumberOfComponents()!=1) return false; - int nbOfTuples=getNumberOfTuples(); + int nbOfTuples(getNumberOfTuples()); const int *pt=getConstPointer(); for(int i=0;igetNumberOfTuples()) and if \a this has \a sizeExpected tuples in it. + * + * \throw If \a this is not allocated. + * \throw If \a this->getNumberOfComponents() != 1. + * \sa isIdentity + */ +bool DataArrayInt::isIdentity2(int sizeExpected) const +{ + bool ret0(isIdentity()); + if(!ret0) + return false; + return getNumberOfTuples()==sizeExpected; +} + /*! * Checks if all values in \a this array are equal to \a val. * \param [in] val - value to check equality of array values to. @@ -7655,7 +7962,7 @@ void DataArrayInt::reAlloc(int nbOfTuples) * \ref py_mcdataarrayint_keepselectedcomponents "Here is a Python example". * \endif */ -DataArray *DataArrayInt::keepSelectedComponents(const std::vector& compoIds) const +DataArrayInt *DataArrayInt::keepSelectedComponents(const std::vector& compoIds) const { checkAllocated(); MEDCouplingAutoRefCountObjectPtr ret(DataArrayInt::New()); @@ -8453,7 +8760,7 @@ DataArrayIntIterator *DataArrayInt::iterator() /*! * Creates a new DataArrayInt containing IDs (indices) of tuples holding value equal to a - * given one. + * given one. The ids are sorted in the ascending order. * \param [in] val - the value to find within \a this. * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this * array using decrRef() as it is no more needed. @@ -9060,6 +9367,32 @@ int DataArrayInt::getMinValueInArray() const return *loc; } +/*! + * Returns in a single walk in \a this the min value and the max value in \a this. + * \a this is expected to be single component array. + * + * \param [out] minValue - the min value in \a this. + * \param [out] maxValue - the max value in \a this. + * + * \sa getMinValueInArray, getMinValue, getMaxValueInArray, getMaxValue + */ +void DataArrayInt::getMinMaxValues(int& minValue, int& maxValue) const +{ + checkAllocated(); + if(getNumberOfComponents()!=1) + throw INTERP_KERNEL::Exception("DataArrayInt::getMinMaxValues : must be applied on DataArrayInt with only one component !"); + int nbTuples(getNumberOfTuples()); + const int *pt(begin()); + minValue=std::numeric_limits::max(); maxValue=-std::numeric_limits::max(); + for(int i=0;imaxValue) + maxValue=*pt; + } +} + /*! * Converts every value of \a this array to its absolute value. * \b WARNING this method is non const. If a new DataArrayInt instance should be built containing the result of abs DataArrayInt::computeAbs @@ -9233,7 +9566,7 @@ void DataArrayInt::applyModulus(int val) * \param [in] vmax end of range. This value is \b not included in range (excluded). * \return a newly allocated data array that the caller should deal with. * - * \sa DataArrayInt::getIdsNotInRange + * \sa DataArrayInt::getIdsNotInRange , DataArrayInt::getIdsStrictlyNegative */ DataArrayInt *DataArrayInt::getIdsInRange(int vmin, int vmax) const { @@ -9258,7 +9591,7 @@ DataArrayInt *DataArrayInt::getIdsInRange(int vmin, int vmax) const * \param [in] vmax end of range. This value is included in range (included). * \return a newly allocated data array that the caller should deal with. * - * \sa DataArrayInt::getIdsInRange + * \sa DataArrayInt::getIdsInRange , DataArrayInt::getIdsStrictlyNegative */ DataArrayInt *DataArrayInt::getIdsNotInRange(int vmin, int vmax) const { @@ -9274,6 +9607,26 @@ DataArrayInt *DataArrayInt::getIdsNotInRange(int vmin, int vmax) const return ret.retn(); } +/*! + * 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::getIdsInRange + */ +DataArrayInt *DataArrayInt::getIdsStrictlyNegative() const +{ + checkAllocated(); + if(getNumberOfComponents()!=1) + throw INTERP_KERNEL::Exception("DataArrayInt::getIdsStrictlyNegative : this must have exactly one component !"); + const int *cptr(getConstPointer()); + MEDCouplingAutoRefCountObjectPtr ret(DataArrayInt::New()); ret->alloc(0,1); + int nbOfTuples(getNumberOfTuples()); + for(int i=0;ipushBackSilent(i); + return ret.retn(); +} + /*! * This method works only on data array with one component. * This method checks that all ids in \b this are in [ \b vmin, \b vmax ). If there is at least one element in \a this not in [ \b vmin, \b vmax ) an exception will be thrown. @@ -9792,7 +10145,8 @@ DataArrayInt *DataArrayInt::buildSubstractionOptimized(const DataArrayInt *other checkAllocated(); other->checkAllocated(); if(getNumberOfComponents()!=1) throw INTERP_KERNEL::Exception(MSG); if(other->getNumberOfComponents()!=1) throw INTERP_KERNEL::Exception(MSG); - const int *pt1Bg(begin()),*pt1End(end()),*pt2Bg(other->begin()),*pt2End(other->end()),*work1(pt1Bg),*work2(pt2Bg); + const int *pt1Bg(begin()),*pt1End(end()),*pt2Bg(other->begin()),*pt2End(other->end()); + const int *work1(pt1Bg),*work2(pt2Bg); MEDCouplingAutoRefCountObjectPtr ret(DataArrayInt::New()); ret->alloc(0,1); for(;work1!=pt1End;work1++) { @@ -9849,6 +10203,7 @@ DataArrayInt *DataArrayInt::buildIntersection(const DataArrayInt *other) const * * \return a newly allocated array that contain the result of the unique operation applied on \a this. * \throw if \a this is not allocated or if \a this has not exactly one component. + * \sa DataArrayInt::buildUniqueNotSorted */ DataArrayInt *DataArrayInt::buildUnique() const { @@ -9865,6 +10220,38 @@ DataArrayInt *DataArrayInt::buildUnique() const return ret.retn(); } +/*! + * This method can be applied on allocated with one component DataArrayInt instance. + * This method keep elements only once by keeping the same order in \a this that is not expected to be sorted. + * + * \return a newly allocated array that contain the result of the unique operation applied on \a this. + * + * \throw if \a this is not allocated or if \a this has not exactly one component. + * + * \sa DataArrayInt::buildUnique + */ +DataArrayInt *DataArrayInt::buildUniqueNotSorted() const +{ + checkAllocated(); + if(getNumberOfComponents()!=1) + throw INTERP_KERNEL::Exception("DataArrayInt::buildUniqueNotSorted : only single component allowed !"); + int minVal,maxVal; + getMinMaxValues(minVal,maxVal); + std::vector b(maxVal-minVal+1,false); + const int *ptBg(begin()),*endBg(end()); + MEDCouplingAutoRefCountObjectPtr ret(DataArrayInt::New()); ret->alloc(0,1); + for(const int *pt=ptBg;pt!=endBg;pt++) + { + if(!b[*pt-minVal]) + { + ret->pushBackSilent(*pt); + b[*pt-minVal]=true; + } + } + ret->copyStringInfoFrom(*this); + return ret.retn(); +} + /*! * Returns a new DataArrayInt which contains size of every of groups described by \a this * "index" array. Such "index" array is returned for example by @@ -10261,6 +10648,68 @@ DataArrayInt *DataArrayInt::findIdInRangeForEachTuple(const DataArrayInt *ranges return ret.retn(); } +/*! + * \b WARNING this method is a \b non \a const \b method. This method works tuple by tuple. Each tuple is expected to be pairs (number of components must be equal to 2). + * This method rearrange each pair in \a this so that, tuple with id \b tid will be after the call \c this->getIJ(tid,0)==this->getIJ(tid-1,1) and \c this->getIJ(tid,1)==this->getIJ(tid+1,0). + * If it is impossible to reach such condition an exception will be thrown ! \b WARNING In case of throw \a this can be partially modified ! + * If this method has correctly worked, \a this will be able to be considered as a linked list. + * This method does nothing if number of tuples is lower of equal to 1. + * + * This method is useful for users having an unstructured mesh having only SEG2 to rearrange internaly the connectibity without any coordinates consideration. + * + * \sa MEDCouplingUMesh::orderConsecutiveCells1D + */ +void DataArrayInt::sortEachPairToMakeALinkedList() +{ + checkAllocated(); + if(getNumberOfComponents()!=2) + throw INTERP_KERNEL::Exception("DataArrayInt::sortEachPairToMakeALinkedList : Only works on DataArrayInt instance with nb of components equal to 2 !"); + int nbOfTuples(getNumberOfTuples()); + if(nbOfTuples<=1) + return ; + int *conn(getPointer()); + for(int i=1;i1) + { + if(conn[2]==conn[3]) + { + std::ostringstream oss; oss << "DataArrayInt::sortEachPairToMakeALinkedList : In the tuple #" << i << " presence of a pair filled with same ids !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + if(conn[2]!=conn[1] && conn[3]==conn[1] && conn[2]!=conn[0]) + std::swap(conn[2],conn[3]); + //not(conn[2]==conn[1] && conn[3]!=conn[1] && conn[3]!=conn[0]) + if(conn[2]!=conn[1] || conn[3]==conn[1] || conn[3]==conn[0]) + { + std::ostringstream oss; oss << "DataArrayInt::sortEachPairToMakeALinkedList : In the tuple #" << i << " something is invalid !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + else + { + if(conn[0]==conn[1] || conn[2]==conn[3]) + throw INTERP_KERNEL::Exception("DataArrayInt::sortEachPairToMakeALinkedList : In the 2 first tuples presence of a pair filled with same ids !"); + int tmp[4]; + std::set s; + s.insert(conn,conn+4); + if(s.size()!=3) + throw INTERP_KERNEL::Exception("DataArrayInt::sortEachPairToMakeALinkedList : This can't be considered as a linked list regarding 2 first tuples !"); + if(std::count(conn,conn+4,conn[0])==2) + { + tmp[0]=conn[1]; + tmp[1]=conn[0]; + tmp[2]=conn[0]; + if(conn[2]==conn[0]) + { tmp[3]=conn[3]; } + else + { tmp[3]=conn[2];} + std::copy(tmp,tmp+4,conn); + } + } + } +} + /*! * * \param [in] nbTimes specifies the nb of times each tuples in \a this will be duplicated contiguouly in returned DataArrayInt instance.