Salome HOME
On the road for massive templating to prepare SALOME9 int64
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingMemArray.txx
index 944b6bcedad207711c7b97f17b05064fa4adcce7..941326a87b3a26b7a52341cddaba9a9abc3f5c16 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <sstream>
 #include <cstdlib>
+#include <numeric>
 #include <algorithm>
 
 namespace MEDCoupling
@@ -2323,6 +2324,25 @@ namespace MEDCoupling
     std::reverse(_info_on_compo.begin(),_info_on_compo.end());
   }
 
+  /*!
+   * Assign pointer to one array to a pointer to another appay. Reference counter of
+   * \a arrayToSet is incremented / decremented.
+   *  \param [in] newArray - the pointer to array to assign to \a arrayToSet.
+   *  \param [in,out] arrayToSet - the pointer to array to assign to.
+   */
+  template<class T>
+  void DataArrayTemplate<T>::SetArrayIn(typename Traits<T>::ArrayType *newArray, typename Traits<T>::ArrayType* &arrayToSet)
+  {
+    if(newArray!=arrayToSet)
+      {
+        if(arrayToSet)
+          arrayToSet->decrRef();
+        arrayToSet=newArray;
+        if(arrayToSet)
+          arrayToSet->incrRef();
+      }
+  }
+
   template<class T>
   template<class U>
   MCAuto< typename Traits<U>::ArrayType > DataArrayTemplateClassic<T>::convertToOtherTypeOfArr() const
@@ -2839,6 +2859,352 @@ namespace MEDCoupling
         return const_cast<typename Traits<T>::ArrayType *>(&self);
       }
   }
