From c3254a26b8081f9192f97143170546821e03b351 Mon Sep 17 00:00:00 2001 From: ageay Date: Thu, 25 Jul 2013 15:19:10 +0000 Subject: [PATCH] DataArrayInt.FindPermutationFromFirstToSecond --- src/MEDCoupling/MEDCouplingMemArray.cxx | 38 +++++++++++++++++++ src/MEDCoupling/MEDCouplingMemArray.hxx | 1 + src/MEDCoupling_Swig/MEDCouplingBasicsTest.py | 13 +++++++ src/MEDCoupling_Swig/MEDCouplingCommon.i | 1 + src/MEDCoupling_Swig/MEDCouplingMemArray.i | 1 + 5 files changed, 54 insertions(+) diff --git a/src/MEDCoupling/MEDCouplingMemArray.cxx b/src/MEDCoupling/MEDCouplingMemArray.cxx index 82082779f..eb91aa22c 100644 --- a/src/MEDCoupling/MEDCouplingMemArray.cxx +++ b/src/MEDCoupling/MEDCouplingMemArray.cxx @@ -6853,6 +6853,44 @@ DataArrayInt *DataArrayInt::checkAndPreparePermutation() const throw(INTERP_KERN return ret; } +/*! + * This method tries to find the permutation to apply to the first input \a ids1 to obtain the same array (without considering strings informations) the second + * input array \a ids2. + * \a ids1 and \a ids2 are expected to be both a list of ids (both with number of components equal to one) not sorted and with values that can be negative. + * This method will throw an exception is no such permutation array can be obtained. It is typically the case if there is some ids in \a ids1 not in \a ids2 or + * inversely. + * In case of success (no throw) : \c ids1->renumber(ret)->isEqual(ids2) where \a ret is the return of this method. + * + * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this + * array using decrRef() as it is no more needed. + * \throw If either ids1 or ids2 is null not allocated or not with one components. + * + */ +DataArrayInt *DataArrayInt::FindPermutationFromFirstToSecond(const DataArrayInt *ids1, const DataArrayInt *ids2) throw(INTERP_KERNEL::Exception) +{ + if(!ids1 || !ids2) + throw INTERP_KERNEL::Exception("DataArrayInt::FindPermutationFromFirstToSecond : the two input arrays must be not null !"); + if(!ids1->isAllocated() || !ids2->isAllocated()) + throw INTERP_KERNEL::Exception("DataArrayInt::FindPermutationFromFirstToSecond : the two input arrays must be allocated !"); + if(ids1->getNumberOfComponents()!=1 || ids2->getNumberOfComponents()!=1) + throw INTERP_KERNEL::Exception("DataArrayInt::FindPermutationFromFirstToSecond : the two input arrays have exactly one component !"); + if(ids1->getNumberOfTuples()!=ids2->getNumberOfTuples()) + { + std::ostringstream oss; oss << "DataArrayInt::FindPermutationFromFirstToSecond : first array has " << ids1->getNumberOfTuples() << " tuples and the second one " << ids2->getNumberOfTuples() << " tuples ! No chance to find a permutation between the 2 arrays !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + MEDCouplingAutoRefCountObjectPtr p1(ids1->deepCpy()); + MEDCouplingAutoRefCountObjectPtr p2(ids2->deepCpy()); + p1->sort(true); p2->sort(true); + if(!p1->isEqualWithoutConsideringStr(*p2)) + throw INTERP_KERNEL::Exception("DataArrayInt::FindPermutationFromFirstToSecond : the two arrays are not lying on same ids ! Impossible to find a permutation betwenn the 2 arrays !"); + p1=ids1->checkAndPreparePermutation(); + p2=ids2->checkAndPreparePermutation(); + p2=p2->invertArrayO2N2N2O(p2->getNumberOfTuples()); + p2=p2->selectByTupleIdSafe(p1->begin(),p1->end()); + return p2.retn(); +} + /*! * Returns two arrays describing a surjective mapping from \a this set of values (\a A) * onto a set of values of size \a targetNb (\a B). The surjective function is diff --git a/src/MEDCoupling/MEDCouplingMemArray.hxx b/src/MEDCoupling/MEDCouplingMemArray.hxx index 9ef0b37de..44b83de9a 100644 --- a/src/MEDCoupling/MEDCouplingMemArray.hxx +++ b/src/MEDCoupling/MEDCouplingMemArray.hxx @@ -484,6 +484,7 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT DataArrayInt *selectByTupleId2(int bg, int end, int step) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT DataArray *selectByTupleRanges(const std::vector >& ranges) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT DataArrayInt *checkAndPreparePermutation() const throw(INTERP_KERNEL::Exception); + MEDCOUPLING_EXPORT static DataArrayInt *FindPermutationFromFirstToSecond(const DataArrayInt *ids1, const DataArrayInt *ids2) throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT void changeSurjectiveFormat(int targetNb, DataArrayInt *&arr, DataArrayInt *&arrI) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT static DataArrayInt *BuildOld2NewArrayFromSurjectiveFormat2(int nbOfOldTuples, const int *arr, const int *arrIBg, const int *arrIEnd, int &newNbOfTuples) throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT DataArrayInt *buildPermArrPerLevel() const throw(INTERP_KERNEL::Exception); diff --git a/src/MEDCoupling_Swig/MEDCouplingBasicsTest.py b/src/MEDCoupling_Swig/MEDCouplingBasicsTest.py index 7bd55b9a2..21137adab 100644 --- a/src/MEDCoupling_Swig/MEDCouplingBasicsTest.py +++ b/src/MEDCoupling_Swig/MEDCouplingBasicsTest.py @@ -13471,6 +13471,19 @@ class MEDCouplingBasicsTest(unittest.TestCase): self.assertTrue(a.buildUnstructured().isEqual(c2.buildUnstructured().buildPartAndReduceNodes(d20)[0],1e-12)) pass + def testSwig2FindPermutationFromFirstToSecond1(self): + ids1=DataArrayInt([3,1,103,4,6,10,-7,205]) + ids2=DataArrayInt([-7,1,205,10,6,3,103,4]) + ids3=DataArrayInt.FindPermutationFromFirstToSecond(ids1,ids2) + self.assertTrue(ids3.isEqual(DataArrayInt([5,1,6,7,4,3,0,2]))) + ids2ToTest=ids1.renumber(ids3) + self.assertTrue(ids2ToTest.isEqual(ids2)) + self.assertRaises(InterpKernelException,DataArrayInt.FindPermutationFromFirstToSecond,DataArrayInt([3,1,103]),DataArrayInt([1,103])) + self.assertRaises(InterpKernelException,DataArrayInt.FindPermutationFromFirstToSecond,DataArrayInt([3,1,103]),DataArrayInt([1,103,2])) + self.assertRaises(InterpKernelException,DataArrayInt.FindPermutationFromFirstToSecond,DataArrayInt([3,1,103]),DataArrayInt([1,103,1])) + self.assertTrue(DataArrayInt.FindPermutationFromFirstToSecond(DataArrayInt([]),DataArrayInt([])).empty()) + pass + def setUp(self): pass pass diff --git a/src/MEDCoupling_Swig/MEDCouplingCommon.i b/src/MEDCoupling_Swig/MEDCouplingCommon.i index 144defc4a..49c9c1695 100644 --- a/src/MEDCoupling_Swig/MEDCouplingCommon.i +++ b/src/MEDCoupling_Swig/MEDCouplingCommon.i @@ -275,6 +275,7 @@ using namespace INTERP_KERNEL; %newobject ParaMEDMEM::DataArrayInt::buildPermutationArr; %newobject ParaMEDMEM::DataArrayInt::buildPermArrPerLevel; %newobject ParaMEDMEM::DataArrayInt::getDifferentValues; +%newobject ParaMEDMEM::DataArrayInt::FindPermutationFromFirstToSecond; %newobject ParaMEDMEM::DataArrayInt::__neg__; %newobject ParaMEDMEM::DataArrayInt::__add__; %newobject ParaMEDMEM::DataArrayInt::__radd__; diff --git a/src/MEDCoupling_Swig/MEDCouplingMemArray.i b/src/MEDCoupling_Swig/MEDCouplingMemArray.i index f2837c8da..aabcd6a1b 100644 --- a/src/MEDCoupling_Swig/MEDCouplingMemArray.i +++ b/src/MEDCoupling_Swig/MEDCouplingMemArray.i @@ -2381,6 +2381,7 @@ namespace ParaMEDMEM static DataArrayInt *MakePartition(const std::vector& groups, int newNb, std::vector< std::vector >& fidsOfGroups) throw(INTERP_KERNEL::Exception); static DataArrayInt *BuildUnion(const std::vector& arr) throw(INTERP_KERNEL::Exception); static DataArrayInt *BuildIntersection(const std::vector& arr) throw(INTERP_KERNEL::Exception); + static DataArrayInt *FindPermutationFromFirstToSecond(const DataArrayInt *ids1, const DataArrayInt *ids2) throw(INTERP_KERNEL::Exception); DataArrayInt *buildComplement(int nbOfElement) const throw(INTERP_KERNEL::Exception); DataArrayInt *buildSubstraction(const DataArrayInt *other) const throw(INTERP_KERNEL::Exception); DataArrayInt *buildSubstractionOptimized(const DataArrayInt *other) const throw(INTERP_KERNEL::Exception); -- 2.39.2