+ /*!
+ * Returns an integer value characterizing \a this array, which is useful for a quick
+ * comparison of many instances of DataArrayInt.
+ * \return mcIdType - the hash value.
+ * \throw If \a this is not allocated.
+ */
+ template<class T>
+ mcIdType DataArrayDiscrete<T>::getHashCode() const
+ {
+ this->checkAllocated();
+ mcIdType nbOfElems=ToIdType(this->getNbOfElems());
+ mcIdType ret=nbOfElems*65536;
+ mcIdType delta=3;
+ if(nbOfElems>48)
+ delta=nbOfElems/8;
+ T ret0(0);
+ const T *pt(this->begin());
+ for(mcIdType i=0;i<nbOfElems;i+=delta)
+ ret0+=pt[i] & 0x1FFF;
+ return ToIdType(ret+ret0);
+ }
+
+ template<class T>
+ void DataArrayDiscrete<T>::reprCppStream(const std::string& varName, std::ostream& stream) const
+ {
+ mcIdType nbTuples(this->getNumberOfTuples());
+ std::size_t nbComp(this->getNumberOfComponents());
+ const T *data(this->getConstPointer());
+ stream << Traits<T>::ArrayTypeName << " *" << varName << "=" << Traits<T>::ArrayTypeName << "::New();" << std::endl;
+ if(nbTuples*nbComp>=1)
+ {
+ stream << "const mcIdType " << varName << "Data[" << nbTuples*nbComp << "]={";
+ std::copy(data,data+nbTuples*nbComp-1,std::ostream_iterator<T>(stream,","));
+ stream << data[nbTuples*nbComp-1] << "};" << std::endl;
+ stream << varName << "->useArray(" << varName << "Data,false,CPP_DEALLOC," << nbTuples << "," << nbComp << ");" << std::endl;
+ }
+ else
+ stream << varName << "->alloc(" << nbTuples << "," << nbComp << ");" << std::endl;
+ stream << varName << "->setName(\"" << this->getName() << "\");" << std::endl;
+ }
+
+ /*!
+ * Method that gives a quick overvien of \a this for python.
+ */
+ template<class T>
+ void DataArrayDiscrete<T>::reprQuickOverview(std::ostream& stream) const
+ {
+ static const std::size_t MAX_NB_OF_BYTE_IN_REPR=300;
+ stream << Traits<T>::ArrayTypeName << " C++ instance at " << this << ". ";
+ if(this->isAllocated())
+ {
+ std::size_t nbOfCompo(this->getNumberOfComponents());
+ if(nbOfCompo>=1)
+ {
+ mcIdType nbOfTuples(this->getNumberOfTuples());
+ stream << "Number of tuples : " << nbOfTuples << ". Number of components : " << nbOfCompo << "." << std::endl;
+ reprQuickOverviewData(stream,MAX_NB_OF_BYTE_IN_REPR);
+ }
+ else
+ stream << "Number of components : 0.";
+ }
+ else
+ stream << "*** No data allocated ****";
+ }
+
+ template<class T>
+ void DataArrayDiscrete<T>::reprQuickOverviewData(std::ostream& stream, std::size_t maxNbOfByteInRepr) const
+ {
+ const T *data(this->begin());
+ mcIdType nbOfTuples(this->getNumberOfTuples());
+ std::size_t nbOfCompo(this->getNumberOfComponents());
+ std::ostringstream oss2; oss2 << "[";
+ std::string oss2Str(oss2.str());
+ bool isFinished=true;
+ for(mcIdType i=0;i<nbOfTuples && isFinished;i++)
+ {
+ if(nbOfCompo>1)
+ {
+ oss2 << "(";
+ for(std::size_t j=0;j<nbOfCompo;j++,data++)
+ {
+ oss2 << *data;
+ if(j!=nbOfCompo-1) oss2 << ", ";
+ }
+ oss2 << ")";
+ }
+ else
+ oss2 << *data++;
+ if(i!=nbOfTuples-1) oss2 << ", ";
+ std::string oss3Str(oss2.str());
+ if(oss3Str.length()<maxNbOfByteInRepr)
+ oss2Str=oss3Str;
+ else
+ isFinished=false;
+ }
+ stream << oss2Str;
+ if(!isFinished)
+ stream << "... ";
+ stream << "]";
+ }
+
+ template<class T>
+ void DataArrayDiscrete<T>::writeVTK(std::ostream& ofs, mcIdType indent, const std::string& type, const std::string& nameInFile, DataArrayByte *byteArr) const
+ {
+ static const char SPACE[4]={' ',' ',' ',' '};
+ this->checkAllocated();
+ std::string idt(indent,' ');
+ ofs << idt << "<DataArray type=\"" << type << "\" Name=\"" << nameInFile << "\" NumberOfComponents=\"" << this->getNumberOfComponents() << "\"";
+ if(byteArr)
+ {
+ ofs << " format=\"appended\" offset=\"" << byteArr->getNumberOfTuples() << "\">";
+ if(std::string(type)==Traits<T>::VTKReprStr)
+ {
+ const char *data(reinterpret_cast<const char *>(this->begin()));
+ std::size_t sz(this->getNbOfElems()*sizeof(T));
+ byteArr->insertAtTheEnd(data,data+sz);
+ byteArr->insertAtTheEnd(SPACE,SPACE+4);
+ }
+ else if(std::string(type)=="Int8")
+ {
+ INTERP_KERNEL::AutoPtr<char> tmp(new char[this->getNbOfElems()]);
+ copyCast(this->begin(),this->end(),(char *)tmp);
+ byteArr->insertAtTheEnd((char *)tmp,(char *)tmp+this->getNbOfElems());
+ byteArr->insertAtTheEnd(SPACE,SPACE+4);
+ }
+ else if(std::string(type)=="UInt8")
+ {
+ INTERP_KERNEL::AutoPtr<unsigned char> tmp(new unsigned char[this->getNbOfElems()]);
+ copyCast(this->begin(),this->end(),(unsigned char *)tmp);
+ byteArr->insertAtTheEnd((unsigned char *)tmp,(unsigned char *)tmp+this->getNbOfElems());
+ byteArr->insertAtTheEnd(SPACE,SPACE+4);
+ }
+ else
+ {
+ std::ostringstream oss;
+ oss << Traits<T>::ArrayTypeName << "::writeVTK : Only " << Traits<T>::VTKReprStr << ", Int8 and UInt8 supported !";
+ throw INTERP_KERNEL::Exception(oss.str());
+ }
+ }
+ else
+ {
+ ofs << " RangeMin=\"" << this->getMinValueInArray() << "\" RangeMax=\"" << this->getMaxValueInArray() << "\" format=\"ascii\">\n" << idt;
+ std::copy(this->begin(),this->end(),std::ostream_iterator<T>(ofs," "));
+ }
+ ofs << std::endl << idt << "</DataArray>\n";
+ }
+
+ /*!
+ * Modifies in place \a this one-dimensional array so that each value \a v = \a indArrBg[ \a v ],
+ * i.e. a current value is used as in index to get a new value from \a indArrBg.
+ * \param [in] indArrBg - pointer to the first element of array of new values to assign
+ * to \a this array.
+ * \param [in] indArrEnd - specifies the end of the array \a indArrBg, so that
+ * the last value of \a indArrBg is \a indArrEnd[ -1 ].
+ * \throw If \a this->getNumberOfComponents() != 1
+ * \throw If any value of \a this can't be used as a valid index for
+ * [\a indArrBg, \a indArrEnd).
+ *
+ * \sa changeValue, findIdForEach
+ */
+ template<class T>
+ void DataArrayDiscrete<T>::transformWithIndArr(const T *indArrBg, const T *indArrEnd)
+ {
+ this->checkAllocated();
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("Call transformWithIndArr method on DataArrayInt with only one component, you can call 'rearrange' method before !");
+ mcIdType nbElemsIn=ToIdType(std::distance(indArrBg,indArrEnd));
+ mcIdType nbOfTuples(this->getNumberOfTuples());
+ T *pt(this->getPointer());
+ for(mcIdType i=0;i<nbOfTuples;i++,pt++)
+ {
+ if(*pt>=0 && *pt<nbElemsIn)
+ *pt=indArrBg[*pt];
+ else
+ {
+ 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());
+ }
+ }
+ this->declareAsNew();
+ }
+
+ template<class T>
+ void DataArrayDiscrete<T>::transformWithIndArr(const MapKeyVal<T, T>& m)
+ {
+ this->checkAllocated();
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("Call transformWithIndArr method on DataArrayInt with only one component, you can call 'rearrange' method before !");
+ const typename std::map<T,T>& dat(m.data());
+ mcIdType nbOfTuples(this->getNumberOfTuples());
+ T *pt(this->getPointer());
+ for(mcIdType i=0;i<nbOfTuples;i++,pt++)
+ {
+ typename std::map<T,T>::const_iterator it(dat.find(*pt));
+ if(it!=dat.end())
+ *pt=(*it).second;
+ else
+ {
+ std::ostringstream oss; oss << "DataArrayInt::transformWithIndArr : error on tuple #" << i << " of this value is " << *pt << " not in map !";
+ throw INTERP_KERNEL::Exception(oss.str());
+ }
+ }
+ this->declareAsNew();
+ }
+
+ /*!
+ * Creates a new DataArrayInt containing IDs (indices) of tuples holding value equal to a
+ * given one. The ids are sorted in the ascending order.
+ * \param [in] val - the value to find within \a this.
+ * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
+ * array using decrRef() as it is no more needed.
+ * \throw If \a this is not allocated.
+ * \throw If \a this->getNumberOfComponents() != 1.
+ * \sa DataArrayInt::findIdsEqualTuple
+ */
+ template<class T>
+ DataArrayIdType *DataArrayDiscrete<T>::findIdsEqual(T val) const
+ {
+ this->checkAllocated();
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::findIdsEqual : the array must have only one component, you can call 'rearrange' method before !");
+ const T *cptr(this->getConstPointer());
+ MCAuto<DataArrayIdType> ret(DataArrayIdType::New()); ret->alloc(0,1);
+ mcIdType nbOfTuples(this->getNumberOfTuples());
+ for(mcIdType i=0;i<nbOfTuples;i++,cptr++)
+ if(*cptr==val)
+ ret->pushBackSilent(ToIdType(i));
+ return ret.retn();
+ }
+
+ /*!
+ * Creates a one-dimensional DataArrayInt (\a res) whose contents are computed from
+ * values of \a this (\a a) and the given (\a indArr) arrays as follows:
+ * \a res[ \a indArr[ \a a[ i ]]] = i. I.e. for each value in place i \a v = \a a[ i ],
+ * new value in place \a indArr[ \a v ] is i.
+ * \param [in] indArrBg - the array holding indices within the result array to assign
+ * indices of values of \a this array pointing to values of \a indArrBg.
+ * \param [in] indArrEnd - specifies the end of the array \a indArrBg, so that
+ * the last value of \a indArrBg is \a indArrEnd[ -1 ].
+ * \return DataArrayInt * - the new instance of DataArrayInt.
+ * The caller is to delete this result array using decrRef() as it is no more
+ * needed.
+ * \throw If \a this->getNumberOfComponents() != 1.
+ * \throw If any value of \a this array is not a valid index for \a indArrBg array.
+ * \throw If any value of \a indArrBg is not a valid index for \a this array.
+ */
+ template<class T>
+ DataArrayIdType *DataArrayDiscrete<T>::transformWithIndArrR(const T *indArrBg, const T *indArrEnd) const
+ {
+ this->checkAllocated();
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("Call transformWithIndArrR method on DataArrayInt with only one component, you can call 'rearrange' method before !");
+ mcIdType nbElemsIn=ToIdType(std::distance(indArrBg,indArrEnd));
+ mcIdType nbOfTuples(this->getNumberOfTuples());
+ const T *pt=this->getConstPointer();
+ MCAuto<DataArrayIdType> ret=DataArrayIdType::New();
+ ret->alloc(nbOfTuples,1);
+ ret->fillWithValue(-1);
+ mcIdType *tmp=ret->getPointer();
+ for(mcIdType i=0;i<nbOfTuples;i++,pt++)
+ {
+ if(*pt>=0 && *pt<nbElemsIn)
+ {
+ T pos=indArrBg[*pt];
+ if(pos>=0 && pos<nbOfTuples)
+ tmp[ToIdType(pos)]=i;
+ else
+ {
+ std::ostringstream oss; oss << "DataArrayInt::transformWithIndArrR : error on tuple #" << i << " value of new pos is " << pos << " ( indArrBg[" << *pt << "]) ! Should be in [0," << nbOfTuples << ") !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
+ }
+ else
+ {
+ std::ostringstream oss; oss << "DataArrayInt::transformWithIndArrR : error on tuple #" << i << " value is " << *pt << " and indirectionnal array as a size equal to " << nbElemsIn << " !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
+ }
+ return ret.retn();
+ }
+
+ /*!
+ * Computes distribution of values of \a this one-dimensional array between given value
+ * ranges (casts). This method is typically useful for entity number splitting by types,
+ * for example.
+ * \warning The values contained in \a arrBg should be sorted ascendently. No
+ * check of this is be done. If not, the result is not warranted.
+ * \param [in] arrBg - the array of ascending values defining the value ranges. The i-th
+ * value of \a arrBg (\a arrBg[ i ]) gives the lowest value of the i-th range,
+ * and the greatest value of the i-th range equals to \a arrBg[ i+1 ] - 1. \a
+ * arrBg containing \a n values defines \a n-1 ranges. The last value of \a arrBg
+ * should be more than every value in \a this array.
+ * \param [in] arrEnd - specifies the end of the array \a arrBg, so that
+ * the last value of \a arrBg is \a arrEnd[ -1 ].
+ * \param [out] castArr - a new instance of DataArrayInt, of same size as \a this array
+ * (same number of tuples and components), the caller is to delete
+ * using decrRef() as it is no more needed.
+ * This array contains indices of ranges for every value of \a this array. I.e.
+ * the i-th value of \a castArr gives the index of range the i-th value of \a this
+ * belongs to. Or, in other words, this parameter contains for each tuple in \a
+ * this in which cast it holds.
+ * \param [out] rankInsideCast - a new instance of DataArrayInt, of same size as \a this
+ * array, the caller is to delete using decrRef() as it is no more needed.
+ * This array contains ranks of values of \a this array within ranges
+ * they belongs to. I.e. the i-th value of \a rankInsideCast gives the rank of
+ * the i-th value of \a this array within the \a castArr[ i ]-th range, to which
+ * the i-th value of \a this belongs to. Or, in other words, this param contains
+ * for each tuple its rank inside its cast. The rank is computed as difference
+ * between the value and the lowest value of range.
+ * \param [out] castsPresent - a new instance of DataArrayInt, containing indices of
+ * ranges (casts) to which at least one value of \a this array belongs.
+ * Or, in other words, this param contains the casts that \a this contains.
+ * The caller is to delete this array using decrRef() as it is no more needed.
+ *
+ * \b Example: If \a this contains [6,5,0,3,2,7,8,1,4] and \a arrBg contains [0,4,9] then
+ * the output of this method will be :
+ * - \a castArr : [1,1,0,0,0,1,1,0,1]
+ * - \a rankInsideCast: [2,1,0,3,2,3,4,1,0]
+ * - \a castsPresent : [0,1]
+ *
+ * I.e. values of \a this array belong to 2 ranges: #0 and #1. Value 6 belongs to the
+ * range #1 and its rank within this range is 2; etc.
+ *
+ * \throw If \a this->getNumberOfComponents() != 1.
+ * \throw If \a arrEnd - arrBg < 2.
+ * \throw If any value of \a this is not less than \a arrEnd[-1].
+ */
+ template<class T>
+ void DataArrayDiscrete<T>::splitByValueRange(const T *arrBg, const T *arrEnd,
+ DataArrayType *& castArr, DataArrayType *& rankInsideCast, DataArrayType *& castsPresent) const
+ {
+ this->checkAllocated();
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("Call splitByValueRange method on DataArrayInt with only one component, you can call 'rearrange' method before !");
+ mcIdType nbOfTuples=this->getNumberOfTuples();
+ std::size_t nbOfCast=std::distance(arrBg,arrEnd);
+ if(nbOfCast<2)
+ throw INTERP_KERNEL::Exception("DataArrayInt::splitByValueRange : The input array giving the cast range values should be of size >=2 !");
+ nbOfCast--;
+ const T *work=this->getConstPointer();
+ typedef std::reverse_iterator<const T *> rintstart;
+ rintstart bg(arrEnd);//OK no problem because size of 'arr' is greater or equal 2
+ rintstart end2(arrBg);
+ MCAuto<DataArrayType> ret1=DataArrayType::New();
+ MCAuto<DataArrayType> ret2=DataArrayType::New();
+ MCAuto<DataArrayType> ret3=DataArrayType::New();
+ ret1->alloc(nbOfTuples,1);
+ ret2->alloc(nbOfTuples,1);
+ T *ret1Ptr=ret1->getPointer();
+ T *ret2Ptr=ret2->getPointer();
+ std::set<T> castsDetected;
+ for(mcIdType i=0;i<nbOfTuples;i++)
+ {
+ rintstart res=std::find_if(bg,end2,std::bind(std::less_equal<T>(),std::placeholders::_1,work[i]));
+ std::size_t pos=std::distance(bg,res);
+ std::size_t pos2=nbOfCast-pos;
+ if(pos2<nbOfCast)
+ {
+ ret1Ptr[i]=static_cast<T>(pos2);
+ ret2Ptr[i]=work[i]-arrBg[pos2];
+ castsDetected.insert(ret1Ptr[i]);
+ }
+ else
+ {
+ 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());
+ }
+ }
+ ret3->alloc(castsDetected.size(),1);
+ std::copy(castsDetected.begin(),castsDetected.end(),ret3->getPointer());
+ castArr=ret1.retn();
+ rankInsideCast=ret2.retn();
+ castsPresent=ret3.retn();
+ }
+
+ /*!
+ * This method look at \a this if it can be considered as a range defined by the 3-tuple ( \a strt , \a sttoopp , \a stteepp ).
+ * If false is returned the tuple must be ignored. If true is returned \a this can be considered by a range( \a strt , \a sttoopp , \a stteepp ).
+ * This method works only if \a this is allocated and single component. If not an exception will be thrown.
+ *
+ * \param [out] strt - the start of the range (included) if true is returned.
+ * \param [out] sttoopp - the end of the range (not included) if true is returned.
+ * \param [out] stteepp - the step of the range if true is returned.
+ * \return the verdict of the check.
+ *
+ * \sa DataArray::GetNumberOfItemGivenBES
+ */
+ template<class T>
+ bool DataArrayDiscrete<T>::isRange(T& strt, T& sttoopp, T& stteepp) const
+ {
+ this->checkAllocated();
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::isRange : this must be single component array !");
+ mcIdType nbTuples(this->getNumberOfTuples());
+ if(nbTuples==0)
+ { strt=0; sttoopp=0; stteepp=1; return true; }
+ const T *pt(this->begin());
+ strt=*pt;
+ if(nbTuples==1)
+ { sttoopp=strt+1; stteepp=1; return true; }
+ strt=*pt; sttoopp=pt[nbTuples-1];
+ if(strt==sttoopp)
+ return false;
+ if(sttoopp>strt)
+ {
+ sttoopp++;
+ T a(sttoopp-1-strt),tmp(strt);
+ if(a%(nbTuples-1)!=0)
+ return false;
+ stteepp=a/(FromIdType<T>(nbTuples)-1);
+ for(mcIdType i=0;i<nbTuples;i++,tmp+=stteepp)
+ if(pt[i]!=tmp)
+ return false;
+ return true;
+ }
+ else
+ {
+ sttoopp--;
+ T a(strt-sttoopp-1),tmp(strt);
+ if(a%(nbTuples-1)!=0)
+ return false;
+ stteepp=-(a/(FromIdType<T>(nbTuples)-1));
+ for(mcIdType i=0;i<nbTuples;i++,tmp+=stteepp)
+ if(pt[i]!=tmp)
+ return false;
+ return true;
+ }
+ }
+
+ /*!
+ * Creates a one-dimensional DataArrayInt of given length, whose contents are computed
+ * from values of \a this array, which is supposed to contain a renumbering map in
+ * "Old to New" mode. The result array contains a renumbering map in "New to Old" mode.
+ * To know how to use the renumbering maps see \ref numbering.
+ * \param [in] newNbOfElem - the number of tuples in the result array.
+ * \return DataArrayInt * - the new instance of DataArrayInt.
+ * The caller is to delete this result array using decrRef() as it is no more
+ * needed.
+ *
+ * \if ENABLE_EXAMPLES
+ * \ref cpp_mcdataarrayint_invertarrayo2n2n2o "Here is a C++ example".<br>
+ * \ref py_mcdataarrayint_invertarrayo2n2n2o "Here is a Python example".
+ * \endif
+ */
+ template<class T>
+ DataArrayIdType * DataArrayDiscrete<T>::invertArrayO2N2N2O(mcIdType newNbOfElem) const
+ {
+ MCAuto<DataArrayIdType> ret(DataArrayIdType::New());
+ ret->alloc(newNbOfElem,1);
+ mcIdType nbOfOldNodes(this->getNumberOfTuples());
+ const T *old2New(this->begin());
+ mcIdType *pt(ret->getPointer());
+ for(mcIdType i=0;i!=nbOfOldNodes;i++)
+ {
+ T newp(old2New[i]);
+ if(newp!=-1)
+ {
+ if(newp>=0 && newp<newNbOfElem)
+ pt[newp]=i;
+ else
+ {
+ std::ostringstream oss; oss << "DataArrayInt::invertArrayO2N2N2O : At place #" << i << " the newplace is " << newp << " must be in [0," << newNbOfElem << ") !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
+ }
+ }
+ return ret.retn();
+ }
+
+ /*!
+ * Creates a one-dimensional DataArrayInt of given length, whose contents are computed
+ * from values of \a this array, which is supposed to contain a renumbering map in
+ * "New to Old" mode. The result array contains a renumbering map in "Old to New" mode.
+ * To know how to use the renumbering maps see \ref numbering.
+ * \param [in] oldNbOfElem - the number of tuples in the result array.
+ * \return DataArrayInt * - the new instance of DataArrayInt.
+ * The caller is to delete this result array using decrRef() as it is no more
+ * needed.
+ *
+ * \if ENABLE_EXAMPLES
+ * \ref cpp_mcdataarrayint_invertarrayn2o2o2n "Here is a C++ example".
+ *
+ * \ref py_mcdataarrayint_invertarrayn2o2o2n "Here is a Python example".
+ * \sa invertArrayN2O2O2NOptimized
+ * \endif
+ */
+ template <class T>
+ DataArrayIdType *DataArrayDiscrete<T>::invertArrayN2O2O2N(mcIdType oldNbOfElem) const
+ {
+ this->checkAllocated();
+ MCAuto<DataArrayIdType> ret=DataArrayIdType::New();
+ ret->alloc(oldNbOfElem,1);
+ const T *new2Old=this->getConstPointer();
+ mcIdType *pt=ret->getPointer();
+ std::fill(pt,pt+oldNbOfElem,-1);
+ mcIdType nbOfNewElems(this->getNumberOfTuples());
+ for(mcIdType i=0;i<nbOfNewElems;i++)
+ {
+ T v(new2Old[i]);
+ if(v>=0 && v<oldNbOfElem)
+ pt[v]=i;
+ else
+ {
+ std::ostringstream oss; oss << "DataArrayInt::invertArrayN2O2O2N : in new id #" << i << " old value is " << v << " expected to be in [0," << oldNbOfElem << ") !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
+ }
+ return ret.retn();
+ }
+
+ /*!
+ * This method is similar to DataArrayInt::invertArrayO2N2N2O except that
+ * Example : If \a this contains [0,1,2,0,3,4,5,4,6,4] this method will return [0,1,2,4,5,6,8] whereas DataArrayInt::invertArrayO2N2N2O returns [3,1,2,4,9,6,8]
+ */
+ template <class T>
+ DataArrayIdType *DataArrayDiscrete<T>::invertArrayO2N2N2OBis(mcIdType newNbOfElem) const
+ {
+ MCAuto<DataArrayIdType> ret=DataArrayIdType::New();
+ ret->alloc(newNbOfElem,1);
+ mcIdType nbOfOldNodes(this->getNumberOfTuples());
+ const T *old2New=this->getConstPointer();
+ mcIdType *pt=ret->getPointer();
+ for(mcIdType i=nbOfOldNodes-1;i>=0;i--)
+ {
+ T newp(old2New[i]);
+ if(newp!=-1)
+ {
+ if(newp>=0 && newp<newNbOfElem)
+ pt[newp]=i;
+ else
+ {
+ std::ostringstream oss; oss << "DataArrayInt::invertArrayO2N2N2OBis : At place #" << i << " the newplace is " << newp << " must be in [0," << newNbOfElem << ") !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
+ }
+ }
+ return ret.retn();
+ }
+
+ /*!
+ * Creates a map, whose contents are computed
+ * from values of \a this array, which is supposed to contain a renumbering map in
+ * "New to Old" mode. The result array contains a renumbering map in "Old to New" mode.
+ * To know how to use the renumbering maps see \ref numbering.
+ * \return MapII - the new instance of Map.
+ *
+ * \if ENABLE_EXAMPLES
+ * \ref cpp_mcdataarrayint_invertarrayn2o2o2n "Here is a C++ example".
+ *
+ * \ref py_mcdataarrayint_invertarrayn2o2o2n "Here is a Python example".
+ * \sa invertArrayN2O2O2N, giveN2OOptimized, MEDCouplingPointSet::renumberNodesInConn
+ * \endif
+ */
+ template <class T>
+ MCAuto< MapKeyVal<T, mcIdType> > DataArrayDiscrete<T>::invertArrayN2O2O2NOptimized() const
+ {
+ this->checkAllocated();
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::invertArrayN2O2O2NOptimized : single component expected !");
+ MCAuto< MapKeyVal<T, mcIdType> > ret(MapKeyVal<T, mcIdType>::New());
+ std::map<T, mcIdType>& m(ret->data());
+ const T *new2Old(this->begin());
+ mcIdType nbOfNewElems(this->getNumberOfTuples());
+ for(mcIdType i=0;i<nbOfNewElems;i++)
+ {
+ T v(new2Old[i]);
+ m[v]=i;
+ }
+ return ret;
+ }
+
+ /*!
+ * Creates a map, whose contents are computed
+ * from values of \a this array, which is supposed to contain a renumbering map in
+ * "New to Old" mode. The result array contains a renumbering map in "New to Old" mode as C++ map for performance reasons.
+ *
+ * \sa invertArrayN2O2O2NOptimized, MEDCouplingPointSet::renumberNodesInConn
+ */
+ template <class T>
+ MCAuto< MapKeyVal<mcIdType, T> > DataArrayDiscrete<T>::giveN2OOptimized() const
+ {
+ this->checkAllocated();
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::giveN2OOptimized : single component expected !");
+ MCAuto< MapKeyVal<mcIdType, T> > ret(MapKeyVal<mcIdType, T>::New());
+ std::map<mcIdType,T>& m(ret->data());
+ const T *new2Old(this->begin());
+ mcIdType nbOfNewElems(this->getNumberOfTuples());
+ for(mcIdType i=0;i<nbOfNewElems;i++)
+ {
+ T v(new2Old[i]);
+ m[i]=v;
+ }
+ return ret;
+ }
+
+ /*!
+ * This method finds for each element \a ELT in [valsBg,valsEnd) elements in \a this equal to it. Associated to ELT
+ * this method will return the tuple id of last element found. If there is no element in \a this equal to ELT
+ * an exception will be thrown.
+ *
+ * In case of success this[ret]==vals. Samely ret->transformWithIndArr(this->begin(),this->end())==vals.
+ * Where \a vals is the [valsBg,valsEnd) array and \a ret the array returned by this method.
+ * This method can be seen as an extension of FindPermutationFromFirstToSecond.
+ * <br>
+ * \b Example: <br>
+ * - \a this: [17,27,2,10,-4,3,12,27,16]
+ * - \a val : [3,16,-4,27,17]
+ * - result: [5,8,4,7,0]
+ *
+ * \return - An array of size std::distance(valsBg,valsEnd)
+ *
+ * \sa DataArrayInt::FindPermutationFromFirstToSecond , DataArrayInt::FindPermutationFromFirstToSecondDuplicate
+ */
+ template <class T>
+ MCAuto<DataArrayIdType> DataArrayDiscrete<T>::findIdForEach(const T *valsBg, const T *valsEnd) const
+ {
+ MCAuto<DataArrayIdType> ret(DataArrayIdType::New());
+ std::size_t nbOfTuplesOut(std::distance(valsBg,valsEnd));
+ ret->alloc(nbOfTuplesOut,1);
+ MCAuto< MapKeyVal<T, mcIdType> > zeMap(this->invertArrayN2O2O2NOptimized());
+ const std::map<T, mcIdType>& dat(zeMap->data());
+ mcIdType *ptToFeed(ret->getPointer());
+ for(const T *pt=valsBg;pt!=valsEnd;pt++)
+ {
+ typename std::map<T,mcIdType>::const_iterator it(dat.find(*pt));
+ if(it!=dat.end())
+ *ptToFeed++=(*it).second;
+ else
+ {
+ std::ostringstream oss; oss << "DataArrayInt::findIdForEach : error for element at place " << std::distance(valsBg,pt);
+ oss << " of input array value is " << *pt << " which is not in this !";
+ throw INTERP_KERNEL::Exception(oss.str());
+ }
+ }
+ return ret;
+ }
+
+ /*!
+ * Returns a new DataArrayInt containing a renumbering map in "Old to New" mode.
+ * This map, if applied to \a this array, would make it sorted. For example, if
+ * \a this array contents are [9,10,0,6,4,11,3,7] then the contents of the result array
+ * are [5,6,0,3,2,7,1,4]; if this result array (\a res) is used as an argument in call
+ * \a this->renumber(\a res) then the returned array contains [0,3,4,6,7,9,10,11].
+ * This method is useful for renumbering (in MED file for example). For more info
+ * on renumbering see \ref numbering.
+ * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
+ * array using decrRef() as it is no more needed.
+ * \throw If \a this is not allocated.
+ * \throw If \a this->getNumberOfComponents() != 1.
+ * \throw If there are equal values in \a this array.
+ */
+ template <class T>
+ DataArrayIdType *DataArrayDiscrete<T>::checkAndPreparePermutation() const
+ {
+ this->checkAllocated();
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::checkAndPreparePermutation : number of components must == 1 !");
+ mcIdType nbTuples(this->getNumberOfTuples());
+ const T *pt=this->getConstPointer();
+ mcIdType *pt2=this->CheckAndPreparePermutation(pt,pt+nbTuples);
+ DataArrayIdType *ret=DataArrayIdType::New();
+ ret->useArray(pt2,true,DeallocType::C_DEALLOC,nbTuples,1);
+ return ret;
+ }
+
+ /*!
+ * 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
+ * \a B[ \a A[ i ]] = i. That is to say that for each \a id in [0,\a targetNb), where \a
+ * targetNb < \a this->getNumberOfTuples(), there exists at least one tupleId (\a tid) so
+ * that <em> this->getIJ( tid, 0 ) == id</em>. <br>
+ * The first of out arrays returns indices of elements of \a this array, grouped by their
+ * place in the set \a B. The second out array is the index of the first one; it shows how
+ * many elements of \a A are mapped into each element of \a B. <br>
+ * For more info on
+ * mapping and its usage in renumbering see \ref numbering. <br>
+ * \b Example:
+ * - \a this: [0,3,2,3,2,2,1,2]
+ * - \a targetNb: 4
+ * - \a arr: [0, 6, 2,4,5,7, 1,3]
+ * - \a arrI: [0,1,2,6,8]
+ *
+ * This result means: <br>
+ * the element of \a B 0 encounters within \a A once (\a arrI[ 0+1 ] - \a arrI[ 0 ]) and
+ * its index within \a A is 0 ( \a arr[ 0:1 ] == \a arr[ \a arrI[ 0 ] : \a arrI[ 0+1 ]]);<br>
+ * the element of \a B 2 encounters within \a A 4 times (\a arrI[ 2+1 ] - \a arrI[ 2 ]) and
+ * its indices within \a A are [2,4,5,7] ( \a arr[ 2:6 ] == \a arr[ \a arrI[ 2 ] :
+ * \a arrI[ 2+1 ]]); <br> etc.
+ * \param [in] targetNb - the size of the set \a B. \a targetNb must be equal or more
+ * than the maximal value of \a A.
+ * \param [out] arr - a new instance of DataArrayInt returning indices of
+ * elements of \a this, grouped by their place in the set \a B. The caller is to delete
+ * this array using decrRef() as it is no more needed.
+ * \param [out] arrI - a new instance of DataArrayInt returning size of groups of equal
+ * elements of \a this. The caller is to delete this array using decrRef() as it
+ * is no more needed.
+ * \throw If \a this is not allocated.
+ * \throw If \a this->getNumberOfComponents() != 1.
+ * \throw If any value in \a this is more or equal to \a targetNb.
+ */
+ template <class T>
+ void DataArrayDiscrete<T>::changeSurjectiveFormat(T targetNb, DataArrayIdType *&arr, DataArrayIdType *&arrI) const
+ {
+ this->checkAllocated();
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::changeSurjectiveFormat : number of components must == 1 !");
+ mcIdType nbOfTuples(this->getNumberOfTuples());
+ const T *input=this->getConstPointer();
+ std::vector< std::vector<mcIdType> > tmp(targetNb);
+ for(mcIdType i=0;i<nbOfTuples;i++)
+ {
+ T tmp2=input[i];
+ if(tmp2>=0 && tmp2<targetNb)
+ tmp[tmp2].push_back(i);
+ else
+ {
+ std::ostringstream oss; oss << "DataArrayInt::changeSurjectiveFormat : At pos " << i << " presence of element " << tmp2 << " ! should be in [0," << targetNb << ") !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
+ }
+
+ MCAuto<DataArrayIdType> retI(DataArrayIdType::New());
+ retI->alloc(targetNb+1,1);
+ mcIdType *retIPtr=retI->getPointer();
+ *retIPtr=0;
+ for(std::vector< std::vector<mcIdType> >::const_iterator it1=tmp.begin();it1!=tmp.end();it1++,retIPtr++)
+ retIPtr[1]=retIPtr[0]+ToIdType((*it1).size());
+ if(nbOfTuples!=retI->getIJ(ToIdType(targetNb),0))
+ throw INTERP_KERNEL::Exception("DataArrayInt::changeSurjectiveFormat : big problem should never happen !");
+ MCAuto<DataArrayIdType> ret(DataArrayIdType::New());
+ ret->alloc(nbOfTuples,1);
+ mcIdType *retPtr=ret->getPointer();
+ for(std::vector< std::vector<mcIdType> >::const_iterator it1=tmp.begin();it1!=tmp.end();it1++)
+ retPtr=std::copy((*it1).begin(),(*it1).end(),retPtr);
+ arr=ret.retn();
+ arrI=retI.retn();
+ }
+
+ /*!
+ * Returns a new DataArrayInt containing a renumbering map in "New to Old" mode,
+ * which if applied to \a this array would make it sorted ascendingly.
+ * For more info on renumbering see \ref numbering. <br>
+ * \b Example: <br>
+ * - \a this: [2,0,1,1,0,1,2,0,1,1,0,0]
+ * - result: [10,0,5,6,1,7,11,2,8,9,3,4]
+ * - after applying result to \a this: [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2]
+ *
+ * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
+ * array using decrRef() as it is no more needed.
+ * \throw If \a this is not allocated.
+ * \throw If \a this->getNumberOfComponents() != 1.
+ */
+ template <class T>
+ DataArrayIdType *DataArrayDiscrete<T>::buildPermArrPerLevel() const
+ {
+ this->checkAllocated();
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::buildPermArrPerLevel : number of components must == 1 !");
+ mcIdType nbOfTuples=this->getNumberOfTuples();
+ const T *pt=this->getConstPointer();
+ std::map<T,mcIdType> m;
+ MCAuto<DataArrayIdType> ret=DataArrayIdType::New();
+ ret->alloc(nbOfTuples,1);
+ mcIdType *opt=ret->getPointer();
+ for(mcIdType i=0;i<nbOfTuples;i++,pt++,opt++)
+ {
+ T val=*pt;
+ typename std::map<T,mcIdType>::iterator it=m.find(val);
+ if(it!=m.end())
+ {
+ *opt=(*it).second;
+ (*it).second++;
+ }
+ else
+ {
+ *opt=0;
+ m.insert(std::pair<T,mcIdType>(val,1));
+ }
+ }
+ mcIdType sum=0;
+ for(typename std::map<T,mcIdType>::iterator it=m.begin();it!=m.end();it++)
+ {
+ mcIdType vt=(*it).second;
+ (*it).second=sum;
+ sum+=vt;
+ }
+ pt=this->getConstPointer();
+ opt=ret->getPointer();
+ for(mcIdType i=0;i<nbOfTuples;i++,pt++,opt++)
+ *opt+=m[*pt];
+ //
+ return ret.retn();
+ }
+
+ /*!
+ * Checks if \a this array has the given size, and if its contents is equal to an array filled with
+ * iota(). This method is particularly useful for DataArrayInt instances that represent
+ * a renumbering array, to check if there is a real need in renumbering.
+ * This method checks than \a this can be considered as an identity mapping
+ * of a set having \a sizeExpected elements into itself.
+ *
+ * \param [in] sizeExpected - The number of elements expected.
+ * \return bool - \a true if \a this array contents == \a range( \a this->getNumberOfTuples())
+ * \throw If \a this is not allocated.
+ * \throw If \a this->getNumberOfComponents() != 1.
+ */
+ template <class T>
+ bool DataArrayDiscrete<T>::isIota(mcIdType sizeExpected) const
+ {
+ this->checkAllocated();
+ if(this->getNumberOfComponents()!=1)
+ return false;
+ mcIdType nbOfTuples(this->getNumberOfTuples());
+ if(nbOfTuples!=sizeExpected)
+ return false;
+ const T *pt=this->getConstPointer();
+ for(mcIdType i=0;i<nbOfTuples;i++,pt++)
+ if(*pt!=i)
+ return false;
+ return true;
+ }
+
+ /*!
+ * Checks if all values in \a this array are equal to \a val.
+ * \param [in] val - value to check equality of array values to.
+ * \return bool - \a true if all values are \a val.
+ * \throw If \a this is not allocated.
+ * \throw If \a this->getNumberOfComponents() != 1
+ * \sa DataArrayInt::checkUniformAndGuess
+ */
+ template <class T>
+ bool DataArrayDiscrete<T>::isUniform(T val) const
+ {
+ this->checkAllocated();
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::isUniform : must be applied on DataArrayInt with only one component, you can call 'rearrange' method before !");
+ const T *w(this->begin()),*end2(this->end());
+ for(;w!=end2;w++)
+ if(*w!=val)
+ return false;
+ return true;
+ }
+
+ /*!
+ * This method checks that \a this is uniform. If not and exception will be thrown.
+ * In case of uniformity the corresponding value is returned.
+ *
+ * \return mcIdType - the unique value contained in this
+ * \throw If \a this is not allocated.
+ * \throw If \a this->getNumberOfComponents() != 1
+ * \throw If \a this is not uniform.
+ * \sa DataArrayInt::isUniform
+ */
+ template <class T>
+ T DataArrayDiscrete<T>::checkUniformAndGuess() const
+ {
+ this->checkAllocated();
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::checkUniformAndGuess : must be applied on DataArrayInt with only one component, you can call 'rearrange' method before !");
+ if(this->empty())
+ throw INTERP_KERNEL::Exception("DataArrayInt::checkUniformAndGuess : this is empty !");
+ const T *w(this->begin()),*end2(this->end());
+ T ret(*w);
+ for(;w!=end2;w++)
+ if(*w!=ret)
+ throw INTERP_KERNEL::Exception("DataArrayInt::checkUniformAndGuess : this is not uniform !");
+ return ret;
+ }
+
+ /*!
+ * Checks if all values in \a this array are unique.
+ * \return bool - \a true if condition above is true
+ * \throw If \a this is not allocated.
+ * \throw If \a this->getNumberOfComponents() != 1
+ */
+ template <class T>
+ bool DataArrayDiscrete<T>::hasUniqueValues() const
+ {
+ this->checkAllocated();
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::hasOnlyUniqueValues: must be applied on DataArrayInt with only one component, you can call 'rearrange' method before !");
+ std::size_t nbOfElements(this->getNumberOfTuples());
+ std::set<T> s(this->begin(),this->end()); // in C++11, should use unordered_set (O(1) complexity)
+ if (s.size() != nbOfElements)
+ return false;
+ return true;
+ }
+
+ /*!
+ * Copy all components in a specified order from another DataArrayInt.
+ * The specified components become the first ones in \a this array.
+ * Both numerical and textual data is copied. The number of tuples in \a this and
+ * the other array can be different.
+ * \param [in] a - the array to copy data from.
+ * \param [in] compoIds - sequence of zero based indices of components, data of which is
+ * to be copied.
+ * \throw If \a a is NULL.
+ * \throw If \a compoIds.size() != \a a->getNumberOfComponents().
+ * \throw If \a compoIds[i] < 0 or \a compoIds[i] > \a this->getNumberOfComponents().
+ *
+ * \if ENABLE_EXAMPLES
+ * \ref py_mcdataarrayint_setselectedcomponents "Here is a Python example".
+ * \endif
+ */
+ template <class T>
+ void DataArrayDiscrete<T>::setSelectedComponents(const DataArrayType *a, const std::vector<std::size_t>& compoIds)
+ {
+ if(!a)
+ throw INTERP_KERNEL::Exception("DataArrayInt::setSelectedComponents : input DataArrayInt is NULL !");
+ this->checkAllocated();
+ a->checkAllocated();
+ this->copyPartOfStringInfoFrom2(compoIds,*a);
+ std::size_t partOfCompoSz=compoIds.size();
+ std::size_t nbOfCompo = this->getNumberOfComponents();
+ mcIdType nbOfTuples=std::min(this->getNumberOfTuples(),a->getNumberOfTuples());
+ const T *ac=a->getConstPointer();
+ T *nc=this->getPointer();
+ for(mcIdType i=0;i<nbOfTuples;i++)
+ for(std::size_t j=0;j<partOfCompoSz;j++,ac++)
+ nc[nbOfCompo*i+compoIds[j]]=*ac;
+ }
+
+ /*!
+ * Creates a new DataArrayInt containing IDs (indices) of tuples holding value \b not
+ * equal to a given one.
+ * \param [in] val - the value to ignore within \a this.
+ * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
+ * array using decrRef() as it is no more needed.
+ * \throw If \a this is not allocated.
+ * \throw If \a this->getNumberOfComponents() != 1.
+ */
+ template <class T>
+ DataArrayIdType *DataArrayDiscrete<T>::findIdsNotEqual(T val) const
+ {
+ this->checkAllocated();
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::findIdsNotEqual : the array must have only one component, you can call 'rearrange' method before !");
+ const T *cptr(this->getConstPointer());
+ MCAuto<DataArrayIdType> ret(DataArrayIdType::New());
+ ret->alloc(0,1);
+ mcIdType nbOfTuples(this->getNumberOfTuples());
+ for(mcIdType i=0;i<nbOfTuples;i++,cptr++)
+ if(*cptr!=val)
+ ret->pushBackSilent(i);
+ return ret.retn();
+ }
+
+ /*!
+ * Creates a new DataArrayInt containing IDs (indices) of tuples holding tuple equal to those defined by [ \a tupleBg , \a tupleEnd )
+ * This method is an extension of DataArrayInt::findIdsEqual method.
+ *
+ * \param [in] tupleBg - the begin (included) of the input tuple to find within \a this.
+ * \param [in] tupleEnd - the end (excluded) of the input tuple to find within \a this.
+ * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
+ * array using decrRef() as it is no more needed.
+ * \throw If \a this is not allocated.
+ * \throw If \a this->getNumberOfComponents() != std::distance(tupleBg,tupleEnd).
+ * \throw If \a this->getNumberOfComponents() is equal to 0.
+ * \sa DataArrayInt::findIdsEqual
+ */
+ template <class T>
+ DataArrayIdType *DataArrayDiscrete<T>::findIdsEqualTuple(const T *tupleBg, const T *tupleEnd) const
+ {
+ std::size_t nbOfCompoExp=std::distance(tupleBg,tupleEnd);
+ this->checkAllocated();
+ if(this->getNumberOfComponents()!=nbOfCompoExp)
+ {
+ std::ostringstream oss; oss << "DataArrayInt::findIdsEqualTuple : mismatch of number of components. Input tuple has " << nbOfCompoExp << " whereas this array has " << this->getNumberOfComponents() << " components !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
+ if(nbOfCompoExp==0)
+ throw INTERP_KERNEL::Exception("DataArrayInt::findIdsEqualTuple : number of components should be > 0 !");
+ MCAuto<DataArrayIdType> ret(DataArrayIdType::New());
+ ret->alloc(0,1);
+ const T *bg(this->begin()),*end2(this->end()),*work(this->begin());
+ while(work!=end2)
+ {
+ work=std::search(work,end2,tupleBg,tupleEnd);
+ if(work!=end2)
+ {
+ std::ptrdiff_t pos=std::distance(bg,work);
+ if(pos%nbOfCompoExp==0)
+ ret->pushBackSilent(ToIdType(pos/nbOfCompoExp));
+ work++;
+ }
+ }
+ return ret.retn();
+ }
+
+ /*!
+ * Creates a new DataArrayInt containing IDs (indices) of tuples holding value equal to
+ * one of given values.
+ * \param [in] valsBg - an array of values to find within \a this array.
+ * \param [in] valsEnd - specifies the end of the array \a valsBg, so that
+ * the last value of \a valsBg is \a valsEnd[ -1 ].
+ * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
+ * array using decrRef() as it is no more needed.
+ * \throw If \a this->getNumberOfComponents() != 1.
+ */
+ template <class T>
+ DataArrayIdType *DataArrayDiscrete<T>::findIdsEqualList(const T *valsBg, const T *valsEnd) const
+ {
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::findIdsEqualList : the array must have only one component, you can call 'rearrange' method before !");
+ std::set<T> vals2(valsBg,valsEnd);
+ const T *cptr(this->getConstPointer());
+ mcIdType nbOfTuples(this->getNumberOfTuples());
+ MCAuto<DataArrayIdType> ret(DataArrayIdType::New()); ret->alloc(0,1);
+ for(mcIdType i=0;i<nbOfTuples;i++,cptr++)
+ if(vals2.find(*cptr)!=vals2.end())
+ ret->pushBackSilent(i);
+ return ret.retn();
+ }
+
+ /*!
+ * Creates a new DataArrayInt containing IDs (indices) of tuples holding values \b not
+ * equal to any of given values.
+ * \param [in] valsBg - an array of values to ignore within \a this array.
+ * \param [in] valsEnd - specifies the end of the array \a valsBg, so that
+ * the last value of \a valsBg is \a valsEnd[ -1 ].
+ * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
+ * array using decrRef() as it is no more needed.
+ * \throw If \a this->getNumberOfComponents() != 1.
+ */
+ template <class T>
+ DataArrayIdType *DataArrayDiscrete<T>::findIdsNotEqualList(const T *valsBg, const T *valsEnd) const
+ {
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::findIdsNotEqualList : the array must have only one component, you can call 'rearrange' method before !");
+ std::set<T> vals2(valsBg,valsEnd);
+ const T *cptr=this->getConstPointer();
+ mcIdType nbOfTuples(this->getNumberOfTuples());
+ MCAuto<DataArrayIdType> ret(DataArrayIdType::New()); ret->alloc(0,1);
+ for(mcIdType i=0;i<nbOfTuples;i++,cptr++)
+ if(vals2.find(*cptr)==vals2.end())
+ ret->pushBackSilent(i);
+ return ret.retn();
+ }
+
+ /*!
+ * This method expects to be called when number of components of this is equal to one.
+ * This method returns the tuple id, if it exists, of the first tuple equal to \b value.
+ * If not any tuple contains \b value -1 is returned.
+ * \sa DataArrayInt::presenceOfValue
+ */
+ template <class T>
+ mcIdType DataArrayDiscrete<T>::findIdFirstEqual(T value) const
+ {
+ this->checkAllocated();
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::presenceOfValue : the array must have only one component, you can call 'rearrange' method before !");
+ const T *cptr=this->getConstPointer();
+ mcIdType nbOfTuples(this->getNumberOfTuples());
+ const T *ret=std::find(cptr,cptr+nbOfTuples,value);
+ if(ret!=cptr+nbOfTuples)
+ return ToIdType(std::distance(cptr,ret));
+ return -1;
+ }
+
+ /*!
+ * This method expects to be called when number of components of this is equal to one.
+ * This method returns the tuple id, if it exists, of the first tuple so that the value is contained in \b vals.
+ * If not any tuple contains one of the values contained in 'vals' -1 is returned.
+ * \sa DataArrayInt::presenceOfValue
+ */
+ template <class T>
+ mcIdType DataArrayDiscrete<T>::findIdFirstEqual(const std::vector<T>& vals) const
+ {
+ this->checkAllocated();
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::presenceOfValue : the array must have only one component, you can call 'rearrange' method before !");
+ std::set<T> vals2(vals.begin(),vals.end());
+ const T *cptr=this->getConstPointer();
+ mcIdType nbOfTuples(this->getNumberOfTuples());
+ for(const T *w=cptr;w!=cptr+nbOfTuples;w++)
+ if(vals2.find(*w)!=vals2.end())
+ return ToIdType(std::distance(cptr,w));
+ return -1;
+ }
+
+ /*!
+ * This method is an extension of DataArrayInt::findIdFirstEqual method because this method works for DataArrayInt with
+ * any number of components excepted 0 (an INTERP_KERNEL::Exception is thrown in this case).
+ * This method searches in \b this is there is a tuple that matched the input parameter \b tupl.
+ * If any the tuple id is returned. If not -1 is returned.
+ *
+ * This method throws an INTERP_KERNEL::Exception if the number of components in \b this mismatches with the size of
+ * the input vector. An INTERP_KERNEL::Exception is thrown too if \b this is not allocated.
+ *
+ * \return tuple id where \b tupl is. -1 if no such tuple exists in \b this.
+ * \sa DataArrayInt::findIdSequence, DataArrayInt::presenceOfTuple.
+ */
+ template <class T>
+ mcIdType DataArrayDiscrete<T>::findIdFirstEqualTuple(const std::vector<T>& tupl) const
+ {
+ this->checkAllocated();
+ std::size_t nbOfCompo(this->getNumberOfComponents());
+ if(nbOfCompo==0)
+ throw INTERP_KERNEL::Exception("DataArrayInt::findIdFirstEqualTuple : 0 components in 'this' !");
+ if(nbOfCompo!=tupl.size())
+ {
+ std::ostringstream oss; oss << "DataArrayInt::findIdFirstEqualTuple : 'this' contains " << nbOfCompo << " components and searching for a tuple of length " << tupl.size() << " !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
+ const T *cptr=this->getConstPointer();
+ std::size_t nbOfVals=this->getNbOfElems();
+ for(const T *work=cptr;work!=cptr+nbOfVals;)
+ {
+ work=std::search(work,cptr+nbOfVals,tupl.begin(),tupl.end());
+ if(work!=cptr+nbOfVals)
+ {
+ if(std::distance(cptr,work)%nbOfCompo!=0)
+ work++;
+ else
+ return ToIdType (std::distance(cptr,work)/nbOfCompo);
+ }
+ }
+ return -1;
+ }
+
+ /*!
+ * This method searches the sequence specified in input parameter \b vals in \b this.
+ * This works only for DataArrayInt having number of components equal to one (if not an INTERP_KERNEL::Exception will be thrown).
+ * This method differs from DataArrayInt::findIdFirstEqualTuple in that the position is internal raw data is not considered here contrary to DataArrayInt::findIdFirstEqualTuple.
+ * \sa DataArrayInt::findIdFirstEqualTuple
+ */
+ template <class T>
+ mcIdType DataArrayDiscrete<T>::findIdSequence(const std::vector<T>& vals) const
+ {
+ this->checkAllocated();
+ std::size_t nbOfCompo=this->getNumberOfComponents();
+ if(nbOfCompo!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::findIdSequence : works only for DataArrayInt instance with one component !");
+ const T *cptr=this->getConstPointer();
+ std::size_t nbOfVals=this->getNbOfElems();
+ const T *loc=std::search(cptr,cptr+nbOfVals,vals.begin(),vals.end());
+ if(loc!=cptr+nbOfVals)
+ return ToIdType(std::distance(cptr,loc));
+ return -1;
+ }
+
+ /*!
+ * Assigns \a newValue to all elements holding \a oldValue within \a this
+ * one-dimensional array.
+ * \param [in] oldValue - the value to replace.
+ * \param [in] newValue - the value to assign.
+ * \return mcIdType - number of replacements performed.
+ * \throw If \a this is not allocated.
+ * \throw If \a this->getNumberOfComponents() != 1.
+ */
+ template <class T>
+ mcIdType DataArrayDiscrete<T>::changeValue(T oldValue, T newValue)
+ {
+ this->checkAllocated();
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::changeValue : the array must have only one component, you can call 'rearrange' method before !");
+ if(oldValue==newValue)
+ return 0;
+ T *start(this->getPointer()),*end2(start+this->getNbOfElems());
+ mcIdType ret(0);
+ for(T *val=start;val!=end2;val++)
+ {
+ if(*val==oldValue)
+ {
+ *val=newValue;
+ ret++;
+ }
+ }
+ if(ret>0)
+ this->declareAsNew();
+ return ret;
+ }
+
+ /*!
+ * This method returns the number of values in \a this that are equals to input parameter \a value.
+ * This method only works for single component array.
+ *
+ * \return a value in [ 0, \c this->getNumberOfTuples() )
+ *
+ * \throw If \a this is not allocated
+ *
+ */
+ template <class T>
+ mcIdType DataArrayDiscrete<T>::count(T value) const
+ {
+ mcIdType ret=0;
+ this->checkAllocated();
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::count : must be applied on DataArrayInt with only one component, you can call 'rearrange' method before !");
+ const T *vals=this->begin();
+ std::size_t nbOfElements=this->getNumberOfTuples();
+ for(std::size_t i=0;i<nbOfElements;i++,vals++)
+ if(*vals==value)
+ ret++;
+ return ret;
+ }
+
+ /*!
+ * This method is an extension of DataArrayInt::presenceOfValue method because this method works for DataArrayInt with
+ * any number of components excepted 0 (an INTERP_KERNEL::Exception is thrown in this case).
+ * This method searches in \b this is there is a tuple that matched the input parameter \b tupl.
+ * This method throws an INTERP_KERNEL::Exception if the number of components in \b this mismatches with the size of
+ * the input vector. An INTERP_KERNEL::Exception is thrown too if \b this is not allocated.
+ * \sa DataArrayInt::findIdFirstEqualTuple
+ */
+ template <class T>
+ bool DataArrayDiscrete<T>::presenceOfTuple(const std::vector<T>& tupl) const
+ {
+ return this->findIdFirstEqualTuple(tupl)!=-1;
+ }
+
+
+ /*!
+ * Returns \a true if a given value is present within \a this one-dimensional array.
+ * \param [in] value - the value to find within \a this array.
+ * \return bool - \a true in case if \a value is present within \a this array.
+ * \throw If \a this is not allocated.
+ * \throw If \a this->getNumberOfComponents() != 1.
+ * \sa findIdFirstEqual()
+ */
+ template <class T>
+ bool DataArrayDiscrete<T>::presenceOfValue(T value) const
+ {
+ return this->findIdFirstEqual(value)!=-1;
+ }
+
+ /*!
+ * This method expects to be called when number of components of this is equal to one.
+ * This method returns true if it exists a tuple so that the value is contained in \b vals.
+ * If not any tuple contains one of the values contained in 'vals' false is returned.
+ * \sa DataArrayInt::findIdFirstEqual
+ */
+ template <class T>
+ bool DataArrayDiscrete<T>::presenceOfValue(const std::vector<T>& vals) const
+ {
+ return this->findIdFirstEqual(vals)!=-1;
+ }
+
+ /*!
+ * Accumulates values of each component of \a this array.
+ * \param [out] res - an array of length \a this->getNumberOfComponents(), allocated
+ * by the caller, that is filled by this method with sum value for each
+ * component.
+ * \throw If \a this is not allocated.
+ */
+ template <class T>
+ void DataArrayDiscrete<T>::accumulate(T *res) const
+ {
+ this->checkAllocated();
+ const T *ptr=this->getConstPointer();
+ mcIdType nbTuple(this->getNumberOfTuples());
+ std::size_t nbComps(this->getNumberOfComponents());
+ std::fill(res,res+nbComps,0);
+ for(mcIdType i=0;i<nbTuple;i++)
+ std::transform(ptr+i*nbComps,ptr+(i+1)*nbComps,res,res,std::plus<T>());
+ }
+
+ template <class T>
+ T DataArrayDiscrete<T>::accumulate(std::size_t compId) const
+ {
+ this->checkAllocated();
+ const T *ptr=this->getConstPointer();
+ mcIdType nbTuple(this->getNumberOfTuples());
+ std::size_t nbComps(this->getNumberOfComponents());
+ if(compId>=nbComps) // compId >= 0 (it is a size_t)
+ throw INTERP_KERNEL::Exception("DataArrayInt::accumulate : Invalid compId specified : No such nb of components !");
+ T ret=0;
+ for(mcIdType i=0;i<nbTuple;i++)
+ ret+=ptr[i*nbComps+compId];
+ return ret;
+ }
+
+ /*!
+ * This method accumulate using addition tuples in \a this using input index array [ \a bgOfIndex, \a endOfIndex ).
+ * The returned array will have same number of components than \a this and number of tuples equal to
+ * \c std::distance(bgOfIndex,endOfIndex) \b minus \b one.
+ *
+ * The input index array is expected to be ascendingly sorted in which the all referenced ids should be in [0, \c this->getNumberOfTuples).
+ *
+ * \param [in] bgOfIndex - begin (included) of the input index array.
+ * \param [in] endOfIndex - end (excluded) of the input index array.
+ * \return DataArrayInt * - the new instance having the same number of components than \a this.
+ *
+ * \throw If bgOfIndex or end is NULL.
+ * \throw If input index array is not ascendingly sorted.
+ * \throw If there is an id in [ \a bgOfIndex, \a endOfIndex ) not in [0, \c this->getNumberOfTuples).
+ * \throw If std::distance(bgOfIndex,endOfIndex)==0.
+ */
+ template <class T>
+ typename Traits<T>::ArrayType *DataArrayDiscrete<T>::accumulatePerChunck(const mcIdType *bgOfIndex, const mcIdType *endOfIndex) const
+ {
+ if(!bgOfIndex || !endOfIndex)
+ throw INTERP_KERNEL::Exception("DataArrayInt::accumulatePerChunck : input pointer NULL !");
+ this->checkAllocated();
+ std::size_t nbCompo(this->getNumberOfComponents());
+ mcIdType nbOfTuples(this->getNumberOfTuples());
+ mcIdType sz=ToIdType(std::distance(bgOfIndex,endOfIndex));
+ if(sz<1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::accumulatePerChunck : invalid size of input index array !");
+ sz--;
+ MCAuto<DataArrayType> ret=DataArrayType::New(); ret->alloc(sz,nbCompo);
+ const mcIdType *w=bgOfIndex;
+ if(*w<0 || *w>=nbOfTuples)
+ throw INTERP_KERNEL::Exception("DataArrayInt::accumulatePerChunck : The first element of the input index not in [0,nbOfTuples) !");
+ const T *srcPt=this->begin()+(*w)*nbCompo;
+ T *tmp=ret->getPointer();
+ for(mcIdType i=0;i<sz;i++,tmp+=nbCompo,w++)
+ {
+ std::fill(tmp,tmp+nbCompo,0);
+ if(w[1]>=w[0])
+ {
+ for(mcIdType j=w[0];j<w[1];j++,srcPt+=nbCompo)
+ {
+ if(j>=0 && j<nbOfTuples)
+ std::transform(srcPt,srcPt+nbCompo,tmp,tmp,std::plus<T>());
+ else
+ {
+ std::ostringstream oss; oss << "DataArrayInt::accumulatePerChunck : At rank #" << i << " the input index array points to id " << j << " should be in [0," << nbOfTuples << ") !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
+ }
+ }
+ else
+ {
+ std::ostringstream oss; oss << "DataArrayInt::accumulatePerChunck : At rank #" << i << " the input index array is not in ascendingly sorted.";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
+ }
+ ret->copyStringInfoFrom(*this);
+ return ret.retn();
+ }
+
+ /*!
+ * Returns in a single walk in \a this the min value and the max value in \a this.
+ * \a this is expected to be single component array.
+ *
+ * \param [out] minValue - the min value in \a this.
+ * \param [out] maxValue - the max value in \a this.
+ *
+ * \sa getMinValueInArray, getMinValue, getMaxValueInArray, getMaxValue
+ */
+ template <class T>
+ void DataArrayDiscrete<T>::getMinMaxValues(T& minValue, T& maxValue) const
+ {
+ this->checkAllocated();
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::getMinMaxValues : must be applied on DataArrayInt with only one component !");
+ std::size_t nbElements(this->getNumberOfTuples());
+ const T *pt(this->begin());
+ minValue=std::numeric_limits<T>::max(); maxValue=-std::numeric_limits<T>::max();
+ for(std::size_t i=0;i<nbElements;i++,pt++)
+ {
+ if(*pt<minValue)
+ minValue=*pt;
+ if(*pt>maxValue)
+ maxValue=*pt;
+ }
+ }
+
+ /*!
+ * Modify all elements of \a this array, so that
+ * an element _x_ becomes \f$ numerator / x \f$.
+ * \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.
+ * \param [in] numerator - the numerator used to modify array elements.
+ * \throw If \a this is not allocated.
+ * \throw If there is an element equal to 0 in \a this array.
+ */
+ template <class T>
+ void DataArrayDiscrete<T>::applyInv(T numerator)
+ {
+ this->checkAllocated();
+ T *ptr=this->getPointer();
+ std::size_t nbOfElems=this->getNbOfElems();
+ for(std::size_t i=0;i<nbOfElems;i++,ptr++)
+ {
+ if(*ptr!=0)
+ {
+ *ptr=numerator/(*ptr);
+ }
+ else
+ {
+ std::ostringstream oss; oss << "DataArrayInt::applyInv : presence of null value in tuple #" << i/(this->getNumberOfComponents()) << " component #" << i%(this->getNumberOfComponents());
+ oss << " !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
+ }
+ this->declareAsNew();
+ }
+
+ /*!
+ * Modify all elements of \a this array, so that
+ * an element _x_ becomes \f$ x / val \f$.
+ * \param [in] val - the denominator used to modify array elements.
+ * \throw If \a this is not allocated.
+ * \throw If \a val == 0.
+ */
+ template <class T>
+ void DataArrayDiscrete<T>::applyDivideBy(T val)
+ {
+ if(val==0)
+ throw INTERP_KERNEL::Exception("DataArrayInt::applyDivideBy : Trying to divide by 0 !");
+ this->checkAllocated();
+ T *ptr=this->getPointer();
+ std::size_t nbOfElems=this->getNbOfElems();
+ std::transform(ptr,ptr+nbOfElems,ptr,std::bind(std::divides<T>(),std::placeholders::_1,val));
+ this->declareAsNew();
+ }
+
+ /*!
+ * Modify all elements of \a this array, so that
+ * an element _x_ becomes <em> x % val </em>.
+ * \param [in] val - the divisor used to modify array elements.
+ * \throw If \a this is not allocated.
+ * \throw If \a val <= 0.
+ */
+ template <class T>
+ void DataArrayDiscrete<T>::applyModulus(T val)
+ {
+ if(val<=0)
+ throw INTERP_KERNEL::Exception("DataArrayInt::applyDivideBy : Trying to operate modulus on value <= 0 !");
+ this->checkAllocated();
+ T *ptr=this->getPointer();
+ std::size_t nbOfElems=this->getNbOfElems();
+ std::transform(ptr,ptr+nbOfElems,ptr,std::bind(std::modulus<T>(),std::placeholders::_1,val));
+ this->declareAsNew();
+ }
+
+ /*!
+ * Modify all elements of \a this array, so that
+ * an element _x_ becomes <em> val % x </em>.
+ * \warning If an exception is thrown because of presence of an element <= 0 in \a this
+ * array, all elements processed before detection of the zero element remain
+ * modified.
+ * \param [in] val - the divident used to modify array elements.
+ * \throw If \a this is not allocated.
+ * \throw If there is an element equal to or less than 0 in \a this array.
+ */
+ template <class T>
+ void DataArrayDiscrete<T>::applyRModulus(T val)
+ {
+ this->checkAllocated();
+ T *ptr=this->getPointer();
+ std::size_t nbOfElems=this->getNbOfElems();
+ for(std::size_t i=0;i<nbOfElems;i++,ptr++)
+ {
+ if(*ptr>0)
+ {
+ *ptr=val%(*ptr);
+ }
+ else
+ {
+ std::ostringstream oss; oss << "DataArrayInt::applyRModulus : presence of value <=0 in tuple #" << i/(this->getNumberOfComponents()) << " component #" << i%(this->getNumberOfComponents());
+ oss << " !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
+ }
+ this->declareAsNew();
+ }
+
+ /*!
+ * Modify all elements of \a this array, so that
+ * an element _x_ becomes <em> val ^ x </em>.
+ * \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.
+ */
+ template <class T>
+ void DataArrayDiscrete<T>::applyPow(T val)
+ {
+ this->checkAllocated();
+ if(val<0)
+ throw INTERP_KERNEL::Exception("DataArrayInt::applyPow : input pow in < 0 !");
+ T *ptr=this->getPointer();
+ std::size_t nbOfElems=this->getNbOfElems();
+ if(val==0)
+ {
+ std::fill(ptr,ptr+nbOfElems,1);
+ return ;
+ }
+ for(std::size_t i=0;i<nbOfElems;i++,ptr++)
+ {
+ T tmp=1;
+ for(T j=0;j<val;j++)
+ tmp*=*ptr;
+ *ptr=tmp;
+ }
+ this->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 there is an element < 0 in \a this array.
+ * \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.
+ */
+ template <class T>
+ void DataArrayDiscrete<T>::applyRPow(T val)
+ {
+ this->checkAllocated();
+ T *ptr=this->getPointer();
+ std::size_t nbOfElems=this->getNbOfElems();
+ for(std::size_t i=0;i<nbOfElems;i++,ptr++)
+ {
+ if(*ptr>=0)
+ {
+ T tmp=1;
+ for(T j=0;j<*ptr;j++)
+ tmp*=val;
+ *ptr=tmp;
+ }
+ else
+ {
+ std::ostringstream oss; oss << "DataArrayInt::applyRPow : presence of negative value in tuple #" << i/(this->getNumberOfComponents()) << " component #" << i%(this->getNumberOfComponents());
+ oss << " !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
+ }
+ this->declareAsNew();
+ }
+
+ /*!
+ * This method works only on data array with one component.
+ * This method returns a newly allocated array storing stored ascendantly tuple ids in \b this so that
+ * this[*id] in [\b vmin,\b vmax)
+ *
+ * \param [in] vmin begin of range. This value is included in range (included).
+ * \param [in] vmax end of range. This value is \b not included in range (excluded).
+ * \return a newly allocated data array that the caller should deal with.
+ *
+ * \sa DataArrayInt::findIdsNotInRange , DataArrayInt::findIdsStricltyNegative
+ */
+ template <class T>
+ DataArrayIdType *DataArrayDiscrete<T>::findIdsInRange(T vmin, T vmax) const
+ {
+ InRange<T> ir(vmin,vmax);
+ MCAuto<DataArrayIdType> ret(this->findIdsAdv(ir));
+ return ret.retn();
+ }
+
+ /*!
+ * This method works only on data array with one component.
+ * This method returns a newly allocated array storing stored ascendantly tuple ids in \b this so that
+ * this[*id] \b not in [\b vmin,\b vmax)
+ *
+ * \param [in] vmin begin of range. This value is \b not included in range (excluded).
+ * \param [in] vmax end of range. This value is included in range (included).
+ * \return a newly allocated data array that the caller should deal with.
+ *
+ * \sa DataArrayInt::findIdsInRange , DataArrayInt::findIdsStricltyNegative
+ */
+ template <class T>
+ DataArrayIdType *DataArrayDiscrete<T>::findIdsNotInRange(T vmin, T vmax) const
+ {
+ NotInRange<T> nir(vmin,vmax);
+ MCAuto<DataArrayIdType> ret(this->findIdsAdv(nir));
+ return ret.retn();
+ }
+
+ /*!
+ * This method works only on data array with one component.
+ * This method checks that all ids in \b this are in [ \b vmin, \b vmax ). If there is at least one element in \a this not in [ \b vmin, \b vmax ) an exception will be thrown.
+ *
+ * \param [in] vmin begin of range. This value is included in range (included).
+ * \param [in] vmax end of range. This value is \b not included in range (excluded).
+ * \return if all ids in \a this are so that (*this)[i]==i for all i in [ 0, \c this->getNumberOfTuples() ). */
+ template <class T>
+ bool DataArrayDiscrete<T>::checkAllIdsInRange(T vmin, T vmax) const
+ {
+ this->checkAllocated();
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::checkAllIdsInRange : this must have exactly one component !");
+ mcIdType nbOfTuples(this->getNumberOfTuples());
+ bool ret=true;
+ const T *cptr=this->getConstPointer();
+ for(mcIdType i=0;i<nbOfTuples;i++,cptr++)
+ {
+ if(*cptr>=vmin && *cptr<vmax)
+ { ret=ret && *cptr==i; }
+ else
+ {
+ std::ostringstream oss; oss << "DataArrayInt::checkAllIdsInRange : tuple #" << i << " has value " << *cptr << " should be in [" << vmin << "," << vmax << ") !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
+ }
+ return ret;
+ }
+
+ /*!
+ * Returns a new DataArrayInt which contains a complement of elements of \a this
+ * one-dimensional array. I.e. the result array contains all elements from the range [0,
+ * \a nbOfElement) not present in \a this array.
+ * \param [in] nbOfElement - maximal size of the result array.
+ * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
+ * array using decrRef() as it is no more needed.
+ * \throw If \a this is not allocated.
+ * \throw If \a this->getNumberOfComponents() != 1.
+ * \throw If any element \a x of \a this array violates condition ( 0 <= \a x < \a
+ * nbOfElement ).
+ */
+ template <class T>
+ DataArrayIdType *DataArrayDiscrete<T>::buildComplement(mcIdType nbOfElement) const
+ {
+ this->checkAllocated();
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::buildComplement : only single component allowed !");
+ std::vector<bool> tmp(nbOfElement);
+ const T *pt=this->getConstPointer();
+ std::size_t nbOfElements=this->getNumberOfTuples();
+ for(const T *w=pt;w!=pt+nbOfElements;w++)
+ if(*w>=0 && *w<nbOfElement)
+ tmp[*w]=true;
+ else
+ throw INTERP_KERNEL::Exception("DataArrayInt::buildComplement : an element is not in valid range : [0,nbOfElement) !");
+ std::size_t nbOfRetVal=std::count(tmp.begin(),tmp.end(),false);
+ DataArrayIdType *ret=DataArrayIdType::New();
+ ret->alloc(nbOfRetVal,1);
+ mcIdType j=0;
+ mcIdType *retPtr=ret->getPointer();
+ for(mcIdType i=0;i<nbOfElement;i++)
+ if(!tmp[i])
+ retPtr[j++]=i;
+ return ret;
+ }
+
+ /*!
+ * Returns a new DataArrayInt containing elements of \a this one-dimensional missing
+ * from an \a other one-dimensional array.
+ * \param [in] other - a DataArrayInt containing elements not to include in the result array.
+ * \return DataArrayInt * - a new instance of DataArrayInt with one component. The
+ * caller is to delete this array using decrRef() as it is no more needed.
+ * \throw If \a other is NULL.
+ * \throw If \a other is not allocated.
+ * \throw If \a other->getNumberOfComponents() != 1.
+ * \throw If \a this is not allocated.
+ * \throw If \a this->getNumberOfComponents() != 1.
+ * \sa DataArrayInt::buildSubstractionOptimized()
+ */
+ template <class T>
+ typename Traits<T>::ArrayType *DataArrayDiscrete<T>::buildSubstraction(const DataArrayType *other) const
+ {
+ if(!other)
+ throw INTERP_KERNEL::Exception("DataArrayInt::buildSubstraction : DataArrayInt pointer in input is NULL !");
+ this->checkAllocated();
+ other->checkAllocated();
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::buildSubstraction : only single component allowed !");
+ if(other->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::buildSubstraction : only single component allowed for other type !");
+ const T *pt=this->getConstPointer();
+ std::size_t nbOfElements=this->getNumberOfTuples();
+ std::set<T> s1(pt,pt+nbOfElements);
+ pt=other->getConstPointer();
+ nbOfElements=other->getNumberOfTuples();
+ std::set<T> s2(pt,pt+nbOfElements);
+ std::vector<T> r;
+ std::set_difference(s1.begin(),s1.end(),s2.begin(),s2.end(),std::back_insert_iterator< std::vector<T> >(r));
+ DataArrayType *ret=DataArrayType::New();
+ ret->alloc(r.size(),1);
+ std::copy(r.begin(),r.end(),ret->getPointer());
+ return ret;
+ }
+
+ /*!
+ * \a this is expected to have one component and to be sorted ascendingly (as for \a other).
+ * \a other is expected to be a part of \a this. If not DataArrayInt::buildSubstraction should be called instead.
+ *
+ * \param [in] other an array with one component and expected to be sorted ascendingly.
+ * \ret list of ids in \a this but not in \a other.
+ * \sa DataArrayInt::buildSubstraction
+ */
+ template <class T>
+ typename Traits<T>::ArrayType *DataArrayDiscrete<T>::buildSubstractionOptimized(const DataArrayType *other) const
+ {
+ static const char *MSG="DataArrayInt::buildSubstractionOptimized : only single component allowed !";
+ if(!other) throw INTERP_KERNEL::Exception("DataArrayInt::buildSubstractionOptimized : NULL input array !");
+ this->checkAllocated(); other->checkAllocated();
+ if(this->getNumberOfComponents()!=1) throw INTERP_KERNEL::Exception(MSG);
+ if(other->getNumberOfComponents()!=1) throw INTERP_KERNEL::Exception(MSG);
+ const T *pt1Bg(this->begin()),*pt1End(this->end()),*pt2Bg(other->begin()),*pt2End(other->end());
+ const T *work1(pt1Bg),*work2(pt2Bg);
+ MCAuto<DataArrayType> ret(DataArrayType::New()); ret->alloc(0,1);
+ for(;work1!=pt1End;work1++)
+ {
+ if(work2!=pt2End && *work1==*work2)
+ work2++;
+ else
+ ret->pushBackSilent(*work1);
+ }
+ return ret.retn();
+ }
+
+ /*!
+ * Returns a new DataArrayInt which contains all elements of \a this and a given
+ * one-dimensional arrays. The result array does not contain any duplicates
+ * and its values are sorted in ascending order.
+ * \param [in] other - an array to unite with \a this one.
+ * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
+ * array using decrRef() as it is no more needed.
+ * \throw If \a this or \a other is not allocated.
+ * \throw If \a this->getNumberOfComponents() != 1.
+ * \throw If \a other->getNumberOfComponents() != 1.
+ */
+ template <class T>
+ typename Traits<T>::ArrayType *DataArrayDiscrete<T>::buildUnion(const DataArrayType *other) const
+ {
+ std::vector<const DataArrayType *>arrs(2);
+ arrs[0]=dynamic_cast<const DataArrayType *>(this); arrs[1]=other;
+ return DataArrayDiscrete<T>::BuildUnion(arrs);
+ }
+
+ /*!
+ * Returns a new DataArrayInt which contains elements present in both \a this and a given
+ * one-dimensional arrays. The result array does not contain any duplicates
+ * and its values are sorted in ascending order.
+ * \param [in] other - an array to intersect with \a this one.
+ * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
+ * array using decrRef() as it is no more needed.
+ * \throw If \a this or \a other is not allocated.
+ * \throw If \a this->getNumberOfComponents() != 1.
+ * \throw If \a other->getNumberOfComponents() != 1.
+ */
+ template <class T>
+ typename Traits<T>::ArrayType *DataArrayDiscrete<T>::buildIntersection(const DataArrayType *other) const
+ {
+ std::vector<const DataArrayType *>arrs(2);
+ arrs[0]=dynamic_cast<const DataArrayType *>(this); arrs[1]=other;
+ return DataArrayDiscrete<T>::BuildIntersection(arrs);
+ }
+ /*!
+ * This method can be applied on allocated with one component DataArrayInt instance.
+ * Locate groups of all consecutive same values in \a this and return them into an indexed array of positions pointing to \a this starting with 0.
+ * Number of tuples of returned array is equal to size of \a this->buildUnique() + 1.
+ * Last value of returned array is equal to \a this->getNumberOfTuples()
+ *
+ * \b Example:
+ * - \a this : [0, 1, 1, 2, 2, 3, 4, 4, 5, 5, 5, 11]
+ * - \a return is : [0, 1, 3, 5, 6, 8, 11, 12]
+ *
+ * \return a newly allocated array containing the indexed array format of groups by same consecutive value.
+ * \throw if \a this is not allocated or if \a this has not exactly one component.
+ * \sa DataArrayInt::buildUnique, MEDCouplingSkyLineArray::groupPacks
+ */
+ template <class T>
+ DataArrayIdType *DataArrayDiscrete<T>::indexOfSameConsecutiveValueGroups() const
+ {
+ this->checkAllocated();
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::indexOfSameConsecutiveValueGroups : only single component allowed !");
+ const T *pt(this->begin());
+ const T *const ptEnd(this->end()) , * const ptBg(this->begin());
+ // first find nb of different values in this
+ std::size_t nbOfTuplesOut(0);
+ while( pt != ptEnd )
+ {
+ T val(*pt);
+ const T *endOfPack(std::find_if(pt+1,ptEnd,[val](T elt){ return val!=elt; }));
+ pt = endOfPack;
+ ++nbOfTuplesOut;
+ }
+ MCAuto<DataArrayIdType> ret(DataArrayIdType::New()); ret->alloc(nbOfTuplesOut+1,1);
+ mcIdType *retPtr(ret->getPointer()); *retPtr++ = 0;
+ pt = this->begin();
+ while( pt != ptEnd )
+ {
+ T val(*pt);
+ const T *endOfPack(std::find_if(pt+1,ptEnd,[val](T elt){ return val!=elt; }));
+ *retPtr++ = ToIdType( std::distance(ptBg,endOfPack) );
+ pt = endOfPack;
+ ++nbOfTuplesOut;
+ }
+ return ret.retn();
+ }
+
+ /*!
+ * This method can be applied on allocated with one component DataArrayInt instance.
+ * This method is typically relevant for sorted arrays. All consecutive duplicated items in \a this will appear only once in returned DataArrayInt instance.
+ * Example : if \a this contains [1,2,2,3,3,3,3,4,5,5,7,7,7,19] the returned array will contain [1,2,3,4,5,7,19]
+ *
+ * \return a newly allocated array that contain the result of the unique operation applied on \a this.
+ * \throw if \a this is not allocated or if \a this has not exactly one component.
+ * \sa DataArrayInt::buildUniqueNotSorted, DataArrayInt::indexOfSameConsecutiveValueGroups
+ */
+ template <class T>
+ typename Traits<T>::ArrayType *DataArrayDiscrete<T>::buildUnique() const
+ {
+ this->checkAllocated();
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::buildUnique : only single component allowed !");
+ std::size_t nbOfElements(this->getNumberOfTuples());
+ MCAuto<DataArrayType> tmp(DataArrayType::New());
+ tmp->deepCopyFrom(*this);
+ T *data(tmp->getPointer());
+ T *last(std::unique(data,data+nbOfElements));
+ MCAuto<DataArrayType> ret(DataArrayType::New());
+ ret->alloc(std::distance(data,last),1);
+ std::copy(data,last,ret->getPointer());
+ return ret.retn();
+ }
+
+ /*!
+ * This method can be applied on allocated with one component DataArrayInt instance.
+ * This method keep elements only once by keeping the same order in \a this that is not expected to be sorted.
+ *
+ * \return a newly allocated array that contain the result of the unique operation applied on \a this.
+ *
+ * \throw if \a this is not allocated or if \a this has not exactly one component.
+ *
+ * \sa DataArrayInt::buildUnique
+ */
+ template <class T>
+ typename Traits<T>::ArrayType *DataArrayDiscrete<T>::buildUniqueNotSorted() const
+ {
+ this->checkAllocated();
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::buildUniqueNotSorted : only single component allowed !");
+ T minVal,maxVal;
+ this->getMinMaxValues(minVal,maxVal);
+ std::vector<bool> b(maxVal-minVal+1,false);
+ const T *ptBg(this->begin()),*endBg(this->end());
+ MCAuto<DataArrayType> ret(DataArrayType::New()); ret->alloc(0,1);
+ for(const T *pt=ptBg;pt!=endBg;pt++)
+ {
+ if(!b[*pt-minVal])
+ {
+ ret->pushBackSilent(*pt);
+ b[*pt-minVal]=true;
+ }
+ }
+ ret->copyStringInfoFrom(*this);
+ return ret.retn();
+ }
+
+ /*!
+ * Returns a new DataArrayInt which contains size of every of groups described by \a this
+ * "index" array. Such "index" array is returned for example by
+ * \ref MEDCoupling::MEDCouplingUMesh::buildDescendingConnectivity
+ * "MEDCouplingUMesh::buildDescendingConnectivity" and
+ * \ref MEDCoupling::MEDCouplingUMesh::getNodalConnectivityIndex
+ * "MEDCouplingUMesh::getNodalConnectivityIndex" etc.
+ * This method performs the reverse operation of DataArrayInt::computeOffsetsFull.
+ * \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.
+ * \throw If \a this is not allocated.
+ * \throw If \a this->getNumberOfComponents() != 1.
+ * \throw If \a this->getNumberOfTuples() < 2.
+ *
+ * \b Example: <br>
+ * - 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::computeOffsetsFull
+ */
+ template <class T>
+ typename Traits<T>::ArrayType *DataArrayDiscrete<T>::deltaShiftIndex() const
+ {
+ this->checkAllocated();
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::deltaShiftIndex : only single component allowed !");
+ std::size_t nbOfElements=this->getNumberOfTuples();
+ if(nbOfElements<2)
+ throw INTERP_KERNEL::Exception("DataArrayInt::deltaShiftIndex : 1 tuple at least must be present in 'this' !");
+ const T *ptr=this->getConstPointer();
+ DataArrayType *ret=DataArrayType::New();
+ ret->alloc(nbOfElements-1,1);
+ T *out=ret->getPointer();
+ std::transform(ptr+1,ptr+nbOfElements,ptr,out,std::minus<T>());
+ return ret;
+ }
+
+ /*!
+ * Modifies \a this one-dimensional array so that value of each element \a x
+ * of \a this array (\a a) is computed as \f$ x_i = \sum_{j=0}^{i-1} a[ j ] \f$.
+ * Or: for each i>0 new[i]=new[i-1]+old[i-1] for i==0 new[i]=0. Number of tuples
+ * and components remains the same.<br>
+ * This method is useful for allToAllV in MPI with contiguous policy. This method
+ * differs from computeOffsetsFull() in that the number of tuples is \b not changed by
+ * this one.
+ * \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]<br>
+ * Note that the last element 19 = 11 + 8 is missing because size of \a this
+ * array is retained and thus there is no space to store the last element.
+ */
+ template <class T>
+ void DataArrayDiscrete<T>::computeOffsets()
+ {
+ this->checkAllocated();
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::computeOffsets : only single component allowed !");
+ std::size_t nbOfElements=this->getNumberOfTuples();
+ if(nbOfElements==0)
+ return ;
+ T *work=this->getPointer();
+ T tmp=work[0];
+ work[0]=0;
+ for(std::size_t i=1;i<nbOfElements;i++)
+ {
+ T tmp2=work[i];
+ work[i]=work[i-1]+tmp;
+ tmp=tmp2;
+ }
+ this->declareAsNew();
+ }
+
+ /*!
+ * Modifies \a this one-dimensional array so that value of each element \a x
+ * of \a this array (\a a) is computed as \f$ x_i = \sum_{j=0}^{i-1} a[ j ] \f$.
+ * Or: for each i>0 new[i]=new[i-1]+old[i-1] for i==0 new[i]=0. Number
+ * 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 performs 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
+ */
+ template <class T>
+ void DataArrayDiscrete<T>::computeOffsetsFull()
+ {
+ this->checkAllocated();
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::computeOffsetsFull : only single component allowed !");
+ std::size_t nbOfElements=this->getNumberOfTuples();
+ T *ret=(T *)malloc((nbOfElements+1)*sizeof(T));
+ const T *work=this->getConstPointer();
+ ret[0]=0;
+ for(std::size_t i=0;i<nbOfElements;i++)
+ ret[i+1]=work[i]+ret[i];
+ this->useArray(ret,true,DeallocType::C_DEALLOC,nbOfElements+1,1);
+ this->declareAsNew();
+ }
+
+ /*!
+ * Returns two new DataArrayInt instances whose contents is computed from that of \a this and \a listOfIds arrays as follows.
+ * \a this is expected to be an offset format ( as returned by DataArrayInt::computeOffsetsFull ) that is to say with one component
+ * and ** sorted strictly increasingly **. \a listOfIds is expected to be sorted ascendingly (not strictly needed for \a listOfIds).
+ * This methods searches in \a this, considered as a set of contiguous \c this->getNumberOfComponents() ranges, all ids in \a listOfIds
+ * filling completely one of the ranges in \a this.
+ *
+ * \param [in] listOfIds a list of ids that has to be sorted ascendingly.
+ * \param [out] rangeIdsFetched the range ids fetched
+ * \param [out] idsInInputListThatFetch contains the list of ids in \a listOfIds that are \b fully included in a range in \a this. So
+ * \a idsInInputListThatFetch is a part of input \a listOfIds.
+ *
+ * \sa DataArrayInt::computeOffsetsFull
+ *
+ * \b Example: <br>
+ * - \a this : [0,3,7,9,15,18]
+ * - \a listOfIds contains [0,1,2,3,7,8,15,16,17]
+ * - \a rangeIdsFetched result array: [0,2,4]
+ * - \a idsInInputListThatFetch result array: [0,1,2,7,8,15,16,17]
+ * In this example id 3 in input \a listOfIds is alone so it do not appear in output \a idsInInputListThatFetch.
+ * <br>
+ */
+ template <class T>
+ void DataArrayDiscrete<T>::findIdsRangesInListOfIds(const DataArrayType *listOfIds, DataArrayIdType *& rangeIdsFetched, DataArrayType *& idsInInputListThatFetch) const
+ {
+ if(!listOfIds)
+ throw INTERP_KERNEL::Exception("DataArrayInt::findIdsRangesInListOfIds : input list of ids is null !");
+ listOfIds->checkAllocated(); this->checkAllocated();
+ if(listOfIds->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::findIdsRangesInListOfIds : input list of ids must have exactly one component !");
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::findIdsRangesInListOfIds : this must have exactly one component !");
+ MCAuto<DataArrayIdType> ret0=DataArrayIdType::New(); ret0->alloc(0,1);
+ MCAuto<DataArrayType> ret1=DataArrayType::New(); ret1->alloc(0,1);
+ const T *tupPtr(listOfIds->begin()), *tupEnd(listOfIds->end());
+ const T *offBg(this->begin()),*offEnd(this->end()-1);
+ const T *offPtr(offBg);
+ while(tupPtr!=tupEnd && offPtr!=offEnd)
+ {
+ if(*tupPtr==*offPtr)
+ {
+ T i=offPtr[0];
+ while(i<offPtr[1] && *tupPtr==i && tupPtr!=tupEnd) { i++; tupPtr++; }
+ if(i==offPtr[1])
+ {
+ ret0->pushBackSilent(ToIdType(std::distance(offBg,offPtr)));
+ ret1->pushBackValsSilent(tupPtr-(offPtr[1]-offPtr[0]),tupPtr);
+ offPtr++;
+ }
+ }
+ else
+ { if(*tupPtr<*offPtr) tupPtr++; else offPtr++; }
+ }
+ rangeIdsFetched=ret0.retn();
+ idsInInputListThatFetch=ret1.retn();
+ }
+
+ /*!
+ * Returns a new DataArrayInt whose contents is computed from that of \a this and \a
+ * offsets arrays as follows. \a offsets is a one-dimensional array considered as an
+ * "index" array of a "iota" array, thus, whose each element gives an index of a group
+ * beginning within the "iota" array. And \a this is a one-dimensional array
+ * considered as a selector of groups described by \a offsets to include into the result array.
+ * \throw If \a offsets is NULL.
+ * \throw If \a offsets is not allocated.
+ * \throw If \a offsets->getNumberOfComponents() != 1.
+ * \throw If \a offsets is not monotonically increasing.
+ * \throw If \a this is not allocated.
+ * \throw If \a this->getNumberOfComponents() != 1.
+ * \throw If any element of \a this is not a valid index for \a offsets array.
+ *
+ * \b Example: <br>
+ * - \a this: [0,2,3]
+ * - \a offsets: [0,3,6,10,14,20]
+ * - result array: [0,1,2,6,7,8,9,10,11,12,13] == <br>
+ * \c range(0,3) + \c range(6,10) + \c range(10,14) ==<br>
+ * \c range( \a offsets[ \a this[0] ], offsets[ \a this[0]+1 ]) +
+ * \c range( \a offsets[ \a this[1] ], offsets[ \a this[1]+1 ]) +
+ * \c range( \a offsets[ \a this[2] ], offsets[ \a this[2]+1 ])
+ */
+ template <class T>
+ typename Traits<T>::ArrayType *DataArrayDiscrete<T>::buildExplicitArrByRanges(const DataArrayType *offsets) const
+ {
+ if(!offsets)
+ throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrByRanges : DataArrayInt pointer in input is NULL !");
+ this->checkAllocated();
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrByRanges : only single component allowed !");
+ offsets->checkAllocated();
+ if(offsets->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrByRanges : input array should have only single component !");
+ mcIdType othNbTuples=offsets->getNumberOfTuples()-1;
+ mcIdType nbOfTuples=this->getNumberOfTuples();
+ T retNbOftuples=0;
+ const T *work=this->getConstPointer();
+ const T *offPtr=offsets->getConstPointer();
+ for(mcIdType i=0;i<nbOfTuples;i++)
+ {
+ T val=work[i];
+ if(val>=0 && val<othNbTuples)
+ {
+ T delta=offPtr[val+1]-offPtr[val];
+ if(delta>=0)
+ retNbOftuples+=delta;
+ else
+ {
+ std::ostringstream oss; oss << "DataArrayInt::buildExplicitArrByRanges : Tuple #" << val << " of offset array has a delta < 0 !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
+ }
+ else
+ {
+ std::ostringstream oss; oss << "DataArrayInt::buildExplicitArrByRanges : Tuple #" << i << " in this contains " << val;
+ oss << " whereas offsets array is of size " << othNbTuples+1 << " !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
+ }
+ MCAuto<DataArrayType> ret=DataArrayType::New();
+ ret->alloc(retNbOftuples,1);
+ T *retPtr=ret->getPointer();
+ for(mcIdType i=0;i<nbOfTuples;i++)
+ {
+ T val=work[i];
+ T start=offPtr[val];
+ T off=offPtr[val+1]-start;
+ for(T j=0;j<off;j++,retPtr++)
+ *retPtr=start+j;
+ }
+ return ret.retn();
+ }
+
+ /*!
+ * Returns a new DataArrayInt whose contents is computed using \a this that must be a
+ * scaled array (monotonically increasing).
+ from that of \a this and \a
+ * offsets arrays as follows. \a offsets is a one-dimensional array considered as an
+ * "index" array of a "iota" array, thus, whose each element gives an index of a group
+ * beginning within the "iota" array. And \a this is a one-dimensional array
+ * considered as a selector of groups described by \a offsets to include into the result array.
+ * \throw If \a is NULL.
+ * \throw If \a this is not allocated.
+ * \throw If \a this->getNumberOfComponents() != 1.
+ * \throw If \a this->getNumberOfTuples() == 0.
+ * \throw If \a this is not monotonically increasing.
+ * \throw If any element of ids in ( \a bg \a stop \a step ) points outside the scale in \a this.
+ *
+ * \b Example: <br>
+ * - \a bg , \a stop and \a step : (0,5,2)
+ * - \a this: [0,3,6,10,14,20]
+ * - result array: [0,0,0, 2,2,2,2, 4,4,4,4,4,4] == <br>
+ */
+ template <class T>
+ typename Traits<T>::ArrayType *DataArrayDiscrete<T>::buildExplicitArrOfSliceOnScaledArr(T bg, T stop, T step) const
+ {
+ if(!this->isAllocated())
+ throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrOfSliceOnScaledArr : not allocated array !");
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrOfSliceOnScaledArr : number of components is expected to be equal to one !");
+ mcIdType nbOfTuples(this->getNumberOfTuples());
+ if(nbOfTuples==0)
+ throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrOfSliceOnScaledArr : number of tuples must be != 0 !");
+ const T *ids(this->begin());
+ mcIdType nbOfEltsInSlc=DataArrayTools<T>::GetNumberOfItemGivenBESRelative(bg,stop,step,"DataArrayInt::buildExplicitArrOfSliceOnScaledArr");
+ T sz(0),pos(bg);
+ for(mcIdType i=0;i<nbOfEltsInSlc;i++,pos+=step)
+ {
+ if(pos>=0 && pos<nbOfTuples-1)
+ {
+ T delta(ids[pos+1]-ids[pos]);
+ sz+=delta;
+ if(delta<0)
+ {
+ std::ostringstream oss; oss << "DataArrayInt::buildExplicitArrOfSliceOnScaledArr : At pos #" << i << " of input slice, value is " << pos << " and at this pos this is not monotonically increasing !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
+ }
+ else
+ {
+ std::ostringstream oss; oss << "DataArrayInt::buildExplicitArrOfSliceOnScaledArr : At pos #" << i << " of input slice, value is " << pos << " should be in [0," << nbOfTuples-1 << ") !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
+ }
+ MCAuto<DataArrayType> ret(DataArrayType::New()); ret->alloc(sz,1);
+ T *retPtr(ret->getPointer());
+ pos=bg;
+ for(mcIdType i=0;i<nbOfEltsInSlc;i++,pos+=step)
+ {
+ T delta(ids[pos+1]-ids[pos]);
+ for(T j=0;j<delta;j++,retPtr++)
+ *retPtr=pos;
+ }
+ return ret.retn();
+ }
+
+ /*!
+ * Given in input ranges \a ranges, it returns a newly allocated DataArrayInt instance having one component and the same number of tuples than \a this.
+ * For each tuple at place **i** in \a this it tells which is the first range in \a ranges that contains value \c this->getIJ(i,0) and put the result
+ * in tuple **i** of returned DataArrayInt.
+ * If ranges overlapped (in theory it should not) this method do not detect it and always returns the first range.
+ *
+ * For example if \a this contains : [1,24,7,8,10,17] and \a ranges contains [(0,3),(3,8),(8,15),(15,22),(22,30)]
+ * The return DataArrayInt will contain : **[0,4,1,2,2,3]**
+ *
+ * \param [in] ranges typically come from output of MEDCouplingUMesh::ComputeRangesFromTypeDistribution. Each range is specified like this : 1st component is
+ * for lower value included and 2nd component is the upper value of corresponding range **excluded**.
+ * \throw If offsets is a null pointer or does not have 2 components or if \a this is not allocated or \a this do not have exactly one component. To finish an exception
+ * is thrown if no ranges in \a ranges contains value in \a this.
+ *
+ * \sa DataArrayInt::findIdInRangeForEachTuple
+ */
+ template <class T>
+ DataArrayIdType *DataArrayDiscrete<T>::findRangeIdForEachTuple(const DataArrayType *ranges) const
+ {
+ if(!ranges)
+ throw INTERP_KERNEL::Exception("DataArrayInt::findRangeIdForEachTuple : null input pointer !");
+ if(ranges->getNumberOfComponents()!=2)
+ throw INTERP_KERNEL::Exception("DataArrayInt::findRangeIdForEachTuple : input DataArrayInt instance should have 2 components !");
+ this->checkAllocated();
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::findRangeIdForEachTuple : this should have only one component !");
+ mcIdType nbTuples(this->getNumberOfTuples());
+ MCAuto<DataArrayIdType> ret=DataArrayIdType::New(); ret->alloc(nbTuples,1);
+ mcIdType nbOfRanges(ranges->getNumberOfTuples());
+ const T *rangesPtr=ranges->getConstPointer();
+ mcIdType *retPtr=ret->getPointer();
+ const T *inPtr=this->getConstPointer();
+ for(mcIdType i=0;i<nbTuples;i++,retPtr++)
+ {
+ T val=inPtr[i];
+ bool found=false;
+ for(mcIdType j=0;j<nbOfRanges && !found;j++)
+ if(val>=rangesPtr[2*j] && val<rangesPtr[2*j+1])
+ { *retPtr=j; found=true; }
+ if(found)
+ continue;
+ else
+ {
+ std::ostringstream oss; oss << "DataArrayInt::findRangeIdForEachTuple : tuple #" << i << " not found by any ranges !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
+ }
+ return ret.retn();
+ }
+
+ /*!
+ * Given in input ranges \a ranges, it returns a newly allocated DataArrayInt instance having one component and the same number of tuples than \a this.
+ * For each tuple at place **i** in \a this it tells which is the sub position of the first range in \a ranges that contains value \c this->getIJ(i,0) and put the result
+ * in tuple **i** of returned DataArrayInt.
+ * If ranges overlapped (in theory it should not) this method do not detect it and always returns the sub position of the first range.
+ *
+ * For example if \a this contains : [1,24,7,8,10,17] and \a ranges contains [(0,3),(3,8),(8,15),(15,22),(22,30)]
+ * The return DataArrayInt will contain : **[1,2,4,0,2,2]**
+ * This method is often called in pair with DataArrayInt::findRangeIdForEachTuple method.
+ *
+ * \param [in] ranges typically come from output of MEDCouplingUMesh::ComputeRangesFromTypeDistribution. Each range is specified like this : 1st component is
+ * for lower value included and 2nd component is the upper value of corresponding range **excluded**.
+ * \throw If offsets is a null pointer or does not have 2 components or if \a this is not allocated or \a this do not have exactly one component. To finish an exception
+ * is thrown if no ranges in \a ranges contains value in \a this.
+ * \sa DataArrayInt::findRangeIdForEachTuple
+ */
+ template <class T>
+ typename Traits<T>::ArrayType *DataArrayDiscrete<T>::findIdInRangeForEachTuple(const DataArrayType *ranges) const
+ {
+ if(!ranges)
+ throw INTERP_KERNEL::Exception("DataArrayInt::findIdInRangeForEachTuple : null input pointer !");
+ if(ranges->getNumberOfComponents()!=2)
+ throw INTERP_KERNEL::Exception("DataArrayInt::findIdInRangeForEachTuple : input DataArrayInt instance should have 2 components !");
+ this->checkAllocated();
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::findIdInRangeForEachTuple : this should have only one component !");
+ mcIdType nbTuples=this->getNumberOfTuples();
+ MCAuto<DataArrayType> ret=DataArrayType::New(); ret->alloc(nbTuples,1);
+ mcIdType nbOfRanges=ranges->getNumberOfTuples();
+ const T *rangesPtr=ranges->getConstPointer();
+ T *retPtr=ret->getPointer();
+ const T *inPtr=this->getConstPointer();
+ for(mcIdType i=0;i<nbTuples;i++,retPtr++)
+ {
+ T val=inPtr[i];
+ bool found=false;
+ for(mcIdType j=0;j<nbOfRanges && !found;j++)
+ if(val>=rangesPtr[2*j] && val<rangesPtr[2*j+1])
+ { *retPtr=val-rangesPtr[2*j]; found=true; }
+ if(found)
+ continue;
+ else
+ {
+ std::ostringstream oss; oss << "DataArrayInt::findIdInRangeForEachTuple : tuple #" << i << " not found by any ranges !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
+ }
+ return ret.retn();
+ }
+
+ /*!
+ * \b WARNING this method is a \b non \a const \b method. This method works tuple by tuple. Each tuple is expected to be pairs (number of components must be equal to 2).
+ * This method rearrange each pair in \a this so that, tuple with id \b tid will be after the call \c this->getIJ(tid,0)==this->getIJ(tid-1,1) and \c this->getIJ(tid,1)==this->getIJ(tid+1,0).
+ * If it is impossible to reach such condition an exception will be thrown ! \b WARNING In case of throw \a this can be partially modified !
+ * If this method has correctly worked, \a this will be able to be considered as a linked list.
+ * This method does nothing if number of tuples is lower of equal to 1.
+ *
+ * This method is useful for users having an unstructured mesh having only SEG2 to rearrange internally the connectivity without any coordinates consideration.
+ *
+ * \sa MEDCouplingUMesh::orderConsecutiveCells1D, DataArrayInt::fromLinkedListOfPairToList
+ */
+ template <class T>
+ void DataArrayDiscrete<T>::sortEachPairToMakeALinkedList()
+ {
+ this->checkAllocated();
+ if(this->getNumberOfComponents()!=2)
+ throw INTERP_KERNEL::Exception("DataArrayInt::sortEachPairToMakeALinkedList : Only works on DataArrayInt instance with nb of components equal to 2 !");
+ mcIdType nbOfTuples(this->getNumberOfTuples());
+ if(nbOfTuples<=1)
+ return ;
+ T *conn(this->getPointer());
+ for(mcIdType i=1;i<nbOfTuples;i++,conn+=2)
+ {
+ if(i>1)
+ {
+ if(conn[2]==conn[3])
+ {
+ std::ostringstream oss; oss << "DataArrayInt::sortEachPairToMakeALinkedList : In the tuple #" << i << " presence of a pair filled with same ids !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
+ if(conn[2]!=conn[1] && conn[3]==conn[1] && conn[2]!=conn[0])
+ std::swap(conn[2],conn[3]);
+ //not(conn[2]==conn[1] && conn[3]!=conn[1] && conn[3]!=conn[0])
+ if(conn[2]!=conn[1] || conn[3]==conn[1] || conn[3]==conn[0])
+ {
+ std::ostringstream oss; oss << "DataArrayInt::sortEachPairToMakeALinkedList : In the tuple #" << i << " something is invalid !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
+ }
+ else
+ {
+ if(conn[0]==conn[1] || conn[2]==conn[3])
+ throw INTERP_KERNEL::Exception("DataArrayInt::sortEachPairToMakeALinkedList : In the 2 first tuples presence of a pair filled with same ids !");
+ T tmp[4];
+ std::set<T> s;
+ s.insert(conn,conn+4);
+ if(s.size()!=3)
+ throw INTERP_KERNEL::Exception("DataArrayInt::sortEachPairToMakeALinkedList : This can't be considered as a linked list regarding 2 first tuples !");
+ if(std::count(conn,conn+4,conn[0])==2)
+ {
+ tmp[0]=conn[1];
+ tmp[1]=conn[0];
+ tmp[2]=conn[0];
+ if(conn[2]==conn[0])
+ { tmp[3]=conn[3]; }
+ else
+ { tmp[3]=conn[2];}
+ std::copy(tmp,tmp+4,conn);
+ }
+ else
+ {//here we are sure to have (std::count(conn,conn+4,conn[1])==2)
+ if(conn[1]==conn[3])
+ std::swap(conn[2],conn[3]);
+ }
+ }
+ }
+ }
+
+ /*!
+ * \a this is expected to be a correctly linked list of pairs.
+ *
+ * \sa DataArrayInt::sortEachPairToMakeALinkedList
+ */
+ template <class T>
+ MCAuto<typename Traits<T>::ArrayType> DataArrayDiscrete<T>::fromLinkedListOfPairToList() const
+ {
+ this->checkAllocated();
+ this->checkNbOfComps(2,"DataArrayInt::fromLinkedListOfPairToList : this is expected to have 2 components");
+ mcIdType nbTuples(this->getNumberOfTuples());
+ if(nbTuples<1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::fromLinkedListOfPairToList : no tuples in this ! Not a linked list !");
+ MCAuto<DataArrayType> ret(DataArrayType::New()); ret->alloc(nbTuples+1,1);
+ const T *thisPtr(this->begin());
+ T *retPtr(ret->getPointer());
+ retPtr[0]=thisPtr[0];
+ for(mcIdType i=0;i<nbTuples;i++)
+ {
+ retPtr[i+1]=thisPtr[2*i+1];
+ if(i<nbTuples-1)
+ if(thisPtr[2*i+1]!=thisPtr[2*(i+1)+0])
+ {
+ std::ostringstream oss; oss << "DataArrayInt::fromLinkedListOfPairToList : this is not a proper linked list of pair. The link is broken between tuple #" << i << " and tuple #" << i+1 << " ! Call sortEachPairToMakeALinkedList ?";
+ throw INTERP_KERNEL::Exception(oss.str());
+ }
+ }
+ return ret;
+ }
+
+ /*!
+ * This method returns all different values found in \a this. This method throws if \a this has not been allocated.
+ * But the number of components can be different from one.
+ * \return a newly allocated array (that should be dealt by the caller) containing different values in \a this.
+ */
+ template <class T>
+ typename Traits<T>::ArrayType *DataArrayDiscrete<T>::getDifferentValues() const
+ {
+ this->checkAllocated();
+ std::set<T> ret;
+ ret.insert(this->begin(),this->end());
+ MCAuto<DataArrayType> ret2=DataArrayType::New();
+ ret2->alloc(ret.size(),1);
+ std::copy(ret.begin(),ret.end(),ret2->getPointer());
+ return ret2.retn();
+ }
+
+ /*!
+ * This method is a refinement of DataArrayInt::getDifferentValues because it returns not only different values in \a this but also, for each of
+ * them it tells which tuple id have this id.
+ * This method works only on arrays with one component (if it is not the case call DataArrayInt::rearrange(1) ).
+ * This method returns two arrays having same size.
+ * The instances of DataArrayInt in the returned vector have be specially allocated and computed by this method. Each of them should be dealt by the caller of this method.
+ * Example : if this is equal to [1,0,1,2,0,2,2,-3,2] -> differentIds=[-3,0,1,2] and returned array will be equal to [[7],[1,4],[0,2],[3,5,6,8]]
+ */
+ template <class T>
+ std::vector<DataArrayIdType *> DataArrayDiscrete<T>::partitionByDifferentValues(std::vector<T>& differentIds) const
+ {
+ this->checkAllocated();
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::partitionByDifferentValues : this should have only one component !");
+ mcIdType id=0;
+ std::map<T,mcIdType> m,m2,m3;
+ for(const T *w=this->begin();w!=this->end();w++)
+ m[*w]++;
+ differentIds.resize(m.size());
+ std::vector<DataArrayIdType *> ret(m.size());
+ std::vector<mcIdType *> retPtr(m.size());
+ for(typename std::map<T,mcIdType>::const_iterator it=m.begin();it!=m.end();it++,id++)
+ {
+ m2[(*it).first]=id;
+ ret[id]=DataArrayIdType::New();
+ ret[id]->alloc((*it).second,1);
+ retPtr[id]=ret[id]->getPointer();
+ differentIds[id]=(*it).first;
+ }
+ id=0;
+ for(const T *w=this->begin();w!=this->end();w++,id++)
+ {
+ retPtr[m2[*w]][m3[*w]++]=id;
+ }
+ return ret;
+ }
+
+ /*!
+ * This method split ids in [0, \c this->getNumberOfTuples() ) using \a this array as a field of weight (>=0 each).
+ * The aim of this method is to return a set of \a nbOfSlices chunk of contiguous ids as balanced as possible.
+ *
+ * \param [in] nbOfSlices - number of slices expected.
+ * \return - a vector having a size equal to \a nbOfSlices giving the start (included) and the stop (excluded) of each chunks.
+ *
+ * \sa DataArray::GetSlice
+ * \throw If \a this is not allocated or not with exactly one component.
+ * \throw If an element in \a this if < 0.
+ */
+ template <class T>
+ std::vector< std::pair<mcIdType,mcIdType> > DataArrayDiscrete<T>::splitInBalancedSlices(mcIdType nbOfSlices) const
+ {
+ if(!this->isAllocated() || this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::splitInBalancedSlices : this array should have number of components equal to one and must be allocated !");
+ if(nbOfSlices<=0)
+ throw INTERP_KERNEL::Exception("DataArrayInt::splitInBalancedSlices : number of slices must be >= 1 !");
+ T sum(this->accumulate((std::size_t)0));
+ mcIdType nbOfTuples(this->getNumberOfTuples());
+ T sumPerSlc(sum/FromIdType<T>(nbOfSlices));
+ mcIdType pos(0);
+ const T *w(this->begin());
+ std::vector< std::pair<mcIdType,mcIdType> > ret(nbOfSlices);
+ for(mcIdType i=0;i<nbOfSlices;i++)
+ {
+ std::pair<mcIdType, mcIdType> p(pos,-1);
+ T locSum(0);
+ while(locSum<sumPerSlc && pos<nbOfTuples) { pos++; locSum+=*w++; }
+ if(i!=nbOfSlices-1)
+ p.second=pos;
+ else
+ p.second=nbOfTuples;
+ ret[i]=p;
+ }
+ return ret;
+ }
+
+ /*!
+ * Modify \a this array so that each value becomes a modulus of division of this value by
+ * a value of another DataArrayInt. There are 3 valid cases.
+ * 1. The arrays have same number of tuples and components. Then each value of
+ * \a this array is divided by the corresponding value of \a other one, i.e.:
+ * _a_ [ i, j ] %= _other_ [ i, j ].
+ * 2. The arrays have same number of tuples and \a other array has one component. Then
+ * _a_ [ i, j ] %= _other_ [ i, 0 ].
+ * 3. The arrays have same number of components and \a other array has one tuple. Then
+ * _a_ [ i, j ] %= _a2_ [ 0, j ].
+ *
+ * \warning No check of division by zero is performed!
+ * \param [in] other - a divisor array.
+ * \throw If \a other is NULL.
+ * \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples() and
+ * \a this->getNumberOfComponents() != \a other->getNumberOfComponents() and
+ * \a other has number of both tuples and components not equal to 1.
+ */
+ template <class T>
+ void DataArrayDiscrete<T>::modulusEqual(const DataArrayType *other)
+ {
+ if(!other)
+ throw INTERP_KERNEL::Exception("DataArrayInt::modulusEqual : input DataArrayInt instance is NULL !");
+ const char *msg="Nb of tuples mismatch for DataArrayInt::modulusEqual !";
+ this->checkAllocated(); other->checkAllocated();
+ mcIdType nbOfTuple(this->getNumberOfTuples());
+ mcIdType nbOfTuple2(other->getNumberOfTuples());
+ std::size_t nbOfComp(this->getNumberOfComponents());
+ std::size_t nbOfComp2(other->getNumberOfComponents());
+ if(nbOfTuple==nbOfTuple2)
+ {
+ if(nbOfComp==nbOfComp2)
+ {
+ std::transform(this->begin(),this->end(),other->begin(),this->getPointer(),std::modulus<T>());
+ }
+ else if(nbOfComp2==1)
+ {
+ if(nbOfComp2==nbOfComp)
+ {
+ T *ptr=this->getPointer();
+ const T *ptrc=other->getConstPointer();
+ for(mcIdType i=0;i<nbOfTuple;i++)
+ std::transform(ptr+i*nbOfComp,ptr+(i+1)*nbOfComp,ptr+i*nbOfComp,std::bind(std::modulus<T>(),std::placeholders::_1,*ptrc++));
+ }
+ else
+ throw INTERP_KERNEL::Exception(msg);
+ }
+ else
+ throw INTERP_KERNEL::Exception(msg);
+ }
+ else if(nbOfTuple2==1)
+ {
+ T *ptr=this->getPointer();
+ const T *ptrc=other->getConstPointer();
+ for(mcIdType i=0;i<nbOfTuple;i++)
+ std::transform(ptr+i*nbOfComp,ptr+(i+1)*nbOfComp,ptrc,ptr+i*nbOfComp,std::modulus<T>());
+ }
+ else
+ throw INTERP_KERNEL::Exception(msg);
+ this->declareAsNew();
+ }
+
+ /*!
+ * Apply pow on values of another DataArrayInt 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 other.
+ */
+ template <class T>
+ void DataArrayDiscrete<T>::powEqual(const DataArrayType *other)
+ {
+ if(!other)
+ throw INTERP_KERNEL::Exception("DataArrayInt::powEqual : input instance is null !");
+ mcIdType nbOfTuple=this->getNumberOfTuples();
+ mcIdType nbOfTuple2=other->getNumberOfTuples();
+ std::size_t nbOfComp=this->getNumberOfComponents();
+ std::size_t nbOfComp2=other->getNumberOfComponents();
+ if(nbOfTuple!=nbOfTuple2)
+ throw INTERP_KERNEL::Exception("DataArrayInt::powEqual : number of tuples mismatches !");
+ if(nbOfComp!=1 || nbOfComp2!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::powEqual : number of components of both arrays must be equal to 1 !");
+ T *ptr=this->getPointer();
+ const T *ptrc=other->begin();
+ for(mcIdType i=0;i<nbOfTuple;i++,ptrc++,ptr++)
+ {
+ if(*ptrc>=0)
+ {
+ T tmp=1;
+ for(T j=0;j<*ptrc;j++)
+ tmp*=*ptr;
+ *ptr=tmp;
+ }
+ else
+ {
+ std::ostringstream oss; oss << "DataArrayInt::powEqual : on tuple #" << i << " of other value is < 0 (" << *ptrc << ") !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
+ }
+ this->declareAsNew();
+ }
+
+ ////////////////////////////////////
+ /*!
+ * Useless method for end user. Only for MPI/Corba/File serialsation for multi arrays class.
+ * Server side.
+ */
+ template <class T>
+ void DataArrayDiscrete<T>::getTinySerializationIntInformation(std::vector<mcIdType>& tinyInfo) const
+ {
+ tinyInfo.resize(2);
+ if(this->isAllocated())
+ {
+ tinyInfo[0]=this->getNumberOfTuples();
+ tinyInfo[1]=ToIdType(this->getNumberOfComponents());
+ }
+ else
+ {
+ tinyInfo[0]=-1;
+ tinyInfo[1]=-1;
+ }
+ }
+
+ /*!
+ * Useless method for end user. Only for MPI/Corba/File serialsation for multi arrays class.
+ * Server side.
+ */
+ template <class T>
+ void DataArrayDiscrete<T>::getTinySerializationStrInformation(std::vector<std::string>& tinyInfo) const
+ {
+ if(this->isAllocated())
+ {
+ std::size_t nbOfCompo(this->getNumberOfComponents());
+ tinyInfo.resize(nbOfCompo+1);
+ tinyInfo[0]=this->getName();
+ for(std::size_t i=0;i<nbOfCompo;i++)
+ tinyInfo[i+1]=this->getInfoOnComponent(i);
+ }
+ else
+ {
+ tinyInfo.resize(1);
+ tinyInfo[0]=this->getName();
+ }
+ }
+
+ /*!
+ * Useless method for end user. Only for MPI/Corba/File serialsation for multi arrays class.
+ * This method returns if a feeding is needed.
+ */
+ template <class T>
+ bool DataArrayDiscrete<T>::resizeForUnserialization(const std::vector<mcIdType>& tinyInfoI)
+ {
+ mcIdType nbOfTuple=tinyInfoI[0];
+ mcIdType nbOfComp=tinyInfoI[1];
+ if(nbOfTuple!=-1 || nbOfComp!=-1)
+ {
+ this->alloc(nbOfTuple,nbOfComp);
+ return true;
+ }
+ return false;
+ }
+
+ /*!
+ * Useless method for end user. Only for MPI/Corba/File serialsation for multi arrays class.
+ * This method returns if a feeding is needed.
+ */
+ template <class T>
+ void DataArrayDiscrete<T>::finishUnserialization(const std::vector<mcIdType>& tinyInfoI, const std::vector<std::string>& tinyInfoS)
+ {
+ this->setName(tinyInfoS[0]);
+ if(this->isAllocated())
+ {
+ mcIdType nbOfCompo=tinyInfoI[1];
+ for(mcIdType i=0;i<nbOfCompo;i++)
+ this->setInfoOnComponent(i,tinyInfoS[i+1]);
+ }
+ }
+