-/*!
- * 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.
- */
-void DataArrayInt::changeSurjectiveFormat(int targetNb, DataArrayInt *&arr, DataArrayInt *&arrI) const
-{
- checkAllocated();
- if(getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::changeSurjectiveFormat : number of components must == 1 !");
- int nbOfTuples=getNumberOfTuples();
- MCAuto<DataArrayInt> ret(DataArrayInt::New());
- MCAuto<DataArrayInt> retI(DataArrayInt::New());
- retI->alloc(targetNb+1,1);
- const int *input=getConstPointer();
- std::vector< std::vector<int> > tmp(targetNb);
- for(int i=0;i<nbOfTuples;i++)
- {
- int 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());
- }
- }
- int *retIPtr=retI->getPointer();
- *retIPtr=0;
- for(std::vector< std::vector<int> >::const_iterator it1=tmp.begin();it1!=tmp.end();it1++,retIPtr++)
- retIPtr[1]=retIPtr[0]+(int)((*it1).size());
- if(nbOfTuples!=retI->getIJ(targetNb,0))
- throw INTERP_KERNEL::Exception("DataArrayInt::changeSurjectiveFormat : big problem should never happen !");
- ret->alloc(nbOfTuples,1);
- int *retPtr=ret->getPointer();
- for(std::vector< std::vector<int> >::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 "Old to New" mode computed
- * from a zip representation of a surjective format (returned e.g. by
- * \ref MEDCoupling::DataArrayDouble::findCommonTuples() "DataArrayDouble::findCommonTuples()"
- * for example). The result array minimizes the permutation. <br>
- * For more info on renumbering see \ref numbering. <br>
- * \b Example: <br>
- * - \a nbOfOldTuples: 10
- * - \a arr : [0,3, 5,7,9]
- * - \a arrIBg : [0,2,5]
- * - \a newNbOfTuples: 7
- * - result array : [0,1,2,0,3,4,5,4,6,4]
- *
- * \param [in] nbOfOldTuples - number of tuples in the initial array \a arr.
- * \param [in] arr - the array of tuple indices grouped by \a arrIBg array.
- * \param [in] arrIBg - the array dividing all indices stored in \a arr into groups of
- * (indices of) equal values. Its every element (except the last one) points to
- * the first element of a group of equal values.
- * \param [in] arrIEnd - specifies the end of \a arrIBg, so that the last element of \a
- * arrIBg is \a arrIEnd[ -1 ].
- * \param [out] newNbOfTuples - number of tuples after surjection application.
- * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
- * array using decrRef() as it is no more needed.
- * \throw If any value of \a arr breaks condition ( 0 <= \a arr[ i ] < \a nbOfOldTuples ).
- */
-DataArrayInt *DataArrayInt::ConvertIndexArrayToO2N(int nbOfOldTuples, const int *arr, const int *arrIBg, const int *arrIEnd, int &newNbOfTuples)
-{
- MCAuto<DataArrayInt> ret=DataArrayInt::New();
- ret->alloc(nbOfOldTuples,1);
- int *pt=ret->getPointer();
- std::fill(pt,pt+nbOfOldTuples,-1);
- int nbOfGrps=((int)std::distance(arrIBg,arrIEnd))-1;
- const int *cIPtr=arrIBg;
- for(int i=0;i<nbOfGrps;i++)
- pt[arr[cIPtr[i]]]=-(i+2);
- int newNb=0;
- for(int iNode=0;iNode<nbOfOldTuples;iNode++)
- {
- if(pt[iNode]<0)
- {
- if(pt[iNode]==-1)
- pt[iNode]=newNb++;
- else
- {
- int grpId=-(pt[iNode]+2);
- for(int j=cIPtr[grpId];j<cIPtr[grpId+1];j++)
- {
- if(arr[j]>=0 && arr[j]<nbOfOldTuples)
- pt[arr[j]]=newNb;
- else
- {
- std::ostringstream oss; oss << "DataArrayInt::ConvertIndexArrayToO2N : With element #" << j << " value is " << arr[j] << " should be in [0," << nbOfOldTuples << ") !";
- throw INTERP_KERNEL::Exception(oss.str().c_str());
- }
- }
- newNb++;
- }
- }
- }
- newNbOfTuples=newNb;
- return ret.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.
- */
-DataArrayInt *DataArrayInt::buildPermArrPerLevel() const
-{
- checkAllocated();
- if(getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::buildPermArrPerLevel : number of components must == 1 !");
- int nbOfTuples=getNumberOfTuples();
- const int *pt=getConstPointer();
- std::map<int,int> m;
- MCAuto<DataArrayInt> ret=DataArrayInt::New();
- ret->alloc(nbOfTuples,1);
- int *opt=ret->getPointer();
- for(int i=0;i<nbOfTuples;i++,pt++,opt++)
- {
- int val=*pt;
- std::map<int,int>::iterator it=m.find(val);
- if(it!=m.end())
- {
- *opt=(*it).second;
- (*it).second++;
- }
- else
- {
- *opt=0;
- m.insert(std::pair<int,int>(val,1));
- }
- }
- int sum=0;
- for(std::map<int,int>::iterator it=m.begin();it!=m.end();it++)
- {
- int vt=(*it).second;
- (*it).second=sum;
- sum+=vt;
- }
- pt=getConstPointer();
- opt=ret->getPointer();
- for(int 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.
- */
-bool DataArrayInt::isIota(int sizeExpected) const
-{
- checkAllocated();
- if(getNumberOfComponents()!=1)
- return false;
- int nbOfTuples(getNumberOfTuples());
- if(nbOfTuples!=sizeExpected)
- return false;
- const int *pt=getConstPointer();
- for(int 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
- */
-bool DataArrayInt::isUniform(int val) const
-{
- checkAllocated();
- if(getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::isUniform : must be applied on DataArrayInt with only one component, you can call 'rearrange' method before !");
- const int *w(begin()),*end2(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 int - 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
- */
-int DataArrayInt::checkUniformAndGuess() const
-{
- checkAllocated();
- if(getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::checkUniformAndGuess : must be applied on DataArrayInt with only one component, you can call 'rearrange' method before !");
- if(empty())
- throw INTERP_KERNEL::Exception("DataArrayInt::checkUniformAndGuess : this is empty !");
- const int *w(begin()),*end2(end());
- int 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
- */
-bool DataArrayInt::hasUniqueValues() const
-{
- checkAllocated();
- if(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 nbOfTuples(getNumberOfTuples());
- std::set<int> s(begin(),end()); // in C++11, should use unordered_set (O(1) complexity)
- if (s.size() != nbOfTuples)
- 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
- */
-void DataArrayInt::setSelectedComponents(const DataArrayInt *a, const std::vector<int>& compoIds)
-{
- if(!a)
- throw INTERP_KERNEL::Exception("DataArrayInt::setSelectedComponents : input DataArrayInt is NULL !");
- checkAllocated();
- a->checkAllocated();
- copyPartOfStringInfoFrom2(compoIds,*a);
- std::size_t partOfCompoSz=compoIds.size();
- int nbOfCompo=getNumberOfComponents();
- int nbOfTuples=std::min(getNumberOfTuples(),a->getNumberOfTuples());
- const int *ac=a->getConstPointer();
- int *nc=getPointer();
- for(int i=0;i<nbOfTuples;i++)
- for(std::size_t j=0;j<partOfCompoSz;j++,ac++)
- nc[nbOfCompo*i+compoIds[j]]=*ac;
-}
-
-DataArrayIntIterator *DataArrayInt::iterator()
-{
- return new DataArrayIntIterator(this);
-}
-
-/*!
- * 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
- */
-DataArrayInt *DataArrayInt::findIdsEqual(int val) const
-{
- checkAllocated();
- if(getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::findIdsEqual : the array must have only one component, you can call 'rearrange' method before !");
- const int *cptr(getConstPointer());
- MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
- std::size_t nbOfTuples(getNumberOfTuples());
- for(std::size_t 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 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.
- */
-DataArrayInt *DataArrayInt::findIdsNotEqual(int val) const
-{
- checkAllocated();
- if(getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::findIdsNotEqual : the array must have only one component, you can call 'rearrange' method before !");
- const int *cptr(getConstPointer());
- MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
- int nbOfTuples=getNumberOfTuples();
- for(int 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
- */
-DataArrayInt *DataArrayInt::findIdsEqualTuple(const int *tupleBg, const int *tupleEnd) const
-{
- std::size_t nbOfCompoExp(std::distance(tupleBg,tupleEnd));
- checkAllocated();
- if(getNumberOfComponents()!=nbOfCompoExp)
- {
- std::ostringstream oss; oss << "DataArrayInt::findIdsEqualTuple : mismatch of number of components. Input tuple has " << nbOfCompoExp << " whereas this array has " << 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<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
- const int *bg(begin()),*end2(end()),*work(begin());
- while(work!=end2)
- {
- work=std::search(work,end2,tupleBg,tupleEnd);
- if(work!=end2)
- {
- std::size_t pos(std::distance(bg,work));
- if(pos%nbOfCompoExp==0)
- ret->pushBackSilent(pos/nbOfCompoExp);
- work++;
- }
- }
- return ret.retn();
-}
-
-/*!
- * 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 DataArrayInt32::FindPermutationFromFirstToSecond
- */
-MCAuto<DataArrayInt32> DataArrayInt32::findIdForEach(const int *valsBg, const int *valsEnd) const
-{
- MCAuto<DataArrayInt32> ret(DataArrayInt32::New());
- std::size_t nbOfTuplesOut(std::distance(valsBg,valsEnd));
- ret->alloc(nbOfTuplesOut,1);
- MCAuto< MapKeyVal<int> > zeMap(invertArrayN2O2O2NOptimized());
- const std::map<int,int>& dat(zeMap->data());
- int *ptToFeed(ret->getPointer());
- for(const int *pt=valsBg;pt!=valsEnd;pt++)
- {
- std::map<int,int>::const_iterator it(dat.find(*pt));
- if(it!=dat.end())
- *ptToFeed++=(*it).second;
- else
- {
- std::ostringstream oss; oss << "DataArrayInt32::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;
-}
-
-/*!
- * 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 int - number of replacements performed.
- * \throw If \a this is not allocated.
- * \throw If \a this->getNumberOfComponents() != 1.
- */
-int DataArrayInt::changeValue(int oldValue, int newValue)
-{
- checkAllocated();
- if(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;
- int *start(getPointer()),*end2(start+getNbOfElems());
- int ret(0);
- for(int *val=start;val!=end2;val++)
- {
- if(*val==oldValue)
- {
- *val=newValue;
- ret++;
- }
- }
- if(ret>0)
- declareAsNew();
- return ret;
-}
-
-/*!
- * 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.
- */
-DataArrayInt *DataArrayInt::findIdsEqualList(const int *valsBg, const int *valsEnd) const
-{
- if(getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::findIdsEqualList : the array must have only one component, you can call 'rearrange' method before !");
- std::set<int> vals2(valsBg,valsEnd);
- const int *cptr(getConstPointer());
- std::vector<int> res;
- int nbOfTuples(getNumberOfTuples());
- MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
- for(int 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.
- */
-DataArrayInt *DataArrayInt::findIdsNotEqualList(const int *valsBg, const int *valsEnd) const
-{
- if(getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::findIdsNotEqualList : the array must have only one component, you can call 'rearrange' method before !");
- std::set<int> vals2(valsBg,valsEnd);
- const int *cptr=getConstPointer();
- std::vector<int> res;
- int nbOfTuples=getNumberOfTuples();
- MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
- for(int i=0;i<nbOfTuples;i++,cptr++)
- if(vals2.find(*cptr)==vals2.end())
- ret->pushBackSilent(i);
- return ret.retn();
-}
-
-/*!
- * 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.
- */
-int DataArrayInt::findIdFirstEqualTuple(const std::vector<int>& tupl) const
-{
- checkAllocated();
- int nbOfCompo=getNumberOfComponents();
- if(nbOfCompo==0)
- throw INTERP_KERNEL::Exception("DataArrayInt::findIdFirstEqualTuple : 0 components in 'this' !");
- if(nbOfCompo!=(int)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 int *cptr=getConstPointer();
- std::size_t nbOfVals=getNbOfElems();
- for(const int *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 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
- */
-int DataArrayInt::findIdSequence(const std::vector<int>& vals) const
-{
- checkAllocated();
- int nbOfCompo=getNumberOfComponents();
- if(nbOfCompo!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::findIdSequence : works only for DataArrayInt instance with one component !");
- const int *cptr=getConstPointer();
- std::size_t nbOfVals=getNbOfElems();
- const int *loc=std::search(cptr,cptr+nbOfVals,vals.begin(),vals.end());
- if(loc!=cptr+nbOfVals)
- return std::distance(cptr,loc);
- 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 equal to \b value.
- * If not any tuple contains \b value -1 is returned.
- * \sa DataArrayInt::presenceOfValue
- */
-int DataArrayInt::findIdFirstEqual(int value) const
-{
- checkAllocated();
- if(getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::presenceOfValue : the array must have only one component, you can call 'rearrange' method before !");
- const int *cptr=getConstPointer();
- int nbOfTuples=getNumberOfTuples();
- const int *ret=std::find(cptr,cptr+nbOfTuples,value);
- if(ret!=cptr+nbOfTuples)
- return 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
- */
-int DataArrayInt::findIdFirstEqual(const std::vector<int>& vals) const
-{
- checkAllocated();
- if(getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::presenceOfValue : the array must have only one component, you can call 'rearrange' method before !");
- std::set<int> vals2(vals.begin(),vals.end());
- const int *cptr=getConstPointer();
- int nbOfTuples=getNumberOfTuples();
- for(const int *w=cptr;w!=cptr+nbOfTuples;w++)
- if(vals2.find(*w)!=vals2.end())
- return std::distance(cptr,w);
- return -1;
-}
-
-/*!
- * 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
- *
- */
-int DataArrayInt::count(int value) const
-{
- int ret=0;
- checkAllocated();
- if(getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::count : must be applied on DataArrayInt with only one component, you can call 'rearrange' method before !");
- const int *vals=begin();
- int nbOfTuples=getNumberOfTuples();
- for(int i=0;i<nbOfTuples;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
- */
-bool DataArrayInt::presenceOfTuple(const std::vector<int>& tupl) const
-{
- return 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()
- */
-bool DataArrayInt::presenceOfValue(int value) const
-{
- return 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
- */
-bool DataArrayInt::presenceOfValue(const std::vector<int>& vals) const
-{
- return 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.
- */
-void DataArrayInt::accumulate(int *res) const
-{
- checkAllocated();
- const int *ptr=getConstPointer();
- int nbTuple=getNumberOfTuples();
- int nbComps=getNumberOfComponents();
- std::fill(res,res+nbComps,0);
- for(int i=0;i<nbTuple;i++)
- std::transform(ptr+i*nbComps,ptr+(i+1)*nbComps,res,res,std::plus<int>());
-}
-
-int DataArrayInt::accumulate(int compId) const
-{
- checkAllocated();
- const int *ptr=getConstPointer();
- int nbTuple=getNumberOfTuples();
- int nbComps=getNumberOfComponents();
- if(compId<0 || compId>=nbComps)
- throw INTERP_KERNEL::Exception("DataArrayInt::accumulate : Invalid compId specified : No such nb of components !");
- int ret=0;
- for(int 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.
- */
-DataArrayInt *DataArrayInt::accumulatePerChunck(const int *bgOfIndex, const int *endOfIndex) const
-{
- if(!bgOfIndex || !endOfIndex)
- throw INTERP_KERNEL::Exception("DataArrayInt::accumulatePerChunck : input pointer NULL !");
- checkAllocated();
- int nbCompo=getNumberOfComponents();
- int nbOfTuples=getNumberOfTuples();
- int sz=(int)std::distance(bgOfIndex,endOfIndex);
- if(sz<1)
- throw INTERP_KERNEL::Exception("DataArrayInt::accumulatePerChunck : invalid size of input index array !");
- sz--;
- MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(sz,nbCompo);
- const int *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 int *srcPt=begin()+(*w)*nbCompo;
- int *tmp=ret->getPointer();
- for(int i=0;i<sz;i++,tmp+=nbCompo,w++)
- {
- std::fill(tmp,tmp+nbCompo,0);
- if(w[1]>=w[0])
- {
- for(int j=w[0];j<w[1];j++,srcPt+=nbCompo)
- {
- if(j>=0 && j<nbOfTuples)
- std::transform(srcPt,srcPt+nbCompo,tmp,tmp,std::plus<int>());
- 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 a new DataArrayInt by concatenating two given arrays, so that (1) the number
- * of tuples in the result array is <em> a1->getNumberOfTuples() + a2->getNumberOfTuples() -
- * offsetA2</em> and (2)
- * the number of component in the result array is same as that of each of given arrays.
- * First \a offsetA2 tuples of \a a2 are skipped and thus are missing from the result array.
- * Info on components is copied from the first of the given arrays. Number of components
- * in the given arrays must be the same.
- * \param [in] a1 - an array to include in the result array.
- * \param [in] a2 - another array to include in the result array.
- * \param [in] offsetA2 - number of tuples of \a a2 to skip.
- * \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 either \a a1 or \a a2 is NULL.
- * \throw If \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents().
- */
-DataArrayInt *DataArrayInt::Aggregate(const DataArrayInt *a1, const DataArrayInt *a2, int offsetA2)
-{
- if(!a1 || !a2)
- throw INTERP_KERNEL::Exception("DataArrayInt::Aggregate : input DataArrayInt instance is NULL !");
- std::size_t nbOfComp(a1->getNumberOfComponents());
- if(nbOfComp!=a2->getNumberOfComponents())
- throw INTERP_KERNEL::Exception("Nb of components mismatch for array Aggregation !");
- std::size_t nbOfTuple1(a1->getNumberOfTuples()),nbOfTuple2(a2->getNumberOfTuples());
- MCAuto<DataArrayInt> ret(DataArrayInt::New());
- ret->alloc(nbOfTuple1+nbOfTuple2-offsetA2,nbOfComp);
- int *pt=std::copy(a1->begin(),a1->end(),ret->getPointer());
- std::copy(a2->getConstPointer()+offsetA2*nbOfComp,a2->getConstPointer()+nbOfTuple2*nbOfComp,pt);
- ret->copyStringInfoFrom(*a1);
- return ret.retn();
-}
-
-/*!
- * Returns a new DataArrayInt by concatenating all given arrays, so that (1) the number
- * of tuples in the result array is a sum of the number of tuples of given arrays and (2)
- * the number of component in the result array is same as that of each of given arrays.
- * Info on components is copied from the first of the given arrays. Number of components
- * in the given arrays must be the same.
- * If the number of non null of elements in \a arr is equal to one the returned object is a copy of it
- * not the object itself.
- * \param [in] arr - a sequence of arrays to include 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.
- * \throw If all arrays within \a arr are NULL.
- * \throw If getNumberOfComponents() of arrays within \a arr.
- */
-DataArrayInt *DataArrayInt::Aggregate(const std::vector<const DataArrayInt *>& arr)
-{
- std::vector<const DataArrayInt *> a;
- for(std::vector<const DataArrayInt *>::const_iterator it4=arr.begin();it4!=arr.end();it4++)
- if(*it4)
- a.push_back(*it4);
- if(a.empty())
- throw INTERP_KERNEL::Exception("DataArrayInt::Aggregate : input list must be NON EMPTY !");
- std::vector<const DataArrayInt *>::const_iterator it=a.begin();
- std::size_t nbOfComp((*it)->getNumberOfComponents()),nbt((*it++)->getNumberOfTuples());
- for(int i=1;it!=a.end();it++,i++)
- {
- if((*it)->getNumberOfComponents()!=nbOfComp)
- throw INTERP_KERNEL::Exception("DataArrayInt::Aggregate : Nb of components mismatch for array aggregation !");
- nbt+=(*it)->getNumberOfTuples();
- }
- MCAuto<DataArrayInt> ret=DataArrayInt::New();
- ret->alloc(nbt,nbOfComp);
- int *pt=ret->getPointer();
- for(it=a.begin();it!=a.end();it++)
- pt=std::copy((*it)->getConstPointer(),(*it)->getConstPointer()+(*it)->getNbOfElems(),pt);
- ret->copyStringInfoFrom(*(a[0]));
- return ret.retn();
-}
-
-/*!
- * This method takes as input a list of DataArrayInt instances \a arrs that represent each a packed index arrays.
- * A packed index array is an allocated array with one component, and at least one tuple. The first element
- * of each array in \a arrs must be 0. Each array in \a arrs is expected to be increasingly monotonic.
- * This method is useful for users that want to aggregate a pair of DataArrayInt representing an indexed data (typically nodal connectivity index in unstructured meshes.
- *
- * \return DataArrayInt * - a new object to be managed by the caller.
- */
-DataArrayInt *DataArrayInt::AggregateIndexes(const std::vector<const DataArrayInt *>& arrs)
-{
- int retSz=1;
- for(std::vector<const DataArrayInt *>::const_iterator it4=arrs.begin();it4!=arrs.end();it4++)
- {
- if(*it4)
- {
- (*it4)->checkAllocated();
- if((*it4)->getNumberOfComponents()!=1)
- {
- std::ostringstream oss; oss << "DataArrayInt::AggregateIndexes : presence of a DataArrayInt instance with nb of compo != 1 at pos " << std::distance(arrs.begin(),it4) << " !";
- throw INTERP_KERNEL::Exception(oss.str().c_str());
- }
- int nbTupl=(*it4)->getNumberOfTuples();
- if(nbTupl<1)
- {
- std::ostringstream oss; oss << "DataArrayInt::AggregateIndexes : presence of a DataArrayInt instance with nb of tuples < 1 at pos " << std::distance(arrs.begin(),it4) << " !";
- throw INTERP_KERNEL::Exception(oss.str().c_str());
- }
- if((*it4)->front()!=0)
- {
- std::ostringstream oss; oss << "DataArrayInt::AggregateIndexes : presence of a DataArrayInt instance with front value != 0 at pos " << std::distance(arrs.begin(),it4) << " !";
- throw INTERP_KERNEL::Exception(oss.str().c_str());
- }
- retSz+=nbTupl-1;
- }
- else
- {
- std::ostringstream oss; oss << "DataArrayInt::AggregateIndexes : presence of a null instance at pos " << std::distance(arrs.begin(),it4) << " !";
- throw INTERP_KERNEL::Exception(oss.str().c_str());
- }
- }
- if(arrs.empty())
- throw INTERP_KERNEL::Exception("DataArrayInt::AggregateIndexes : input list must be NON EMPTY !");
- MCAuto<DataArrayInt> ret=DataArrayInt::New();
- ret->alloc(retSz,1);
- int *pt=ret->getPointer(); *pt++=0;
- for(std::vector<const DataArrayInt *>::const_iterator it=arrs.begin();it!=arrs.end();it++)
- pt=std::transform((*it)->begin()+1,(*it)->end(),pt,std::bind2nd(std::plus<int>(),pt[-1]));
- ret->copyStringInfoFrom(*(arrs[0]));
- return ret.retn();
-}
-
-/*!
- * Returns 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
- */
-void DataArrayInt::getMinMaxValues(int& minValue, int& maxValue) const
-{
- checkAllocated();
- if(getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::getMinMaxValues : must be applied on DataArrayInt with only one component !");
- int nbTuples(getNumberOfTuples());
- const int *pt(begin());
- minValue=std::numeric_limits<int>::max(); maxValue=-std::numeric_limits<int>::max();
- for(int i=0;i<nbTuples;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.
- */
-void DataArrayInt::applyInv(int numerator)
-{
- checkAllocated();
- int *ptr=getPointer();
- std::size_t nbOfElems=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/getNumberOfComponents() << " component #" << i%getNumberOfComponents();
- oss << " !";
- throw INTERP_KERNEL::Exception(oss.str().c_str());
- }
- }
- 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.
- */
-void DataArrayInt::applyDivideBy(int val)
-{
- if(val==0)
- throw INTERP_KERNEL::Exception("DataArrayInt::applyDivideBy : Trying to divide by 0 !");
- checkAllocated();
- int *ptr=getPointer();
- std::size_t nbOfElems=getNbOfElems();
- std::transform(ptr,ptr+nbOfElems,ptr,std::bind2nd(std::divides<int>(),val));
- 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.
- */
-void DataArrayInt::applyModulus(int val)
-{
- if(val<=0)
- throw INTERP_KERNEL::Exception("DataArrayInt::applyDivideBy : Trying to operate modulus on value <= 0 !");
- checkAllocated();
- int *ptr=getPointer();
- std::size_t nbOfElems=getNbOfElems();
- std::transform(ptr,ptr+nbOfElems,ptr,std::bind2nd(std::modulus<int>(),val));
- 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
- */
-DataArrayInt *DataArrayInt::findIdsInRange(int vmin, int vmax) const
-{
- InRange<int> ir(vmin,vmax);
- MCAuto<DataArrayInt> ret(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
- */
-DataArrayInt *DataArrayInt::findIdsNotInRange(int vmin, int vmax) const
-{
- NotInRange<int> nir(vmin,vmax);
- MCAuto<DataArrayInt> ret(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() ). */
-bool DataArrayInt::checkAllIdsInRange(int vmin, int vmax) const
-{
- checkAllocated();
- if(getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::checkAllIdsInRange : this must have exactly one component !");
- int nbOfTuples=getNumberOfTuples();
- bool ret=true;
- const int *cptr=getConstPointer();
- for(int 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;
-}
-
-/*!
- * 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.
- */
-void DataArrayInt::applyRModulus(int val)
-{
- checkAllocated();
- int *ptr=getPointer();
- std::size_t nbOfElems=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/getNumberOfComponents() << " component #" << i%getNumberOfComponents();
- oss << " !";
- throw INTERP_KERNEL::Exception(oss.str().c_str());
- }
- }
- 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.
- */
-void DataArrayInt::applyPow(int val)
-{
- checkAllocated();
- if(val<0)
- throw INTERP_KERNEL::Exception("DataArrayInt::applyPow : input pow in < 0 !");
- int *ptr=getPointer();
- std::size_t nbOfElems=getNbOfElems();
- if(val==0)
- {
- std::fill(ptr,ptr+nbOfElems,1);
- return ;
- }
- for(std::size_t i=0;i<nbOfElems;i++,ptr++)
- {
- int tmp=1;
- for(int j=0;j<val;j++)
- tmp*=*ptr;
- *ptr=tmp;
- }
- 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.
- */
-void DataArrayInt::applyRPow(int val)
-{
- checkAllocated();
- int *ptr=getPointer();
- std::size_t nbOfElems=getNbOfElems();
- for(std::size_t i=0;i<nbOfElems;i++,ptr++)
- {
- if(*ptr>=0)
- {
- int tmp=1;
- for(int j=0;j<*ptr;j++)
- tmp*=val;
- *ptr=tmp;
- }
- else
- {
- std::ostringstream oss; oss << "DataArrayInt::applyRPow : presence of negative value in tuple #" << i/getNumberOfComponents() << " component #" << i%getNumberOfComponents();
- oss << " !";
- throw INTERP_KERNEL::Exception(oss.str().c_str());
- }
- }
- declareAsNew();
-}
-
-/*!
- * Returns a new DataArrayInt which is a minimal partition of elements of \a groups.
- * The i-th item of the result array is an ID of a set of elements belonging to a
- * unique set of groups, which the i-th element is a part of. This set of elements
- * belonging to a unique set of groups is called \a family, so the result array contains
- * IDs of families each element belongs to.
- *
- * \b Example: if we have two groups of elements: \a group1 [0,4] and \a group2 [ 0,1,2 ],
- * then there are 3 families:
- * - \a family1 (with ID 1) contains element [0] belonging to ( \a group1 + \a group2 ),
- * - \a family2 (with ID 2) contains elements [4] belonging to ( \a group1 ),
- * - \a family3 (with ID 3) contains element [1,2] belonging to ( \a group2 ), <br>
- * and the result array contains IDs of families [ 1,3,3,0,2 ]. <br> Note a family ID 0 which
- * stands for the element #3 which is in none of groups.
- *
- * \param [in] groups - sequence of groups of element IDs.
- * \param [in] newNb - total number of elements; it must be more than max ID of element
- * in \a groups.
- * \param [out] fidsOfGroups - IDs of families the elements of each group belong to.
- * \return DataArrayInt * - a new instance of DataArrayInt containing IDs of families
- * each element with ID from range [0, \a newNb ) belongs to. The caller is to
- * delete this array using decrRef() as it is no more needed.
- * \throw If any element ID in \a groups violates condition ( 0 <= ID < \a newNb ).
- */
-DataArrayInt *DataArrayInt::MakePartition(const std::vector<const DataArrayInt *>& groups, int newNb, std::vector< std::vector<int> >& fidsOfGroups)
-{
- std::vector<const DataArrayInt *> groups2;
- for(std::vector<const DataArrayInt *>::const_iterator it4=groups.begin();it4!=groups.end();it4++)
- if(*it4)
- groups2.push_back(*it4);
- MCAuto<DataArrayInt> ret=DataArrayInt::New();
- ret->alloc(newNb,1);
- int *retPtr=ret->getPointer();
- std::fill(retPtr,retPtr+newNb,0);
- int fid=1;
- for(std::vector<const DataArrayInt *>::const_iterator iter=groups2.begin();iter!=groups2.end();iter++)
- {
- const int *ptr=(*iter)->getConstPointer();
- std::size_t nbOfElem=(*iter)->getNbOfElems();
- int sfid=fid;
- for(int j=0;j<sfid;j++)
- {
- bool found=false;
- for(std::size_t i=0;i<nbOfElem;i++)
- {
- if(ptr[i]>=0 && ptr[i]<newNb)
- {
- if(retPtr[ptr[i]]==j)
- {
- retPtr[ptr[i]]=fid;
- found=true;
- }
- }
- else
- {
- std::ostringstream oss; oss << "DataArrayInt::MakePartition : In group \"" << (*iter)->getName() << "\" in tuple #" << i << " value = " << ptr[i] << " ! Should be in [0," << newNb;
- oss << ") !";
- throw INTERP_KERNEL::Exception(oss.str().c_str());
- }
- }
- if(found)
- fid++;
- }
- }
- fidsOfGroups.clear();
- fidsOfGroups.resize(groups2.size());
- int grId=0;
- for(std::vector<const DataArrayInt *>::const_iterator iter=groups2.begin();iter!=groups2.end();iter++,grId++)
- {
- std::set<int> tmp;
- const int *ptr=(*iter)->getConstPointer();
- std::size_t nbOfElem=(*iter)->getNbOfElems();
- for(const int *p=ptr;p!=ptr+nbOfElem;p++)
- tmp.insert(retPtr[*p]);
- fidsOfGroups[grId].insert(fidsOfGroups[grId].end(),tmp.begin(),tmp.end());
- }
- return ret.retn();
-}
-
-/*!
- * Returns a new DataArrayInt which contains all elements of given one-dimensional
- * arrays. The result array does not contain any duplicates and its values
- * are sorted in ascending order.
- * \param [in] arr - sequence of DataArrayInt's to unite.
- * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
- * array using decrRef() as it is no more needed.
- * \throw If any \a arr[i] is not allocated.
- * \throw If \a arr[i]->getNumberOfComponents() != 1.
- */
-DataArrayInt *DataArrayInt::BuildUnion(const std::vector<const DataArrayInt *>& arr)
-{
- std::vector<const DataArrayInt *> a;
- for(std::vector<const DataArrayInt *>::const_iterator it4=arr.begin();it4!=arr.end();it4++)
- if(*it4)
- a.push_back(*it4);
- for(std::vector<const DataArrayInt *>::const_iterator it=a.begin();it!=a.end();it++)
- {
- (*it)->checkAllocated();
- if((*it)->getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::BuildUnion : only single component allowed !");
- }
- //
- std::set<int> r;
- for(std::vector<const DataArrayInt *>::const_iterator it=a.begin();it!=a.end();it++)
- {
- const int *pt=(*it)->getConstPointer();
- int nbOfTuples=(*it)->getNumberOfTuples();
- r.insert(pt,pt+nbOfTuples);
- }
- DataArrayInt *ret=DataArrayInt::New();
- ret->alloc((int)r.size(),1);
- std::copy(r.begin(),r.end(),ret->getPointer());
- return ret;
-}
-
-/*!
- * Returns a new DataArrayInt which contains elements present in each of given one-dimensional
- * arrays. The result array does not contain any duplicates and its values
- * are sorted in ascending order.
- * \param [in] arr - sequence of DataArrayInt's to intersect.
- * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
- * array using decrRef() as it is no more needed.
- * \throw If any \a arr[i] is not allocated.
- * \throw If \a arr[i]->getNumberOfComponents() != 1.
- */
-DataArrayInt *DataArrayInt::BuildIntersection(const std::vector<const DataArrayInt *>& arr)
-{
- std::vector<const DataArrayInt *> a;
- for(std::vector<const DataArrayInt *>::const_iterator it4=arr.begin();it4!=arr.end();it4++)
- if(*it4)
- a.push_back(*it4);
- for(std::vector<const DataArrayInt *>::const_iterator it=a.begin();it!=a.end();it++)
- {
- (*it)->checkAllocated();
- if((*it)->getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::BuildIntersection : only single component allowed !");
- }
- //
- std::set<int> r;
- for(std::vector<const DataArrayInt *>::const_iterator it=a.begin();it!=a.end();it++)
- {
- const int *pt=(*it)->getConstPointer();
- int nbOfTuples=(*it)->getNumberOfTuples();
- std::set<int> s1(pt,pt+nbOfTuples);
- if(it!=a.begin())
- {
- std::set<int> r2;
- std::set_intersection(r.begin(),r.end(),s1.begin(),s1.end(),inserter(r2,r2.end()));
- r=r2;
- }
- else
- r=s1;
- }
- DataArrayInt *ret(DataArrayInt::New());
- ret->alloc((int)r.size(),1);
- std::copy(r.begin(),r.end(),ret->getPointer());
- return ret;
-}
-
-/// @cond INTERNAL
-namespace MEDCouplingImpl
-{
- class OpSwitchedOn
- {
- public:
- OpSwitchedOn(int *pt):_pt(pt),_cnt(0) { }
- void operator()(const bool& b) { if(b) *_pt++=_cnt; _cnt++; }
- private:
- int *_pt;
- int _cnt;
- };
-
- class OpSwitchedOff
- {
- public:
- OpSwitchedOff(int *pt):_pt(pt),_cnt(0) { }
- void operator()(const bool& b) { if(!b) *_pt++=_cnt; _cnt++; }
- private:
- int *_pt;
- int _cnt;
- };
-}
-/// @endcond
-
-/*!
- * This method returns the list of ids in ascending mode so that v[id]==true.
- */
-DataArrayInt *DataArrayInt::BuildListOfSwitchedOn(const std::vector<bool>& v)
-{
- int sz((int)std::count(v.begin(),v.end(),true));
- MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(sz,1);
- std::for_each(v.begin(),v.end(),MEDCouplingImpl::OpSwitchedOn(ret->getPointer()));
- return ret.retn();
-}
-
-/*!
- * This method returns the list of ids in ascending mode so that v[id]==false.
- */
-DataArrayInt *DataArrayInt::BuildListOfSwitchedOff(const std::vector<bool>& v)
-{
- int sz((int)std::count(v.begin(),v.end(),false));
- MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(sz,1);
- std::for_each(v.begin(),v.end(),MEDCouplingImpl::OpSwitchedOff(ret->getPointer()));
- return ret.retn();
-}
-
-/*!
- * This method allows to put a vector of vector of integer into a more compact data structure (skyline).
- * This method is not available into python because no available optimized data structure available to map std::vector< std::vector<int> >.
- *
- * \param [in] v the input data structure to be translate into skyline format.
- * \param [out] data the first element of the skyline format. The user is expected to deal with newly allocated array.
- * \param [out] dataIndex the second element of the skyline format.
- */
-void DataArrayInt::PutIntoToSkylineFrmt(const std::vector< std::vector<int> >& v, DataArrayInt *& data, DataArrayInt *& dataIndex)
-{
- int sz((int)v.size());
- MCAuto<DataArrayInt> ret0(DataArrayInt::New()),ret1(DataArrayInt::New());
- ret1->alloc(sz+1,1);
- int *pt(ret1->getPointer()); *pt=0;
- for(int i=0;i<sz;i++,pt++)
- pt[1]=pt[0]+(int)v[i].size();
- ret0->alloc(ret1->back(),1);
- pt=ret0->getPointer();
- for(int i=0;i<sz;i++)
- pt=std::copy(v[i].begin(),v[i].end(),pt);
- data=ret0.retn(); dataIndex=ret1.retn();
-}
-
-/*!
- * 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 ).
- */
-DataArrayInt *DataArrayInt::buildComplement(int nbOfElement) const
-{
- checkAllocated();
- if(getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::buildComplement : only single component allowed !");
- std::vector<bool> tmp(nbOfElement);
- const int *pt=getConstPointer();
- int nbOfTuples=getNumberOfTuples();
- for(const int *w=pt;w!=pt+nbOfTuples;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) !");
- int nbOfRetVal=(int)std::count(tmp.begin(),tmp.end(),false);
- DataArrayInt *ret=DataArrayInt::New();
- ret->alloc(nbOfRetVal,1);
- int j=0;
- int *retPtr=ret->getPointer();
- for(int 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()
- */
-DataArrayInt *DataArrayInt::buildSubstraction(const DataArrayInt *other) const
-{
- if(!other)
- throw INTERP_KERNEL::Exception("DataArrayInt::buildSubstraction : DataArrayInt pointer in input is NULL !");
- checkAllocated();
- other->checkAllocated();
- if(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 int *pt=getConstPointer();
- int nbOfTuples=getNumberOfTuples();
- std::set<int> s1(pt,pt+nbOfTuples);
- pt=other->getConstPointer();
- nbOfTuples=other->getNumberOfTuples();
- std::set<int> s2(pt,pt+nbOfTuples);
- std::vector<int> r;
- std::set_difference(s1.begin(),s1.end(),s2.begin(),s2.end(),std::back_insert_iterator< std::vector<int> >(r));
- DataArrayInt *ret=DataArrayInt::New();
- ret->alloc((int)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
- */
-DataArrayInt *DataArrayInt::buildSubstractionOptimized(const DataArrayInt *other) const
-{
- static const char *MSG="DataArrayInt::buildSubstractionOptimized : only single component allowed !";
- if(!other) throw INTERP_KERNEL::Exception("DataArrayInt::buildSubstractionOptimized : NULL input array !");
- checkAllocated(); other->checkAllocated();
- if(getNumberOfComponents()!=1) throw INTERP_KERNEL::Exception(MSG);
- if(other->getNumberOfComponents()!=1) throw INTERP_KERNEL::Exception(MSG);
- const int *pt1Bg(begin()),*pt1End(end()),*pt2Bg(other->begin()),*pt2End(other->end());
- const int *work1(pt1Bg),*work2(pt2Bg);
- MCAuto<DataArrayInt> ret(DataArrayInt::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.
- */
-DataArrayInt *DataArrayInt::buildUnion(const DataArrayInt *other) const
-{
- std::vector<const DataArrayInt *>arrs(2);
- arrs[0]=this; arrs[1]=other;
- return 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.
- */
-DataArrayInt *DataArrayInt::buildIntersection(const DataArrayInt *other) const
-{
- std::vector<const DataArrayInt *>arrs(2);
- arrs[0]=this; arrs[1]=other;
- return BuildIntersection(arrs);
-}
-
-/*!
- * 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 *DataArrayInt::buildUnique() const
-{
- checkAllocated();
- if(getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::buildUnique : only single component allowed !");
- int nbOfTuples=getNumberOfTuples();
- MCAuto<DataArrayInt> tmp=deepCopy();
- int *data=tmp->getPointer();
- int *last=std::unique(data,data+nbOfTuples);
- MCAuto<DataArrayInt> ret=DataArrayInt::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
- */
-DataArrayInt *DataArrayInt::buildUniqueNotSorted() const
-{
- checkAllocated();
- if(getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::buildUniqueNotSorted : only single component allowed !");
- int minVal,maxVal;
- getMinMaxValues(minVal,maxVal);
- std::vector<bool> b(maxVal-minVal+1,false);
- const int *ptBg(begin()),*endBg(end());
- MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
- for(const int *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
- */
-DataArrayInt *DataArrayInt::deltaShiftIndex() const
-{
- checkAllocated();
- if(getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::deltaShiftIndex : only single component allowed !");
- int nbOfTuples=getNumberOfTuples();
- if(nbOfTuples<2)
- throw INTERP_KERNEL::Exception("DataArrayInt::deltaShiftIndex : 1 tuple at least must be present in 'this' !");
- const int *ptr=getConstPointer();
- DataArrayInt *ret=DataArrayInt::New();
- ret->alloc(nbOfTuples-1,1);
- int *out=ret->getPointer();
- std::transform(ptr+1,ptr+nbOfTuples,ptr,out,std::minus<int>());
- 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.
- */
-void DataArrayInt::computeOffsets()
-{
- checkAllocated();
- if(getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::computeOffsets : only single component allowed !");
- int nbOfTuples=getNumberOfTuples();
- if(nbOfTuples==0)
- return ;
- int *work=getPointer();
- int tmp=work[0];
- work[0]=0;
- for(int i=1;i<nbOfTuples;i++)
- {
- int tmp2=work[i];
- work[i]=work[i-1]+tmp;
- tmp=tmp2;
- }
- 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
- */
-void DataArrayInt::computeOffsetsFull()
-{
- checkAllocated();
- if(getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::computeOffsetsFull : only single component allowed !");
- int nbOfTuples=getNumberOfTuples();
- int *ret=(int *)malloc((nbOfTuples+1)*sizeof(int));
- const int *work=getConstPointer();
- ret[0]=0;
- for(int i=0;i<nbOfTuples;i++)
- ret[i+1]=work[i]+ret[i];
- useArray(ret,true,DeallocType::C_DEALLOC,nbOfTuples+1,1);
- 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>
- */
-void DataArrayInt::findIdsRangesInListOfIds(const DataArrayInt *listOfIds, DataArrayInt *& rangeIdsFetched, DataArrayInt *& idsInInputListThatFetch) const
-{
- if(!listOfIds)
- throw INTERP_KERNEL::Exception("DataArrayInt::findIdsRangesInListOfIds : input list of ids is null !");
- listOfIds->checkAllocated(); checkAllocated();
- if(listOfIds->getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::findIdsRangesInListOfIds : input list of ids must have exactly one component !");
- if(getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::findIdsRangesInListOfIds : this must have exactly one component !");
- MCAuto<DataArrayInt> ret0=DataArrayInt::New(); ret0->alloc(0,1);
- MCAuto<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(0,1);
- const int *tupEnd(listOfIds->end()),*offBg(begin()),*offEnd(end()-1);
- const int *tupPtr(listOfIds->begin()),*offPtr(offBg);
- while(tupPtr!=tupEnd && offPtr!=offEnd)
- {
- if(*tupPtr==*offPtr)
- {
- int i=offPtr[0];
- while(i<offPtr[1] && *tupPtr==i && tupPtr!=tupEnd) { i++; tupPtr++; }
- if(i==offPtr[1])
- {
- ret0->pushBackSilent((int)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 ])
- */
-DataArrayInt *DataArrayInt::buildExplicitArrByRanges(const DataArrayInt *offsets) const
-{
- if(!offsets)
- throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrByRanges : DataArrayInt pointer in input is NULL !");
- checkAllocated();
- if(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 !");
- int othNbTuples=offsets->getNumberOfTuples()-1;
- int nbOfTuples=getNumberOfTuples();
- int retNbOftuples=0;
- const int *work=getConstPointer();
- const int *offPtr=offsets->getConstPointer();
- for(int i=0;i<nbOfTuples;i++)
- {
- int val=work[i];
- if(val>=0 && val<othNbTuples)
- {
- int 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<DataArrayInt> ret=DataArrayInt::New();
- ret->alloc(retNbOftuples,1);
- int *retPtr=ret->getPointer();
- for(int i=0;i<nbOfTuples;i++)
- {
- int val=work[i];
- int start=offPtr[val];
- int off=offPtr[val+1]-start;
- for(int 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>
- */
-DataArrayInt *DataArrayInt::buildExplicitArrOfSliceOnScaledArr(int bg, int stop, int step) const
-{
- if(!isAllocated())
- throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrOfSliceOnScaledArr : not allocated array !");
- if(getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrOfSliceOnScaledArr : number of components is expected to be equal to one !");
- int nbOfTuples(getNumberOfTuples());
- if(nbOfTuples==0)
- throw INTERP_KERNEL::Exception("DataArrayInt::buildExplicitArrOfSliceOnScaledArr : number of tuples must be != 0 !");
- const int *ids(begin());
- int nbOfEltsInSlc(GetNumberOfItemGivenBESRelative(bg,stop,step,"DataArrayInt::buildExplicitArrOfSliceOnScaledArr")),sz(0),pos(bg);
- for(int i=0;i<nbOfEltsInSlc;i++,pos+=step)
- {
- if(pos>=0 && pos<nbOfTuples-1)
- {
- int 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<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(sz,1);
- int *retPtr(ret->getPointer());
- pos=bg;
- for(int i=0;i<nbOfEltsInSlc;i++,pos+=step)
- {
- int delta(ids[pos+1]-ids[pos]);
- for(int 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
- */
-DataArrayInt *DataArrayInt::findRangeIdForEachTuple(const DataArrayInt *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 !");
- checkAllocated();
- if(getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::findRangeIdForEachTuple : this should have only one component !");
- int nbTuples=getNumberOfTuples();
- MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbTuples,1);
- int nbOfRanges=ranges->getNumberOfTuples();
- const int *rangesPtr=ranges->getConstPointer();
- int *retPtr=ret->getPointer();
- const int *inPtr=getConstPointer();
- for(int i=0;i<nbTuples;i++,retPtr++)
- {
- int val=inPtr[i];
- bool found=false;
- for(int 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
- */
-DataArrayInt *DataArrayInt::findIdInRangeForEachTuple(const DataArrayInt *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 !");
- checkAllocated();
- if(getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::findIdInRangeForEachTuple : this should have only one component !");
- int nbTuples=getNumberOfTuples();
- MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbTuples,1);
- int nbOfRanges=ranges->getNumberOfTuples();
- const int *rangesPtr=ranges->getConstPointer();
- int *retPtr=ret->getPointer();
- const int *inPtr=getConstPointer();
- for(int i=0;i<nbTuples;i++,retPtr++)
- {
- int val=inPtr[i];
- bool found=false;
- for(int 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
- */
-void DataArrayInt::sortEachPairToMakeALinkedList()
-{
- checkAllocated();
- if(getNumberOfComponents()!=2)
- throw INTERP_KERNEL::Exception("DataArrayInt::sortEachPairToMakeALinkedList : Only works on DataArrayInt instance with nb of components equal to 2 !");
- int nbOfTuples(getNumberOfTuples());
- if(nbOfTuples<=1)
- return ;
- int *conn(getPointer());
- for(int 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 !");
- int tmp[4];
- std::set<int> 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
- */
-MCAuto<DataArrayInt> DataArrayInt::fromLinkedListOfPairToList() const
-{
- checkAllocated();
- checkNbOfComps(2,"DataArrayInt::fromLinkedListOfPairToList : this is expected to have 2 components");
- int nbTuples(getNumberOfTuples());
- if(nbTuples<1)
- throw INTERP_KERNEL::Exception("DataArrayInt::fromLinkedListOfPairToList : no tuples in this ! Not a linked list !");
- MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbTuples+1,1);
- const int *thisPtr(begin());
- int *retPtr(ret->getPointer());
- retPtr[0]=thisPtr[0];
- for(int 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.
- */
-DataArrayInt *DataArrayInt::getDifferentValues() const
-{
- checkAllocated();
- std::set<int> ret;
- ret.insert(begin(),end());
- MCAuto<DataArrayInt> ret2=DataArrayInt::New(); ret2->alloc((int)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]]
- */
-std::vector<DataArrayInt *> DataArrayInt::partitionByDifferentValues(std::vector<int>& differentIds) const
-{
- checkAllocated();
- if(getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::partitionByDifferentValues : this should have only one component !");
- int id=0;
- std::map<int,int> m,m2,m3;
- for(const int *w=begin();w!=end();w++)
- m[*w]++;
- differentIds.resize(m.size());
- std::vector<DataArrayInt *> ret(m.size());
- std::vector<int *> retPtr(m.size());
- for(std::map<int,int>::const_iterator it=m.begin();it!=m.end();it++,id++)
- {
- m2[(*it).first]=id;
- ret[id]=DataArrayInt::New();
- ret[id]->alloc((*it).second,1);
- retPtr[id]=ret[id]->getPointer();
- differentIds[id]=(*it).first;
- }
- id=0;
- for(const int *w=begin();w!=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.
- */
-std::vector< std::pair<int,int> > DataArrayInt::splitInBalancedSlices(int nbOfSlices) const
-{
- if(!isAllocated() || 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 !");
- int sum(accumulate(0)),nbOfTuples(getNumberOfTuples());
- int sumPerSlc(sum/nbOfSlices),pos(0);
- const int *w(begin());
- std::vector< std::pair<int,int> > ret(nbOfSlices);
- for(int i=0;i<nbOfSlices;i++)
- {
- std::pair<int,int> p(pos,-1);
- int 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;
-}
-
-/*!
- * Returns a new DataArrayInt that is a modulus of two given arrays. There are 3
- * valid cases.
- * 1. The arrays have same number of tuples and components. Then each value of
- * the result array (_a_) is a division of the corresponding values of \a a1 and
- * \a a2, i.e.: _a_ [ i, j ] = _a1_ [ i, j ] % _a2_ [ i, j ].
- * 2. The arrays have same number of tuples and one array, say _a2_, has one
- * component. Then
- * _a_ [ i, j ] = _a1_ [ i, j ] % _a2_ [ i, 0 ].
- * 3. The arrays have same number of components and one array, say _a2_, has one
- * tuple. Then
- * _a_ [ i, j ] = _a1_ [ i, j ] % _a2_ [ 0, j ].
- *
- * Info on components is copied either from the first array (in the first case) or from
- * the array with maximal number of elements (getNbOfElems()).
- * \warning No check of division by zero is performed!
- * \param [in] a1 - a dividend array.
- * \param [in] a2 - a divisor array.
- * \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 either \a a1 or \a a2 is NULL.
- * \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples() and
- * \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents() and
- * none of them has number of tuples or components equal to 1.
- */
-DataArrayInt *DataArrayInt::Modulus(const DataArrayInt *a1, const DataArrayInt *a2)
-{
- if(!a1 || !a2)
- throw INTERP_KERNEL::Exception("DataArrayInt::Modulus : input DataArrayInt instance is NULL !");
- int nbOfTuple1=a1->getNumberOfTuples();
- int nbOfTuple2=a2->getNumberOfTuples();
- int nbOfComp1=a1->getNumberOfComponents();
- int nbOfComp2=a2->getNumberOfComponents();
- if(nbOfTuple2==nbOfTuple1)
- {
- if(nbOfComp1==nbOfComp2)
- {
- MCAuto<DataArrayInt> ret=DataArrayInt::New();
- ret->alloc(nbOfTuple2,nbOfComp1);
- std::transform(a1->begin(),a1->end(),a2->begin(),ret->getPointer(),std::modulus<int>());
- ret->copyStringInfoFrom(*a1);
- return ret.retn();
- }
- else if(nbOfComp2==1)
- {
- MCAuto<DataArrayInt> ret=DataArrayInt::New();
- ret->alloc(nbOfTuple1,nbOfComp1);
- const int *a2Ptr=a2->getConstPointer();
- const int *a1Ptr=a1->getConstPointer();
- int *res=ret->getPointer();
- for(int i=0;i<nbOfTuple1;i++)
- res=std::transform(a1Ptr+i*nbOfComp1,a1Ptr+(i+1)*nbOfComp1,res,std::bind2nd(std::modulus<int>(),a2Ptr[i]));
- ret->copyStringInfoFrom(*a1);
- return ret.retn();
- }
- else
- {
- a1->checkNbOfComps(nbOfComp2,"Nb of components mismatch for array Modulus !");
- return 0;
- }
- }
- else if(nbOfTuple2==1)
- {
- a1->checkNbOfComps(nbOfComp2,"Nb of components mismatch for array Modulus !");
- MCAuto<DataArrayInt> ret=DataArrayInt::New();
- ret->alloc(nbOfTuple1,nbOfComp1);
- const int *a1ptr=a1->getConstPointer(),*a2ptr=a2->getConstPointer();
- int *pt=ret->getPointer();
- for(int i=0;i<nbOfTuple1;i++)
- pt=std::transform(a1ptr+i*nbOfComp1,a1ptr+(i+1)*nbOfComp1,a2ptr,pt,std::modulus<int>());
- ret->copyStringInfoFrom(*a1);
- return ret.retn();
- }
- else
- {
- a1->checkNbOfTuples(nbOfTuple2,"Nb of tuples mismatch for array Modulus !");//will always throw an exception
- return 0;
- }
-}
-
-/*!
- * 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.
- */
-void DataArrayInt::modulusEqual(const DataArrayInt *other)
-{
- if(!other)
- throw INTERP_KERNEL::Exception("DataArrayInt::modulusEqual : input DataArrayInt instance is NULL !");
- const char *msg="Nb of tuples mismatch for DataArrayInt::modulusEqual !";
- checkAllocated(); other->checkAllocated();
- int nbOfTuple=getNumberOfTuples();
- int nbOfTuple2=other->getNumberOfTuples();
- int nbOfComp=getNumberOfComponents();
- int nbOfComp2=other->getNumberOfComponents();
- if(nbOfTuple==nbOfTuple2)
- {
- if(nbOfComp==nbOfComp2)
- {
- std::transform(begin(),end(),other->begin(),getPointer(),std::modulus<int>());
- }
- else if(nbOfComp2==1)
- {
- if(nbOfComp2==nbOfComp)
- {
- int *ptr=getPointer();
- const int *ptrc=other->getConstPointer();
- for(int i=0;i<nbOfTuple;i++)
- std::transform(ptr+i*nbOfComp,ptr+(i+1)*nbOfComp,ptr+i*nbOfComp,std::bind2nd(std::modulus<int>(),*ptrc++));
- }
- else
- throw INTERP_KERNEL::Exception(msg);
- }
- else
- throw INTERP_KERNEL::Exception(msg);
- }
- else if(nbOfTuple2==1)
- {
- int *ptr=getPointer();
- const int *ptrc=other->getConstPointer();
- for(int i=0;i<nbOfTuple;i++)
- std::transform(ptr+i*nbOfComp,ptr+(i+1)*nbOfComp,ptrc,ptr+i*nbOfComp,std::modulus<int>());
- }
- else
- throw INTERP_KERNEL::Exception(msg);
- declareAsNew();
-}
-
-/*!
- * Returns a new DataArrayInt that is the result of pow of two given arrays. There are 3
- * valid cases.
- *
- * \param [in] a1 - an array to pow up.
- * \param [in] a2 - another array to sum up.
- * \return DataArrayInt * - the new instance of DataArrayInt.
- * The caller is to delete this result array using decrRef() as it is no more
- * needed.
- * \throw If either \a a1 or \a a2 is NULL.
- * \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples()
- * \throw If \a a1->getNumberOfComponents() != 1 or \a a2->getNumberOfComponents() != 1.
- * \throw If there is a negative value in \a a2.
- */
-DataArrayInt *DataArrayInt::Pow(const DataArrayInt *a1, const DataArrayInt *a2)
-{
- if(!a1 || !a2)
- throw INTERP_KERNEL::Exception("DataArrayInt::Pow : at least one of input instances is null !");
- int nbOfTuple=a1->getNumberOfTuples();
- int nbOfTuple2=a2->getNumberOfTuples();
- int nbOfComp=a1->getNumberOfComponents();
- int nbOfComp2=a2->getNumberOfComponents();
- if(nbOfTuple!=nbOfTuple2)
- throw INTERP_KERNEL::Exception("DataArrayInt::Pow : number of tuples mismatches !");
- if(nbOfComp!=1 || nbOfComp2!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::Pow : number of components of both arrays must be equal to 1 !");
- MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfTuple,1);
- const int *ptr1(a1->begin()),*ptr2(a2->begin());
- int *ptr=ret->getPointer();
- for(int i=0;i<nbOfTuple;i++,ptr1++,ptr2++,ptr++)
- {
- if(*ptr2>=0)
- {
- int tmp=1;
- for(int j=0;j<*ptr2;j++)
- tmp*=*ptr1;
- *ptr=tmp;
- }
- else
- {
- std::ostringstream oss; oss << "DataArrayInt::Pow : on tuple #" << i << " of a2 value is < 0 (" << *ptr2 << ") !";
- throw INTERP_KERNEL::Exception(oss.str().c_str());
- }
- }
- return ret.retn();
-}
-
-/*!
- * 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.
- */
-void DataArrayInt::powEqual(const DataArrayInt *other)
-{
- if(!other)
- throw INTERP_KERNEL::Exception("DataArrayInt::powEqual : input instance is null !");
- int nbOfTuple=getNumberOfTuples();
- int nbOfTuple2=other->getNumberOfTuples();
- int nbOfComp=getNumberOfComponents();
- int nbOfComp2=other->getNumberOfComponents();
- if(nbOfTuple!=nbOfTuple2)
- throw INTERP_KERNEL::Exception("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 !");
- int *ptr=getPointer();
- const int *ptrc=other->begin();
- for(int i=0;i<nbOfTuple;i++,ptrc++,ptr++)
- {
- if(*ptrc>=0)
- {
- int tmp=1;
- for(int 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());
- }
- }
- declareAsNew();
-}
-
-/*!
- * Returns a C array which is a renumbering map in "Old to New" mode for the input array.
- * This map, if applied to \a start array, would make it sorted. For example, if
- * \a start array contents are [9,10,0,6,4,11,3,7] then the contents of the result array is
- * [5,6,0,3,2,7,1,4].
- * \param [in] start - pointer to the first element of the array for which the
- * permutation map is computed.
- * \param [in] end - pointer specifying the end of the array \a start, so that
- * the last value of \a start is \a end[ -1 ].
- * \return int * - the result permutation array that the caller is to delete as it is no
- * more needed.
- * \throw If there are equal values in the input array.
- */
-int *DataArrayInt::CheckAndPreparePermutation(const int *start, const int *end)
-{
- std::size_t sz=std::distance(start,end);
- int *ret=(int *)malloc(sz*sizeof(int));
- int *work=new int[sz];
- std::copy(start,end,work);
- std::sort(work,work+sz);
- if(std::unique(work,work+sz)!=work+sz)
- {
- delete [] work;
- free(ret);
- throw INTERP_KERNEL::Exception("Some elements are equals in the specified array !");
- }
- std::map<int,int> m;
- for(int *workPt=work;workPt!=work+sz;workPt++)
- m[*workPt]=(int)std::distance(work,workPt);
- int *iter2=ret;
- for(const int *iter=start;iter!=end;iter++,iter2++)
- *iter2=m[*iter];
- delete [] work;
- return ret;
-}
-
-/*!
- * Returns a new DataArrayInt containing an arithmetic progression
- * that is equal to the sequence returned by Python \c range(\a begin,\a end,\a step )
- * function.
- * \param [in] begin - the start value of the result sequence.
- * \param [in] end - limiting value, so that every value of the result array is less than
- * \a end.
- * \param [in] step - specifies the increment or decrement.
- * \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 step == 0.
- * \throw If \a end < \a begin && \a step > 0.
- * \throw If \a end > \a begin && \a step < 0.
- */
-DataArrayInt *DataArrayInt::Range(int begin, int end, int step)
-{
- int nbOfTuples=GetNumberOfItemGivenBESRelative(begin,end,step,"DataArrayInt::Range");
- MCAuto<DataArrayInt> ret=DataArrayInt::New();
- ret->alloc(nbOfTuples,1);
- int *ptr=ret->getPointer();
- if(step>0)
- {
- for(int i=begin;i<end;i+=step,ptr++)
- *ptr=i;
- }
- else
- {
- for(int i=begin;i>end;i+=step,ptr++)
- *ptr=i;
- }
- return ret.retn();
-}
-
-/*!
- * Useless method for end user. Only for MPI/Corba/File serialsation for multi arrays class.
- * Server side.
- */
-void DataArrayInt::getTinySerializationIntInformation(std::vector<int>& tinyInfo) const
-{
- tinyInfo.resize(2);
- if(isAllocated())
- {
- tinyInfo[0]=getNumberOfTuples();
- tinyInfo[1]=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.
- */
-void DataArrayInt::getTinySerializationStrInformation(std::vector<std::string>& tinyInfo) const
-{
- if(isAllocated())
- {
- int nbOfCompo=getNumberOfComponents();
- tinyInfo.resize(nbOfCompo+1);
- tinyInfo[0]=getName();
- for(int i=0;i<nbOfCompo;i++)
- tinyInfo[i+1]=getInfoOnComponent(i);
- }
- else
- {
- tinyInfo.resize(1);
- tinyInfo[0]=getName();
- }
-}
-
-/*!
- * Useless method for end user. Only for MPI/Corba/File serialsation for multi arrays class.
- * This method returns if a feeding is needed.
- */
-bool DataArrayInt::resizeForUnserialization(const std::vector<int>& tinyInfoI)
-{
- int nbOfTuple=tinyInfoI[0];
- int nbOfComp=tinyInfoI[1];
- if(nbOfTuple!=-1 || nbOfComp!=-1)
- {
- 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.
- */
-void DataArrayInt::finishUnserialization(const std::vector<int>& tinyInfoI, const std::vector<std::string>& tinyInfoS)
-{
- setName(tinyInfoS[0]);
- if(isAllocated())
- {
- int nbOfCompo=tinyInfoI[1];
- for(int i=0;i<nbOfCompo;i++)
- setInfoOnComponent(i,tinyInfoS[i+1]);
- }
-}
-
-DataArrayIntIterator::DataArrayIntIterator(DataArrayInt *da):DataArrayIterator<int>(da)
-{
-}
-
-DataArrayInt32Tuple::DataArrayInt32Tuple(int *pt, int nbOfComp):DataArrayTuple<int>(pt,nbOfComp)