From: Anthony Geay Date: Fri, 21 Nov 2014 15:57:43 +0000 (+0100) Subject: Addition of tools for combination of part definition for // manip. X-Git-Tag: V7_5_1b1~5^2~1 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=62a3e1a7f12332a2fd01f5751b9f5ca99b8727e1;p=tools%2Fmedcoupling.git Addition of tools for combination of part definition for // manip. --- diff --git a/src/MEDCoupling/MEDCouplingMemArray.cxx b/src/MEDCoupling/MEDCouplingMemArray.cxx index 685de65de..d3f460529 100644 --- a/src/MEDCoupling/MEDCouplingMemArray.cxx +++ b/src/MEDCoupling/MEDCouplingMemArray.cxx @@ -6424,7 +6424,7 @@ void DataArrayInt::transformWithIndArr(const int *indArrBg, const int *indArrEnd */ void DataArrayInt::splitByValueRange(const int *arrBg, const int *arrEnd, DataArrayInt *& castArr, DataArrayInt *& rankInsideCast, DataArrayInt *& castsPresent) const - { +{ checkAllocated(); if(getNumberOfComponents()!=1) throw INTERP_KERNEL::Exception("Call splitByValueRange method on DataArrayInt with only one component, you can call 'rearrange' method before !"); @@ -6467,7 +6467,60 @@ void DataArrayInt::splitByValueRange(const int *arrBg, const int *arrEnd, castArr=ret1.retn(); rankInsideCast=ret2.retn(); castsPresent=ret3.retn(); +} + +/*! + * This method look at \a this if it can be considered as a range defined by the 3-tuple ( \a strt , \a sttoopp , \a stteepp ). + * If false is returned the tuple must be ignored. If true is returned \a this can be considered by a range( \a strt , \a sttoopp , \a stteepp ). + * This method works only if \a this is allocated and single component. If not an exception will be thrown. + * + * \param [out] strt - the start of the range (included) if true is returned. + * \param [out] sttoopp - the end of the range (not included) if true is returned. + * \param [out] stteepp - the step of the range if true is returned. + * \return the verdict of the check. + * + * \sa DataArray::GetNumberOfItemGivenBES + */ +bool DataArrayInt::isRange(int& strt, int& sttoopp, int& stteepp) const +{ + checkAllocated(); + if(getNumberOfComponents()!=1) + throw INTERP_KERNEL::Exception("DataArrayInt::isRange : this must be single component array !"); + int nbTuples(getNumberOfTuples()); + if(nbTuples==0) + { strt=0; sttoopp=0; stteepp=1; return true; } + const int *pt(begin()); + strt=*pt; + if(nbTuples==1) + { sttoopp=strt+1; stteepp=1; return true; } + strt=*pt; sttoopp=pt[nbTuples-1]; + if(strt==sttoopp) + return false; + if(sttoopp>strt) + { + sttoopp++; + int a(sttoopp-1-strt),tmp(strt); + if(a%(nbTuples-1)!=0) + return false; + stteepp=a/(nbTuples-1); + for(int i=0;i DataArrayPartDefinition([4,5,6,7,11,12,13]) will be returned + */ +PartDefinition *DataArrayPartDefinition::composeWith(const PartDefinition *other) const +{ + if(!other) + throw INTERP_KERNEL::Exception("DataArrayPartDefinition::composeWith : input PartDef must be not NULL !"); + checkCoherency(); + other->checkCoherency(); + const SlicePartDefinition *spd(dynamic_cast(other)); + if(spd) + {//special case for optim + int a(0),b(0),c(0); + spd->getSlice(a,b,c); + if(c==1) + { + MEDCouplingAutoRefCountObjectPtr arr(DataArrayInt::New()); + arr->alloc(_arr->getNumberOfTuples(),1); + std::transform(_arr->begin(),_arr->end(),arr->getPointer(),std::bind2nd(std::plus(),a)); + return DataArrayPartDefinition::New(arr); + } + } + // + MEDCouplingAutoRefCountObjectPtr arr1(other->toDAI()); + MEDCouplingAutoRefCountObjectPtr arr2(arr1->selectByTupleIdSafe(_arr->begin(),_arr->end())); + return DataArrayPartDefinition::New(arr2); +} + +void DataArrayPartDefinition::checkCoherency() const +{ + CheckInternalArrayOK(_arr); +} + +/*! + * This method tries to simplify \a this if possible. + * + * \return a new reference (equal to this) to be decrRefed. + */ +PartDefinition *DataArrayPartDefinition::tryToSimplify() const +{ + checkCoherency(); + int a(0),b(0),c(0); + if(_arr->isRange(a,b,c)) + { + return SlicePartDefinition::New(a,b,c); + } + else + { + PartDefinition *ret(const_cast(this)); + ret->incrRef(); + return ret; + } +} + DataArrayInt *DataArrayPartDefinition::toDAI() const { checkInternalArrayOK(); @@ -165,6 +220,40 @@ PartDefinition *SlicePartDefinition::operator+(const PartDefinition& other) cons throw INTERP_KERNEL::Exception("SlicePartDefinition::operator+ : unrecognized type in input !"); } +/*! + * This method operates FoG where F is \a this and G is \a other. + * Example : if \a this is SlicePart(4,6,1) and if \a other is DataArrayPartDefinition([12,13,17,18,22,28,34,44]) -> DataArrayPartDefinition([22,28]) will be returned + */ +PartDefinition *SlicePartDefinition::composeWith(const PartDefinition *other) const +{ + if(!other) + throw INTERP_KERNEL::Exception("SlicePartDefinition::composeWith : input PartDef must be not NULL !"); + checkCoherency(); + other->checkCoherency(); + MEDCouplingAutoRefCountObjectPtr arr(other->toDAI()); + MEDCouplingAutoRefCountObjectPtr arr1(arr->selectByTupleId2(_start,_stop,_step)); + return DataArrayPartDefinition::New(arr1); +} + +/*! + * Do nothing it is not a bug. + */ +void SlicePartDefinition::checkCoherency() const +{ +} + +/*! + * Return \a this (because it cannot be simplified) + * + * \return a new reference (equal to this) to be decrRefed. + */ +PartDefinition *SlicePartDefinition::tryToSimplify() const +{ + PartDefinition *ret(const_cast(this)); + ret->incrRef(); + return ret; +} + std::string SlicePartDefinition::getRepr() const { std::ostringstream oss; diff --git a/src/MEDCoupling/MEDCouplingPartDefinition.hxx b/src/MEDCoupling/MEDCouplingPartDefinition.hxx index d30868f0b..95456d6b3 100644 --- a/src/MEDCoupling/MEDCouplingPartDefinition.hxx +++ b/src/MEDCoupling/MEDCouplingPartDefinition.hxx @@ -36,6 +36,9 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT virtual int getNumberOfElems() const = 0; MEDCOUPLING_EXPORT virtual PartDefinition *operator+(const PartDefinition& other) const = 0; MEDCOUPLING_EXPORT virtual std::string getRepr() const = 0; + MEDCOUPLING_EXPORT virtual PartDefinition *composeWith(const PartDefinition *other) const = 0; + MEDCOUPLING_EXPORT virtual void checkCoherency() const = 0; + MEDCOUPLING_EXPORT virtual PartDefinition *tryToSimplify() const = 0; protected: virtual ~PartDefinition(); }; @@ -50,6 +53,9 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT int getNumberOfElems() const; MEDCOUPLING_EXPORT PartDefinition *operator+(const PartDefinition& other) const; MEDCOUPLING_EXPORT std::string getRepr() const; + MEDCOUPLING_EXPORT PartDefinition *composeWith(const PartDefinition *other) const; + MEDCOUPLING_EXPORT void checkCoherency() const; + MEDCOUPLING_EXPORT PartDefinition *tryToSimplify() const; private: DataArrayPartDefinition(DataArrayInt *listOfIds); void checkInternalArrayOK() const; @@ -72,6 +78,9 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT int getNumberOfElems() const; MEDCOUPLING_EXPORT PartDefinition *operator+(const PartDefinition& other) const; MEDCOUPLING_EXPORT std::string getRepr() const; + MEDCOUPLING_EXPORT PartDefinition *composeWith(const PartDefinition *other) const; + MEDCOUPLING_EXPORT void checkCoherency() const; + MEDCOUPLING_EXPORT PartDefinition *tryToSimplify() const; //specific method MEDCOUPLING_EXPORT int getEffectiveStop() const; MEDCOUPLING_EXPORT void getSlice(int& start, int& stop, int& step) const; diff --git a/src/MEDCoupling_Swig/MEDCouplingBasicsTest.py b/src/MEDCoupling_Swig/MEDCouplingBasicsTest.py index 08f0fc859..63502a8f1 100644 --- a/src/MEDCoupling_Swig/MEDCouplingBasicsTest.py +++ b/src/MEDCoupling_Swig/MEDCouplingBasicsTest.py @@ -15964,6 +15964,64 @@ class MEDCouplingBasicsTest(unittest.TestCase): self.assertTrue(d.isEqual(DataArrayInt([(49,50),(50,51),(51,52),(52,53),(53,54),(54,55),(55,56),(56,57),(57,58),(58,59),(59,60),(60,61),(61,62),(62,63),(63,64),(64,65),(65,66),(66,67)]))) pass + def testSwig2DAIIsRange(self): + d=DataArrayInt([2,6,10]) + a,b=d.isRange() + self.assertTrue(a) + self.assertEqual(b,slice(2,11,4)) + self.assertTrue(DataArrayInt.Range(b.start,b.stop,b.step).isEqual(d)) + # + d=DataArrayInt([2,7,10]) + a,b=d.isRange() + self.assertTrue(not a) + self.assertTrue(b is None) + # + d=DataArrayInt([22,17,12]) + a,b=d.isRange() + self.assertTrue(a) + self.assertEqual(b,slice(22,11,-5)) + self.assertTrue(DataArrayInt.Range(b.start,b.stop,b.step).isEqual(d)) + # + d=DataArrayInt([22,16,12]) + a,b=d.isRange() + self.assertTrue(not a) + self.assertTrue(b is None) + # + d=DataArrayInt([33]) + a,b=d.isRange() + self.assertTrue(a) + self.assertEqual(b,slice(33,34,1)) + self.assertTrue(DataArrayInt.Range(b.start,b.stop,b.step).isEqual(d)) + # + d=DataArrayInt([]) + a,b=d.isRange() + self.assertTrue(a) + self.assertEqual(b,slice(0,0,1)) + self.assertTrue(DataArrayInt.Range(b.start,b.stop,b.step).isEqual(d)) + # + d=DataArrayInt([2,6,10,2]) + a,b=d.isRange() + self.assertTrue(not a) + self.assertTrue(b is None) + pass + + def testSwig2PartDefinitionComposeWith1(self): + f=PartDefinition.New(DataArrayInt([0,1,2,3,6,7,8,9])) + g=PartDefinition.New(4,14,1) + h=f.composeWith(g) + self.assertTrue(isinstance(h,DataArrayPartDefinition)) + self.assertTrue(h.toDAI().isEqual(DataArrayInt([4,5,6,7,10,11,12,13]))) + f2=f.tryToSimplify() + g2=g.tryToSimplify() + self.assertEqual(f2.getHiddenCppPointer(),f.getHiddenCppPointer())# same because no simplification due to content of array + self.assertEqual(g2.getHiddenCppPointer(),g.getHiddenCppPointer())# same because no simplification linked to type of PartDef + p=PartDefinition.New(DataArrayInt([2,6,10])) + p2=p.tryToSimplify() + self.assertNotEqual(p2.getHiddenCppPointer(),p.getHiddenCppPointer()) + self.assertTrue(isinstance(p2,SlicePartDefinition)) + self.assertEqual(p2.getSlice(),slice(2,11,4)) + pass + pass if __name__ == '__main__': diff --git a/src/MEDCoupling_Swig/MEDCouplingCommon.i b/src/MEDCoupling_Swig/MEDCouplingCommon.i index 86dbd41ac..b78056bfb 100644 --- a/src/MEDCoupling_Swig/MEDCouplingCommon.i +++ b/src/MEDCoupling_Swig/MEDCouplingCommon.i @@ -390,6 +390,8 @@ using namespace INTERP_KERNEL; %newobject ParaMEDMEM::PartDefinition::New; %newobject ParaMEDMEM::PartDefinition::toDAI; %newobject ParaMEDMEM::PartDefinition::__add__; +%newobject ParaMEDMEM::PartDefinition::composeWith; +%newobject ParaMEDMEM::PartDefinition::tryToSimplify; %newobject ParaMEDMEM::DataArrayPartDefinition::New; %newobject ParaMEDMEM::SlicePartDefinition::New; @@ -5417,6 +5419,9 @@ namespace ParaMEDMEM virtual DataArrayInt *toDAI() const throw(INTERP_KERNEL::Exception); virtual int getNumberOfElems() const throw(INTERP_KERNEL::Exception); virtual std::string getRepr() const throw(INTERP_KERNEL::Exception); + virtual PartDefinition *composeWith(const PartDefinition *other) const throw(INTERP_KERNEL::Exception); + virtual void checkCoherency() const throw(INTERP_KERNEL::Exception); + virtual PartDefinition *tryToSimplify() const throw(INTERP_KERNEL::Exception); %extend { virtual PartDefinition *__add__(const PartDefinition& other) const throw(INTERP_KERNEL::Exception) diff --git a/src/MEDCoupling_Swig/MEDCouplingMemArray.i b/src/MEDCoupling_Swig/MEDCouplingMemArray.i index 705d80db2..911cb7a39 100644 --- a/src/MEDCoupling_Swig/MEDCouplingMemArray.i +++ b/src/MEDCoupling_Swig/MEDCouplingMemArray.i @@ -4444,6 +4444,25 @@ namespace ParaMEDMEM PyTuple_SetItem(pyRet,1,SWIG_NewPointerObj(SWIG_as_voidptr(ret1),SWIGTYPE_p_ParaMEDMEM__DataArrayInt, SWIG_POINTER_OWN | 0 )); return pyRet; } + + PyObject *isRange() const throw(INTERP_KERNEL::Exception) + { + int a(0),b(0),c(0); + bool ret(self->isRange(a,b,c)); + PyObject *pyRet=PyTuple_New(2); + PyObject *ret0Py=ret?Py_True:Py_False,*ret1Py(0); + Py_XINCREF(ret0Py); + PyTuple_SetItem(pyRet,0,ret0Py); + if(ret) + ret1Py=PySlice_New(PyInt_FromLong(a),PyInt_FromLong(b),PyInt_FromLong(c)); + else + { + ret1Py=Py_None; + Py_XINCREF(ret1Py); + } + PyTuple_SetItem(pyRet,1,ret1Py); + return pyRet; + } } };