]> SALOME platform Git repositories - tools/medcoupling.git/commitdiff
Salome HOME
pow on DataArrayDouble
authorageay <ageay>
Tue, 26 Mar 2013 09:58:50 +0000 (09:58 +0000)
committerageay <ageay>
Tue, 26 Mar 2013 09:58:50 +0000 (09:58 +0000)
src/MEDCoupling/MEDCouplingMemArray.cxx
src/MEDCoupling/MEDCouplingMemArray.hxx
src/MEDCoupling_Swig/MEDCoupling.i
src/MEDCoupling_Swig/MEDCouplingBasicsTest.py
src/MEDCoupling_Swig/MEDCouplingCommon.i
src/MEDCoupling_Swig/MEDCouplingFinalize.i

index d2a322a0d538710ea830975f4767b292afbea62b..81cdfe77c22810a1fb0ba02968c7ee14783ae848 100644 (file)
@@ -3619,6 +3619,66 @@ DataArrayDouble *DataArrayDouble::negate() const throw(INTERP_KERNEL::Exception)
   return newArr;
 }
 
+/*!
+ * Modify all elements of \a this array, so that
+ * an element _x_ becomes <em> val ^ x </em>. Contrary to DataArrayInt::applyPow
+ * all values in \a this have to be >= 0 if val is \b not integer.
+ *  \param [in] val - the value used to apply pow on all array elements.
+ *  \throw If \a this is not allocated.
+ *  \warning If an exception is thrown because of presence of 0 element in \a this 
+ *           array and \a val is \b not integer, all elements processed before detection of the zero element remain
+ *           modified.
+ */
+void DataArrayDouble::applyPow(double val) throw(INTERP_KERNEL::Exception)
+{
+  checkAllocated();
+  double *ptr=getPointer();
+  std::size_t nbOfElems=getNbOfElems();
+  int val2=(int)val;
+  bool isInt=((double)val2)==val;
+  if(!isInt)
+    {
+      for(std::size_t i=0;i<nbOfElems;i++,ptr++)
+        {
+          if(*ptr>=0)
+            *ptr=pow(*ptr,val);
+          else
+            {
+              std::ostringstream oss; oss << "DataArrayDouble::applyPow (double) : At elem # " << i << " value is " << *ptr << " ! must be >=0. !";
+              throw INTERP_KERNEL::Exception(oss.str().c_str());
+            }
+        }
+    }
+  else
+    {
+      for(std::size_t i=0;i<nbOfElems;i++,ptr++)
+        *ptr=pow(*ptr,val2);
+    }
+  declareAsNew();
+}
+
+/*!
+ * Modify all elements of \a this array, so that
+ * an element _x_ becomes \f$ val ^ x \f$.
+ *  \param [in] val - the value used to apply pow on all array elements.
+ *  \throw If \a this is not allocated.
+ *  \throw If \a val < 0.
+ *  \warning If an exception is thrown because of presence of 0 element in \a this 
+ *           array, all elements processed before detection of the zero element remain
+ *           modified.
+ */
+void DataArrayDouble::applyRPow(double val) throw(INTERP_KERNEL::Exception)
+{
+  checkAllocated();
+  if(val<0.)
+    throw INTERP_KERNEL::Exception("DataArrayDouble::applyRPow : the input value has to be >= 0 !");
+  double *ptr=getPointer();
+  std::size_t nbOfElems=getNbOfElems();
+  for(std::size_t i=0;i<nbOfElems;i++,ptr++)
+    *ptr=pow(val,*ptr);
+  declareAsNew();
+}
+
 /*!
  * Returns a new DataArrayDouble created from \a this one by applying \a
  * FunctionToEvaluate to every tuple of \a this array. Textual data is not copied.
@@ -4833,6 +4893,86 @@ void DataArrayDouble::divideEqual(const DataArrayDouble *other) throw(INTERP_KER
   declareAsNew();
 }
 
+/*!
+ * Returns a new DataArrayDouble that is the result of pow of two given arrays. There are 3
+ * valid cases.
+ *
+ *  \param [in] a1 - an array to pow up.
+ *  \param [in] a2 - another array to sum up.
+ *  \return DataArrayDouble * - the new instance of DataArrayDouble.
+ *          The caller is to delete this result array using decrRef() as it is no more
+ *          needed.
+ *  \throw If either \a a1 or \a a2 is NULL.
+ *  \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples()
+ *  \throw If \a a1->getNumberOfComponents() != 1 or \a a2->getNumberOfComponents() != 1.
+ *  \throw If there is a negative value in \a a1.
+ */
+DataArrayDouble *DataArrayDouble::Pow(const DataArrayDouble *a1, const DataArrayDouble *a2) throw(INTERP_KERNEL::Exception)
+{
+  if(!a1 || !a2)
+    throw INTERP_KERNEL::Exception("DataArrayDouble::Pow : at least one of input instances is null !");
+  int nbOfTuple=a1->getNumberOfTuples();
+  int nbOfTuple2=a2->getNumberOfTuples();
+  int nbOfComp=a1->getNumberOfComponents();
+  int nbOfComp2=a2->getNumberOfComponents();
+  if(nbOfTuple!=nbOfTuple2)
+    throw INTERP_KERNEL::Exception("DataArrayDouble::Pow : number of tuples mismatches !");
+  if(nbOfComp!=1 || nbOfComp2!=1)
+    throw INTERP_KERNEL::Exception("DataArrayDouble::Pow : number of components of both arrays must be equal to 1 !");
+  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New(); ret->alloc(nbOfTuple,1);
+  const double *ptr1(a1->begin()),*ptr2(a2->begin());
+  double *ptr=ret->getPointer();
+  for(int i=0;i<nbOfTuple;i++,ptr1++,ptr2++,ptr++)
+    {
+      if(*ptr1>=0)
+        {
+          *ptr=pow(*ptr1,*ptr2);
+        }
+      else
+        {
+          std::ostringstream oss; oss << "DataArrayDouble::Pow : on tuple #" << i << " of a1 value is < 0 (" << *ptr1 << ") !";
+          throw INTERP_KERNEL::Exception(oss.str().c_str());
+        }
+    }
+  return ret.retn();
+}
+
+/*!
+ * Apply pow on values of another DataArrayDouble to values of \a this one.
+ *
+ *  \param [in] other - an array to pow to \a this one.
+ *  \throw If \a other is NULL.
+ *  \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples()
+ *  \throw If \a this->getNumberOfComponents() != 1 or \a other->getNumberOfComponents() != 1
+ *  \throw If there is a negative value in \a this.
+ */
+void DataArrayDouble::powEqual(const DataArrayDouble *other) throw(INTERP_KERNEL::Exception)
+{
+  if(!other)
+    throw INTERP_KERNEL::Exception("DataArrayDouble::powEqual : input instance is null !");
+  int nbOfTuple=getNumberOfTuples();
+  int nbOfTuple2=other->getNumberOfTuples();
+  int nbOfComp=getNumberOfComponents();
+  int nbOfComp2=other->getNumberOfComponents();
+  if(nbOfTuple!=nbOfTuple2)
+    throw INTERP_KERNEL::Exception("DataArrayDouble::powEqual : number of tuples mismatches !");
+  if(nbOfComp!=1 || nbOfComp2!=1)
+    throw INTERP_KERNEL::Exception("DataArrayDouble::powEqual : number of components of both arrays must be equal to 1 !");
+  double *ptr=getPointer();
+  const double *ptrc=other->begin();
+  for(int i=0;i<nbOfTuple;i++,ptrc++,ptr++)
+    {
+      if(*ptr>=0)
+        *ptr=pow(*ptr,*ptrc);
+      else
+        {
+          std::ostringstream oss; oss << "DataArrayDouble::powEqual : on tuple #" << i << " of this value is < 0 (" << *ptr << ") !";
+          throw INTERP_KERNEL::Exception(oss.str().c_str());
+        }
+    }
+  declareAsNew();
+}
+
 /*!
  * Useless method for end user. Only for MPI/Corba/File serialsation for multi arrays class.
  * Server side.
@@ -8094,7 +8234,7 @@ void DataArrayInt::applyRPow(int val) throw(INTERP_KERNEL::Exception)
           int tmp=1;
           for(int j=0;j<*ptr;j++)
             tmp*=val;
-          *ptr=val;
+          *ptr=tmp;
         }
       else
         {
index 6bb2c48ee1d3f2398a149f8becba8d952d147e73..cfebca035b6805619958a35f8958ae7a9cd6e1ec 100644 (file)
@@ -287,6 +287,8 @@ namespace ParaMEDMEM
     MEDCOUPLING_EXPORT void applyLin(double a, double b, int compoId) throw(INTERP_KERNEL::Exception);
     MEDCOUPLING_EXPORT void applyLin(double a, double b) throw(INTERP_KERNEL::Exception);
     MEDCOUPLING_EXPORT void applyInv(double numerator) throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT void applyPow(double val) throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT void applyRPow(double val) throw(INTERP_KERNEL::Exception);
     MEDCOUPLING_EXPORT DataArrayDouble *negate() const throw(INTERP_KERNEL::Exception);
     MEDCOUPLING_EXPORT DataArrayDouble *applyFunc(int nbOfComp, FunctionToEvaluate func) const throw(INTERP_KERNEL::Exception);
     MEDCOUPLING_EXPORT DataArrayDouble *applyFunc(int nbOfComp, const char *func) const throw(INTERP_KERNEL::Exception);
@@ -312,6 +314,8 @@ namespace ParaMEDMEM
     MEDCOUPLING_EXPORT void multiplyEqual(const DataArrayDouble *other) throw(INTERP_KERNEL::Exception);
     MEDCOUPLING_EXPORT static DataArrayDouble *Divide(const DataArrayDouble *a1, const DataArrayDouble *a2) throw(INTERP_KERNEL::Exception);
     MEDCOUPLING_EXPORT void divideEqual(const DataArrayDouble *other) throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT static DataArrayDouble *Pow(const DataArrayDouble *a1, const DataArrayDouble *a2) throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT void powEqual(const DataArrayDouble *other) throw(INTERP_KERNEL::Exception);
     MEDCOUPLING_EXPORT void updateTime() const { }
   public:
     MEDCOUPLING_EXPORT void getTinySerializationIntInformation(std::vector<int>& tinyInfo) const;
index de843c7b65fc1ee9a9b1bee1e20d7850fc1db865..754e78b4a89654c28c3ff82c0ccb6ec782cc777b 100644 (file)
@@ -32,6 +32,9 @@ def ParaMEDMEMDataArrayDoubleImul(self,*args):
 def ParaMEDMEMDataArrayDoubleIdiv(self,*args):
     import _MEDCoupling
     return _MEDCoupling.DataArrayDouble____idiv___(self, self, *args)
+def ParaMEDMEMDataArrayDoubleIpow(self,*args):
+    import _MEDCoupling
+    return _MEDCoupling.DataArrayDouble____ipow___(self, self, *args)
 def ParaMEDMEMMEDCouplingFieldDoubleIadd(self,*args):
     import _MEDCoupling
     return _MEDCoupling.MEDCouplingFieldDouble____iadd___(self, self, *args)
index 82d5e46a9f6654ccd71443e9c21f87cdfecbffd8..e20306b2ad8a602047717d0ffae99c97b808c929 100644 (file)
@@ -11714,6 +11714,51 @@ class MEDCouplingBasicsTest(unittest.TestCase):
         self.assertTrue(d.isEqual(DataArrayInt([6,16,5,15,4,14,3,13,2,12,1,11,0,10],7,2)))
         pass
 
+    def testSwig2DAPow1(self):
+        d=DataArrayInt(10)
+        d.iota(0)
+        d1=d.deepCpy()
+        d.setIJ(2,0,-2)
+        self.assertTrue((d**2).isEqual(DataArrayInt([0,1,4,9,16,25,36,49,64,81])))
+        self.assertTrue((d**3).isEqual(DataArrayInt([0,1,-8,27,64,125,216,343,512,729])))
+        for elt in [d]:
+            elt**=2
+            pass
+        self.assertTrue(d.isEqual(DataArrayInt([0,1,4,9,16,25,36,49,64,81])))
+        self.assertTrue((d1[:4]**d1[:4]).isEqual(DataArrayInt([1,1,4,27])))
+        self.assertTrue((3**d1[:4]).isEqual(DataArrayInt([1,3,9,27])))
+        d2=d1[:4]
+        d2**=d2
+        self.assertTrue(d2.isEqual(DataArrayInt([1,1,4,27])))
+        self.assertRaises(InterpKernelException,d2.__pow__,-1)#non supporting negative pow in DataArrayInt.__pow__
+        self.assertRaises(InterpKernelException,d2.__ipow__,-1)#non supporting negative pow in DataArrayInt.__pow__
+        #
+        d=DataArrayDouble(10)
+        d.iota(0)
+        d1=d.deepCpy()
+        d.setIJ(2,0,-2.)
+        self.assertTrue((d**2).isEqual(DataArrayDouble([0,1,4,9,16,25,36,49,64,81]),1e-12))
+        self.assertTrue((d**3).isEqual(DataArrayDouble([0,1,-8,27,64,125,216,343,512,729]),1e-12))
+        self.assertRaises(InterpKernelException,d.__pow__,3.1)#3.1 is double not integer -> not supporting negative values in d
+        for elt in [d]:
+            elt**=2
+            pass
+        self.assertTrue(d.isEqual(DataArrayDouble([0,1,4,9,16,25,36,49,64,81]),1e-12))
+        self.assertTrue((d1[:4]**d1[:4]).isEqual(DataArrayDouble([1,1,4,27]),1e-12))
+        self.assertTrue((3**d1[:4]).isEqual(DataArrayDouble([1,3,9,27]),1e-12))
+        d2=d1[:4]
+        d2**=d2
+        self.assertTrue(d2.isEqual(DataArrayDouble([1,1,4,27]),1e-12))
+        d2**=-0.5
+        self.assertTrue(d2.isEqual(DataArrayDouble([1,1,1./2,1./sqrt(27.)]),1e-14))
+        d3=-1./d1[1:5]
+        self.assertTrue((3**d3).isEqual(DataArrayDouble([0.3333333333333333,0.5773502691896257,0.6933612743506348,0.7598356856515925]),1e-14))
+        d4=d3.deepCpy() ; d4.abs()
+        self.assertTrue((d4**d3).isEqual(DataArrayDouble([1.,sqrt(2.),1.4422495703074083,sqrt(2.)]),1e-14))
+        d4**=d3
+        self.assertTrue(d4.isEqual(DataArrayDouble([1.,sqrt(2.),1.4422495703074083,sqrt(2.)]),1e-14))
+        pass
+
     def setUp(self):
         pass
     pass
index b60d7000e5bd37786bdcbff73108ebe0eba7e75a..f1adae767b96cdb17d92ce778d5bc7b6279b1055 100644 (file)
@@ -244,6 +244,7 @@ using namespace INTERP_KERNEL;
 %newobject ParaMEDMEM::DataArrayDouble::Substract;
 %newobject ParaMEDMEM::DataArrayDouble::Multiply;
 %newobject ParaMEDMEM::DataArrayDouble::Divide;
+%newobject ParaMEDMEM::DataArrayDouble::Pow;
 %newobject ParaMEDMEM::DataArrayDouble::substr;
 %newobject ParaMEDMEM::DataArrayDouble::changeNbOfComponents;
 %newobject ParaMEDMEM::DataArrayDouble::keepSelectedComponents;
@@ -288,6 +289,8 @@ using namespace INTERP_KERNEL;
 %newobject ParaMEDMEM::DataArrayDouble::__rmul__;
 %newobject ParaMEDMEM::DataArrayDouble::__div__;
 %newobject ParaMEDMEM::DataArrayDouble::__rdiv__;
+%newobject ParaMEDMEM::DataArrayDouble::__pow__;
+%newobject ParaMEDMEM::DataArrayDouble::__rpow__;
 %newobject ParaMEDMEM::DataArrayDoubleTuple::buildDADouble;
 %newobject ParaMEDMEM::MEDCouplingMesh::deepCpy;
 %newobject ParaMEDMEM::MEDCouplingMesh::checkDeepEquivalOnSameNodesWith;
@@ -5437,6 +5440,116 @@ namespace ParaMEDMEM
        }
    }
    
+   DataArrayDouble *__pow__(PyObject *obj) throw(INTERP_KERNEL::Exception)
+   {
+     const char msg[]="Unexpected situation in __pow__ !";
+     double val;
+     DataArrayDouble *a;
+     DataArrayDoubleTuple *aa;
+     std::vector<double> bb;
+     int sw;
+     convertObjToPossibleCpp5(obj,sw,val,a,aa,bb);
+     switch(sw)
+       {
+       case 1:
+         {
+           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=self->deepCpy();
+           ret->applyPow(val);
+           return ret.retn();
+         }
+       case 2:
+         {
+           return DataArrayDouble::Pow(self,a);
+         }
+       case 3:
+         {
+           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> aaa=aa->buildDADouble(1,self->getNumberOfComponents());
+           return DataArrayDouble::Pow(self,aaa);
+         }
+       case 4:
+         {
+           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> aaa=DataArrayDouble::New(); aaa->useArray(&bb[0],false,CPP_DEALLOC,1,(int)bb.size());
+           return DataArrayDouble::Pow(self,aaa);
+         }
+       default:
+         throw INTERP_KERNEL::Exception(msg);
+       }
+   }
+
+   DataArrayDouble *__rpow__(PyObject *obj) throw(INTERP_KERNEL::Exception)
+   {
+     const char msg[]="Unexpected situation in __rpow__ !";
+     double val;
+     DataArrayDouble *a;
+     DataArrayDoubleTuple *aa;
+     std::vector<double> bb;
+     int sw;
+     convertObjToPossibleCpp5(obj,sw,val,a,aa,bb);
+     switch(sw)
+       {
+       case 1:
+         {
+           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=self->deepCpy();
+           ret->applyRPow(val);
+           return ret.retn();
+         }
+       case 3:
+         {
+           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> aaa=aa->buildDADouble(1,self->getNumberOfComponents());
+           return DataArrayDouble::Pow(aaa,self);
+         }
+       case 4:
+         {
+           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> aaa=DataArrayDouble::New(); aaa->useArray(&bb[0],false,CPP_DEALLOC,1,(int)bb.size());
+           return DataArrayDouble::Pow(aaa,self);
+         }
+       default:
+         throw INTERP_KERNEL::Exception(msg);
+       }
+   }
+
+   PyObject *___ipow___(PyObject *trueSelf, PyObject *obj) throw(INTERP_KERNEL::Exception)
+   {
+     const char msg[]="Unexpected situation in __ipow__ !";
+     double val;
+     DataArrayDouble *a;
+     DataArrayDoubleTuple *aa;
+     std::vector<double> bb;
+     int sw;
+     convertObjToPossibleCpp5(obj,sw,val,a,aa,bb);
+     switch(sw)
+       {
+       case 1:
+         {
+           self->applyPow(val);
+           Py_XINCREF(trueSelf);
+           return trueSelf;
+         }
+       case 2:
+         {
+           self->powEqual(a);
+           Py_XINCREF(trueSelf);
+           return trueSelf;
+         }
+       case 3:
+         {
+           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> aaa=aa->buildDADouble(1,self->getNumberOfComponents());
+           self->powEqual(aaa);
+           Py_XINCREF(trueSelf);
+           return trueSelf;
+         }
+       case 4:
+         {
+           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> aaa=DataArrayDouble::New(); aaa->useArray(&bb[0],false,CPP_DEALLOC,1,(int)bb.size());
+           self->powEqual(aaa);
+           Py_XINCREF(trueSelf);
+           return trueSelf;
+         }
+       default:
+         throw INTERP_KERNEL::Exception(msg);
+       }
+   }
+   
    PyObject *computeTupleIdsNearTuples(const DataArrayDouble *other, double eps)
    {
      DataArrayInt *c=0,*cI=0;
index d686aa607e9b8eebbfcf48d7b59ca69bbbb8efd7..f6c73e1dc86283f393b155106c9e7a39c4b36e09 100644 (file)
@@ -22,6 +22,7 @@ DataArrayDouble.__iadd__=ParaMEDMEMDataArrayDoubleIadd
 DataArrayDouble.__isub__=ParaMEDMEMDataArrayDoubleIsub
 DataArrayDouble.__imul__=ParaMEDMEMDataArrayDoubleImul
 DataArrayDouble.__idiv__=ParaMEDMEMDataArrayDoubleIdiv
+DataArrayDouble.__ipow__=ParaMEDMEMDataArrayDoubleIpow
 
 DataArrayInt.__iadd__=ParaMEDMEMDataArrayIntIadd
 DataArrayInt.__isub__=ParaMEDMEMDataArrayIntIsub