+ * Equivalent to DataArrayInt::isEqual except that if false the reason of
+ * mismatch is given.
+ *
+ * \param [in] other the instance to be compared with \a this
+ * \param [out] reason In case of inequality returns the reason.
+ * \sa DataArrayInt::isEqual
+ */
+ template<class T>
+ bool DataArrayDiscrete<T>::isEqualIfNotWhy(const DataArrayDiscrete<T>& other, std::string& reason) const
+ {
+ if(!this->areInfoEqualsIfNotWhy(other,reason))
+ return false;
+ return this->_mem.isEqual(other._mem,0,reason);
+ }
+
+ /*!
+ * Checks if \a this and another DataArrayInt are fully equal. For more info see
+ * \ref MEDCouplingArrayBasicsCompare.
+ * \param [in] other - an instance of DataArrayInt to compare with \a this one.
+ * \return bool - \a true if the two arrays are equal, \a false else.
+ */
+ template<class T>
+ bool DataArrayDiscrete<T>::isEqual(const DataArrayDiscrete<T>& other) const
+ {
+ std::string tmp;
+ return isEqualIfNotWhy(other,tmp);
+ }
+
+ /*!
+ * Checks if values of \a this and another DataArrayInt are equal. For more info see
+ * \ref MEDCouplingArrayBasicsCompare.
+ * \param [in] other - an instance of DataArrayInt to compare with \a this one.
+ * \return bool - \a true if the values of two arrays are equal, \a false else.
+ */
+ template<class T>
+ bool DataArrayDiscrete<T>::isEqualWithoutConsideringStr(const DataArrayDiscrete<T>& other) const
+ {
+ std::string tmp;
+ return this->_mem.isEqual(other._mem,0,tmp);
+ }
+
+ /*!
+ * Checks if values of \a this and another DataArrayInt are equal. Comparison is
+ * performed on sorted value sequences.
+ * For more info see\ref MEDCouplingArrayBasicsCompare.
+ * \param [in] other - an instance of DataArrayInt to compare with \a this one.
+ * \return bool - \a true if the sorted values of two arrays are equal, \a false else.
+ */
+ template<class T>
+ bool DataArrayDiscrete<T>::isEqualWithoutConsideringStrAndOrder(const typename Traits<T>::ArrayType& other) const
+ {
+ MCAuto<DataArrayInt> a(static_cast<const typename Traits<T>::ArrayType *>(this)->deepCopy()),b(other.deepCopy());
+ a->sort();
+ b->sort();
+ return a->isEqualWithoutConsideringStr(*b);
+ }
+
+ template<class T>
+ template<class ALG>
+ void DataArrayDiscrete<T>::switchOnTupleAlg(T val, std::vector<bool>& vec, ALG algo) const
+ {
+ this->checkAllocated();
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::switchOnTupleEqualTo : number of components of this should be equal to one !");
+ int nbOfTuples(this->getNumberOfTuples());
+ if(nbOfTuples!=(int)vec.size())
+ throw INTERP_KERNEL::Exception("DataArrayInt::switchOnTupleEqualTo : number of tuples of this should be equal to size of input vector of bool !");
+ const T *pt(this->begin());
+ for(int i=0;i<nbOfTuples;i++)
+ if(algo(pt[i],val))
+ vec[i]=true;
+ }
+
+ /*!
+ * This method assumes that \a this has one component and is allocated. This method scans all tuples in \a this and for all tuple equal to \a val
+ * put True to the corresponding entry in \a vec.
+ * \a vec is expected to be with the same size than the number of tuples of \a this.
+ *
+ * \sa DataArrayInt::switchOnTupleNotEqualTo.
+ */
+ template<class T>
+ void DataArrayDiscrete<T>::switchOnTupleEqualTo(T val, std::vector<bool>& vec) const
+ {
+ switchOnTupleAlg(val,vec,std::equal_to<T>());
+ }
+
+ /*!
+ * This method assumes that \a this has one component and is allocated. This method scans all tuples in \a this and for all tuple different from \a val
+ * put True to the corresponding entry in \a vec.
+ * \a vec is expected to be with the same size than the number of tuples of \a this.
+ *
+ * \sa DataArrayInt::switchOnTupleEqualTo.
+ */
+ template<class T>
+ void DataArrayDiscrete<T>::switchOnTupleNotEqualTo(T val, std::vector<bool>& vec) const
+ {
+ switchOnTupleAlg(val,vec,std::not_equal_to<T>());
+ }
+
+ /*!
+ * Creates a new one-dimensional DataArrayInt of the same size as \a this and a given
+ * one-dimensional arrays that must be of the same length. The result array describes
+ * correspondence between \a this and \a other arrays, so that
+ * <em> other.getIJ(i,0) == this->getIJ(ret->getIJ(i),0)</em>. If such a permutation is
+ * not possible because some element in \a other is not in \a this, an exception is thrown.
+ * \param [in] other - an array to compute permutation to.
+ * \return DataArrayInt * - a new instance of DataArrayInt, which is a permutation array
+ * from \a this to \a other. The caller is to delete this array using decrRef() as it is
+ * no more needed.
+ * \throw If \a this->getNumberOfComponents() != 1.
+ * \throw If \a other->getNumberOfComponents() != 1.
+ * \throw If \a this->getNumberOfTuples() != \a other->getNumberOfTuples().
+ * \throw If \a other includes a value which is not in \a this array.
+ *
+ * \if ENABLE_EXAMPLES
+ * \ref cpp_mcdataarrayint_buildpermutationarr "Here is a C++ example".
+ *
+ * \ref py_mcdataarrayint_buildpermutationarr "Here is a Python example".
+ * \endif
+ */
+ template<class T>
+ DataArrayIdType *DataArrayDiscrete<T>::buildPermutationArr(const DataArrayDiscrete<T>& other) const
+ {
+ this->checkAllocated();
+ if(this->getNumberOfComponents()!=1 || other.getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::buildPermutationArr : 'this' and 'other' have to have exactly ONE component !");
+ std::size_t nbTuple(this->getNumberOfTuples());
+ other.checkAllocated();
+ if(nbTuple!=other.getNumberOfTuples())
+ throw INTERP_KERNEL::Exception("DataArrayInt::buildPermutationArr : 'this' and 'other' must have the same number of tuple !");
+ MCAuto<DataArrayIdType> ret(DataArrayIdType::New());
+ ret->alloc(nbTuple,1);
+ ret->fillWithValue(-1);
+ const T *pt(this->begin());
+ std::map<int,mcIdType> mm;
+ for(std::size_t i=0;i<nbTuple;i++)
+ mm[pt[i]]=(mcIdType)i;
+ pt=other.begin();
+ mcIdType *retToFill(ret->getPointer());
+ for(std::size_t i=0;i<nbTuple;i++)
+ {
+ std::map<int,int>::const_iterator it=mm.find(pt[i]);
+ if(it==mm.end())
+ {
+ std::ostringstream oss; oss << "DataArrayInt::buildPermutationArr : Arrays mismatch : element (" << pt[i] << ") in 'other' not findable in 'this' !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
+ retToFill[i]=(*it).second;
+ }
+ return ret.retn();
+ }
+
+ /*!
+ * Elements of \a partOfThis are expected to be included in \a this.
+ * The returned array \a ret is so that this[ret]==partOfThis
+ *
+ * For example, if \a this array contents are [9,10,0,6,4,11,3,8] and if \a partOfThis contains [6,0,11,8]
+ * the return array will contain [3,2,5,7].
+ *
+ * \a this is expected to be a 1 compo allocated array.
+ * \param [in] partOfThis - A 1 compo allocated array
+ * \return - A newly allocated array to be dealed by caller having the same number of tuples than \a partOfThis.
+ * \throw if two same element is present twice in \a this
+ * \throw if an element in \a partOfThis is \b NOT in \a this.
+ */
+ template<class T>
+ DataArrayIdType *DataArrayDiscrete<T>::indicesOfSubPart(const DataArrayDiscrete<T>& partOfThis) const
+ {
+ if(this->getNumberOfComponents()!=1 || partOfThis.getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayInt::indicesOfSubPart : this and input array must be one component array !");
+ this->checkAllocated(); partOfThis.checkAllocated();
+ std::size_t thisNbTuples(this->getNumberOfTuples()),nbTuples(partOfThis.getNumberOfTuples());
+ const T *thisPt(this->begin()),*pt(partOfThis.begin());
+ MCAuto<DataArrayIdType> ret(DataArrayIdType::New());
+ ret->alloc(nbTuples,1);
+ T *retPt(ret->getPointer());
+ std::map<int,mcIdType> m;
+ for(std::size_t i=0;i<thisNbTuples;i++,thisPt++)
+ m[*thisPt]=(mcIdType)i;
+ if(m.size()!=thisNbTuples)
+ throw INTERP_KERNEL::Exception("DataArrayInt::indicesOfSubPart : some elements appears more than once !");
+ for(std::size_t i=0;i<nbTuples;i++,retPt++,pt++)
+ {
+ std::map<int,mcIdType>::const_iterator it(m.find(*pt));
+ if(it!=m.end())
+ *retPt=(*it).second;
+ else
+ {
+ std::ostringstream oss; oss << "DataArrayInt::indicesOfSubPart : At pos #" << i << " of input array value is " << *pt << " not in this !";
+ throw INTERP_KERNEL::Exception(oss.str());
+ }
+ }
+ return ret.retn();
+ }
+
+ /*!
+ * Checks that \a this array is consistently **increasing** or **decreasing** in value.
+ * If not an exception is thrown.
+ * \param [in] increasing - if \a true, the array values should be increasing.
+ * \throw If sequence of values is not strictly monotonic in agreement with \a
+ * increasing arg.
+ * \throw If \a this->getNumberOfComponents() != 1.
+ * \throw If \a this is not allocated.
+ */
+ template<class T>
+ void DataArrayDiscrete<T>::checkMonotonic(bool increasing) const
+ {
+ if(!isMonotonic(increasing))
+ {
+ if (increasing)
+ throw INTERP_KERNEL::Exception("DataArrayInt::checkMonotonic : 'this' is not INCREASING monotonic !");
+ else
+ throw INTERP_KERNEL::Exception("DataArrayInt::checkMonotonic : 'this' is not DECREASING monotonic !");
+ }
+ }
+
+ /*!
+ * Checks that \a this array is consistently **increasing** or **decreasing** in value.
+ * \param [in] increasing - if \a true, array values should be increasing.
+ * \return bool - \a true if values change in accordance with \a increasing arg.
+ * \throw If \a this->getNumberOfComponents() != 1.