From ace35991d7eb227e517fd62de772d798730bb658 Mon Sep 17 00:00:00 2001 From: ageay Date: Mon, 23 Apr 2012 14:52:31 +0000 Subject: [PATCH] Some new functionnalities with arrays in python. --- src/MEDCoupling/MEDCouplingMemArray.cxx | 98 ++++++-- src/MEDCoupling_Swig/MEDCoupling.i | 226 ++++++++++++++---- src/MEDCoupling_Swig/MEDCouplingBasicsTest.py | 46 +++- src/MEDCoupling_Swig/MEDCouplingTypemaps.i | 34 ++- 4 files changed, 337 insertions(+), 67 deletions(-) diff --git a/src/MEDCoupling/MEDCouplingMemArray.cxx b/src/MEDCoupling/MEDCouplingMemArray.cxx index 65520c5a9..63d64bcab 100644 --- a/src/MEDCoupling/MEDCouplingMemArray.cxx +++ b/src/MEDCoupling/MEDCouplingMemArray.cxx @@ -2331,13 +2331,48 @@ DataArrayDouble *DataArrayDouble::Min(const DataArrayDouble *a1, const DataArray DataArrayDouble *DataArrayDouble::Add(const DataArrayDouble *a1, const DataArrayDouble *a2) throw(INTERP_KERNEL::Exception) { - int nbOfTuple=a2->getNumberOfTuples(); - int nbOfComp=a2->getNumberOfComponents(); - a1->checkNbOfTuplesAndComp(nbOfTuple,nbOfComp,"Nb of components mismatch for array Add !"); - DataArrayDouble *ret=DataArrayDouble::New(); - ret->alloc(nbOfTuple,nbOfComp); - std::transform(a1->begin(),a1->end(),a2->begin(),ret->getPointer(),std::plus()); - ret->copyStringInfoFrom(*a1); + int nbOfTuple=a1->getNumberOfTuples(); + int nbOfTuple2=a2->getNumberOfTuples(); + int nbOfComp=a1->getNumberOfComponents(); + int nbOfComp2=a2->getNumberOfComponents(); + if(nbOfTuple!=nbOfTuple2) + throw INTERP_KERNEL::Exception("Nb of tuples mismatch for array Add !"); + DataArrayDouble *ret=0; + if(nbOfComp==nbOfComp2) + { + ret=DataArrayDouble::New(); + ret->alloc(nbOfTuple,nbOfComp); + std::transform(a1->begin(),a1->end(),a2->begin(),ret->getPointer(),std::plus()); + ret->copyStringInfoFrom(*a1); + } + else + { + int nbOfCompMin,nbOfCompMax; + const DataArrayDouble *aMin, *aMax; + if(nbOfComp>nbOfComp2) + { + nbOfCompMin=nbOfComp2; nbOfCompMax=nbOfComp; + aMin=a2; aMax=a1; + } + else + { + nbOfCompMin=nbOfComp; nbOfCompMax=nbOfComp2; + aMin=a1; aMax=a2; + } + if(nbOfCompMin==1) + { + ret=DataArrayDouble::New(); + ret->alloc(nbOfTuple,nbOfCompMax); + const double *aMinPtr=aMin->getConstPointer(); + const double *aMaxPtr=aMax->getConstPointer(); + double *res=ret->getPointer(); + for(int i=0;i(),aMinPtr[i])); + ret->copyStringInfoFrom(*aMax); + } + else + throw INTERP_KERNEL::Exception("Nb of components mismatch for array Add !"); + } return ret; } @@ -4775,13 +4810,48 @@ std::set DataArrayInt::getDifferentValues() const throw(INTERP_KERNEL::Exce DataArrayInt *DataArrayInt::Add(const DataArrayInt *a1, const DataArrayInt *a2) throw(INTERP_KERNEL::Exception) { - int nbOfTuple=a2->getNumberOfTuples(); - int nbOfComp=a2->getNumberOfComponents(); - a1->checkNbOfTuplesAndComp(nbOfTuple,nbOfComp,"Nb of components mismatch for array Add !"); - DataArrayInt *ret=DataArrayInt::New(); - ret->alloc(nbOfTuple,nbOfComp); - std::transform(a1->begin(),a1->end(),a2->begin(),ret->getPointer(),std::plus()); - ret->copyStringInfoFrom(*a1); + int nbOfTuple=a1->getNumberOfTuples(); + int nbOfTuple2=a2->getNumberOfTuples(); + int nbOfComp=a1->getNumberOfComponents(); + int nbOfComp2=a2->getNumberOfComponents(); + if(nbOfTuple!=nbOfTuple2) + throw INTERP_KERNEL::Exception("Nb of tuples mismatch for array Add !"); + DataArrayInt *ret=0; + if(nbOfComp==nbOfComp2) + { + ret=DataArrayInt::New(); + ret->alloc(nbOfTuple,nbOfComp); + std::transform(a1->begin(),a1->end(),a2->begin(),ret->getPointer(),std::plus()); + ret->copyStringInfoFrom(*a1); + } + else + { + int nbOfCompMin,nbOfCompMax; + const DataArrayInt *aMin, *aMax; + if(nbOfComp>nbOfComp2) + { + nbOfCompMin=nbOfComp2; nbOfCompMax=nbOfComp; + aMin=a2; aMax=a1; + } + else + { + nbOfCompMin=nbOfComp; nbOfCompMax=nbOfComp2; + aMin=a1; aMax=a2; + } + if(nbOfCompMin==1) + { + ret=DataArrayInt::New(); + ret->alloc(nbOfTuple,nbOfCompMax); + const int *aMinPtr=aMin->getConstPointer(); + const int *aMaxPtr=aMax->getConstPointer(); + int *res=ret->getPointer(); + for(int i=0;i(),aMinPtr[i])); + ret->copyStringInfoFrom(*aMax); + } + else + throw INTERP_KERNEL::Exception("Nb of components mismatch for array Add !"); + } return ret; } diff --git a/src/MEDCoupling_Swig/MEDCoupling.i b/src/MEDCoupling_Swig/MEDCoupling.i index ae0e4349c..21b52859e 100644 --- a/src/MEDCoupling_Swig/MEDCoupling.i +++ b/src/MEDCoupling_Swig/MEDCoupling.i @@ -1899,32 +1899,101 @@ namespace ParaMEDMEM %extend ParaMEDMEM::DataArrayDouble { - static DataArrayDouble *New(int nbOfTuples, int nbOfComp) throw(INTERP_KERNEL::Exception) + static DataArrayDouble *New(PyObject *elt0, PyObject *elt1=0, PyObject *elt2=0) throw(INTERP_KERNEL::Exception) { - MEDCouplingAutoRefCountObjectPtr ret=DataArrayDouble::New(); - ret->alloc(nbOfTuples,nbOfComp); - ret->incrRef(); - return ret; - } - - static DataArrayDouble *New(PyObject *li, int nbOfTuples, int nbOfComp) throw(INTERP_KERNEL::Exception) - { - if(nbOfTuples<0 || nbOfComp<0) - throw INTERP_KERNEL::Exception("DataArrayDouble::New(PyList,nbOfTuples,nbOfComponents) : should be a positive set of allocated memory !"); - MEDCouplingAutoRefCountObjectPtr ret=DataArrayDouble::New(); - double *tmp=new double[nbOfTuples*nbOfComp]; - try + const char *msg="ParaMEDMEM::DataArrayDouble::New : Available API are : \n-DataArrayDouble.New()\n--DataArrayDouble.New([1.,3.,4.])\n-DataArrayDouble.New([1.,3.,4.],3)\n-DataArrayDouble.New([1.,3.,4.,5.],2,2)\n-DataArrayDouble.New(5)\n-DataArrayDouble.New(5,2) !"; + if(PyList_Check(elt0) || PyTuple_Check(elt0)) { - fillArrayWithPyListDbl(li,tmp,nbOfTuples*nbOfComp,0.); + if(elt1) + { + if(PyInt_Check(elt1)) + { + int nbOfTuples=PyInt_AS_LONG(elt1); + if(nbOfTuples<0) + throw INTERP_KERNEL::Exception("DataArrayDouble::New : should be a positive set of allocated memory !"); + if(elt2) + { + if(PyInt_Check(elt2)) + {//DataArrayDouble.New([1.,3.,4.,5.],2,2) + int nbOfCompo=PyInt_AS_LONG(elt2); + if(nbOfCompo<0) + throw INTERP_KERNEL::Exception("DataArrayDouble::New : should be a positive number of components !"); + MEDCouplingAutoRefCountObjectPtr ret=DataArrayDouble::New(); + double *tmp=new double[nbOfTuples*nbOfCompo]; + try { fillArrayWithPyListDbl(elt0,tmp,nbOfTuples*nbOfCompo,0.,true); } + catch(INTERP_KERNEL::Exception& e) { delete [] tmp; throw e; } + ret->useArray(tmp,true,CPP_DEALLOC,nbOfTuples,nbOfCompo); + ret->incrRef(); + return ret; + } + else + throw INTERP_KERNEL::Exception(msg); + } + else + {//DataArrayDouble.New([1.,3.,4.],3) + MEDCouplingAutoRefCountObjectPtr ret=DataArrayDouble::New(); + double *tmp=new double[nbOfTuples]; + try { fillArrayWithPyListDbl(elt0,tmp,nbOfTuples,0.,true); } + catch(INTERP_KERNEL::Exception& e) { delete [] tmp; throw e; } + ret->useArray(tmp,true,CPP_DEALLOC,nbOfTuples,1); + ret->incrRef(); + return ret; + } + } + else + throw INTERP_KERNEL::Exception(msg); + } + else + {// DataArrayDouble.New([1.,3.,4.]) + int szz=-1; + if(PyList_Check(elt0)) + szz=PyList_Size(elt0); + else + szz=PyTuple_Size(elt0); + MEDCouplingAutoRefCountObjectPtr ret=DataArrayDouble::New(); + double *tmp=new double[szz]; + try { fillArrayWithPyListDbl(elt0,tmp,szz,0.,true); } + catch(INTERP_KERNEL::Exception& e) { delete [] tmp; throw e; } + ret->useArray(tmp,true,CPP_DEALLOC,szz,1); + ret->incrRef(); + return ret; + } } - catch(INTERP_KERNEL::Exception& e) + else if(PyInt_Check(elt0)) { - delete [] tmp; - throw e; + int nbOfTuples=PyInt_AS_LONG(elt0); + if(nbOfTuples<0) + throw INTERP_KERNEL::Exception("DataArrayDouble::New : should be a positive set of allocated memory !"); + if(elt1) + { + if(!elt2) + { + if(PyInt_Check(elt1)) + {//DataArrayDouble.New(5,2) + int nbOfCompo=PyInt_AS_LONG(elt1); + if(nbOfCompo<0) + throw INTERP_KERNEL::Exception("DataArrayDouble::New : should be a positive number of components !"); + MEDCouplingAutoRefCountObjectPtr ret=DataArrayDouble::New(); + ret->alloc(nbOfTuples,nbOfCompo); + ret->incrRef(); + return ret; + } + else + throw INTERP_KERNEL::Exception(msg); + } + else + throw INTERP_KERNEL::Exception(msg); + } + else + {//DataArrayDouble.New(5) + MEDCouplingAutoRefCountObjectPtr ret=DataArrayDouble::New(); + ret->alloc(nbOfTuples,1); + ret->incrRef(); + return ret; + } } - ret->useArray(tmp,true,CPP_DEALLOC,nbOfTuples,nbOfComp); - ret->incrRef(); - return ret; + else + throw INTERP_KERNEL::Exception(msg); } std::string __str__() const @@ -1959,7 +2028,7 @@ namespace ParaMEDMEM double *tmp=new double[nbOfTuples*nbOfElsPerTuple]; try { - fillArrayWithPyListDbl(li,tmp,nbOfTuples*nbOfElsPerTuple,0.); + fillArrayWithPyListDbl(li,tmp,nbOfTuples*nbOfElsPerTuple,0.,false); } catch(INTERP_KERNEL::Exception& e) { @@ -3424,32 +3493,101 @@ namespace ParaMEDMEM %extend ParaMEDMEM::DataArrayInt { - static DataArrayInt *New(int nbOfTuples, int nbOfComp) throw(INTERP_KERNEL::Exception) + static DataArrayInt *New(PyObject *elt0, PyObject *elt1=0, PyObject *elt2=0) throw(INTERP_KERNEL::Exception) { - MEDCouplingAutoRefCountObjectPtr ret=DataArrayInt::New(); - ret->alloc(nbOfTuples,nbOfComp); - ret->incrRef(); - return ret; - } - - static DataArrayInt *New(PyObject *li, int nbOfTuples, int nbOfComp) throw(INTERP_KERNEL::Exception) - { - if(nbOfTuples<0 || nbOfComp<0) - throw INTERP_KERNEL::Exception("DataArrayDouble::New(PyList,nbOfTuples,nbOfComponents) : should be a positive set of allocated memory !"); - MEDCouplingAutoRefCountObjectPtr ret=DataArrayInt::New(); - int *tmp=new int[nbOfTuples*nbOfComp]; - try + const char *msg="ParaMEDMEM::DataArrayInt::New : Available API are : \n-DataArrayInt.New()\n--DataArrayInt.New([1,3,4])\n-DataArrayInt.New([1,3,4],3)\n-DataArrayInt.New([1,3,4,5],2,2)\n-DataArrayInt.New(5)\n-DataArrayInt.New(5,2) !"; + if(PyList_Check(elt0) || PyTuple_Check(elt0)) { - fillArrayWithPyListInt(li,tmp,nbOfTuples*nbOfComp,0); + if(elt1) + { + if(PyInt_Check(elt1)) + { + int nbOfTuples=PyInt_AS_LONG(elt1); + if(nbOfTuples<0) + throw INTERP_KERNEL::Exception("DataArrayInt::New : should be a positive set of allocated memory !"); + if(elt2) + { + if(PyInt_Check(elt2)) + {//DataArrayInt.New([1,3,4,5],2,2) + int nbOfCompo=PyInt_AS_LONG(elt2); + if(nbOfCompo<0) + throw INTERP_KERNEL::Exception("DataArrayInt::New : should be a positive number of components !"); + MEDCouplingAutoRefCountObjectPtr ret=DataArrayInt::New(); + int *tmp=new int[nbOfTuples*nbOfCompo]; + try { fillArrayWithPyListInt(elt0,tmp,nbOfTuples*nbOfCompo,0.,true); } + catch(INTERP_KERNEL::Exception& e) { delete [] tmp; throw e; } + ret->useArray(tmp,true,CPP_DEALLOC,nbOfTuples,nbOfCompo); + ret->incrRef(); + return ret; + } + else + throw INTERP_KERNEL::Exception(msg); + } + else + {//DataArrayInt.New([1,3,4],3) + MEDCouplingAutoRefCountObjectPtr ret=DataArrayInt::New(); + int *tmp=new int[nbOfTuples]; + try { fillArrayWithPyListInt(elt0,tmp,nbOfTuples,0.,true); } + catch(INTERP_KERNEL::Exception& e) { delete [] tmp; throw e; } + ret->useArray(tmp,true,CPP_DEALLOC,nbOfTuples,1); + ret->incrRef(); + return ret; + } + } + else + throw INTERP_KERNEL::Exception(msg); + } + else + {// DataArrayInt.New([1,3,4]) + int szz=-1; + if(PyList_Check(elt0)) + szz=PyList_Size(elt0); + else + szz=PyTuple_Size(elt0); + MEDCouplingAutoRefCountObjectPtr ret=DataArrayInt::New(); + int *tmp=new int[szz]; + try { fillArrayWithPyListInt(elt0,tmp,szz,0.,true); } + catch(INTERP_KERNEL::Exception& e) { delete [] tmp; throw e; } + ret->useArray(tmp,true,CPP_DEALLOC,szz,1); + ret->incrRef(); + return ret; + } } - catch(INTERP_KERNEL::Exception& e) + else if(PyInt_Check(elt0)) { - delete [] tmp; - throw e; + int nbOfTuples=PyInt_AS_LONG(elt0); + if(nbOfTuples<0) + throw INTERP_KERNEL::Exception("DataArrayInt::New : should be a positive set of allocated memory !"); + if(elt1) + { + if(!elt2) + { + if(PyInt_Check(elt1)) + {//DataArrayInt.New(5,2) + int nbOfCompo=PyInt_AS_LONG(elt1); + if(nbOfCompo<0) + throw INTERP_KERNEL::Exception("DataArrayInt::New : should be a positive number of components !"); + MEDCouplingAutoRefCountObjectPtr ret=DataArrayInt::New(); + ret->alloc(nbOfTuples,nbOfCompo); + ret->incrRef(); + return ret; + } + else + throw INTERP_KERNEL::Exception(msg); + } + else + throw INTERP_KERNEL::Exception(msg); + } + else + {//DataArrayInt.New(5) + MEDCouplingAutoRefCountObjectPtr ret=DataArrayInt::New(); + ret->alloc(nbOfTuples,1); + ret->incrRef(); + return ret; + } } - ret->useArray(tmp,true,CPP_DEALLOC,nbOfTuples,nbOfComp); - ret->incrRef(); - return ret; + else + throw INTERP_KERNEL::Exception(msg); } std::string __str__() const @@ -3500,7 +3638,7 @@ namespace ParaMEDMEM int *tmp=new int[nbOfTuples*nbOfElsPerTuple]; try { - fillArrayWithPyListInt(li,tmp,nbOfTuples*nbOfElsPerTuple,0); + fillArrayWithPyListInt(li,tmp,nbOfTuples*nbOfElsPerTuple,0,false); } catch(INTERP_KERNEL::Exception& e) { diff --git a/src/MEDCoupling_Swig/MEDCouplingBasicsTest.py b/src/MEDCoupling_Swig/MEDCouplingBasicsTest.py index 6e68917bd..161e49cde 100644 --- a/src/MEDCoupling_Swig/MEDCouplingBasicsTest.py +++ b/src/MEDCoupling_Swig/MEDCouplingBasicsTest.py @@ -8525,7 +8525,7 @@ class MEDCouplingBasicsTest(unittest.TestCase): for i in xrange(6): self.assertEqual(arr[5-i],a.getIJ(i,0)); pass - a.setValues(arr,5,1); + a.setValues(arr[:-1],5,1); a.reverse(); for i in xrange(5): self.assertEqual(arr[4-i],a.getIJ(i,0)); @@ -9506,7 +9506,7 @@ class MEDCouplingBasicsTest(unittest.TestCase): self.assertEqual(da.getIJ(0,i),expected1[i]) pass da=-dabis - da/=[2,3] + da/=DataArrayInt.New([2,3],1,2) self.assertEqual(12,da.getNumberOfTuples()); self.assertEqual(2,da.getNumberOfComponents()); expected2=[3,2,4,3,5,3,6,4,7,5,8,5,9,6,10,7,11,7,12,8,13,9,14,9] @@ -9515,6 +9515,48 @@ class MEDCouplingBasicsTest(unittest.TestCase): pass pass + def testSwigDADOp5(self): + da=DataArrayDouble.New([5,6,7,8,9,6,7,-2,3,9,8,10]) + da.rearrange(3) + da2=DataArrayDouble.New([5.,8.,10.,12]) + self.assertEqual(4,da2.getNumberOfTuples()); + self.assertEqual(1,da2.getNumberOfComponents()); + da3=da+da2 + self.assertEqual(4,da3.getNumberOfTuples()); + self.assertEqual(3,da3.getNumberOfComponents()); + expected1=[10.,11.,12.,16.,17.,14.,17.,8.,13.,21.,20.,22.] + for i in xrange(12): + self.assertAlmostEqual(da3.getIJ(0,i),expected1[i],13) + pass + da3=da2+da + self.assertEqual(4,da3.getNumberOfTuples()); + self.assertEqual(3,da3.getNumberOfComponents()); + for i in xrange(12): + self.assertAlmostEqual(da3.getIJ(0,i),expected1[i],13) + pass + pass + + def testSwigDADOp6(self): + da=DataArrayInt.New([5,6,7,8,9,6,7,-2,3,9,8,10]) + da.rearrange(3) + da2=DataArrayInt.New([5,8,10,12]) + self.assertEqual(4,da2.getNumberOfTuples()); + self.assertEqual(1,da2.getNumberOfComponents()); + da3=da+da2 + self.assertEqual(4,da3.getNumberOfTuples()); + self.assertEqual(3,da3.getNumberOfComponents()); + expected1=[10,11,12,16,17,14,17,8,13,21,20,22] + for i in xrange(12): + self.assertEqual(da3.getIJ(0,i),expected1[i]) + pass + da3=da2+da + self.assertEqual(4,da3.getNumberOfTuples()); + self.assertEqual(3,da3.getNumberOfComponents()); + for i in xrange(12): + self.assertEqual(da3.getIJ(0,i),expected1[i]) + pass + pass + def setUp(self): pass pass diff --git a/src/MEDCoupling_Swig/MEDCouplingTypemaps.i b/src/MEDCoupling_Swig/MEDCouplingTypemaps.i index 607eded72..ccd64ca86 100644 --- a/src/MEDCoupling_Swig/MEDCouplingTypemaps.i +++ b/src/MEDCoupling_Swig/MEDCouplingTypemaps.i @@ -297,11 +297,17 @@ static void convertPyToNewIntArr3(PyObject *pyLi, std::vector& arr) throw(I } } -static void fillArrayWithPyListInt(PyObject *pyLi, int *arrToFill, int sizeOfArray, int dftVal) throw(INTERP_KERNEL::Exception) +static void fillArrayWithPyListInt(PyObject *pyLi, int *arrToFill, int sizeOfArray, int dftVal, bool chckSize) throw(INTERP_KERNEL::Exception) { if(PyList_Check(pyLi)) { int size=PyList_Size(pyLi); + if(chckSize) + if(size!=sizeOfArray) + { + std::ostringstream oss; oss << "fillArrayWithPyListInt : List expected to be of size " << sizeOfArray << " but the size is " << size << " !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } for(int i=0;i