//
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
-// Author : Anthony Geay (CEA/DEN)
+// Author : Anthony Geay (EDF R&D)
#include "MEDCouplingMemArray.txx"
using namespace MEDCoupling;
-template class DataArrayTemplate<int>;
-template class DataArrayTemplate<double>;
+template class MEDCoupling::MemArray<int>;
+template class MEDCoupling::MemArray<double>;
+template class MEDCoupling::DataArrayTemplate<int>;
+template class MEDCoupling::DataArrayTemplate<double>;
+template class MEDCoupling::DataArrayTemplateClassic<int>;
+template class MEDCoupling::DataArrayTemplateClassic<double>;
+template class MEDCoupling::DataArrayTemplateFP<double>;
+template class MEDCoupling::DataArrayIterator<double>;
+template class MEDCoupling::DataArrayIterator<int>;
+template class MEDCoupling::DataArrayDiscrete<Int32>;
+template class MEDCoupling::DataArrayDiscreteSigned<Int32>;
template<int SPACEDIM>
void DataArrayDouble::findCommonTuplesAlg(const double *bbox, int nbNodes, int limitNodeId, double prec, DataArrayInt *c, DataArrayInt *cI) const
}
}
+int DataArray::EffectiveCircPerm(int nbOfShift, int nbOfTuples)
+{
+ if(nbOfTuples<=0)
+ throw INTERP_KERNEL::Exception("DataArray::EffectiveCircPerm : number of tuples is expected to be > 0 !");
+ if(nbOfShift>=0)
+ {
+ return nbOfShift%nbOfTuples;
+ }
+ else
+ {
+ int tmp(-nbOfShift);
+ tmp=tmp%nbOfTuples;
+ return nbOfTuples-tmp;
+ }
+}
+
std::size_t DataArray::getHeapMemorySizeWithoutChildren() const
{
std::size_t sz1=_name.capacity();
return new DataArrayDouble(*this);
}
-/*!
- * Returns either a \a deep or \a shallow copy of this array. For more info see
- * \ref MEDCouplingArrayBasicsCopyDeep and \ref MEDCouplingArrayBasicsCopyShallow.
- * \param [in] dCpy - if \a true, a deep copy is returned, else, a shallow one.
- * \return DataArrayDouble * - either a new instance of DataArrayDouble (if \a dCpy
- * == \a true) or \a this instance (if \a dCpy == \a false).
- */
-DataArrayDouble *DataArrayDouble::performCopyOrIncrRef(bool dCpy) const
-{
- if(dCpy)
- return deepCopy();
- else
- {
- incrRef();
- return const_cast<DataArrayDouble *>(this);
- }
-}
-
-/*!
- * Assign zero to all values in \a this array. To know more on filling arrays see
- * \ref MEDCouplingArrayFill.
- * \throw If \a this is not allocated.
- */
-void DataArrayDouble::fillWithZero()
-{
- fillWithValue(0.);
-}
-
-/*!
- * Set all values in \a this array so that the i-th element equals to \a init + i
- * (i starts from zero). To know more on filling arrays see \ref MEDCouplingArrayFill.
- * \param [in] init - value to assign to the first element of array.
- * \throw If \a this->getNumberOfComponents() != 1
- * \throw If \a this is not allocated.
- */
-void DataArrayDouble::iota(double init)
-{
- checkAllocated();
- if(getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayDouble::iota : works only for arrays with only one component, you can call 'rearrange' method before !");
- double *ptr=getPointer();
- int ntuples=getNumberOfTuples();
- for(int i=0;i<ntuples;i++)
- ptr[i]=init+double(i);
- declareAsNew();
-}
-
-/*!
- * Checks if all values in \a this array are equal to \a val at precision \a eps.
- * \param [in] val - value to check equality of array values to.
- * \param [in] eps - precision to check the equality.
- * \return bool - \a true if all values are in range (_val_ - _eps_; _val_ + _eps_),
- * \a false else.
- * \throw If \a this->getNumberOfComponents() != 1
- * \throw If \a this is not allocated.
- */
-bool DataArrayDouble::isUniform(double val, double eps) const
-{
- checkAllocated();
- if(getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayDouble::isUniform : must be applied on DataArrayDouble with only one component, you can call 'rearrange' method before !");
- int nbOfTuples=getNumberOfTuples();
- const double *w=getConstPointer();
- const double *end2=w+nbOfTuples;
- const double vmin=val-eps;
- const double vmax=val+eps;
- for(;w!=end2;w++)
- if(*w<vmin || *w>vmax)
- return false;
- return true;
-}
-
/*!
* Checks that \a this array is consistently **increasing** or **decreasing** in value,
* with at least absolute difference value of |\a eps| at each step.
void DataArrayDouble::reprCppStream(const std::string& varName, std::ostream& stream) const
{
- int nbTuples=getNumberOfTuples(),nbComp=getNumberOfComponents();
- const double *data=getConstPointer();
+ int nbTuples(getNumberOfTuples()),nbComp(getNumberOfComponents());
+ const double *data(getConstPointer());
stream.precision(17);
stream << "DataArrayDouble *" << varName << "=DataArrayDouble::New();" << std::endl;
if(nbTuples*nbComp>=1)
return _mem.isEqual(other._mem,prec,tmp);
}
-/*!
- * Creates a new DataArrayInt and assigns all (textual and numerical) data of \a this
- * array to the new one.
- * \return DataArrayInt * - the new instance of DataArrayInt.
- */
-DataArrayInt *DataArrayDouble::convertToIntArr() const
-{
- DataArrayInt *ret=DataArrayInt::New();
- ret->alloc(getNumberOfTuples(),getNumberOfComponents());
- int *dest=ret->getPointer();
- // to make Visual C++ happy : instead of std::size_t nbOfVals=getNbOfElems(); std::copy(src,src+nbOfVals,dest);
- for(const double *src=begin();src!=end();src++,dest++)
- *dest=(int)*src;
- ret->copyStringInfoFrom(*this);
- return ret;
-}
-
-/*!
- * Returns a new DataArrayDouble holding the same values as \a this array but differently
- * arranged in memory. If \a this array holds 2 components of 3 values:
- * \f$ x_0,x_1,x_2,y_0,y_1,y_2 \f$, then the result array holds these values arranged
- * as follows: \f$ x_0,y_0,x_1,y_1,x_2,y_2 \f$.
- * \warning Do not confuse this method with transpose()!
- * \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
- * is to delete using decrRef() as it is no more needed.
- * \throw If \a this is not allocated.
- */
-DataArrayDouble *DataArrayDouble::fromNoInterlace() const
-{
- if(_mem.isNull())
- throw INTERP_KERNEL::Exception("DataArrayDouble::fromNoInterlace : Not defined array !");
- double *tab=_mem.fromNoInterlace(getNumberOfComponents());
- DataArrayDouble *ret=DataArrayDouble::New();
- ret->useArray(tab,true,C_DEALLOC,getNumberOfTuples(),getNumberOfComponents());
- return ret;
-}
-
-/*!
- * Returns a new DataArrayDouble holding the same values as \a this array but differently
- * arranged in memory. If \a this array holds 2 components of 3 values:
- * \f$ x_0,y_0,x_1,y_1,x_2,y_2 \f$, then the result array holds these values arranged
- * as follows: \f$ x_0,x_1,x_2,y_0,y_1,y_2 \f$.
- * \warning Do not confuse this method with transpose()!
- * \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
- * is to delete using decrRef() as it is no more needed.
- * \throw If \a this is not allocated.
- */
-DataArrayDouble *DataArrayDouble::toNoInterlace() const
-{
- if(_mem.isNull())
- throw INTERP_KERNEL::Exception("DataArrayDouble::toNoInterlace : Not defined array !");
- double *tab=_mem.toNoInterlace(getNumberOfComponents());
- DataArrayDouble *ret=DataArrayDouble::New();
- ret->useArray(tab,true,C_DEALLOC,getNumberOfTuples(),getNumberOfComponents());
- return ret;
-}
-
-/*!
- * Appends components of another array to components of \a this one, tuple by tuple.
- * So that the number of tuples of \a this array remains the same and the number of
- * components increases.
- * \param [in] other - the DataArrayDouble to append to \a this one.
- * \throw If \a this is not allocated.
- * \throw If \a this and \a other arrays have different number of tuples.
- *
- * \if ENABLE_EXAMPLES
- * \ref cpp_mcdataarraydouble_meldwith "Here is a C++ example".
- *
- * \ref py_mcdataarraydouble_meldwith "Here is a Python example".
- * \endif
- */
-void DataArrayDouble::meldWith(const DataArrayDouble *other)
-{
- checkAllocated();
- other->checkAllocated();
- int nbOfTuples=getNumberOfTuples();
- if(nbOfTuples!=other->getNumberOfTuples())
- throw INTERP_KERNEL::Exception("DataArrayDouble::meldWith : mismatch of number of tuples !");
- int nbOfComp1=getNumberOfComponents();
- int nbOfComp2=other->getNumberOfComponents();
- double *newArr=(double *)malloc((nbOfTuples*(nbOfComp1+nbOfComp2))*sizeof(double));
- double *w=newArr;
- const double *inp1=getConstPointer();
- const double *inp2=other->getConstPointer();
- for(int i=0;i<nbOfTuples;i++,inp1+=nbOfComp1,inp2+=nbOfComp2)
- {
- w=std::copy(inp1,inp1+nbOfComp1,w);
- w=std::copy(inp2,inp2+nbOfComp2,w);
- }
- useArray(newArr,true,C_DEALLOC,nbOfTuples,nbOfComp1+nbOfComp2);
- std::vector<int> compIds(nbOfComp2);
- for(int i=0;i<nbOfComp2;i++)
- compIds[i]=nbOfComp1+i;
- copyPartOfStringInfoFrom2(compIds,*other);
-}
-
/*!
* This method checks that all tuples in \a other are in \a this.
* If true, the output param \a tupleIds contains the tuples ids of \a this that correspond to tupes in \a this.
commIndex=cI.retn();
}
-/*!
- *
- * \param [in] nbTimes specifies the nb of times each tuples in \a this will be duplicated contiguouly in returned DataArrayDouble instance.
- * \a nbTimes should be at least equal to 1.
- * \return a newly allocated DataArrayDouble having one component and number of tuples equal to \a nbTimes * \c this->getNumberOfTuples.
- * \throw if \a this is not allocated or if \a this has not number of components set to one or if \a nbTimes is lower than 1.
- */
-DataArrayDouble *DataArrayDouble::duplicateEachTupleNTimes(int nbTimes) const
-{
- checkAllocated();
- if(getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayDouble::duplicateEachTupleNTimes : this should have only one component !");
- if(nbTimes<1)
- throw INTERP_KERNEL::Exception("DataArrayDouble::duplicateEachTupleNTimes : nb times should be >= 1 !");
- int nbTuples=getNumberOfTuples();
- const double *inPtr=getConstPointer();
- MCAuto<DataArrayDouble> ret=DataArrayDouble::New(); ret->alloc(nbTimes*nbTuples,1);
- double *retPtr=ret->getPointer();
- for(int i=0;i<nbTuples;i++,inPtr++)
- {
- double val=*inPtr;
- for(int j=0;j<nbTimes;j++,retPtr++)
- *retPtr=val;
- }
- ret->copyStringInfoFrom(*this);
- return ret.retn();
-}
-
/*!
* This methods returns the minimal distance between the two set of points \a this and \a other.
* So \a this and \a other have to have the same number of components. If not an INTERP_KERNEL::Exception will be thrown.
nc[nbOfCompo*i+compoIds[j]]=*ac;
}
-void DataArrayDouble::SetArrayIn(DataArrayDouble *newArray, DataArrayDouble* &arrayToSet)
-{
- if(newArray!=arrayToSet)
- {
- if(arrayToSet)
- arrayToSet->decrRef();
- arrayToSet=newArray;
- if(arrayToSet)
- arrayToSet->incrRef();
- }
-}
-
-void DataArrayDouble::aggregate(const DataArrayDouble *other)
-{
- if(!other)
- throw INTERP_KERNEL::Exception("DataArrayDouble::aggregate : null pointer !");
- if(getNumberOfComponents()!=other->getNumberOfComponents())
- throw INTERP_KERNEL::Exception("DataArrayDouble::aggregate : mismatch number of components !");
- _mem.insertAtTheEnd(other->begin(),other->end());
-}
-
/*!
* Checks if 0.0 value is present in \a this array. If it is the case, an exception
* is thrown.
return ret.retn();
}
+/*!
+ * This method is close to numpy cumSum except that number of element is equal to \a this->getNumberOfTuples()+1. First element of DataArray returned is equal to 0.
+ * This method expects that \a this as only one component. The returned array will have \a this->getNumberOfTuples()+1 tuple with also one component.
+ * The ith element of returned array is equal to the sum of elements in \a this with rank strictly lower than i.
+ *
+ * \return DataArrayDouble - A newly built array containing cum sum of \a this.
+ */
+MCAuto<DataArrayDouble> DataArrayDouble::cumSum() const
+{
+ checkAllocated();
+ checkNbOfComps(1,"DataArrayDouble::cumSum : this is expected to be single component");
+ int nbOfTuple(getNumberOfTuples());
+ MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfTuple+1,1);
+ double *ptr(ret->getPointer());
+ ptr[0]=0.;
+ const double *thisPtr(begin());
+ for(int i=0;i<nbOfTuple;i++)
+ ptr[i+1]=ptr[i]+thisPtr[i];
+ return ret;
+}
+
/*!
* Converts each 2D point defined by the tuple of \a this array from the Polar to the
* Cartesian coordinate system. The two components of the tuple of \a this array are
return ret;
}
-/*!
- * Computes for each tuple the sum of number of components values in the tuple and return it.
- *
- * \return DataArrayDouble * - the new instance of DataArrayDouble containing the
- * same number of tuples as \a this array and one component.
- * The caller is to delete this result array using decrRef() as it is no more
- * needed.
- * \throw If \a this is not allocated.
- */
-DataArrayDouble *DataArrayDouble::sumPerTuple() const
-{
- checkAllocated();
- int nbOfComp(getNumberOfComponents()),nbOfTuple(getNumberOfTuples());
- MCAuto<DataArrayDouble> ret(DataArrayDouble::New());
- ret->alloc(nbOfTuple,1);
- const double *src(getConstPointer());
- double *dest(ret->getPointer());
- for(int i=0;i<nbOfTuple;i++,dest++,src+=nbOfComp)
- *dest=std::accumulate(src,src+nbOfComp,0.);
- return ret.retn();
-}
-
/*!
* Computes the maximal value within every tuple of \a this array.
* \return DataArrayDouble * - the new instance of DataArrayDouble containing the
declareAsNew();
}
-/*!
- * Converts every value of \a this array to its absolute value.
- * \b WARNING this method is non const. If a new DataArrayDouble instance should be built containing the result of abs DataArrayDouble::computeAbs
- * should be called instead.
- *
- * \throw If \a this is not allocated.
- * \sa DataArrayDouble::computeAbs
- */
-void DataArrayDouble::abs()
-{
- checkAllocated();
- double *ptr(getPointer());
- std::size_t nbOfElems(getNbOfElems());
- std::transform(ptr,ptr+nbOfElems,ptr,std::ptr_fun<double,double>(fabs));
- declareAsNew();
-}
-
-/*!
- * This method builds a new instance of \a this object containing the result of std::abs applied of all elements in \a this.
- * This method is a const method (that do not change any values in \a this) contrary to DataArrayDouble::abs method.
- *
- * \return DataArrayDouble * - the new instance of DataArrayDouble containing the
- * same number of tuples and component as \a this array.
- * The caller is to delete this result array using decrRef() as it is no more
- * needed.
- * \throw If \a this is not allocated.
- * \sa DataArrayDouble::abs
- */
-DataArrayDouble *DataArrayDouble::computeAbs() const
-{
- checkAllocated();
- DataArrayDouble *newArr(DataArrayDouble::New());
- int nbOfTuples(getNumberOfTuples());
- int nbOfComp(getNumberOfComponents());
- newArr->alloc(nbOfTuples,nbOfComp);
- std::transform(begin(),end(),newArr->getPointer(),std::ptr_fun<double,double>(fabs));
- newArr->copyStringInfoFrom(*this);
- return newArr;
-}
-
-/*!
- * Apply a linear function to a given component of \a this array, so that
- * an array element <em>(x)</em> becomes \f$ a * x + b \f$.
- * \param [in] a - the first coefficient of the function.
- * \param [in] b - the second coefficient of the function.
- * \param [in] compoId - the index of component to modify.
- * \throw If \a this is not allocated, or \a compoId is not in [0,\c this->getNumberOfComponents() ).
- */
-void DataArrayDouble::applyLin(double a, double b, int compoId)
-{
- checkAllocated();
- double *ptr(getPointer()+compoId);
- int nbOfComp(getNumberOfComponents()),nbOfTuple(getNumberOfTuples());
- if(compoId<0 || compoId>=nbOfComp)
- {
- std::ostringstream oss; oss << "DataArrayDouble::applyLin : The compoId requested (" << compoId << ") is not valid ! Must be in [0," << nbOfComp << ") !";
- throw INTERP_KERNEL::Exception(oss.str().c_str());
- }
- for(int i=0;i<nbOfTuple;i++,ptr+=nbOfComp)
- *ptr=a*(*ptr)+b;
- declareAsNew();
-}
-
-/*!
- * Apply a linear function to all elements of \a this array, so that
- * an element _x_ becomes \f$ a * x + b \f$.
- * \param [in] a - the first coefficient of the function.
- * \param [in] b - the second coefficient of the function.
- * \throw If \a this is not allocated.
- */
-void DataArrayDouble::applyLin(double a, double b)
-{
- checkAllocated();
- double *ptr=getPointer();
- std::size_t nbOfElems=getNbOfElems();
- for(std::size_t i=0;i<nbOfElems;i++,ptr++)
- *ptr=a*(*ptr)+b;
- declareAsNew();
-}
-
/*!
* Modify all elements of \a this array, so that
* an element _x_ becomes \f$ numerator / x \f$.
declareAsNew();
}
-/*!
- * Returns a full copy of \a this array except that sign of all elements is reversed.
- * \return DataArrayDouble * - the new instance of DataArrayDouble containing the
- * same number of tuples and component as \a this array.
- * The caller is to delete this result array using decrRef() as it is no more
- * needed.
- * \throw If \a this is not allocated.
- */
-DataArrayDouble *DataArrayDouble::negate() const
-{
- checkAllocated();
- DataArrayDouble *newArr=DataArrayDouble::New();
- int nbOfTuples=getNumberOfTuples();
- int nbOfComp=getNumberOfComponents();
- newArr->alloc(nbOfTuples,nbOfComp);
- const double *cptr=getConstPointer();
- std::transform(cptr,cptr+nbOfTuples*nbOfComp,newArr->getPointer(),std::negate<double>());
- newArr->copyStringInfoFrom(*this);
- return newArr;
-}
-
/*!
* Modify all elements of \a this array, so that
* an element _x_ becomes <em> val ^ x </em>. Contrary to DataArrayInt::applyPow
return ret.retn();
}
-/*!
- * Returns a new DataArrayDouble by aggregating two given arrays, so that (1) the number
- * of components in the result array is a sum of the number of components of given arrays
- * and (2) the number of tuples in the result array is same as that of each of given
- * arrays. In other words the i-th tuple of result array includes all components of
- * i-th tuples of all given arrays.
- * Number of tuples in the given arrays must be the same.
- * \param [in] a1 - an array to include in the result array.
- * \param [in] a2 - another array to include in the result array.
- * \return DataArrayDouble * - the new instance of DataArrayDouble.
- * The caller is to delete this result array using decrRef() as it is no more
- * needed.
- * \throw If both \a a1 and \a a2 are NULL.
- * \throw If any given array is not allocated.
- * \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples()
- */
-DataArrayDouble *DataArrayDouble::Meld(const DataArrayDouble *a1, const DataArrayDouble *a2)
-{
- std::vector<const DataArrayDouble *> arr(2);
- arr[0]=a1; arr[1]=a2;
- return Meld(arr);
-}
-
-/*!
- * Returns a new DataArrayDouble by aggregating all given arrays, so that (1) the number
- * of components in the result array is a sum of the number of components of given arrays
- * and (2) the number of tuples in the result array is same as that of each of given
- * arrays. In other words the i-th tuple of result array includes all components of
- * i-th tuples of all given arrays.
- * Number of tuples in the given arrays must be the same.
- * \param [in] arr - a sequence of arrays to include in the result array.
- * \return DataArrayDouble * - the new instance of DataArrayDouble.
- * The caller is to delete this result array using decrRef() as it is no more
- * needed.
- * \throw If all arrays within \a arr are NULL.
- * \throw If any given array is not allocated.
- * \throw If getNumberOfTuples() of arrays within \a arr is different.
- */
-DataArrayDouble *DataArrayDouble::Meld(const std::vector<const DataArrayDouble *>& arr)
-{
- std::vector<const DataArrayDouble *> a;
- for(std::vector<const DataArrayDouble *>::const_iterator it4=arr.begin();it4!=arr.end();it4++)
- if(*it4)
- a.push_back(*it4);
- if(a.empty())
- throw INTERP_KERNEL::Exception("DataArrayDouble::Meld : input list must contain at least one NON EMPTY DataArrayDouble !");
- std::vector<const DataArrayDouble *>::const_iterator it;
- for(it=a.begin();it!=a.end();it++)
- (*it)->checkAllocated();
- it=a.begin();
- int nbOfTuples=(*it)->getNumberOfTuples();
- std::vector<int> nbc(a.size());
- std::vector<const double *> pts(a.size());
- nbc[0]=(*it)->getNumberOfComponents();
- pts[0]=(*it++)->getConstPointer();
- for(int i=1;it!=a.end();it++,i++)
- {
- if(nbOfTuples!=(*it)->getNumberOfTuples())
- throw INTERP_KERNEL::Exception("DataArrayDouble::Meld : mismatch of number of tuples !");
- nbc[i]=(*it)->getNumberOfComponents();
- pts[i]=(*it)->getConstPointer();
- }
- int totalNbOfComp=std::accumulate(nbc.begin(),nbc.end(),0);
- DataArrayDouble *ret=DataArrayDouble::New();
- ret->alloc(nbOfTuples,totalNbOfComp);
- double *retPtr=ret->getPointer();
- for(int i=0;i<nbOfTuples;i++)
- for(int j=0;j<(int)a.size();j++)
- {
- retPtr=std::copy(pts[j],pts[j]+nbc[j],retPtr);
- pts[j]+=nbc[j];
- }
- int k=0;
- for(int i=0;i<(int)a.size();i++)
- for(int j=0;j<nbc[i];j++,k++)
- ret->setInfoOnComponent(k,a[i]->getInfoOnComponent(j));
- return ret;
-}
-
/*!
* Returns a new DataArrayDouble containing a dot product of two given arrays, so that
* the i-th tuple of the result array is a sum of products of j-th components of i-th
}
/*!
- * Returns a new DataArrayDouble that is a sum of two given arrays. There are 3
+ * Returns a new DataArrayDouble that is the result of pow 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 sum 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()).
- * \param [in] a1 - an array to sum up.
+ * \param [in] a1 - an array to pow up.
* \param [in] a2 - another array to sum up.
* \return DataArrayDouble * - the new instance of DataArrayDouble.
* The caller is to delete this result array using decrRef() as it is no more
* needed.
* \throw If 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.
+ * \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 a1.
*/
-DataArrayDouble *DataArrayDouble::Add(const DataArrayDouble *a1, const DataArrayDouble *a2)
+DataArrayDouble *DataArrayDouble::Pow(const DataArrayDouble *a1, const DataArrayDouble *a2)
{
if(!a1 || !a2)
- throw INTERP_KERNEL::Exception("DataArrayDouble::Add : input DataArrayDouble instance is NULL !");
+ throw INTERP_KERNEL::Exception("DataArrayDouble::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();
- MCAuto<DataArrayDouble> ret=0;
- if(nbOfTuple==nbOfTuple2)
+ if(nbOfTuple!=nbOfTuple2)
+ throw INTERP_KERNEL::Exception("DataArrayDouble::Pow : number of tuples mismatches !");
+ if(nbOfComp!=1 || nbOfComp2!=1)
+ throw INTERP_KERNEL::Exception("DataArrayDouble::Pow : number of components of both arrays must be equal to 1 !");
+ MCAuto<DataArrayDouble> ret=DataArrayDouble::New(); ret->alloc(nbOfTuple,1);
+ const double *ptr1(a1->begin()),*ptr2(a2->begin());
+ double *ptr=ret->getPointer();
+ for(int i=0;i<nbOfTuple;i++,ptr1++,ptr2++,ptr++)
{
- if(nbOfComp==nbOfComp2)
+ if(*ptr1>=0)
{
- ret=DataArrayDouble::New();
- ret->alloc(nbOfTuple,nbOfComp);
- std::transform(a1->begin(),a1->end(),a2->begin(),ret->getPointer(),std::plus<double>());
- ret->copyStringInfoFrom(*a1);
+ *ptr=pow(*ptr1,*ptr2);
}
else
{
- int nbOfCompMin,nbOfCompMax;
- const DataArrayDouble *aMin, *aMax;
- if(nbOfComp>nbOfComp2)
- {
- nbOfCompMin=nbOfComp2; nbOfCompMax=nbOfComp;
- aMin=a2; aMax=a1;
- }
- else
- {
- nbOfCompMin=nbOfComp; nbOfCompMax=nbOfComp2;
- aMin=a1; aMax=a2;
- }
- if(nbOfCompMin==1)
- {
- ret=DataArrayDouble::New();
- ret->alloc(nbOfTuple,nbOfCompMax);
- const double *aMinPtr=aMin->getConstPointer();
- const double *aMaxPtr=aMax->getConstPointer();
- double *res=ret->getPointer();
- for(int i=0;i<nbOfTuple;i++)
- res=std::transform(aMaxPtr+i*nbOfCompMax,aMaxPtr+(i+1)*nbOfCompMax,res,std::bind2nd(std::plus<double>(),aMinPtr[i]));
- ret->copyStringInfoFrom(*aMax);
- }
- else
- throw INTERP_KERNEL::Exception("Nb of components mismatch for array Add !");
- }
- }
- else if((nbOfTuple==1 && nbOfTuple2>1) || (nbOfTuple>1 && nbOfTuple2==1))
- {
- if(nbOfComp==nbOfComp2)
- {
- int nbOfTupleMax=std::max(nbOfTuple,nbOfTuple2);
- const DataArrayDouble *aMin=nbOfTuple>nbOfTuple2?a2:a1;
- const DataArrayDouble *aMax=nbOfTuple>nbOfTuple2?a1:a2;
- const double *aMinPtr=aMin->getConstPointer(),*aMaxPtr=aMax->getConstPointer();
- ret=DataArrayDouble::New();
- ret->alloc(nbOfTupleMax,nbOfComp);
- double *res=ret->getPointer();
- for(int i=0;i<nbOfTupleMax;i++)
- res=std::transform(aMaxPtr+i*nbOfComp,aMaxPtr+(i+1)*nbOfComp,aMinPtr,res,std::plus<double>());
- ret->copyStringInfoFrom(*aMax);
+ std::ostringstream oss; oss << "DataArrayDouble::Pow : on tuple #" << i << " of a1 value is < 0 (" << *ptr1 << ") !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
}
- else
- throw INTERP_KERNEL::Exception("Nb of components mismatch for array Add !");
}
- else
- throw INTERP_KERNEL::Exception("Nb of tuples mismatch for array Add !");
return ret.retn();
}
/*!
- * Adds values of another DataArrayDouble to values of \a this one. There are 3
- * valid cases.
- * 1. The arrays have same number of tuples and components. Then each value of
- * \a other array is added to the corresponding value of \a this array, 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 ].
+ * Apply pow on values of another DataArrayDouble to values of \a this one.
*
- * \param [in] other - an array to add to \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() and
- * \a this->getNumberOfComponents() != \a other->getNumberOfComponents() and
- * \a other has number of both tuples and components not equal to 1.
+ * \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 this.
*/
-void DataArrayDouble::addEqual(const DataArrayDouble *other)
+void DataArrayDouble::powEqual(const DataArrayDouble *other)
{
if(!other)
- throw INTERP_KERNEL::Exception("DataArrayDouble::addEqual : input DataArrayDouble instance is NULL !");
- const char *msg="Nb of tuples mismatch for DataArrayDouble::addEqual !";
- checkAllocated();
- other->checkAllocated();
+ throw INTERP_KERNEL::Exception("DataArrayDouble::powEqual : input instance is null !");
int nbOfTuple=getNumberOfTuples();
int nbOfTuple2=other->getNumberOfTuples();
int nbOfComp=getNumberOfComponents();
int nbOfComp2=other->getNumberOfComponents();
- if(nbOfTuple==nbOfTuple2)
+ if(nbOfTuple!=nbOfTuple2)
+ throw INTERP_KERNEL::Exception("DataArrayDouble::powEqual : number of tuples mismatches !");
+ if(nbOfComp!=1 || nbOfComp2!=1)
+ throw INTERP_KERNEL::Exception("DataArrayDouble::powEqual : number of components of both arrays must be equal to 1 !");
+ double *ptr=getPointer();
+ const double *ptrc=other->begin();
+ for(int i=0;i<nbOfTuple;i++,ptrc++,ptr++)
{
- if(nbOfComp==nbOfComp2)
- {
- std::transform(begin(),end(),other->begin(),getPointer(),std::plus<double>());
- }
- else if(nbOfComp2==1)
- {
- double *ptr=getPointer();
- const double *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::plus<double>(),*ptrc++));
- }
+ if(*ptr>=0)
+ *ptr=pow(*ptr,*ptrc);
else
- throw INTERP_KERNEL::Exception(msg);
- }
- else if(nbOfTuple2==1)
- {
- if(nbOfComp2==nbOfComp)
{
- double *ptr=getPointer();
- const double *ptrc=other->getConstPointer();
- for(int i=0;i<nbOfTuple;i++)
- std::transform(ptr+i*nbOfComp,ptr+(i+1)*nbOfComp,ptrc,ptr+i*nbOfComp,std::plus<double>());
+ std::ostringstream oss; oss << "DataArrayDouble::powEqual : on tuple #" << i << " of this value is < 0 (" << *ptr << ") !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
}
- else
- throw INTERP_KERNEL::Exception(msg);
}
- else
- throw INTERP_KERNEL::Exception(msg);
declareAsNew();
}
/*!
- * Returns a new DataArrayDouble that is a subtraction 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 subtraction 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 ].
+ * This method is \b NOT wrapped into python because it can be useful only for performance reasons in C++ context.
+ * All values in \a this must be 0. or 1. within eps error. 0 means false, 1 means true.
+ * If an another value than 0 or 1 appear (within eps precision) an INTERP_KERNEL::Exception will be thrown.
*
- * Info on components is copied either from the first array (in the first case) or from
- * the array with maximal number of elements (getNbOfElems()).
- * \param [in] a1 - an array to subtract from.
- * \param [in] a2 - an array to subtract.
- * \return DataArrayDouble * - the new instance of DataArrayDouble.
- * The caller is to delete this result array using decrRef() as it is no more
- * needed.
- * \throw If 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.
+ * \throw if \a this is not allocated.
+ * \throw if \a this has not exactly one component.
*/
-DataArrayDouble *DataArrayDouble::Substract(const DataArrayDouble *a1, const DataArrayDouble *a2)
+std::vector<bool> DataArrayDouble::toVectorOfBool(double eps) const
{
- if(!a1 || !a2)
- throw INTERP_KERNEL::Exception("DataArrayDouble::Substract : input DataArrayDouble instance is NULL !");
- int nbOfTuple1=a1->getNumberOfTuples();
- int nbOfTuple2=a2->getNumberOfTuples();
- int nbOfComp1=a1->getNumberOfComponents();
- int nbOfComp2=a2->getNumberOfComponents();
- if(nbOfTuple2==nbOfTuple1)
+ checkAllocated();
+ if(getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("DataArrayDouble::toVectorOfBool : must be applied on single component array !");
+ int nbt(getNumberOfTuples());
+ std::vector<bool> ret(nbt);
+ const double *pt(begin());
+ for(int i=0;i<nbt;i++)
{
- if(nbOfComp1==nbOfComp2)
- {
- MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
- ret->alloc(nbOfTuple2,nbOfComp1);
- std::transform(a1->begin(),a1->end(),a2->begin(),ret->getPointer(),std::minus<double>());
- ret->copyStringInfoFrom(*a1);
- return ret.retn();
- }
- else if(nbOfComp2==1)
- {
- MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
- ret->alloc(nbOfTuple1,nbOfComp1);
- const double *a2Ptr=a2->getConstPointer();
- const double *a1Ptr=a1->getConstPointer();
- double *res=ret->getPointer();
- for(int i=0;i<nbOfTuple1;i++)
- res=std::transform(a1Ptr+i*nbOfComp1,a1Ptr+(i+1)*nbOfComp1,res,std::bind2nd(std::minus<double>(),a2Ptr[i]));
- ret->copyStringInfoFrom(*a1);
- return ret.retn();
- }
+ if(fabs(pt[i])<eps)
+ ret[i]=false;
+ else if(fabs(pt[i]-1.)<eps)
+ ret[i]=true;
else
{
- a1->checkNbOfComps(nbOfComp2,"Nb of components mismatch for array Substract !");
- return 0;
+ std::ostringstream oss; oss << "DataArrayDouble::toVectorOfBool : the tuple #" << i << " has value " << pt[i] << " is invalid ! must be 0. or 1. !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
}
}
- else if(nbOfTuple2==1)
+ return ret;
+}
+
+/*!
+ * Useless method for end user. Only for MPI/Corba/File serialsation for multi arrays class.
+ * Server side.
+ */
+void DataArrayDouble::getTinySerializationIntInformation(std::vector<int>& tinyInfo) const
+{
+ tinyInfo.resize(2);
+ if(isAllocated())
{
- a1->checkNbOfComps(nbOfComp2,"Nb of components mismatch for array Substract !");
- MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
- ret->alloc(nbOfTuple1,nbOfComp1);
- const double *a1ptr=a1->getConstPointer(),*a2ptr=a2->getConstPointer();
- double *pt=ret->getPointer();
- for(int i=0;i<nbOfTuple1;i++)
- pt=std::transform(a1ptr+i*nbOfComp1,a1ptr+(i+1)*nbOfComp1,a2ptr,pt,std::minus<double>());
- ret->copyStringInfoFrom(*a1);
- return ret.retn();
+ tinyInfo[0]=getNumberOfTuples();
+ tinyInfo[1]=getNumberOfComponents();
}
else
{
- a1->checkNbOfTuples(nbOfTuple2,"Nb of tuples mismatch for array Substract !");//will always throw an exception
- return 0;
+ tinyInfo[0]=-1;
+ tinyInfo[1]=-1;
}
}
/*!
- * Subtract values of another DataArrayDouble from values of \a this one. There are 3
- * valid cases.
- * 1. The arrays have same number of tuples and components. Then each value of
- * \a other array is subtracted from the corresponding value of \a this array, 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 ].
- *
- * \param [in] other - an array to subtract from \a this one.
- * \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.
+ * Useless method for end user. Only for MPI/Corba/File serialsation for multi arrays class.
+ * Server side.
*/
-void DataArrayDouble::substractEqual(const DataArrayDouble *other)
+void DataArrayDouble::getTinySerializationStrInformation(std::vector<std::string>& tinyInfo) const
{
- if(!other)
- throw INTERP_KERNEL::Exception("DataArrayDouble::substractEqual : input DataArrayDouble instance is NULL !");
- const char *msg="Nb of tuples mismatch for DataArrayDouble::substractEqual !";
- checkAllocated();
- other->checkAllocated();
- int nbOfTuple=getNumberOfTuples();
- int nbOfTuple2=other->getNumberOfTuples();
- int nbOfComp=getNumberOfComponents();
- int nbOfComp2=other->getNumberOfComponents();
- if(nbOfTuple==nbOfTuple2)
+ if(isAllocated())
{
- if(nbOfComp==nbOfComp2)
- {
- std::transform(begin(),end(),other->begin(),getPointer(),std::minus<double>());
- }
- else if(nbOfComp2==1)
- {
- double *ptr=getPointer();
- const double *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::minus<double>(),*ptrc++));
- }
- else
- throw INTERP_KERNEL::Exception(msg);
+ int nbOfCompo=getNumberOfComponents();
+ tinyInfo.resize(nbOfCompo+1);
+ tinyInfo[0]=getName();
+ for(int i=0;i<nbOfCompo;i++)
+ tinyInfo[i+1]=getInfoOnComponent(i);
}
- else if(nbOfTuple2==1)
+ else
{
- if(nbOfComp2==nbOfComp)
- {
- double *ptr=getPointer();
- const double *ptrc=other->getConstPointer();
- for(int i=0;i<nbOfTuple;i++)
- std::transform(ptr+i*nbOfComp,ptr+(i+1)*nbOfComp,ptrc,ptr+i*nbOfComp,std::minus<double>());
- }
- else
- throw INTERP_KERNEL::Exception(msg);
+ tinyInfo.resize(1);
+ tinyInfo[0]=getName();
}
- else
- throw INTERP_KERNEL::Exception(msg);
- declareAsNew();
}
/*!
- * Returns a new DataArrayDouble that is a product 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 product 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()).
- * \param [in] a1 - a factor array.
- * \param [in] a2 - another factor array.
- * \return DataArrayDouble * - the new instance of DataArrayDouble.
- * The caller is to delete this result array using decrRef() as it is no more
- * needed.
- * \throw If 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.
+ * Useless method for end user. Only for MPI/Corba/File serialsation for multi arrays class.
+ * This method returns if a feeding is needed.
*/
-DataArrayDouble *DataArrayDouble::Multiply(const DataArrayDouble *a1, const DataArrayDouble *a2)
+bool DataArrayDouble::resizeForUnserialization(const std::vector<int>& tinyInfoI)
{
- if(!a1 || !a2)
- throw INTERP_KERNEL::Exception("DataArrayDouble::Multiply : input DataArrayDouble instance is NULL !");
- int nbOfTuple=a1->getNumberOfTuples();
- int nbOfTuple2=a2->getNumberOfTuples();
- int nbOfComp=a1->getNumberOfComponents();
- int nbOfComp2=a2->getNumberOfComponents();
- MCAuto<DataArrayDouble> ret=0;
- if(nbOfTuple==nbOfTuple2)
- {
- if(nbOfComp==nbOfComp2)
- {
- ret=DataArrayDouble::New();
- ret->alloc(nbOfTuple,nbOfComp);
- std::transform(a1->begin(),a1->end(),a2->begin(),ret->getPointer(),std::multiplies<double>());
- ret->copyStringInfoFrom(*a1);
- }
- else
- {
- int nbOfCompMin,nbOfCompMax;
- const DataArrayDouble *aMin, *aMax;
- if(nbOfComp>nbOfComp2)
- {
- nbOfCompMin=nbOfComp2; nbOfCompMax=nbOfComp;
- aMin=a2; aMax=a1;
- }
- else
- {
- nbOfCompMin=nbOfComp; nbOfCompMax=nbOfComp2;
- aMin=a1; aMax=a2;
- }
- if(nbOfCompMin==1)
- {
- ret=DataArrayDouble::New();
- ret->alloc(nbOfTuple,nbOfCompMax);
- const double *aMinPtr=aMin->getConstPointer();
- const double *aMaxPtr=aMax->getConstPointer();
- double *res=ret->getPointer();
- for(int i=0;i<nbOfTuple;i++)
- res=std::transform(aMaxPtr+i*nbOfCompMax,aMaxPtr+(i+1)*nbOfCompMax,res,std::bind2nd(std::multiplies<double>(),aMinPtr[i]));
- ret->copyStringInfoFrom(*aMax);
- }
- else
- throw INTERP_KERNEL::Exception("Nb of components mismatch for array Multiply !");
- }
- }
- else if((nbOfTuple==1 && nbOfTuple2>1) || (nbOfTuple>1 && nbOfTuple2==1))
+ int nbOfTuple=tinyInfoI[0];
+ int nbOfComp=tinyInfoI[1];
+ if(nbOfTuple!=-1 || nbOfComp!=-1)
{
- if(nbOfComp==nbOfComp2)
- {
- int nbOfTupleMax=std::max(nbOfTuple,nbOfTuple2);
- const DataArrayDouble *aMin=nbOfTuple>nbOfTuple2?a2:a1;
- const DataArrayDouble *aMax=nbOfTuple>nbOfTuple2?a1:a2;
- const double *aMinPtr=aMin->getConstPointer(),*aMaxPtr=aMax->getConstPointer();
- ret=DataArrayDouble::New();
- ret->alloc(nbOfTupleMax,nbOfComp);
- double *res=ret->getPointer();
- for(int i=0;i<nbOfTupleMax;i++)
- res=std::transform(aMaxPtr+i*nbOfComp,aMaxPtr+(i+1)*nbOfComp,aMinPtr,res,std::multiplies<double>());
- ret->copyStringInfoFrom(*aMax);
- }
- else
- throw INTERP_KERNEL::Exception("Nb of components mismatch for array Multiply !");
+ alloc(nbOfTuple,nbOfComp);
+ return true;
}
- else
- throw INTERP_KERNEL::Exception("Nb of tuples mismatch for array Multiply !");
- return ret.retn();
-}
-
-/*!
- * Multiply values of another DataArrayDouble to values of \a this one. There are 3
- * valid cases.
- * 1. The arrays have same number of tuples and components. Then each value of
- * \a other array is multiplied to the corresponding value of \a this array, i.e.
- * _this_ [ i, j ] *= _other_ [ i, j ].
- * 2. The arrays have same number of tuples and \a other array has one component. Then
- * _this_ [ i, j ] *= _other_ [ i, 0 ].
- * 3. The arrays have same number of components and \a other array has one tuple. Then
- * _this_ [ i, j ] *= _a2_ [ 0, j ].
- *
- * \param [in] other - an array to multiply to \a this one.
- * \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 DataArrayDouble::multiplyEqual(const DataArrayDouble *other)
-{
- if(!other)
- throw INTERP_KERNEL::Exception("DataArrayDouble::multiplyEqual : input DataArrayDouble instance is NULL !");
- const char *msg="Nb of tuples mismatch for DataArrayDouble::multiplyEqual !";
- 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::multiplies<double>());
- }
- else if(nbOfComp2==1)
- {
- double *ptr=getPointer();
- const double *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::multiplies<double>(),*ptrc++));
- }
- else
- throw INTERP_KERNEL::Exception(msg);
- }
- else if(nbOfTuple2==1)
- {
- if(nbOfComp2==nbOfComp)
- {
- double *ptr=getPointer();
- const double *ptrc=other->getConstPointer();
- for(int i=0;i<nbOfTuple;i++)
- std::transform(ptr+i*nbOfComp,ptr+(i+1)*nbOfComp,ptrc,ptr+i*nbOfComp,std::multiplies<double>());
- }
- else
- throw INTERP_KERNEL::Exception(msg);
- }
- else
- throw INTERP_KERNEL::Exception(msg);
- declareAsNew();
-}
-
-/*!
- * Returns a new DataArrayDouble that is a division 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 numerator array.
- * \param [in] a2 - a denominator array.
- * \return DataArrayDouble * - the new instance of DataArrayDouble.
- * The caller is to delete this result array using decrRef() as it is no more
- * needed.
- * \throw If 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.
- */
-DataArrayDouble *DataArrayDouble::Divide(const DataArrayDouble *a1, const DataArrayDouble *a2)
-{
- if(!a1 || !a2)
- throw INTERP_KERNEL::Exception("DataArrayDouble::Divide : input DataArrayDouble 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<DataArrayDouble> ret=DataArrayDouble::New();
- ret->alloc(nbOfTuple2,nbOfComp1);
- std::transform(a1->begin(),a1->end(),a2->begin(),ret->getPointer(),std::divides<double>());
- ret->copyStringInfoFrom(*a1);
- return ret.retn();
- }
- else if(nbOfComp2==1)
- {
- MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
- ret->alloc(nbOfTuple1,nbOfComp1);
- const double *a2Ptr=a2->getConstPointer();
- const double *a1Ptr=a1->getConstPointer();
- double *res=ret->getPointer();
- for(int i=0;i<nbOfTuple1;i++)
- res=std::transform(a1Ptr+i*nbOfComp1,a1Ptr+(i+1)*nbOfComp1,res,std::bind2nd(std::divides<double>(),a2Ptr[i]));
- ret->copyStringInfoFrom(*a1);
- return ret.retn();
- }
- else
- {
- a1->checkNbOfComps(nbOfComp2,"Nb of components mismatch for array Divide !");
- return 0;
- }
- }
- else if(nbOfTuple2==1)
- {
- a1->checkNbOfComps(nbOfComp2,"Nb of components mismatch for array Divide !");
- MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
- ret->alloc(nbOfTuple1,nbOfComp1);
- const double *a1ptr=a1->getConstPointer(),*a2ptr=a2->getConstPointer();
- double *pt=ret->getPointer();
- for(int i=0;i<nbOfTuple1;i++)
- pt=std::transform(a1ptr+i*nbOfComp1,a1ptr+(i+1)*nbOfComp1,a2ptr,pt,std::divides<double>());
- ret->copyStringInfoFrom(*a1);
- return ret.retn();
- }
- else
- {
- a1->checkNbOfTuples(nbOfTuple2,"Nb of tuples mismatch for array Divide !");//will always throw an exception
- return 0;
- }
-}
-
-/*!
- * Divide values of \a this array by values of another DataArrayDouble. 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 - an array to divide \a this one by.
- * \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 DataArrayDouble::divideEqual(const DataArrayDouble *other)
-{
- if(!other)
- throw INTERP_KERNEL::Exception("DataArrayDouble::divideEqual : input DataArrayDouble instance is NULL !");
- const char *msg="Nb of tuples mismatch for DataArrayDouble::divideEqual !";
- 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::divides<double>());
- }
- else if(nbOfComp2==1)
- {
- double *ptr=getPointer();
- const double *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::divides<double>(),*ptrc++));
- }
- else
- throw INTERP_KERNEL::Exception(msg);
- }
- else if(nbOfTuple2==1)
- {
- if(nbOfComp2==nbOfComp)
- {
- double *ptr=getPointer();
- const double *ptrc=other->getConstPointer();
- for(int i=0;i<nbOfTuple;i++)
- std::transform(ptr+i*nbOfComp,ptr+(i+1)*nbOfComp,ptrc,ptr+i*nbOfComp,std::divides<double>());
- }
- else
- throw INTERP_KERNEL::Exception(msg);
- }
- else
- throw INTERP_KERNEL::Exception(msg);
- declareAsNew();
-}
-
-/*!
- * Returns a new DataArrayDouble 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 DataArrayDouble * - the new instance of DataArrayDouble.
- * 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 a1.
- */
-DataArrayDouble *DataArrayDouble::Pow(const DataArrayDouble *a1, const DataArrayDouble *a2)
-{
- if(!a1 || !a2)
- throw INTERP_KERNEL::Exception("DataArrayDouble::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("DataArrayDouble::Pow : number of tuples mismatches !");
- if(nbOfComp!=1 || nbOfComp2!=1)
- throw INTERP_KERNEL::Exception("DataArrayDouble::Pow : number of components of both arrays must be equal to 1 !");
- MCAuto<DataArrayDouble> ret=DataArrayDouble::New(); ret->alloc(nbOfTuple,1);
- const double *ptr1(a1->begin()),*ptr2(a2->begin());
- double *ptr=ret->getPointer();
- for(int i=0;i<nbOfTuple;i++,ptr1++,ptr2++,ptr++)
- {
- if(*ptr1>=0)
- {
- *ptr=pow(*ptr1,*ptr2);
- }
- else
- {
- std::ostringstream oss; oss << "DataArrayDouble::Pow : on tuple #" << i << " of a1 value is < 0 (" << *ptr1 << ") !";
- throw INTERP_KERNEL::Exception(oss.str().c_str());
- }
- }
- return ret.retn();
-}
-
-/*!
- * Apply pow on values of another DataArrayDouble 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 this.
- */
-void DataArrayDouble::powEqual(const DataArrayDouble *other)
-{
- if(!other)
- throw INTERP_KERNEL::Exception("DataArrayDouble::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("DataArrayDouble::powEqual : number of tuples mismatches !");
- if(nbOfComp!=1 || nbOfComp2!=1)
- throw INTERP_KERNEL::Exception("DataArrayDouble::powEqual : number of components of both arrays must be equal to 1 !");
- double *ptr=getPointer();
- const double *ptrc=other->begin();
- for(int i=0;i<nbOfTuple;i++,ptrc++,ptr++)
- {
- if(*ptr>=0)
- *ptr=pow(*ptr,*ptrc);
- else
- {
- std::ostringstream oss; oss << "DataArrayDouble::powEqual : on tuple #" << i << " of this value is < 0 (" << *ptr << ") !";
- throw INTERP_KERNEL::Exception(oss.str().c_str());
- }
- }
- declareAsNew();
-}
-
-/*!
- * This method is \b NOT wrapped into python because it can be useful only for performance reasons in C++ context.
- * All values in \a this must be 0. or 1. within eps error. 0 means false, 1 means true.
- * If an another value than 0 or 1 appear (within eps precision) an INTERP_KERNEL::Exception will be thrown.
- *
- * \throw if \a this is not allocated.
- * \throw if \a this has not exactly one component.
- */
-std::vector<bool> DataArrayDouble::toVectorOfBool(double eps) const
-{
- checkAllocated();
- if(getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayDouble::toVectorOfBool : must be applied on single component array !");
- int nbt(getNumberOfTuples());
- std::vector<bool> ret(nbt);
- const double *pt(begin());
- for(int i=0;i<nbt;i++)
- {
- if(fabs(pt[i])<eps)
- ret[i]=false;
- else if(fabs(pt[i]-1.)<eps)
- ret[i]=true;
- else
- {
- std::ostringstream oss; oss << "DataArrayDouble::toVectorOfBool : the tuple #" << i << " has value " << pt[i] << " is invalid ! must be 0. or 1. !";
- throw INTERP_KERNEL::Exception(oss.str().c_str());
- }
- }
- return ret;
-}
-
-/*!
- * Useless method for end user. Only for MPI/Corba/File serialsation for multi arrays class.
- * Server side.
- */
-void DataArrayDouble::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 DataArrayDouble::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 DataArrayDouble::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;
+ return false;
}
/*!
}
}
-DataArrayDoubleIterator::DataArrayDoubleIterator(DataArrayDouble *da):_da(da),_tuple_id(0),_nb_comp(0),_nb_tuple(0)
-{
- if(_da)
- {
- _da->incrRef();
- if(_da->isAllocated())
- {
- _nb_comp=da->getNumberOfComponents();
- _nb_tuple=da->getNumberOfTuples();
- _pt=da->getPointer();
- }
- }
-}
-
-DataArrayDoubleIterator::~DataArrayDoubleIterator()
+DataArrayDoubleIterator::DataArrayDoubleIterator(DataArrayDouble *da):DataArrayIterator<double>(da)
{
- if(_da)
- _da->decrRef();
}
-DataArrayDoubleTuple *DataArrayDoubleIterator::nextt()
-{
- if(_tuple_id<_nb_tuple)
- {
- _tuple_id++;
- DataArrayDoubleTuple *ret=new DataArrayDoubleTuple(_pt,_nb_comp);
- _pt+=_nb_comp;
- return ret;
- }
- else
- return 0;
-}
-
-DataArrayDoubleTuple::DataArrayDoubleTuple(double *pt, int nbOfComp):_pt(pt),_nb_of_compo(nbOfComp)
+DataArrayDoubleTuple::DataArrayDoubleTuple(double *pt, int nbOfComp):DataArrayTuple<double>(pt,nbOfComp)
{
}
double DataArrayDoubleTuple::doubleValue() const
{
- if(_nb_of_compo==1)
- return *_pt;
- throw INTERP_KERNEL::Exception("DataArrayDoubleTuple::doubleValue : DataArrayDoubleTuple instance has not exactly 1 component -> Not possible to convert it into a double precision float !");
+ return this->zeValue();
}
/*!
*/
DataArrayDouble *DataArrayDoubleTuple::buildDADouble(int nbOfTuples, int nbOfCompo) const
{
- if((_nb_of_compo==nbOfCompo && nbOfTuples==1) || (_nb_of_compo==nbOfTuples && nbOfCompo==1))
- {
- DataArrayDouble *ret=DataArrayDouble::New();
- ret->useExternalArrayWithRWAccess(_pt,nbOfTuples,nbOfCompo);
- return ret;
- }
- else
- {
- std::ostringstream oss; oss << "DataArrayDoubleTuple::buildDADouble : unable to build a requested DataArrayDouble instance with nbofTuple=" << nbOfTuples << " and nbOfCompo=" << nbOfCompo;
- oss << ".\nBecause the number of elements in this is " << _nb_of_compo << " !";
- throw INTERP_KERNEL::Exception(oss.str().c_str());
- }
+ return this->buildDA(nbOfTuples,nbOfCompo);
}
/*!
* \ref MEDCouplingArrayBasicsCopyDeep.
* \return DataArrayInt * - a new instance of DataArrayInt.
*/
-DataArrayInt *DataArrayInt::deepCopy() const
-{
- return new DataArrayInt(*this);
-}
-
-/*!
- * Returns either a \a deep or \a shallow copy of this array. For more info see
- * \ref MEDCouplingArrayBasicsCopyDeep and \ref MEDCouplingArrayBasicsCopyShallow.
- * \param [in] dCpy - if \a true, a deep copy is returned, else, a shallow one.
- * \return DataArrayInt * - either a new instance of DataArrayInt (if \a dCpy
- * == \a true) or \a this instance (if \a dCpy == \a false).
- */
-DataArrayInt *DataArrayInt::performCopyOrIncrRef(bool dCpy) const
-{
- if(dCpy)
- return deepCopy();
- else
- {
- incrRef();
- return const_cast<DataArrayInt *>(this);
- }
-}
-
-/*!
- * Assign zero to all values in \a this array. To know more on filling arrays see
- * \ref MEDCouplingArrayFill.
- * \throw If \a this is not allocated.
- */
-void DataArrayInt::fillWithZero()
-{
- fillWithValue(0);
-}
-
-/*!
- * Set all values in \a this array so that the i-th element equals to \a init + i
- * (i starts from zero). To know more on filling arrays see \ref MEDCouplingArrayFill.
- * \param [in] init - value to assign to the first element of array.
- * \throw If \a this->getNumberOfComponents() != 1
- * \throw If \a this is not allocated.
- */
-void DataArrayInt::iota(int init)
+DataArrayInt32 *DataArrayInt32::deepCopy() const
{
- checkAllocated();
- if(getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::iota : works only for arrays with only one component, you can call 'rearrange' method before !");
- int *ptr=getPointer();
- int ntuples=getNumberOfTuples();
- for(int i=0;i<ntuples;i++)
- ptr[i]=init+i;
- declareAsNew();
+ return new DataArrayInt32(*this);
}
/*!
stream << "]";
}
-/*!
- * Modifies in place \a this one-dimensional array so that each value \a v = \a indArrBg[ \a v ],
- * i.e. a current value is used as in index to get a new value from \a indArrBg.
- * \param [in] indArrBg - pointer to the first element of array of new values to assign
- * to \a this array.
- * \param [in] indArrEnd - specifies the end of the array \a indArrBg, so that
- * the last value of \a indArrBg is \a indArrEnd[ -1 ].
- * \throw If \a this->getNumberOfComponents() != 1
- * \throw If any value of \a this can't be used as a valid index for
- * [\a indArrBg, \a indArrEnd).
- *
- * \sa changeValue
- */
-void DataArrayInt::transformWithIndArr(const int *indArrBg, const int *indArrEnd)
-{
- checkAllocated();
- if(getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("Call transformWithIndArr method on DataArrayInt with only one component, you can call 'rearrange' method before !");
- int nbElemsIn((int)std::distance(indArrBg,indArrEnd)),nbOfTuples(getNumberOfTuples()),*pt(getPointer());
- for(int i=0;i<nbOfTuples;i++,pt++)
- {
- if(*pt>=0 && *pt<nbElemsIn)
- *pt=indArrBg[*pt];
- else
- {
- std::ostringstream oss; oss << "DataArrayInt::transformWithIndArr : error on tuple #" << i << " of this value is " << *pt << ", should be in [0," << nbElemsIn << ") !";
- throw INTERP_KERNEL::Exception(oss.str().c_str());
- }
- }
- declareAsNew();
-}
-
/*!
* Computes distribution of values of \a this one-dimensional array between given value
* ranges (casts). This method is typically useful for entity number spliting by types,
return false;
if(sttoopp>strt)
{
- sttoopp++;
- int a(sttoopp-1-strt),tmp(strt);
- if(a%(nbTuples-1)!=0)
- return false;
- stteepp=a/(nbTuples-1);
- for(int i=0;i<nbTuples;i++,tmp+=stteepp)
- if(pt[i]!=tmp)
- return false;
- return true;
+ sttoopp++;
+ int a(sttoopp-1-strt),tmp(strt);
+ if(a%(nbTuples-1)!=0)
+ return false;
+ stteepp=a/(nbTuples-1);
+ for(int i=0;i<nbTuples;i++,tmp+=stteepp)
+ if(pt[i]!=tmp)
+ return false;
+ return true;
+ }
+ else
+ {
+ sttoopp--;
+ int a(strt-sttoopp-1),tmp(strt);
+ if(a%(nbTuples-1)!=0)
+ return false;
+ stteepp=-(a/(nbTuples-1));
+ for(int i=0;i<nbTuples;i++,tmp+=stteepp)
+ if(pt[i]!=tmp)
+ return false;
+ return true;
+ }
+}
+
+
+/*!
+ * Modifies in place \a this one-dimensional array so that each value \a v = \a indArrBg[ \a v ],
+ * i.e. a current value is used as in index to get a new value from \a indArrBg.
+ * \param [in] indArrBg - pointer to the first element of array of new values to assign
+ * to \a this array.
+ * \param [in] indArrEnd - specifies the end of the array \a indArrBg, so that
+ * the last value of \a indArrBg is \a indArrEnd[ -1 ].
+ * \throw If \a this->getNumberOfComponents() != 1
+ * \throw If any value of \a this can't be used as a valid index for
+ * [\a indArrBg, \a indArrEnd).
+ *
+ * \sa changeValue
+ */
+void DataArrayInt::transformWithIndArr(const int *indArrBg, const int *indArrEnd)
+{
+ this->checkAllocated();
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("Call transformWithIndArr method on DataArrayInt with only one component, you can call 'rearrange' method before !");
+ int nbElemsIn((int)std::distance(indArrBg,indArrEnd)),nbOfTuples(getNumberOfTuples()),*pt(getPointer());
+ for(int i=0;i<nbOfTuples;i++,pt++)
+ {
+ if(*pt>=0 && *pt<nbElemsIn)
+ *pt=indArrBg[*pt];
+ else
+ {
+ std::ostringstream oss; oss << "DataArrayInt::transformWithIndArr : error on tuple #" << i << " of this value is " << *pt << ", should be in [0," << nbElemsIn << ") !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
}
- else
+ this->declareAsNew();
+}
+
+void DataArrayInt::transformWithIndArr(const MapKeyVal<int>& m)
+{
+ this->checkAllocated();
+ if(this->getNumberOfComponents()!=1)
+ throw INTERP_KERNEL::Exception("Call transformWithIndArr method on DataArrayInt with only one component, you can call 'rearrange' method before !");
+ const std::map<int,int> dat(m.data());
+ int nbOfTuples(getNumberOfTuples()),*pt(getPointer());
+ for(int i=0;i<nbOfTuples;i++,pt++)
{
- sttoopp--;
- int a(strt-sttoopp-1),tmp(strt);
- if(a%(nbTuples-1)!=0)
- return false;
- stteepp=-(a/(nbTuples-1));
- for(int i=0;i<nbTuples;i++,tmp+=stteepp)
- if(pt[i]!=tmp)
- return false;
- return true;
+ std::map<int,int>::const_iterator it(dat.find(*pt));
+ if(it!=dat.end())
+ *pt=(*it).second;
+ else
+ {
+ std::ostringstream oss; oss << "DataArrayInt::transformWithIndArr : error on tuple #" << i << " of this value is " << *pt << " not in map !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
}
+ this->declareAsNew();
}
/*!
*/
DataArrayInt *DataArrayInt::invertArrayO2N2N2O(int newNbOfElem) const
{
- MCAuto<DataArrayInt> ret=DataArrayInt::New();
+ MCAuto<DataArrayInt> ret(DataArrayInt::New());
ret->alloc(newNbOfElem,1);
- int nbOfOldNodes=getNumberOfTuples();
- const int *old2New=getConstPointer();
- int *pt=ret->getPointer();
+ int nbOfOldNodes(this->getNumberOfTuples());
+ const int *old2New(begin());
+ int *pt(ret->getPointer());
for(int i=0;i!=nbOfOldNodes;i++)
{
int newp(old2New[i]);
int nbOfOldNodes=getNumberOfTuples();
const int *old2New=getConstPointer();
int *pt=ret->getPointer();
- for(int i=nbOfOldNodes-1;i>=0;i--)
- {
- int newp(old2New[i]);
- if(newp!=-1)
- {
- if(newp>=0 && newp<newNbOfElem)
- pt[newp]=i;
- else
- {
- std::ostringstream oss; oss << "DataArrayInt::invertArrayO2N2N2OBis : At place #" << i << " the newplace is " << newp << " must be in [0," << newNbOfElem << ") !";
- throw INTERP_KERNEL::Exception(oss.str().c_str());
- }
- }
- }
- return ret.retn();
-}
-
-/*!
- * Creates a one-dimensional DataArrayInt of given length, whose contents are computed
- * from values of \a this array, which is supposed to contain a renumbering map in
- * "New to Old" mode. The result array contains a renumbering map in "Old to New" mode.
- * To know how to use the renumbering maps see \ref numbering.
- * \param [in] newNbOfElem - the number of tuples in the result array.
- * \return DataArrayInt * - the new instance of DataArrayInt.
- * The caller is to delete this result array using decrRef() as it is no more
- * needed.
- *
- * \if ENABLE_EXAMPLES
- * \ref cpp_mcdataarrayint_invertarrayn2o2o2n "Here is a C++ example".
- *
- * \ref py_mcdataarrayint_invertarrayn2o2o2n "Here is a Python example".
- * \endif
- */
-DataArrayInt *DataArrayInt::invertArrayN2O2O2N(int oldNbOfElem) const
-{
- checkAllocated();
- MCAuto<DataArrayInt> ret=DataArrayInt::New();
- ret->alloc(oldNbOfElem,1);
- const int *new2Old=getConstPointer();
- int *pt=ret->getPointer();
- std::fill(pt,pt+oldNbOfElem,-1);
- int nbOfNewElems=getNumberOfTuples();
- for(int i=0;i<nbOfNewElems;i++)
- {
- int v(new2Old[i]);
- if(v>=0 && v<oldNbOfElem)
- pt[v]=i;
- else
- {
- std::ostringstream oss; oss << "DataArrayInt::invertArrayN2O2O2N : in new id #" << i << " old value is " << v << " expected to be in [0," << oldNbOfElem << ") !";
- throw INTERP_KERNEL::Exception(oss.str().c_str());
- }
- }
- return ret.retn();
-}
-
-/*!
- * 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
- */
-bool DataArrayInt::isEqualIfNotWhy(const DataArrayInt& other, std::string& reason) const
-{
- if(!areInfoEqualsIfNotWhy(other,reason))
- return false;
- return _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.
- */
-bool DataArrayInt::isEqual(const DataArrayInt& 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.
- */
-bool DataArrayInt::isEqualWithoutConsideringStr(const DataArrayInt& other) const
-{
- std::string tmp;
- return _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.
- */
-bool DataArrayInt::isEqualWithoutConsideringStrAndOrder(const DataArrayInt& other) const
-{
- MCAuto<DataArrayInt> a=deepCopy();
- MCAuto<DataArrayInt> b=other.deepCopy();
- a->sort();
- b->sort();
- return a->isEqualWithoutConsideringStr(*b);
-}
-
-/*!
- * This method compares content of input vector \a v and \a this.
- * If for each id in \a this v[id]==True and for all other ids id2 not in \a this v[id2]==False, true is returned.
- * For performance reasons \a this is expected to be sorted ascendingly. If not an exception will be thrown.
- *
- * \param [in] v - the vector of 'flags' to be compared with \a this.
- *
- * \throw If \a this is not sorted ascendingly.
- * \throw If \a this has not exactly one component.
- * \throw If \a this is not allocated.
- */
-bool DataArrayInt::isFittingWith(const std::vector<bool>& v) const
-{
- checkAllocated();
- if(getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::isFittingWith : number of components of this should be equal to one !");
- const int *w(begin()),*end2(end());
- int refVal=-std::numeric_limits<int>::max();
- int i=0;
- std::vector<bool>::const_iterator it(v.begin());
- for(;it!=v.end();it++,i++)
- {
- if(*it)
- {
- if(w!=end2)
- {
- if(*w++==i)
- {
- if(i>refVal)
- refVal=i;
- else
- {
- std::ostringstream oss; oss << "DataArrayInt::isFittingWith : At pos #" << std::distance(begin(),w-1) << " this is not sorted ascendingly !";
- throw INTERP_KERNEL::Exception(oss.str().c_str());
- }
- }
- else
- return false;
- }
- else
- return false;
- }
- }
- return w==end2;
-}
-
-/*!
- * 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.
- */
-void DataArrayInt::switchOnTupleEqualTo(int val, std::vector<bool>& vec) const
-{
- checkAllocated();
- if(getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::switchOnTupleEqualTo : number of components of this should be equal to one !");
- int nbOfTuples(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 int *pt(begin());
- for(int i=0;i<nbOfTuples;i++)
- if(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 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.
- */
-void DataArrayInt::switchOnTupleNotEqualTo(int val, std::vector<bool>& vec) const
-{
- checkAllocated();
- if(getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::switchOnTupleNotEqualTo : number of components of this should be equal to one !");
- int nbOfTuples(getNumberOfTuples());
- if(nbOfTuples!=(int)vec.size())
- throw INTERP_KERNEL::Exception("DataArrayInt::switchOnTupleNotEqualTo : number of tuples of this should be equal to size of input vector of bool !");
- const int *pt(begin());
- for(int i=0;i<nbOfTuples;i++)
- if(pt[i]!=val)
- vec[i]=true;
-}
-
-/*!
- * Computes for each tuple the sum of number of components values in the tuple and return it.
- *
- * \return DataArrayInt * - the new instance of DataArrayInt containing the
- * same number of tuples as \a this array and one component.
- * The caller is to delete this result array using decrRef() as it is no more
- * needed.
- * \throw If \a this is not allocated.
- */
-DataArrayInt *DataArrayInt::sumPerTuple() const
-{
- checkAllocated();
- int nbOfComp(getNumberOfComponents()),nbOfTuple(getNumberOfTuples());
- MCAuto<DataArrayInt> ret(DataArrayInt::New());
- ret->alloc(nbOfTuple,1);
- const int *src(getConstPointer());
- int *dest(ret->getPointer());
- for(int i=0;i<nbOfTuple;i++,dest++,src+=nbOfComp)
- *dest=std::accumulate(src,src+nbOfComp,0);
- 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.
- */
-void DataArrayInt::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.
- * \throw If \a this is not allocated.
- */
-bool DataArrayInt::isMonotonic(bool increasing) const
-{
- checkAllocated();
- if(getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::isMonotonic : only supported with 'this' array with ONE component !");
- int nbOfElements=getNumberOfTuples();
- const int *ptr=getConstPointer();
- if(nbOfElements==0)
- return true;
- int ref=ptr[0];
- if(increasing)
- {
- for(int i=1;i<nbOfElements;i++)
- {
- if(ptr[i]>=ref)
- ref=ptr[i];
- else
- return false;
- }
- }
- else
- {
- for(int i=1;i<nbOfElements;i++)
- {
- if(ptr[i]<=ref)
- ref=ptr[i];
- else
- return false;
- }
- }
- return true;
-}
-
-/*!
- * This method check that array consistently INCREASING or DECREASING in value.
- */
-bool DataArrayInt::isStrictlyMonotonic(bool increasing) const
-{
- checkAllocated();
- if(getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::isStrictlyMonotonic : only supported with 'this' array with ONE component !");
- int nbOfElements=getNumberOfTuples();
- const int *ptr=getConstPointer();
- if(nbOfElements==0)
- return true;
- int ref=ptr[0];
- if(increasing)
- {
- for(int i=1;i<nbOfElements;i++)
- {
- if(ptr[i]>ref)
- ref=ptr[i];
- else
- return false;
- }
- }
- else
+ for(int i=nbOfOldNodes-1;i>=0;i--)
{
- for(int i=1;i<nbOfElements;i++)
+ int newp(old2New[i]);
+ if(newp!=-1)
{
- if(ptr[i]<ref)
- ref=ptr[i];
+ if(newp>=0 && newp<newNbOfElem)
+ pt[newp]=i;
else
- return false;
+ {
+ std::ostringstream oss; oss << "DataArrayInt::invertArrayO2N2N2OBis : At place #" << i << " the newplace is " << newp << " must be in [0," << newNbOfElem << ") !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
}
}
- return true;
-}
-
-/*!
- * This method check that array consistently INCREASING or DECREASING in value.
- */
-void DataArrayInt::checkStrictlyMonotonic(bool increasing) const
-{
- if(!isStrictlyMonotonic(increasing))
- {
- if (increasing)
- throw INTERP_KERNEL::Exception("DataArrayInt::checkStrictlyMonotonic : 'this' is not strictly INCREASING monotonic !");
- else
- throw INTERP_KERNEL::Exception("DataArrayInt::checkStrictlyMonotonic : 'this' is not strictly DECREASING monotonic !");
- }
+ return ret.retn();
}
/*!
- * 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.
+ * Creates a one-dimensional DataArrayInt of given length, whose contents are computed
+ * from values of \a this array, which is supposed to contain a renumbering map in
+ * "New to Old" mode. The result array contains a renumbering map in "Old to New" mode.
+ * To know how to use the renumbering maps see \ref numbering.
+ * \param [in] newNbOfElem - the number of tuples in the result array.
+ * \return DataArrayInt * - the new instance of DataArrayInt.
+ * The caller is to delete this result array using decrRef() as it is no more
+ * needed.
*
* \if ENABLE_EXAMPLES
- * \ref cpp_mcdataarrayint_buildpermutationarr "Here is a C++ example".
+ * \ref cpp_mcdataarrayint_invertarrayn2o2o2n "Here is a C++ example".
*
- * \ref py_mcdataarrayint_buildpermutationarr "Here is a Python example".
+ * \ref py_mcdataarrayint_invertarrayn2o2o2n "Here is a Python example".
+ * \sa invertArrayN2O2O2NOptimized
* \endif
*/
-DataArrayInt *DataArrayInt::buildPermutationArr(const DataArrayInt& other) const
+DataArrayInt *DataArrayInt::invertArrayN2O2O2N(int oldNbOfElem) const
{
checkAllocated();
- if(getNumberOfComponents()!=1 || other.getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::buildPermutationArr : 'this' and 'other' have to have exactly ONE component !");
- int nbTuple=getNumberOfTuples();
- other.checkAllocated();
- if(nbTuple!=other.getNumberOfTuples())
- throw INTERP_KERNEL::Exception("DataArrayInt::buildPermutationArr : 'this' and 'other' must have the same number of tuple !");
MCAuto<DataArrayInt> ret=DataArrayInt::New();
- ret->alloc(nbTuple,1);
- ret->fillWithValue(-1);
- const int *pt=getConstPointer();
- std::map<int,int> mm;
- for(int i=0;i<nbTuple;i++)
- mm[pt[i]]=i;
- pt=other.getConstPointer();
- int *retToFill=ret->getPointer();
- for(int i=0;i<nbTuple;i++)
+ ret->alloc(oldNbOfElem,1);
+ const int *new2Old=getConstPointer();
+ int *pt=ret->getPointer();
+ std::fill(pt,pt+oldNbOfElem,-1);
+ int nbOfNewElems=getNumberOfTuples();
+ for(int i=0;i<nbOfNewElems;i++)
{
- std::map<int,int>::const_iterator it=mm.find(pt[i]);
- if(it==mm.end())
+ int v(new2Old[i]);
+ if(v>=0 && v<oldNbOfElem)
+ pt[v]=i;
+ else
{
- std::ostringstream oss; oss << "DataArrayInt::buildPermutationArr : Arrays mismatch : element (" << pt[i] << ") in 'other' not findable in 'this' !";
+ std::ostringstream oss; oss << "DataArrayInt::invertArrayN2O2O2N : in new id #" << i << " old value is " << v << " expected to be in [0," << oldNbOfElem << ") !";
throw INTERP_KERNEL::Exception(oss.str().c_str());
}
- retToFill[i]=(*it).second;
}
return ret.retn();
}
-void DataArrayInt::aggregate(const DataArrayInt *other)
-{
- if(!other)
- throw INTERP_KERNEL::Exception("DataArrayInt::aggregate : null pointer !");
- if(getNumberOfComponents()!=other->getNumberOfComponents())
- throw INTERP_KERNEL::Exception("DataArrayInt::aggregate : mismatch number of components !");
- _mem.insertAtTheEnd(other->begin(),other->end());
-}
-
-/*!
- * Returns a new DataArrayInt holding the same values as \a this array but differently
- * arranged in memory. If \a this array holds 2 components of 3 values:
- * \f$ x_0,x_1,x_2,y_0,y_1,y_2 \f$, then the result array holds these values arranged
- * as follows: \f$ x_0,y_0,x_1,y_1,x_2,y_2 \f$.
- * \warning Do not confuse this method with transpose()!
- * \return DataArrayInt * - the new instance of DataArrayInt that the caller
- * is to delete using decrRef() as it is no more needed.
- * \throw If \a this is not allocated.
- */
-DataArrayInt *DataArrayInt::fromNoInterlace() const
-{
- checkAllocated();
- if(_mem.isNull())
- throw INTERP_KERNEL::Exception("DataArrayInt::fromNoInterlace : Not defined array !");
- int *tab=_mem.fromNoInterlace(getNumberOfComponents());
- DataArrayInt *ret=DataArrayInt::New();
- ret->useArray(tab,true,C_DEALLOC,getNumberOfTuples(),getNumberOfComponents());
- return ret;
-}
-
/*!
- * Returns a new DataArrayInt holding the same values as \a this array but differently
- * arranged in memory. If \a this array holds 2 components of 3 values:
- * \f$ x_0,y_0,x_1,y_1,x_2,y_2 \f$, then the result array holds these values arranged
- * as follows: \f$ x_0,x_1,x_2,y_0,y_1,y_2 \f$.
- * \warning Do not confuse this method with transpose()!
- * \return DataArrayInt * - the new instance of DataArrayInt that the caller
- * is to delete using decrRef() as it is no more needed.
- * \throw If \a this is not allocated.
+ * Creates a map, whose contents are computed
+ * from values of \a this array, which is supposed to contain a renumbering map in
+ * "New to Old" mode. The result array contains a renumbering map in "Old to New" mode.
+ * To know how to use the renumbering maps see \ref numbering.
+ * \param [in] newNbOfElem - the number of tuples in the result array.
+ * \return MapII - the new instance of Map.
+ *
+ * \if ENABLE_EXAMPLES
+ * \ref cpp_mcdataarrayint_invertarrayn2o2o2n "Here is a C++ example".
+ *
+ * \ref py_mcdataarrayint_invertarrayn2o2o2n "Here is a Python example".
+ * \sa invertArrayN2O2O2N
+ * \endif
*/
-DataArrayInt *DataArrayInt::toNoInterlace() const
+MCAuto< MapKeyVal<int> > DataArrayInt::invertArrayN2O2O2NOptimized() const
{
checkAllocated();
- if(_mem.isNull())
- throw INTERP_KERNEL::Exception("DataArrayInt::toNoInterlace : Not defined array !");
- int *tab=_mem.toNoInterlace(getNumberOfComponents());
- DataArrayInt *ret=DataArrayInt::New();
- ret->useArray(tab,true,C_DEALLOC,getNumberOfTuples(),getNumberOfComponents());
+ MCAuto< MapKeyVal<int> > ret(MapKeyVal<int>::New());
+ std::map<int,int>& m(ret->data());
+ const int *new2Old(begin());
+ int nbOfNewElems(this->getNumberOfTuples());
+ for(int i=0;i<nbOfNewElems;i++)
+ {
+ int v(new2Old[i]);
+ m[v]=i;
+ }
return ret;
}
* \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 !");
- int nbOfTuples=getNumberOfTuples();
- const int *w=getConstPointer();
- const int *end2=w+nbOfTuples;
+ 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
return true;
}
-/*!
- * Creates a new DataArrayDouble and assigns all (textual and numerical) data of \a this
- * array to the new one.
- * \return DataArrayDouble * - the new instance of DataArrayInt.
- */
-DataArrayDouble *DataArrayInt::convertToDblArr() const
-{
- checkAllocated();
- DataArrayDouble *ret=DataArrayDouble::New();
- ret->alloc(getNumberOfTuples(),getNumberOfComponents());
- std::size_t nbOfVals=getNbOfElems();
- const int *src=getConstPointer();
- double *dest=ret->getPointer();
- std::copy(src,src+nbOfVals,dest);
- ret->copyStringInfoFrom(*this);
- return ret;
-}
-
-/*!
- * Appends components of another array to components of \a this one, tuple by tuple.
- * So that the number of tuples of \a this array remains the same and the number of
- * components increases.
- * \param [in] other - the DataArrayInt to append to \a this one.
- * \throw If \a this is not allocated.
- * \throw If \a this and \a other arrays have different number of tuples.
- *
- * \if ENABLE_EXAMPLES
- * \ref cpp_mcdataarrayint_meldwith "Here is a C++ example".
- *
- * \ref py_mcdataarrayint_meldwith "Here is a Python example".
- * \endif
- */
-void DataArrayInt::meldWith(const DataArrayInt *other)
-{
- if(!other)
- throw INTERP_KERNEL::Exception("DataArrayInt::meldWith : DataArrayInt pointer in input is NULL !");
- checkAllocated();
- other->checkAllocated();
- int nbOfTuples=getNumberOfTuples();
- if(nbOfTuples!=other->getNumberOfTuples())
- throw INTERP_KERNEL::Exception("DataArrayInt::meldWith : mismatch of number of tuples !");
- int nbOfComp1=getNumberOfComponents();
- int nbOfComp2=other->getNumberOfComponents();
- int *newArr=(int *)malloc(nbOfTuples*(nbOfComp1+nbOfComp2)*sizeof(int));
- int *w=newArr;
- const int *inp1=getConstPointer();
- const int *inp2=other->getConstPointer();
- for(int i=0;i<nbOfTuples;i++,inp1+=nbOfComp1,inp2+=nbOfComp2)
- {
- w=std::copy(inp1,inp1+nbOfComp1,w);
- w=std::copy(inp2,inp2+nbOfComp2,w);
- }
- useArray(newArr,true,C_DEALLOC,nbOfTuples,nbOfComp1+nbOfComp2);
- std::vector<int> compIds(nbOfComp2);
- for(int i=0;i<nbOfComp2;i++)
- compIds[i]=nbOfComp1+i;
- copyPartOfStringInfoFrom2(compIds,*other);
-}
-
/*!
* Copy all components in a specified order from another DataArrayInt.
* The specified components become the first ones in \a this array.
nc[nbOfCompo*i+compoIds[j]]=*ac;
}
-/*!
- * Assign pointer to one array to a pointer to another appay. Reference counter of
- * \a arrayToSet is incremented / decremented.
- * \param [in] newArray - the pointer to array to assign to \a arrayToSet.
- * \param [in,out] arrayToSet - the pointer to array to assign to.
- */
-void DataArrayInt::SetArrayIn(DataArrayInt *newArray, DataArrayInt* &arrayToSet)
-{
- if(newArray!=arrayToSet)
- {
- if(arrayToSet)
- arrayToSet->decrRef();
- arrayToSet=newArray;
- if(arrayToSet)
- arrayToSet->incrRef();
- }
-}
-
DataArrayIntIterator *DataArrayInt::iterator()
{
return new DataArrayIntIterator(this);
}
}
-/*!
- * Converts every value of \a this array to its absolute value.
- * \b WARNING this method is non const. If a new DataArrayInt instance should be built containing the result of abs DataArrayInt::computeAbs
- * should be called instead.
- *
- * \throw If \a this is not allocated.
- * \sa DataArrayInt::computeAbs
- */
-void DataArrayInt::abs()
-{
- checkAllocated();
- int *ptr(getPointer());
- std::size_t nbOfElems(getNbOfElems());
- std::transform(ptr,ptr+nbOfElems,ptr,std::ptr_fun<int,int>(std::abs));
- declareAsNew();
-}
-
-/*!
- * This method builds a new instance of \a this object containing the result of std::abs applied of all elements in \a this.
- * This method is a const method (that do not change any values in \a this) contrary to DataArrayInt::abs method.
- *
- * \return DataArrayInt * - the new instance of DataArrayInt containing the
- * same number of tuples and component as \a this array.
- * The caller is to delete this result array using decrRef() as it is no more
- * needed.
- * \throw If \a this is not allocated.
- * \sa DataArrayInt::abs
- */
-DataArrayInt *DataArrayInt::computeAbs() const
-{
- checkAllocated();
- DataArrayInt *newArr(DataArrayInt::New());
- int nbOfTuples(getNumberOfTuples());
- int nbOfComp(getNumberOfComponents());
- newArr->alloc(nbOfTuples,nbOfComp);
- std::transform(begin(),end(),newArr->getPointer(),std::ptr_fun<int,int>(std::abs));
- newArr->copyStringInfoFrom(*this);
- return newArr;
-}
-
-/*!
- * Apply a liner function to a given component of \a this array, so that
- * an array element <em>(x)</em> becomes \f$ a * x + b \f$.
- * \param [in] a - the first coefficient of the function.
- * \param [in] b - the second coefficient of the function.
- * \param [in] compoId - the index of component to modify.
- * \throw If \a this is not allocated.
- */
-void DataArrayInt::applyLin(int a, int b, int compoId)
-{
- checkAllocated();
- int *ptr=getPointer()+compoId;
- int nbOfComp=getNumberOfComponents();
- int nbOfTuple=getNumberOfTuples();
- for(int i=0;i<nbOfTuple;i++,ptr+=nbOfComp)
- *ptr=a*(*ptr)+b;
- declareAsNew();
-}
-
-/*!
- * Apply a liner function to all elements of \a this array, so that
- * an element _x_ becomes \f$ a * x + b \f$.
- * \param [in] a - the first coefficient of the function.
- * \param [in] b - the second coefficient of the function.
- * \throw If \a this is not allocated.
- */
-void DataArrayInt::applyLin(int a, int b)
-{
- checkAllocated();
- int *ptr=getPointer();
- std::size_t nbOfElems=getNbOfElems();
- for(std::size_t i=0;i<nbOfElems;i++,ptr++)
- *ptr=a*(*ptr)+b;
- declareAsNew();
-}
-
-/*!
- * Returns a full copy of \a this array except that sign of all elements is reversed.
- * \return DataArrayInt * - the new instance of DataArrayInt containing the
- * same number of tuples and component as \a this array.
- * The caller is to delete this result array using decrRef() as it is no more
- * needed.
- * \throw If \a this is not allocated.
- */
-DataArrayInt *DataArrayInt::negate() const
-{
- checkAllocated();
- DataArrayInt *newArr=DataArrayInt::New();
- int nbOfTuples=getNumberOfTuples();
- int nbOfComp=getNumberOfComponents();
- newArr->alloc(nbOfTuples,nbOfComp);
- const int *cptr=getConstPointer();
- std::transform(cptr,cptr+nbOfTuples*nbOfComp,newArr->getPointer(),std::negate<int>());
- newArr->copyStringInfoFrom(*this);
- return newArr;
-}
-
/*!
* Modify all elements of \a this array, so that
* an element _x_ becomes \f$ numerator / x \f$.
*/
DataArrayInt *DataArrayInt::findIdsInRange(int vmin, int vmax) const
{
- checkAllocated();
- if(getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::findIdsInRange : this must have exactly one component !");
- const int *cptr(begin());
- MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
- int nbOfTuples(getNumberOfTuples());
- for(int i=0;i<nbOfTuples;i++,cptr++)
- if(*cptr>=vmin && *cptr<vmax)
- ret->pushBackSilent(i);
+ InRange<int> ir(vmin,vmax);
+ MCAuto<DataArrayInt> ret(findIdsAdv(ir));
return ret.retn();
}
*/
DataArrayInt *DataArrayInt::findIdsNotInRange(int vmin, int vmax) const
{
- checkAllocated();
- if(getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::findIdsNotInRange : this must have exactly one component !");
- 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<vmin || *cptr>=vmax)
- ret->pushBackSilent(i);
- return ret.retn();
-}
-
-/*!
- * This method works only on data array with one component. This method returns a newly allocated array storing stored ascendantly of tuple ids in \a this so that this[id]<0.
- *
- * \return a newly allocated data array that the caller should deal with.
- * \sa DataArrayInt::findIdsInRange
- */
-DataArrayInt *DataArrayInt::findIdsStricltyNegative() const
-{
- checkAllocated();
- if(getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::findIdsStricltyNegative : this must have exactly one component !");
- 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<0)
- ret->pushBackSilent(i);
+ NotInRange<int> nir(vmin,vmax);
+ MCAuto<DataArrayInt> ret(findIdsAdv(nir));
return ret.retn();
}
}
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 by aggregating two given arrays, so that (1) the number
- * of components in the result array is a sum of the number of components of given arrays
- * and (2) the number of tuples in the result array is same as that of each of given
- * arrays. In other words the i-th tuple of result array includes all components of
- * i-th tuples of all given arrays.
- * Number of tuples in the given arrays must be the same.
- * \param [in] a1 - an array to include in the result array.
- * \param [in] a2 - another array to include in the result array.
- * \return DataArrayInt * - the new instance of DataArrayInt.
- * The caller is to delete this result array using decrRef() as it is no more
- * needed.
- * \throw If both \a a1 and \a a2 are NULL.
- * \throw If any given array is not allocated.
- * \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples()
- */
-DataArrayInt *DataArrayInt::Meld(const DataArrayInt *a1, const DataArrayInt *a2)
-{
- std::vector<const DataArrayInt *> arr(2);
- arr[0]=a1; arr[1]=a2;
- return Meld(arr);
-}
-
-/*!
- * Returns a new DataArrayInt by aggregating all given arrays, so that (1) the number
- * of components in the result array is a sum of the number of components of given arrays
- * and (2) the number of tuples in the result array is same as that of each of given
- * arrays. In other words the i-th tuple of result array includes all components of
- * i-th tuples of all given arrays.
- * Number of tuples in the given arrays must be the same.
- * \param [in] arr - a sequence of arrays to include in the result array.
- * \return 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 any given array is not allocated.
- * \throw If getNumberOfTuples() of arrays within \a arr is different.
- */
-DataArrayInt *DataArrayInt::Meld(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::Meld : array must be NON empty !");
- std::vector<const DataArrayInt *>::const_iterator it;
- for(it=a.begin();it!=a.end();it++)
- (*it)->checkAllocated();
- it=a.begin();
- int nbOfTuples=(*it)->getNumberOfTuples();
- std::vector<int> nbc(a.size());
- std::vector<const int *> pts(a.size());
- nbc[0]=(*it)->getNumberOfComponents();
- pts[0]=(*it++)->getConstPointer();
- for(int i=1;it!=a.end();it++,i++)
- {
- if(nbOfTuples!=(*it)->getNumberOfTuples())
- throw INTERP_KERNEL::Exception("DataArrayInt::meld : mismatch of number of tuples !");
- nbc[i]=(*it)->getNumberOfComponents();
- pts[i]=(*it)->getConstPointer();
+ 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());
+ }
}
- int totalNbOfComp=std::accumulate(nbc.begin(),nbc.end(),0);
- DataArrayInt *ret=DataArrayInt::New();
- ret->alloc(nbOfTuples,totalNbOfComp);
- int *retPtr=ret->getPointer();
- for(int i=0;i<nbOfTuples;i++)
- for(int j=0;j<(int)a.size();j++)
- {
- retPtr=std::copy(pts[j],pts[j]+nbc[j],retPtr);
- pts[j]+=nbc[j];
- }
- int k=0;
- for(int i=0;i<(int)a.size();i++)
- for(int j=0;j<nbc[i];j++,k++)
- ret->setInfoOnComponent(k,a[i]->getInfoOnComponent(j));
- return ret;
+ declareAsNew();
}
/*!
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 preforms 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 preforms the reverse operation of DataArrayInt::deltaShiftIndex.
+}
+
+/*!
+ * 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.
- *
- * \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
+ * \sa DataArrayInt::buildSubstractionOptimized()
*/
-void DataArrayInt::computeOffsetsFull()
+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::computeOffsetsFull : only single component allowed !");
+ 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();
- 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,C_DEALLOC,nbOfTuples+1,1);
- declareAsNew();
+ 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;
}
/*!
- * 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>
+ * \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
*/
-void DataArrayInt::findIdsRangesInListOfIds(const DataArrayInt *listOfIds, DataArrayInt *& rangeIdsFetched, DataArrayInt *& idsInInputListThatFetch) const
+DataArrayInt *DataArrayInt::buildSubstractionOptimized(const DataArrayInt *other) 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)
+ 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(*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++;
- }
- }
+ if(work2!=pt2End && *work1==*work2)
+ work2++;
else
- { if(*tupPtr<*offPtr) tupPtr++; else offPtr++; }
+ ret->pushBackSilent(*work1);
}
- rangeIdsFetched=ret0.retn();
- idsInInputListThatFetch=ret1.retn();
+ return ret.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.
+ * 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 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 ])
+ * \throw If \a other->getNumberOfComponents() != 1.
*/
-DataArrayInt *DataArrayInt::buildExplicitArrByRanges(const DataArrayInt *offsets) const
+DataArrayInt *DataArrayInt::buildUnion(const DataArrayInt *other) 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();
+ std::vector<const DataArrayInt *>arrs(2);
+ arrs[0]=this; arrs[1]=other;
+ return BuildUnion(arrs);
}
+
/*!
- * 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.
+ * 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 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();
+ * \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);
}
/*!
- * 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.
+ * 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]
*
- * \sa DataArrayInt::findIdInRangeForEachTuple
+ * \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::findRangeIdForEachTuple(const DataArrayInt *ranges) const
+DataArrayInt *DataArrayInt::buildUnique() 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());
- }
- }
+ 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();
}
/*!
- * 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.
+ * 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.
*
- * 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
+ * \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::findIdInRangeForEachTuple(const DataArrayInt *ranges) const
+DataArrayInt *DataArrayInt::buildUniqueNotSorted() 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++)
+ 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++)
{
- 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
+ if(!b[*pt-minVal])
{
- std::ostringstream oss; oss << "DataArrayInt::findIdInRangeForEachTuple : tuple #" << i << " not found by any ranges !";
- throw INTERP_KERNEL::Exception(oss.str().c_str());
+ ret->pushBackSilent(*pt);
+ b[*pt-minVal]=true;
}
}
+ ret->copyStringInfoFrom(*this);
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.
+ * 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 preforms 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.
*
- * This method is useful for users having an unstructured mesh having only SEG2 to rearrange internaly the connectibity without any coordinates consideration.
+ * \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 MEDCouplingUMesh::orderConsecutiveCells1D
+ * \sa DataArrayInt::computeOffsetsFull
*/
-void DataArrayInt::sortEachPairToMakeALinkedList()
+DataArrayInt *DataArrayInt::deltaShiftIndex() const
{
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]);
- }
- }
- }
+ 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;
}
/*!
- *
- * \param [in] nbTimes specifies the nb of times each tuples in \a this will be duplicated contiguouly in returned DataArrayInt instance.
- * \a nbTimes should be at least equal to 1.
- * \return a newly allocated DataArrayInt having one component and number of tuples equal to \a nbTimes * \c this->getNumberOfTuples.
- * \throw if \a this is not allocated or if \a this has not number of components set to one or if \a nbTimes is lower than 1.
+ * 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.
*/
-DataArrayInt *DataArrayInt::duplicateEachTupleNTimes(int nbTimes) const
+void DataArrayInt::computeOffsets()
{
checkAllocated();
if(getNumberOfComponents()!=1)
- throw INTERP_KERNEL::Exception("DataArrayInt::duplicateEachTupleNTimes : this should have only one component !");
- if(nbTimes<1)
- throw INTERP_KERNEL::Exception("DataArrayInt::duplicateEachTupleNTimes : nb times should be >= 1 !");
- int nbTuples=getNumberOfTuples();
- const int *inPtr=getConstPointer();
- MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbTimes*nbTuples,1);
- int *retPtr=ret->getPointer();
- for(int i=0;i<nbTuples;i++,inPtr++)
+ 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 val=*inPtr;
- for(int j=0;j<nbTimes;j++,retPtr++)
- *retPtr=val;
+ int tmp2=work[i];
+ work[i]=work[i-1]+tmp;
+ tmp=tmp2;
}
- ret->copyStringInfoFrom(*this);
- return ret.retn();
-}
-
-/*!
- * 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();
+ declareAsNew();
}
+
/*!
- * 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]]
+ * 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 preforms the reverse operation of DataArrayInt::deltaShiftIndex.
+ * \throw If \a this is not allocated.
+ * \throw If \a this->getNumberOfComponents() != 1.
+ *
+ * \b Example: <br>
+ * - Before \a this contains [3,5,1,2,0,8]
+ * - After \a this contains [0,3,8,9,11,11,19]<br>
+ * \sa DataArrayInt::deltaShiftIndex
*/
-std::vector<DataArrayInt *> DataArrayInt::partitionByDifferentValues(std::vector<int>& differentIds) const
+void DataArrayInt::computeOffsetsFull()
{
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;
+ 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,C_DEALLOC,nbOfTuples+1,1);
+ declareAsNew();
}
/*!
- * 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.
+ * 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] 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.
+ * \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>
*/
-std::vector< std::pair<int,int> > DataArrayInt::splitInBalancedSlices(int nbOfSlices) const
+void DataArrayInt::findIdsRangesInListOfIds(const DataArrayInt *listOfIds, DataArrayInt *& rangeIdsFetched, DataArrayInt *& idsInInputListThatFetch) 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++)
+ 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)
{
- 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;
+ 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
- p.second=nbOfTuples;
- ret[i]=p;
+ { if(*tupPtr<*offPtr) tupPtr++; else offPtr++; }
}
- return ret;
+ rangeIdsFetched=ret0.retn();
+ idsInInputListThatFetch=ret1.retn();
}
/*!
- * Returns a new DataArrayInt that is a sum 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 sum 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 ].
+ * 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.
*
- * Info on components is copied either from the first array (in the first case) or from
- * the array with maximal number of elements (getNbOfElems()).
- * \param [in] a1 - an array to sum 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() and
- * \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents() and
- * none of them has number of tuples or components equal to 1.
+ * \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::Add(const DataArrayInt *a1, const DataArrayInt *a2)
+DataArrayInt *DataArrayInt::buildExplicitArrByRanges(const DataArrayInt *offsets) const
{
- if(!a1 || !a2)
- throw INTERP_KERNEL::Exception("DataArrayInt::Add : input DataArrayInt instance is NULL !");
- int nbOfTuple=a1->getNumberOfTuples();
- int nbOfTuple2=a2->getNumberOfTuples();
- int nbOfComp=a1->getNumberOfComponents();
- int nbOfComp2=a2->getNumberOfComponents();
- MCAuto<DataArrayInt> ret=0;
- if(nbOfTuple==nbOfTuple2)
+ 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++)
{
- if(nbOfComp==nbOfComp2)
- {
- ret=DataArrayInt::New();
- ret->alloc(nbOfTuple,nbOfComp);
- std::transform(a1->begin(),a1->end(),a2->begin(),ret->getPointer(),std::plus<int>());
- ret->copyStringInfoFrom(*a1);
- }
- else
+ int val=work[i];
+ if(val>=0 && val<othNbTuples)
{
- int nbOfCompMin,nbOfCompMax;
- const DataArrayInt *aMin, *aMax;
- if(nbOfComp>nbOfComp2)
- {
- nbOfCompMin=nbOfComp2; nbOfCompMax=nbOfComp;
- aMin=a2; aMax=a1;
- }
+ int delta=offPtr[val+1]-offPtr[val];
+ if(delta>=0)
+ retNbOftuples+=delta;
else
{
- nbOfCompMin=nbOfComp; nbOfCompMax=nbOfComp2;
- aMin=a1; aMax=a2;
- }
- if(nbOfCompMin==1)
- {
- ret=DataArrayInt::New();
- ret->alloc(nbOfTuple,nbOfCompMax);
- const int *aMinPtr=aMin->getConstPointer();
- const int *aMaxPtr=aMax->getConstPointer();
- int *res=ret->getPointer();
- for(int i=0;i<nbOfTuple;i++)
- res=std::transform(aMaxPtr+i*nbOfCompMax,aMaxPtr+(i+1)*nbOfCompMax,res,std::bind2nd(std::plus<int>(),aMinPtr[i]));
- ret->copyStringInfoFrom(*aMax);
+ std::ostringstream oss; oss << "DataArrayInt::buildExplicitArrByRanges : Tuple #" << val << " of offset array has a delta < 0 !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
}
- else
- throw INTERP_KERNEL::Exception("Nb of components mismatch for array Add !");
}
- }
- else if((nbOfTuple==1 && nbOfTuple2>1) || (nbOfTuple>1 && nbOfTuple2==1))
- {
- if(nbOfComp==nbOfComp2)
+ else
{
- int nbOfTupleMax=std::max(nbOfTuple,nbOfTuple2);
- const DataArrayInt *aMin=nbOfTuple>nbOfTuple2?a2:a1;
- const DataArrayInt *aMax=nbOfTuple>nbOfTuple2?a1:a2;
- const int *aMinPtr=aMin->getConstPointer(),*aMaxPtr=aMax->getConstPointer();
- ret=DataArrayInt::New();
- ret->alloc(nbOfTupleMax,nbOfComp);
- int *res=ret->getPointer();
- for(int i=0;i<nbOfTupleMax;i++)
- res=std::transform(aMaxPtr+i*nbOfComp,aMaxPtr+(i+1)*nbOfComp,aMinPtr,res,std::plus<int>());
- ret->copyStringInfoFrom(*aMax);
+ 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());
}
- else
- throw INTERP_KERNEL::Exception("Nb of components mismatch for array Add !");
}
- else
- throw INTERP_KERNEL::Exception("Nb of tuples mismatch for array Add !");
+ 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();
}
/*!
- * Adds values of another DataArrayInt to values of \a this one. There are 3
- * valid cases.
- * 1. The arrays have same number of tuples and components. Then each value of
- * \a other array is added to the corresponding value of \a this array, 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 ].
+ * 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.
*
- * \param [in] other - an array to add to \a this one.
- * \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.
+ * \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>
*/
-void DataArrayInt::addEqual(const DataArrayInt *other)
-{
- if(!other)
- throw INTERP_KERNEL::Exception("DataArrayInt::addEqual : input DataArrayInt instance is NULL !");
- const char *msg="Nb of tuples mismatch for DataArrayInt::addEqual !";
- checkAllocated(); other->checkAllocated();
- int nbOfTuple=getNumberOfTuples();
- int nbOfTuple2=other->getNumberOfTuples();
- int nbOfComp=getNumberOfComponents();
- int nbOfComp2=other->getNumberOfComponents();
- if(nbOfTuple==nbOfTuple2)
+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(nbOfComp==nbOfComp2)
+ if(pos>=0 && pos<nbOfTuples-1)
{
- std::transform(begin(),end(),other->begin(),getPointer(),std::plus<int>());
+ 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 if(nbOfComp2==1)
+ else
{
- 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::plus<int>(),*ptrc++));
+ 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());
}
- else
- throw INTERP_KERNEL::Exception(msg);
}
- else if(nbOfTuple2==1)
+ MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(sz,1);
+ int *retPtr(ret->getPointer());
+ pos=bg;
+ for(int i=0;i<nbOfEltsInSlc;i++,pos+=step)
{
- 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,ptrc,ptr+i*nbOfComp,std::plus<int>());
- }
- else
- throw INTERP_KERNEL::Exception(msg);
+ int delta(ids[pos+1]-ids[pos]);
+ for(int j=0;j<delta;j++,retPtr++)
+ *retPtr=pos;
}
- else
- throw INTERP_KERNEL::Exception(msg);
- declareAsNew();
+ return ret.retn();
}
/*!
- * Returns a new DataArrayInt that is a subtraction 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 subtraction 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 ].
+ * 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.
*
- * Info on components is copied either from the first array (in the first case) or from
- * the array with maximal number of elements (getNbOfElems()).
- * \param [in] a1 - an array to subtract from.
- * \param [in] a2 - an array to subtract.
- * \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.
+ * 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::Substract(const DataArrayInt *a1, const DataArrayInt *a2)
+DataArrayInt *DataArrayInt::findRangeIdForEachTuple(const DataArrayInt *ranges) const
{
- if(!a1 || !a2)
- throw INTERP_KERNEL::Exception("DataArrayInt::Substract : 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(!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++)
{
- if(nbOfComp1==nbOfComp2)
- {
- MCAuto<DataArrayInt> ret=DataArrayInt::New();
- ret->alloc(nbOfTuple2,nbOfComp1);
- std::transform(a1->begin(),a1->end(),a2->begin(),ret->getPointer(),std::minus<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::minus<int>(),a2Ptr[i]));
- ret->copyStringInfoFrom(*a1);
- return ret.retn();
- }
+ 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
{
- a1->checkNbOfComps(nbOfComp2,"Nb of components mismatch for array Substract !");
- return 0;
+ std::ostringstream oss; oss << "DataArrayInt::findRangeIdForEachTuple : tuple #" << i << " not found by any ranges !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
}
}
- else if(nbOfTuple2==1)
- {
- a1->checkNbOfComps(nbOfComp2,"Nb of components mismatch for array Substract !");
- 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::minus<int>());
- ret->copyStringInfoFrom(*a1);
- return ret.retn();
- }
- else
- {
- a1->checkNbOfTuples(nbOfTuple2,"Nb of tuples mismatch for array Substract !");//will always throw an exception
- return 0;
- }
+ return ret.retn();
}
/*!
- * Subtract values of another DataArrayInt from values of \a this one. There are 3
- * valid cases.
- * 1. The arrays have same number of tuples and components. Then each value of
- * \a other array is subtracted from the corresponding value of \a this array, 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 ].
+ * 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.
*
- * \param [in] other - an array to subtract from \a this one.
- * \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.
+ * 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
*/
-void DataArrayInt::substractEqual(const DataArrayInt *other)
+DataArrayInt *DataArrayInt::findIdInRangeForEachTuple(const DataArrayInt *ranges) const
{
- if(!other)
- throw INTERP_KERNEL::Exception("DataArrayInt::substractEqual : input DataArrayInt instance is NULL !");
- const char *msg="Nb of tuples mismatch for DataArrayInt::substractEqual !";
- checkAllocated(); other->checkAllocated();
- int nbOfTuple=getNumberOfTuples();
- int nbOfTuple2=other->getNumberOfTuples();
- int nbOfComp=getNumberOfComponents();
- int nbOfComp2=other->getNumberOfComponents();
- if(nbOfTuple==nbOfTuple2)
+ 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++)
{
- if(nbOfComp==nbOfComp2)
- {
- std::transform(begin(),end(),other->begin(),getPointer(),std::minus<int>());
- }
- else if(nbOfComp2==1)
+ 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
{
- 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::minus<int>(),*ptrc++));
+ std::ostringstream oss; oss << "DataArrayInt::findIdInRangeForEachTuple : tuple #" << i << " not found by any ranges !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
}
- 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::minus<int>());
}
- else
- throw INTERP_KERNEL::Exception(msg);
- declareAsNew();
+ return ret.retn();
}
/*!
- * Returns a new DataArrayInt that is a product 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 product 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 ].
+ * \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.
*
- * Info on components is copied either from the first array (in the first case) or from
- * the array with maximal number of elements (getNbOfElems()).
- * \param [in] a1 - a factor array.
- * \param [in] a2 - another factor 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.
+ * This method is useful for users having an unstructured mesh having only SEG2 to rearrange internaly the connectibity without any coordinates consideration.
+ *
+ * \sa MEDCouplingUMesh::orderConsecutiveCells1D, DataArrayInt::fromLinkedListOfPairToList
*/
-DataArrayInt *DataArrayInt::Multiply(const DataArrayInt *a1, const DataArrayInt *a2)
+void DataArrayInt::sortEachPairToMakeALinkedList()
{
- if(!a1 || !a2)
- throw INTERP_KERNEL::Exception("DataArrayInt::Multiply : input DataArrayInt instance is NULL !");
- int nbOfTuple=a1->getNumberOfTuples();
- int nbOfTuple2=a2->getNumberOfTuples();
- int nbOfComp=a1->getNumberOfComponents();
- int nbOfComp2=a2->getNumberOfComponents();
- MCAuto<DataArrayInt> ret=0;
- if(nbOfTuple==nbOfTuple2)
+ 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(nbOfComp==nbOfComp2)
+ if(i>1)
{
- ret=DataArrayInt::New();
- ret->alloc(nbOfTuple,nbOfComp);
- std::transform(a1->begin(),a1->end(),a2->begin(),ret->getPointer(),std::multiplies<int>());
- ret->copyStringInfoFrom(*a1);
+ 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
{
- int nbOfCompMin,nbOfCompMax;
- const DataArrayInt *aMin, *aMax;
- if(nbOfComp>nbOfComp2)
+ 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)
{
- nbOfCompMin=nbOfComp2; nbOfCompMax=nbOfComp;
- aMin=a2; aMax=a1;
+ 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
- {
- nbOfCompMin=nbOfComp; nbOfCompMax=nbOfComp2;
- aMin=a1; aMax=a2;
- }
- if(nbOfCompMin==1)
- {
- ret=DataArrayInt::New();
- ret->alloc(nbOfTuple,nbOfCompMax);
- const int *aMinPtr=aMin->getConstPointer();
- const int *aMaxPtr=aMax->getConstPointer();
- int *res=ret->getPointer();
- for(int i=0;i<nbOfTuple;i++)
- res=std::transform(aMaxPtr+i*nbOfCompMax,aMaxPtr+(i+1)*nbOfCompMax,res,std::bind2nd(std::multiplies<int>(),aMinPtr[i]));
- ret->copyStringInfoFrom(*aMax);
+ {//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]);
}
- else
- throw INTERP_KERNEL::Exception("Nb of components mismatch for array Multiply !");
}
}
- else if((nbOfTuple==1 && nbOfTuple2>1) || (nbOfTuple>1 && nbOfTuple2==1))
- {
- if(nbOfComp==nbOfComp2)
- {
- int nbOfTupleMax=std::max(nbOfTuple,nbOfTuple2);
- const DataArrayInt *aMin=nbOfTuple>nbOfTuple2?a2:a1;
- const DataArrayInt *aMax=nbOfTuple>nbOfTuple2?a1:a2;
- const int *aMinPtr=aMin->getConstPointer(),*aMaxPtr=aMax->getConstPointer();
- ret=DataArrayInt::New();
- ret->alloc(nbOfTupleMax,nbOfComp);
- int *res=ret->getPointer();
- for(int i=0;i<nbOfTupleMax;i++)
- res=std::transform(aMaxPtr+i*nbOfComp,aMaxPtr+(i+1)*nbOfComp,aMinPtr,res,std::multiplies<int>());
- ret->copyStringInfoFrom(*aMax);
- }
- else
- throw INTERP_KERNEL::Exception("Nb of components mismatch for array Multiply !");
- }
- else
- throw INTERP_KERNEL::Exception("Nb of tuples mismatch for array Multiply !");
- return ret.retn();
}
-
/*!
- * Multiply values of another DataArrayInt to values of \a this one. There are 3
- * valid cases.
- * 1. The arrays have same number of tuples and components. Then each value of
- * \a other array is multiplied to the corresponding value of \a this array, 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 ].
- *
- * \param [in] other - an array to multiply to \a this one.
- * \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.
+ * \a this is expected to be a correctly linked list of pairs.
+ *
+ * \sa DataArrayInt::sortEachPairToMakeALinkedList
*/
-void DataArrayInt::multiplyEqual(const DataArrayInt *other)
+MCAuto<DataArrayInt> DataArrayInt::fromLinkedListOfPairToList() const
{
- if(!other)
- throw INTERP_KERNEL::Exception("DataArrayInt::multiplyEqual : input DataArrayInt instance is NULL !");
- const char *msg="Nb of tuples mismatch for DataArrayInt::multiplyEqual !";
- 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::multiplies<int>());
- }
- else if(nbOfComp2==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,ptr+i*nbOfComp,std::bind2nd(std::multiplies<int>(),*ptrc++));
- }
- else
- throw INTERP_KERNEL::Exception(msg);
- }
- else if(nbOfTuple2==1)
+ 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++)
{
- 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,ptrc,ptr+i*nbOfComp,std::multiplies<int>());
- }
- else
- throw INTERP_KERNEL::Exception(msg);
+ 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());
+ }
}
- else
- throw INTERP_KERNEL::Exception(msg);
- declareAsNew();
+ 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();
+}
/*!
- * Returns a new DataArrayInt that is a division 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 numerator array.
- * \param [in] a2 - a denominator 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.
+ * 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]]
*/
-DataArrayInt *DataArrayInt::Divide(const DataArrayInt *a1, const DataArrayInt *a2)
+std::vector<DataArrayInt *> DataArrayInt::partitionByDifferentValues(std::vector<int>& differentIds) const
{
- if(!a1 || !a2)
- throw INTERP_KERNEL::Exception("DataArrayInt::Divide : 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::divides<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::divides<int>(),a2Ptr[i]));
- ret->copyStringInfoFrom(*a1);
- return ret.retn();
- }
- else
- {
- a1->checkNbOfComps(nbOfComp2,"Nb of components mismatch for array Divide !");
- return 0;
- }
- }
- else if(nbOfTuple2==1)
+ 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++)
{
- a1->checkNbOfComps(nbOfComp2,"Nb of components mismatch for array Divide !");
- 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::divides<int>());
- ret->copyStringInfoFrom(*a1);
- return ret.retn();
+ m2[(*it).first]=id;
+ ret[id]=DataArrayInt::New();
+ ret[id]->alloc((*it).second,1);
+ retPtr[id]=ret[id]->getPointer();
+ differentIds[id]=(*it).first;
}
- else
+ id=0;
+ for(const int *w=begin();w!=end();w++,id++)
{
- a1->checkNbOfTuples(nbOfTuple2,"Nb of tuples mismatch for array Divide !");//will always throw an exception
- return 0;
+ retPtr[m2[*w]][m3[*w]++]=id;
}
+ return ret;
}
/*!
- * Divide values of \a this array by values 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 ].
+ * 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.
*
- * \warning No check of division by zero is performed!
- * \param [in] other - an array to divide \a this one by.
- * \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.
+ * \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.
*/
-void DataArrayInt::divideEqual(const DataArrayInt *other)
+std::vector< std::pair<int,int> > DataArrayInt::splitInBalancedSlices(int nbOfSlices) const
{
- if(!other)
- throw INTERP_KERNEL::Exception("DataArrayInt::divideEqual : input DataArrayInt instance is NULL !");
- const char *msg="Nb of tuples mismatch for DataArrayInt::divideEqual !";
- 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::divides<int>());
- }
- else if(nbOfComp2==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,ptr+i*nbOfComp,std::bind2nd(std::divides<int>(),*ptrc++));
- }
- else
- throw INTERP_KERNEL::Exception(msg);
- }
- else if(nbOfTuple2==1)
+ 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++)
{
- 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,ptrc,ptr+i*nbOfComp,std::divides<int>());
- }
+ 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
- throw INTERP_KERNEL::Exception(msg);
+ p.second=nbOfTuples;
+ ret[i]=p;
}
- else
- throw INTERP_KERNEL::Exception(msg);
- declareAsNew();
+ return ret;
}
-
/*!
* Returns a new DataArrayInt that is a modulus of two given arrays. There are 3
* valid cases.
}
}
-DataArrayIntIterator::DataArrayIntIterator(DataArrayInt *da):_da(da),_pt(0),_tuple_id(0),_nb_comp(0),_nb_tuple(0)
-{
- if(_da)
- {
- _da->incrRef();
- if(_da->isAllocated())
- {
- _nb_comp=da->getNumberOfComponents();
- _nb_tuple=da->getNumberOfTuples();
- _pt=da->getPointer();
- }
- }
-}
-
-DataArrayIntIterator::~DataArrayIntIterator()
-{
- if(_da)
- _da->decrRef();
-}
-
-DataArrayIntTuple *DataArrayIntIterator::nextt()
+DataArrayIntIterator::DataArrayIntIterator(DataArrayInt *da):DataArrayIterator<int>(da)
{
- if(_tuple_id<_nb_tuple)
- {
- _tuple_id++;
- DataArrayIntTuple *ret=new DataArrayIntTuple(_pt,_nb_comp);
- _pt+=_nb_comp;
- return ret;
- }
- else
- return 0;
}
-DataArrayIntTuple::DataArrayIntTuple(int *pt, int nbOfComp):_pt(pt),_nb_of_compo(nbOfComp)
+DataArrayInt32Tuple::DataArrayInt32Tuple(int *pt, int nbOfComp):DataArrayTuple<int>(pt,nbOfComp)
{
}
int DataArrayIntTuple::intValue() const
{
- if(_nb_of_compo==1)
- return *_pt;
- throw INTERP_KERNEL::Exception("DataArrayIntTuple::intValue : DataArrayIntTuple instance has not exactly 1 component -> Not possible to convert it into an integer !");
+ return this->zeValue();
}
/*!
*/
DataArrayInt *DataArrayIntTuple::buildDAInt(int nbOfTuples, int nbOfCompo) const
{
- if((_nb_of_compo==nbOfCompo && nbOfTuples==1) || (_nb_of_compo==nbOfTuples && nbOfCompo==1))
- {
- DataArrayInt *ret=DataArrayInt::New();
- ret->useExternalArrayWithRWAccess(_pt,nbOfTuples,nbOfCompo);
- return ret;
- }
- else
- {
- std::ostringstream oss; oss << "DataArrayIntTuple::buildDAInt : unable to build a requested DataArrayInt instance with nbofTuple=" << nbOfTuples << " and nbOfCompo=" << nbOfCompo;
- oss << ".\nBecause the number of elements in this is " << _nb_of_compo << " !";
- throw INTERP_KERNEL::Exception(oss.str().c_str());
- }
+ return this->buildDA(nbOfTuples,nbOfCompo);
}