Salome HOME
Addition of tools for combination of part definition for // manip.
authorAnthony Geay <anthony.geay@edf.fr>
Fri, 21 Nov 2014 15:57:43 +0000 (16:57 +0100)
committerAnthony Geay <anthony.geay@edf.fr>
Fri, 21 Nov 2014 15:57:43 +0000 (16:57 +0100)
src/MEDCoupling/MEDCouplingMemArray.cxx
src/MEDCoupling/MEDCouplingMemArray.hxx
src/MEDCoupling/MEDCouplingPartDefinition.cxx
src/MEDCoupling/MEDCouplingPartDefinition.hxx
src/MEDCoupling_Swig/MEDCouplingBasicsTest.py
src/MEDCoupling_Swig/MEDCouplingCommon.i
src/MEDCoupling_Swig/MEDCouplingMemArray.i

index 685de65decd662bd4d9c853d0edc786345ca5f67..d3f460529a0a2edb09ea81fa3377fd89b5b2c3c6 100644 (file)
@@ -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<nbTuples;i++,tmp+=stteepp)
+        if(pt[i]!=tmp)
+          return false;
+      return true;
     }
+  else
+    {
+      sttoopp--;
+      int a(strt-sttoopp-1),tmp(strt);
+      if(a%(nbTuples-1)!=0)
+        return false;
+      stteepp=-(a/(nbTuples-1));
+      for(int i=0;i<nbTuples;i++,tmp+=stteepp)
+        if(pt[i]!=tmp)
+          return false;
+      return true;
+    }
+}
 
 /*!
  * Creates a one-dimensional DataArrayInt (\a res) whose contents are computed from 
index 5b65d09a3caf60a2e5020927c0d0d96f293f0c08..8c25de2fb6e94cf3c859a79924322ff7aab17c0a 100644 (file)
@@ -479,6 +479,7 @@ namespace ParaMEDMEM
     MEDCOUPLING_EXPORT DataArrayInt *transformWithIndArrR(const int *indArrBg, const int *indArrEnd) const;
     MEDCOUPLING_EXPORT void splitByValueRange(const int *arrBg, const int *arrEnd,
                                               DataArrayInt *& castArr, DataArrayInt *& rankInsideCast, DataArrayInt *& castsPresent) const;
+    MEDCOUPLING_EXPORT bool isRange(int& strt, int& sttoopp, int& stteepp) const;
     MEDCOUPLING_EXPORT DataArrayInt *invertArrayO2N2N2O(int newNbOfElem) const;
     MEDCOUPLING_EXPORT DataArrayInt *invertArrayN2O2O2N(int oldNbOfElem) const;
     MEDCOUPLING_EXPORT DataArrayInt *invertArrayO2N2N2OBis(int newNbOfElem) const;
index 4ff6ad4a0618b6252cb07135e72d02b695059dbf..4af214cc01f98000e446f219cf00504c8ac63c4c 100644 (file)
@@ -72,6 +72,61 @@ std::string DataArrayPartDefinition::getRepr() const
   return oss.str();
 }
 
+/*!
+ * This method operates FoG where F is \a this and G is \a other.
+ * Example : if \a other is SlicePart(4,14,1) and if \a this is DataArrayPartDefinition([0,1,2,3,6,7,8,9]) -> 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<const SlicePartDefinition *>(other));
+  if(spd)
+    {//special case for optim
+      int a(0),b(0),c(0);
+      spd->getSlice(a,b,c);
+      if(c==1)
+        {
+          MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr(DataArrayInt::New());
+          arr->alloc(_arr->getNumberOfTuples(),1);
+          std::transform(_arr->begin(),_arr->end(),arr->getPointer(),std::bind2nd(std::plus<int>(),a));
+          return DataArrayPartDefinition::New(arr);
+        }
+    }
+  //
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr1(other->toDAI());
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> 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<DataArrayPartDefinition *>(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<DataArrayInt> arr(other->toDAI());
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> 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<SlicePartDefinition *>(this));
+  ret->incrRef();
+  return ret;
+}
+
 std::string SlicePartDefinition::getRepr() const
 {
   std::ostringstream oss;
index d30868f0b6c93415c32afc8b9e232c76272c0e5a..95456d6b3dc12049f7c445d1a7935c6ded237ecb 100644 (file)
@@ -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;
index 08f0fc859aee0cec873da1de1f9d2968369a46cf..63502a8f10ec2ed300248b64241319b4d4b72efa 100644 (file)
@@ -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__':
index 86dbd41ac15028fbea034af4175f2557bb235e5c..b78056bfb231b87ddf145d4a5f946c0b1dcee346 100644 (file)
@@ -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)
index 705d80db2fb8bc8a609b7899bf1fa1d300b24bc9..911cb7a39a666c74833891b9b993b26057ba5b3a 100644 (file)
@@ -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;
+      }
     }
   };