Salome HOME
OK thanks to INV !
[modules/med.git] / src / MEDCoupling / MEDCouplingMemArray.cxx
index d8dee0b6a7f7552bfa07fd860474debac6ad252b..b5dd7300f7f12119403989e236734f7e6bbe0449 100644 (file)
@@ -402,7 +402,8 @@ void DataArray::setInfoOnComponent(int i, const char *info) throw(INTERP_KERNEL:
 /*!
  * Sets information on all components. This method can change number of components
  * at certain conditions; if the conditions are not respected, an exception is thrown.
- * The number of components can be changed provided that \a this is not allocated.
+ * The number of components can be changed in \a this only if \a this is not allocated.
+ * The condition of number of components must not be changed.
  *
  * To know more on format of the component information see
  * \ref MEDCouplingArrayBasicsCompoName "DataArrays infos".
@@ -652,6 +653,16 @@ void DataArrayDouble::checkAllocated() const throw(INTERP_KERNEL::Exception)
     throw INTERP_KERNEL::Exception("DataArrayDouble::checkAllocated : Array is defined but not allocated ! Call alloc or setValues method first !");
 }
 
+/*!
+ * This method desallocated \a this without modification of informations relative to the components.
+ * After call of this method, DataArrayDouble::isAllocated will return false.
+ * If \a this is already not allocated, \a this is let unchanged.
+ */
+void DataArrayDouble::desallocate() throw(INTERP_KERNEL::Exception)
+{
+  _mem.destroy();
+}
+
 std::size_t DataArrayDouble::getHeapMemorySize() const
 {
   std::size_t sz=_mem.getNbOfElemAllocated();
@@ -1209,9 +1220,12 @@ bool DataArrayDouble::isEqualWithoutConsideringStr(const DataArrayDouble& other,
  * than the current number the array is truncated, otherwise the array is extended.
  *  \param [in] nbOfTuples - new number of tuples. 
  *  \throw If \a this is not allocated.
+ *  \throw If \a nbOfTuples is negative.
  */
 void DataArrayDouble::reAlloc(int nbOfTuples) throw(INTERP_KERNEL::Exception)
 {
+  if(nbOfTuples<0)
+    throw INTERP_KERNEL::Exception("DataArrayDouble::reAlloc : input new number of tuples should be >=0 !");
   checkAllocated();
   _mem.reAlloc(getNumberOfComponents()*(std::size_t)nbOfTuples);
   declareAsNew();
@@ -1291,7 +1305,16 @@ void DataArrayDouble::renumberInPlace(const int *old2New) throw(INTERP_KERNEL::E
   double *tmp=new double[nbTuples*nbOfCompo];
   const double *iptr=getConstPointer();
   for(int i=0;i<nbTuples;i++)
-    std::copy(iptr+nbOfCompo*i,iptr+nbOfCompo*(i+1),tmp+nbOfCompo*old2New[i]);
+    {
+      int v=old2New[i];
+      if(v>=0 && v<nbTuples)
+        std::copy(iptr+nbOfCompo*i,iptr+nbOfCompo*(i+1),tmp+nbOfCompo*v);
+      else
+        {
+          std::ostringstream oss; oss << "DataArrayDouble::renumberInPlace : At place #" << i << " value is " << v << " ! Should be in [0," << nbTuples << ") !";
+          throw INTERP_KERNEL::Exception(oss.str().c_str());
+        }
+    }
   std::copy(tmp,tmp+nbTuples*nbOfCompo,getPointer());
   delete [] tmp;
   declareAsNew();
@@ -1315,7 +1338,16 @@ void DataArrayDouble::renumberInPlaceR(const int *new2Old) throw(INTERP_KERNEL::
   double *tmp=new double[nbTuples*nbOfCompo];
   const double *iptr=getConstPointer();
   for(int i=0;i<nbTuples;i++)
-    std::copy(iptr+nbOfCompo*new2Old[i],iptr+nbOfCompo*(new2Old[i]+1),tmp+nbOfCompo*i);
+    {
+      int v=new2Old[i];
+      if(v>=0 && v<nbTuples)
+        std::copy(iptr+nbOfCompo*v,iptr+nbOfCompo*(v+1),tmp+nbOfCompo*i);
+      else
+        {
+          std::ostringstream oss; oss << "DataArrayDouble::renumberInPlaceR : At place #" << i << " value is " << v << " ! Should be in [0," << nbTuples << ") !";
+          throw INTERP_KERNEL::Exception(oss.str().c_str());
+        }
+    }
   std::copy(tmp,tmp+nbTuples*nbOfCompo,getPointer());
   delete [] tmp;
   declareAsNew();
@@ -1768,6 +1800,33 @@ void DataArrayDouble::meldWith(const DataArrayDouble *other) throw(INTERP_KERNEL
   copyPartOfStringInfoFrom2(compIds,*other);
 }
 
+/*!
+ * This method checks that all tuples in \a other are in \a this.
+ * If true, the output param \a tupleIds contains the tuples ids of \a this that correspond to tupes in \a this.
+ * For each i in [ 0 , other->getNumberOfTuples() ) tuple #i in \a other is equal ( regarding input precision \a prec ) to tuple tupleIds[i] in \a this.
+ *
+ * \param [in] other - the array having the same number of components than \a this.
+ * \param [out] tupleIds - the tuple ids containing the same number of tuples than \a other has.
+ * \sa DataArrayDouble::findCommonTuples
+ */
+bool DataArrayDouble::areIncludedInMe(const DataArrayDouble *other, double prec, DataArrayInt *&tupleIds) const throw(INTERP_KERNEL::Exception)
+{
+  if(!other)
+    throw INTERP_KERNEL::Exception("DataArrayDouble::areIncludedInMe : input array is NULL !");
+  checkAllocated(); other->checkAllocated();
+  if(getNumberOfComponents()!=other->getNumberOfComponents())
+    throw INTERP_KERNEL::Exception("DataArrayDouble::areIncludedInMe : the number of components does not match !");
+  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> a=DataArrayDouble::Aggregate(this,other);
+  DataArrayInt *c=0,*ci=0;
+  a->findCommonTuples(prec,getNumberOfTuples(),c,ci);
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cSafe(c),ciSafe(ci);
+  int newNbOfTuples=-1;
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(a->getNumberOfTuples(),c->begin(),ci->begin(),ci->end(),newNbOfTuples);
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=ids->selectByTupleId2(getNumberOfTuples(),a->getNumberOfTuples(),1);
+  tupleIds=ret1.retn();
+  return newNbOfTuples==getNumberOfTuples();
+}
+
 /*!
  * Searches for tuples coincident within \a prec tolerance. Each tuple is considered
  * as coordinates of a point in getNumberOfComponents()-dimensional space. The
@@ -1797,7 +1856,7 @@ void DataArrayDouble::meldWith(const DataArrayDouble *other) throw(INTERP_KERNEL
  *  \ref cpp_mcdataarraydouble_findcommontuples "Here is a C++ example".
  *
  *  \ref py_mcdataarraydouble_findcommontuples  "Here is a Python example".
- *  \sa DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2().
+ *  \sa DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(), DataArrayDouble::areIncludedInMe
  */
 void DataArrayDouble::findCommonTuples(double prec, int limitTupleId, DataArrayInt *&comm, DataArrayInt *&commIndex) const throw(INTERP_KERNEL::Exception)
 {
@@ -2665,6 +2724,24 @@ double DataArrayDouble::getIJSafe(int tupleId, int compoId) const throw(INTERP_K
   return _mem[tupleId*_info_on_compo.size()+compoId];
 }
 
+/*!
+ * Returns the first value of \a this. 
+ *  \return double - the last value of \a this array.
+ *  \throw If \a this is not allocated.
+ *  \throw If \a this->getNumberOfComponents() != 1.
+ *  \throw If \a this->getNumberOfTuples() < 1.
+ */
+double DataArrayDouble::front() const throw(INTERP_KERNEL::Exception)
+{
+  checkAllocated();
+  if(getNumberOfComponents()!=1)
+    throw INTERP_KERNEL::Exception("DataArrayDouble::front : number of components not equal to one !");
+  int nbOfTuples=getNumberOfTuples();
+  if(nbOfTuples<1)
+    throw INTERP_KERNEL::Exception("DataArrayDouble::front : number of tuples must be >= 1 !");
+  return *(getConstPointer());
+}
+
 /*!
  * Returns the last value of \a this. 
  *  \return double - the last value of \a this array.
@@ -5365,6 +5442,16 @@ void DataArrayInt::checkAllocated() const throw(INTERP_KERNEL::Exception)
     throw INTERP_KERNEL::Exception("DataArrayInt::checkAllocated : Array is defined but not allocated ! Call alloc or setValues method first !");
 }
 
+/*!
+ * This method desallocated \a this without modification of informations relative to the components.
+ * After call of this method, DataArrayInt::isAllocated will return false.
+ * If \a this is already not allocated, \a this is let unchanged.
+ */
+void DataArrayInt::desallocate() throw(INTERP_KERNEL::Exception)
+{
+  _mem.destroy();
+}
+
 std::size_t DataArrayInt::getHeapMemorySize() const
 {
   std::size_t sz=_mem.getNbOfElemAllocated();
@@ -5798,7 +5885,7 @@ void DataArrayInt::transformWithIndArr(const int *indArrBg, const int *indArrEnd
         *pt=indArrBg[*pt];
       else
         {
-          std::ostringstream oss; oss << "DataArrayInt::transformWithIndArr : error on tuple #" << i << " value is " << *pt << " and indirectionnal array as a size equal to " << nbElemsIn;
+          std::ostringstream oss; oss << "DataArrayInt::transformWithIndArr : error on tuple #" << i << " of this value is " << *pt << ", should be in [0," << nbElemsIn << ") !";
           throw INTERP_KERNEL::Exception(oss.str().c_str());
         }
     }
@@ -5887,7 +5974,7 @@ void DataArrayInt::splitByValueRange(const int *arrBg, const int *arrEnd,
         }
       else
         {
-          std::ostringstream oss; oss << "DataArrayInt::splitByValueRange : At rank #" << i << " the value is " << work[i] << " whereas the last value is " << *bg;
+          std::ostringstream oss; oss << "DataArrayInt::splitByValueRange : At rank #" << i << " the value is " << work[i] << " should be in [0," << *bg << ") !";
           throw INTERP_KERNEL::Exception(oss.str().c_str());
         }
     }
@@ -6346,7 +6433,16 @@ void DataArrayInt::renumberInPlace(const int *old2New) throw(INTERP_KERNEL::Exce
   int *tmp=new int[nbTuples*nbOfCompo];
   const int *iptr=getConstPointer();
   for(int i=0;i<nbTuples;i++)
-    std::copy(iptr+nbOfCompo*i,iptr+nbOfCompo*(i+1),tmp+nbOfCompo*old2New[i]);
+    {
+      int v=old2New[i];
+      if(v>=0 && v<nbTuples)
+        std::copy(iptr+nbOfCompo*i,iptr+nbOfCompo*(i+1),tmp+nbOfCompo*v);
+      else
+        {
+          std::ostringstream oss; oss << "DataArrayInt::renumberInPlace : At place #" << i << " value is " << v << " ! Should be in [0," << nbTuples << ") !";
+          throw INTERP_KERNEL::Exception(oss.str().c_str());
+        }
+    }
   std::copy(tmp,tmp+nbTuples*nbOfCompo,getPointer());
   delete [] tmp;
   declareAsNew();
@@ -6370,7 +6466,16 @@ void DataArrayInt::renumberInPlaceR(const int *new2Old) throw(INTERP_KERNEL::Exc
   int *tmp=new int[nbTuples*nbOfCompo];
   const int *iptr=getConstPointer();
   for(int i=0;i<nbTuples;i++)
-    std::copy(iptr+nbOfCompo*new2Old[i],iptr+nbOfCompo*(new2Old[i]+1),tmp+nbOfCompo*i);
+    {
+      int v=new2Old[i];
+      if(v>=0 && v<nbTuples)
+        std::copy(iptr+nbOfCompo*v,iptr+nbOfCompo*(v+1),tmp+nbOfCompo*i);
+      else
+        {
+          std::ostringstream oss; oss << "DataArrayInt::renumberInPlaceR : At place #" << i << " value is " << v << " ! Should be in [0," << nbTuples << ") !";
+          throw INTERP_KERNEL::Exception(oss.str().c_str());
+        }
+    }
   std::copy(tmp,tmp+nbTuples*nbOfCompo,getPointer());
   delete [] tmp;
   declareAsNew();
@@ -7030,9 +7135,12 @@ DataArrayInt *DataArrayInt::changeNbOfComponents(int newNbOfComp, int dftValue)
  * than the current number the array is truncated, otherwise the array is extended.
  *  \param [in] nbOfTuples - new number of tuples. 
  *  \throw If \a this is not allocated.
+ *  \throw If \a nbOfTuples is negative.
  */
 void DataArrayInt::reAlloc(int nbOfTuples) throw(INTERP_KERNEL::Exception)
 {
+  if(nbOfTuples<0)
+    throw INTERP_KERNEL::Exception("DataArrayInt::reAlloc : input new number of tuples should be >=0 !");
   checkAllocated();
   _mem.reAlloc(getNumberOfComponents()*(std::size_t)nbOfTuples);
   declareAsNew();
@@ -7775,9 +7883,27 @@ int DataArrayInt::getIJSafe(int tupleId, int compoId) const throw(INTERP_KERNEL:
   return _mem[tupleId*_info_on_compo.size()+compoId];
 }
 
+/*!
+ * Returns the first value of \a this. 
+ *  \return int - the last value of \a this array.
+ *  \throw If \a this is not allocated.
+ *  \throw If \a this->getNumberOfComponents() != 1.
+ *  \throw If \a this->getNumberOfTuples() < 1.
+ */
+int DataArrayInt::front() const throw(INTERP_KERNEL::Exception)
+{
+  checkAllocated();
+  if(getNumberOfComponents()!=1)
+    throw INTERP_KERNEL::Exception("DataArrayInt::front : number of components not equal to one !");
+  int nbOfTuples=getNumberOfTuples();
+  if(nbOfTuples<1)
+    throw INTERP_KERNEL::Exception("DataArrayInt::front : number of tuples must be >= 1 !");
+  return *(getConstPointer());
+}
+
 /*!
  * Returns the last value of \a this. 
- *  \return double - the last value of \a this array.
+ *  \return int - the last value of \a this array.
  *  \throw If \a this is not allocated.
  *  \throw If \a this->getNumberOfComponents() != 1.
  *  \throw If \a this->getNumberOfTuples() < 1.
@@ -8264,6 +8390,57 @@ DataArrayInt *DataArrayInt::Aggregate(const std::vector<const DataArrayInt *>& a
   return ret.retn();
 }
 
+/*!
+ * This method takes as input a list of DataArrayInt instances \a arrs that represent each a packed index arrays.
+ * A packed index array is an allocated array with one component, and at least one tuple. The first element
+ * of each array in \a arrs must be 0. Each array in \a arrs is expected to be increasingly monotonic.
+ * This method is useful for users that want to aggregate a pair of DataArrayInt representing an indexed data (typically nodal connectivity index in unstructured meshes.
+ * 
+ * \return DataArrayInt * - a new object to be managed by the caller.
+ */
+DataArrayInt *DataArrayInt::AggregateIndexes(const std::vector<const DataArrayInt *>& arrs) throw(INTERP_KERNEL::Exception)
+{
+  int retSz=1;
+  for(std::vector<const DataArrayInt *>::const_iterator it4=arrs.begin();it4!=arrs.end();it4++)
+    {
+      if(*it4)
+        {
+          (*it4)->checkAllocated();
+          if((*it4)->getNumberOfComponents()!=1)
+            {
+              std::ostringstream oss; oss << "DataArrayInt::AggregateIndexes : presence of a DataArrayInt instance with nb of compo != 1 at pos " << std::distance(arrs.begin(),it4) << " !";
+              throw INTERP_KERNEL::Exception(oss.str().c_str());
+            }
+          int nbTupl=(*it4)->getNumberOfTuples();
+          if(nbTupl<1)
+            {
+              std::ostringstream oss; oss << "DataArrayInt::AggregateIndexes : presence of a DataArrayInt instance with nb of tuples < 1 at pos " << std::distance(arrs.begin(),it4) << " !";
+              throw INTERP_KERNEL::Exception(oss.str().c_str());
+            }
+          if((*it4)->front()!=0)
+            {
+              std::ostringstream oss; oss << "DataArrayInt::AggregateIndexes : presence of a DataArrayInt instance with front value != 0 at pos " << std::distance(arrs.begin(),it4) << " !";
+              throw INTERP_KERNEL::Exception(oss.str().c_str());
+            }
+          retSz+=nbTupl-1;
+        }
+      else
+        {
+          std::ostringstream oss; oss << "DataArrayInt::AggregateIndexes : presence of a null instance at pos " << std::distance(arrs.begin(),it4) << " !";
+          throw INTERP_KERNEL::Exception(oss.str().c_str());
+        }
+    }
+  if(arrs.empty())
+    throw INTERP_KERNEL::Exception("DataArrayInt::AggregateIndexes : input list must be NON EMPTY !");
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
+  ret->alloc(retSz,1);
+  int *pt=ret->getPointer(); *pt++=0;
+  for(std::vector<const DataArrayInt *>::const_iterator it=arrs.begin();it!=arrs.end();it++)
+    pt=std::transform((*it)->begin()+1,(*it)->end(),pt,std::bind2nd(std::plus<int>(),pt[-1]));
+  ret->copyStringInfoFrom(*(arrs[0]));
+  return ret.retn();
+}
+
 /*!
  * Returns the maximal value and its location within \a this one-dimensional array.
  *  \param [out] tupleId - index of the tuple holding the maximal value.
@@ -9021,6 +9198,7 @@ DataArrayInt *DataArrayInt::buildUnique() const throw(INTERP_KERNEL::Exception)
  * "MEDCouplingUMesh::buildDescendingConnectivity" and
  * \ref ParaMEDMEM::MEDCouplingUMesh::getNodalConnectivityIndex
  * "MEDCouplingUMesh::getNodalConnectivityIndex" etc.
+ * This method preforms the reverse operation of DataArrayInt::computeOffsets2.
  *  \return DataArrayInt * - a new instance of DataArrayInt, whose number of tuples
  *          equals to \a this->getNumberOfComponents() - 1, and number of components is 1.
  *          The caller is to delete this array using decrRef() as it is no more needed. 
@@ -9032,6 +9210,8 @@ DataArrayInt *DataArrayInt::buildUnique() const throw(INTERP_KERNEL::Exception)
  *         - this contains [1,3,6,7,7,9,15]
  *         - result array contains [2,3,1,0,2,6],
  *          where 2 = 3 - 1, 3 = 6 - 3, 1 = 7 - 6 etc.
+ *
+ * \sa DataArrayInt::computeOffsets2
  */
 DataArrayInt *DataArrayInt::deltaShiftIndex() const throw(INTERP_KERNEL::Exception)
 {
@@ -9094,12 +9274,14 @@ void DataArrayInt::computeOffsets() throw(INTERP_KERNEL::Exception)
  * components remains the same and number of tuples is inceamented by one.<br>
  * This method is useful for allToAllV in MPI with contiguous policy. This method
  * differs from computeOffsets() in that the number of tuples is changed by this one.
+ * This method preforms the reverse operation of DataArrayInt::deltaShiftIndex.
  *  \throw If \a this is not allocated.
  *  \throw If \a this->getNumberOfComponents() != 1.
  *
  *  \b Example: <br>
  *          - Before \a this contains [3,5,1,2,0,8]
  *          - After \a this contains  [0,3,8,9,11,11,19]<br>
+ * \sa DataArrayInt::deltaShiftIndex
  */
 void DataArrayInt::computeOffsets2() throw(INTERP_KERNEL::Exception)
 {