+
+  template<class T>
+  struct GreatEqual
+  {
+    GreatEqual(T v):_v(v) { }
+    bool operator()(T v) const { return v>=_v; }
+    T _v;
+  };
+  
+  template<class T>
+  struct GreaterThan
+  {
+    GreaterThan(T v):_v(v) { }
+    bool operator()(T v) const { return v>_v; }
+    T _v;
+  };
+  
+  template<class T>
+  struct LowerEqual
+  {
+    LowerEqual(T v):_v(v) { }
+    bool operator()(T v) const { return v<=_v; }
+    T _v;
+  };
+  
+  template<class T>
+  struct LowerThan
+  {
+    LowerThan(T v):_v(v) { }
+    bool operator()(T v) const { return v<_v; }
+    T _v;
+  };
+  
+  template<class T>
+  struct InRange
+  {
+    InRange(T a, T b):_a(a),_b(b) { }
+    bool operator()(T v) const { return v>=_a && v<_b; }
+    T _a,_b;
+  };
+
+template<class T>
+struct NotInRange
+{
+  NotInRange(T a, T b):_a(a),_b(b) { }
+  bool operator()(T v) const { return v<_a || v>=_b; }
+  T _a,_b;
+};
+
+  /*!
+   * This method works only on data array with one component. This method returns a newly allocated array storing stored ascendantly of tuple ids in \a this so that this[id]<0.
+   *
+   * \return a newly allocated data array that the caller should deal with.
+   * \sa DataArrayInt::findIdsInRange
+   */
+  template<class T>
+  DataArrayInt *DataArrayTemplateClassic<T>::findIdsStrictlyNegative() const
+  {
+    LowerThan<T> lt((T)0);
+    MCAuto<DataArrayInt> ret(findIdsAdv(lt));
+    return ret.retn();
+  }
+  
+  template<class T>
+  MCAuto<DataArrayInt> DataArrayTemplateClassic<T>::findIdsGreaterOrEqualTo(T val) const
+  {
+    GreatEqual<T> ge(val);
+    return findIdsAdv(ge);
+  }
+  
+  template<class T>
+  MCAuto<DataArrayInt> DataArrayTemplateClassic<T>::findIdsGreaterThan(T val) const
+  {
+    GreaterThan<T> gt(val);
+    return findIdsAdv(gt);
+  }
+  
+  template<class T>
+  MCAuto<DataArrayInt> DataArrayTemplateClassic<T>::findIdsLowerOrEqualTo(T val) const
+  {
+    LowerEqual<T> le(val);
+    return findIdsAdv(le);
+  }
+  
+  template<class T>
+  MCAuto<DataArrayInt> DataArrayTemplateClassic<T>::findIdsLowerThan(T val) const
+  {
+    LowerThan<T> lt(val);
+    return findIdsAdv(lt);
+  }
+
+  /*!
+   * Returns a new DataArrayDouble by aggregating two given arrays, so that (1) the number
+   * of components in the result array is a sum of the number of components of given arrays
+   * and (2) the number of tuples in the result array is same as that of each of given
+   * arrays. In other words the i-th tuple of result array includes all components of
+   * i-th tuples of all given arrays.
+   * Number of tuples in the given arrays must be  the same.
+   *  \param [in] a1 - an array to include in the result array.
+   *  \param [in] a2 - another array to include in the result array.
+   *  \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 both \a a1 and \a a2 are NULL.
+   *  \throw If any given array is not allocated.
+   *  \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples()
+   */
+  template<class T>
+  typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::Meld(const typename Traits<T>::ArrayType *a1, const typename Traits<T>::ArrayType *a2)
+  {
+    std::vector<const typename Traits<T>::ArrayType *> arr(2);
+    arr[0]=a1; arr[1]=a2;
+    return Meld(arr);
+  }
+
+  /*!
+   * Returns a new DataArrayDouble by aggregating all given arrays, so that (1) the number
+   * of components in the result array is a sum of the number of components of given arrays
+   * and (2) the number of tuples in the result array is same as that of each of given
+   * arrays. In other words the i-th tuple of result array includes all components of
+   * i-th tuples of all given arrays.
+   * Number of tuples in the given arrays must be  the same.
+   *  \param [in] arr - a sequence of arrays to include in the result array.
+   *  \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 all arrays within \a arr are NULL.
+   *  \throw If any given array is not allocated.
+   *  \throw If getNumberOfTuples() of arrays within \a arr is different.
+   */
+  template<class T>
+  typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::Meld(const std::vector<const typename Traits<T>::ArrayType *>& arr)
+  {
+    std::vector<const typename Traits<T>::ArrayType *> a;
+    for(typename std::vector<const typename Traits<T>::ArrayType *>::const_iterator it4=arr.begin();it4!=arr.end();it4++)
+      if(*it4)
+        a.push_back(*it4);
+    if(a.empty())
+      throw INTERP_KERNEL::Exception("DataArrayDouble::Meld : input list must contain at least one NON EMPTY DataArrayDouble !");
+    typename std::vector<const typename Traits<T>::ArrayType *>::const_iterator it;
+    for(it=a.begin();it!=a.end();it++)
+      (*it)->checkAllocated();
+    it=a.begin();
+    int nbOfTuples((*it)->getNumberOfTuples());
+    std::vector<int> nbc(a.size());
+    std::vector<const T *> pts(a.size());
+    nbc[0]=(*it)->getNumberOfComponents();
+    pts[0]=(*it++)->getConstPointer();
+    for(int i=1;it!=a.end();it++,i++)
+      {
+        if(nbOfTuples!=(*it)->getNumberOfTuples())
+          throw INTERP_KERNEL::Exception("DataArrayDouble::Meld : mismatch of number of tuples !");
+        nbc[i]=(*it)->getNumberOfComponents();
+        pts[i]=(*it)->getConstPointer();
+      }
+    int totalNbOfComp=std::accumulate(nbc.begin(),nbc.end(),0);
+    typename Traits<T>::ArrayType *ret(Traits<T>::ArrayType::New());
+    ret->alloc(nbOfTuples,totalNbOfComp);
+    T *retPtr(ret->getPointer());
+    for(int i=0;i<nbOfTuples;i++)
+      for(int j=0;j<(int)a.size();j++)
+        {
+          retPtr=std::copy(pts[j],pts[j]+nbc[j],retPtr);
+          pts[j]+=nbc[j];
+        }
+    int k=0;
+    for(int i=0;i<(int)a.size();i++)
+      for(int j=0;j<nbc[i];j++,k++)
+        ret->setInfoOnComponent(k,a[i]->getInfoOnComponent(j));
+    return ret;
+  }
+
+  /*!
+   * Returns a new DataArrayDouble holding the same values as \a this array but differently
+   * arranged in memory. If \a this array holds 2 components of 3 values:
+   * \f$ x_0,x_1,x_2,y_0,y_1,y_2 \f$, then the result array holds these values arranged
+   * as follows: \f$ x_0,y_0,x_1,y_1,x_2,y_2 \f$.
+   *  \warning Do not confuse this method with transpose()!
+   *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
+   *          is to delete using decrRef() as it is no more needed.
+   *  \throw If \a this is not allocated.
+   */
+  template<class T>
+  typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::fromNoInterlace() const
+  {
+    if(this->_mem.isNull())
+      throw INTERP_KERNEL::Exception("DataArrayDouble::fromNoInterlace : Not defined array !");
+    T *tab(this->_mem.fromNoInterlace(this->getNumberOfComponents()));
+    MCAuto<typename Traits<T>::ArrayType> ret(Traits<T>::ArrayType::New());
+    ret->useArray(tab,true,C_DEALLOC,this->getNumberOfTuples(),this->getNumberOfComponents());
+    return ret.retn();
+  }
+
+  /*!
+   * Returns a new DataArrayDouble holding the same values as \a this array but differently
+   * arranged in memory. If \a this array holds 2 components of 3 values:
+   * \f$ x_0,y_0,x_1,y_1,x_2,y_2 \f$, then the result array holds these values arranged
+   * as follows: \f$ x_0,x_1,x_2,y_0,y_1,y_2 \f$.
+   *  \warning Do not confuse this method with transpose()!
+   *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
+   *          is to delete using decrRef() as it is no more needed.
+   *  \throw If \a this is not allocated.
+   */
+  template<class T>
+  typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::toNoInterlace() const
+  {
+    if(this->_mem.isNull())
+      throw INTERP_KERNEL::Exception("DataArrayDouble::toNoInterlace : Not defined array !");
+    T *tab(this->_mem.toNoInterlace(this->getNumberOfComponents()));
+    MCAuto<typename Traits<T>::ArrayType> ret(Traits<T>::ArrayType::New());
+    ret->useArray(tab,true,C_DEALLOC,this->getNumberOfTuples(),this->getNumberOfComponents());
+    return ret.retn();
+  }
+  
+  /*!
+   * Appends components of another array to components of \a this one, tuple by tuple.
+   * So that the number of tuples of \a this array remains the same and the number of 
+   * components increases.
+   *  \param [in] other - the DataArrayDouble to append to \a this one.
+   *  \throw If \a this is not allocated.
+   *  \throw If \a this and \a other arrays have different number of tuples.
+   *
+   *  \if ENABLE_EXAMPLES
+   *  \ref cpp_mcdataarraydouble_meldwith "Here is a C++ example".
+   *
+   *  \ref py_mcdataarraydouble_meldwith "Here is a Python example".
+   *  \endif
+   */
+  template<class T>
+  void DataArrayTemplateClassic<T>::meldWith(const typename Traits<T>::ArrayType *other)
+  {
+    this->checkAllocated();
+    other->checkAllocated();
+    int nbOfTuples(this->getNumberOfTuples());
+    if(nbOfTuples!=other->getNumberOfTuples())
+      throw INTERP_KERNEL::Exception("DataArrayDouble::meldWith : mismatch of number of tuples !");
+    int nbOfComp1(this->getNumberOfComponents()),nbOfComp2(other->getNumberOfComponents());
+    T *newArr=(T *)malloc((nbOfTuples*(nbOfComp1+nbOfComp2))*sizeof(T));
+    T *w=newArr;
+    const T *inp1(this->begin()),*inp2(other->begin());
+    for(int i=0;i<nbOfTuples;i++,inp1+=nbOfComp1,inp2+=nbOfComp2)
+      {
+        w=std::copy(inp1,inp1+nbOfComp1,w);
+        w=std::copy(inp2,inp2+nbOfComp2,w);
+      }
+    this->useArray(newArr,true,C_DEALLOC,nbOfTuples,nbOfComp1+nbOfComp2);
+    std::vector<int> compIds(nbOfComp2);
+    for(int i=0;i<nbOfComp2;i++)
+      compIds[i]=nbOfComp1+i;
+    this->copyPartOfStringInfoFrom2(compIds,*other);
+  }
+
+  /*!
+   * 
+   * \param [in] nbTimes specifies the nb of times each tuples in \a this will be duplicated contiguouly in returned DataArrayDouble instance.
+   *             \a nbTimes  should be at least equal to 1.
+   * \return a newly allocated DataArrayDouble having one component and number of tuples equal to \a nbTimes * \c this->getNumberOfTuples.
+   * \throw if \a this is not allocated or if \a this has not number of components set to one or if \a nbTimes is lower than 1.
+   */
+  template<class T>
+  typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::duplicateEachTupleNTimes(int nbTimes) const
+  {
+    this->checkAllocated();
+    if(this->getNumberOfComponents()!=1)
+      throw INTERP_KERNEL::Exception("DataArrayDouble::duplicateEachTupleNTimes : this should have only one component !");
+    if(nbTimes<1)
+      throw INTERP_KERNEL::Exception("DataArrayDouble::duplicateEachTupleNTimes : nb times should be >= 1 !");
+    int nbTuples(this->getNumberOfTuples());
+    const T *inPtr(this->begin());
+    MCAuto<typename Traits<T>::ArrayType> ret(Traits<T>::ArrayType::New()); ret->alloc(nbTimes*nbTuples,1);
+    T *retPtr(ret->getPointer());
+    for(int i=0;i<nbTuples;i++,inPtr++)
+      {
+        T val(*inPtr);
+        for(int j=0;j<nbTimes;j++,retPtr++)
+          *retPtr=val;
+      }
+    ret->copyStringInfoFrom(*this);
+    return ret.retn();
+  }
+  
+  template<class T>
+  void DataArrayTemplateClassic<T>::aggregate(const typename Traits<T>::ArrayType *other)
+  {
+    if(!other)
+      throw INTERP_KERNEL::Exception("DataArrayDouble::aggregate : null pointer !");
+    if(this->getNumberOfComponents()!=other->getNumberOfComponents())
+      throw INTERP_KERNEL::Exception("DataArrayDouble::aggregate : mismatch number of components !");
+    this->_mem.insertAtTheEnd(other->begin(),other->end());
+  }
+
+  /*!
+   * Converts every value of \a this array to its absolute value.
+   * \b WARNING this method is non const. If a new DataArrayDouble instance should be built containing the result of abs DataArrayDouble::computeAbs
+   * should be called instead.
+   *
+   * \throw If \a this is not allocated.
+   * \sa DataArrayDouble::computeAbs
+   */
+  template<class T>
+  void DataArrayTemplateClassic<T>::abs()
+  {
+    this->checkAllocated();
+    T *ptr(this->getPointer());
+    std::size_t nbOfElems(this->getNbOfElems());
+    std::transform(ptr,ptr+nbOfElems,ptr,std::ptr_fun<T,T>(std::abs));
+    this->declareAsNew();
+  }
+
+  /*!
+   * This method builds a new instance of \a this object containing the result of std::abs applied of all elements in \a this.
+   * This method is a const method (that do not change any values in \a this) contrary to  DataArrayDouble::abs method.
+   *
+   * \return DataArrayDouble * - the new instance of DataArrayDouble containing the
+   *         same number of tuples and component as \a this array.
+   *         The caller is to delete this result array using decrRef() as it is no more
+   *         needed.
+   * \throw If \a this is not allocated.
+   * \sa DataArrayDouble::abs
+   */
+  template<class T>
+  typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::computeAbs() const
+  {
+    this->checkAllocated();
+    MCAuto<typename Traits<T>::ArrayType> newArr(Traits<T>::ArrayType::New());
+    int nbOfTuples(this->getNumberOfTuples());
+    int nbOfComp(this->getNumberOfComponents());
+    newArr->alloc(nbOfTuples,nbOfComp);
+    std::transform(this->begin(),this->end(),newArr->getPointer(),std::ptr_fun<T,T>(std::abs));
+    newArr->copyStringInfoFrom(*this);
+    return newArr.retn();
+  }
+
+  /*!
+   * Returns either a \a deep or \a shallow copy of this array. For more info see
+   * \ref MEDCouplingArrayBasicsCopyDeep and \ref MEDCouplingArrayBasicsCopyShallow.
+   *  \param [in] dCpy - if \a true, a deep copy is returned, else, a shallow one.
+   *  \return DataArrayDouble * - either a new instance of DataArrayDouble (if \a dCpy
+   *          == \a true) or \a this instance (if \a dCpy == \a false).
+   */
+  template<class T>
+  typename Traits<T>::ArrayType *DataArrayTemplateClassic<T>::performCopyOrIncrRef(bool dCpy) const
+  {
+    const typename Traits<T>::ArrayType *thisC(static_cast<const typename Traits<T>::ArrayType *>(this));
+    return DataArrayTemplateClassic<T>::PerformCopyOrIncrRef(dCpy,*thisC);
+  }
   
   /*!
    * Checks if all values in \a this array are equal to \a val at precision \a eps.