Salome HOME
Merge branch 'abn/tests_from_build'
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingMemArray.cxx
index 44a708d7cf31c9543516f4b9396a76ae46e03864..709fd85cd70e1e182b85aacc5ddbd676a1ef3b2e 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2014  CEA/DEN, EDF R&D
+// Copyright (C) 2007-2015  CEA/DEN, EDF R&D
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
@@ -120,7 +120,7 @@ std::size_t DataArray::getHeapMemorySizeWithoutChildren() const
   return sz1+sz2+sz3;
 }
 
-std::vector<const BigMemoryObject *> DataArray::getDirectChildren() const
+std::vector<const BigMemoryObject *> DataArray::getDirectChildrenWithNull() const
 {
   return std::vector<const BigMemoryObject *>();
 }
@@ -903,7 +903,7 @@ void DataArrayDouble::pushBackSilent(double val)
  * This method adds at the end of \a this a serie of values [\c valsBg,\c valsEnd). This method do \b not update its time label to avoid useless incrementation
  * of counter. So the caller is expected to call TimeLabel::declareAsNew on \a this at the end of the push session.
  *
- *  \param [in] valsBg - an array of values to push at the end of \this.
+ *  \param [in] valsBg - an array of values to push at the end of \this.
  *  \param [in] valsEnd - specifies the end of the array \a valsBg, so that
  *              the last value of \a valsBg is \a valsEnd[ -1 ].
  * \throw If \a this has already been allocated with number of components different from one.
@@ -1146,7 +1146,9 @@ bool DataArrayDouble::isMonotonic(bool increasing, double eps) const
 /*!
  * Returns a textual and human readable representation of \a this instance of
  * DataArrayDouble. This text is shown when a DataArrayDouble is printed in Python.
- *  \return std::string - text describing \a this DataArrayDouble.
+ * \return std::string - text describing \a this DataArrayDouble.
+ *
+ * \sa reprNotTooLong, reprZip
  */
 std::string DataArrayDouble::repr() const
 {
@@ -1162,6 +1164,18 @@ std::string DataArrayDouble::reprZip() const
   return ret.str();
 }
 
+/*!
+ * This method is close to repr method except that when \a this has more than 1000 tuples, all tuples are not
+ * printed out to avoid to consume too much space in interpretor.
+ * \sa repr
+ */
+std::string DataArrayDouble::reprNotTooLong() const
+{
+  std::ostringstream ret;
+  reprNotTooLongStream(ret);
+  return ret.str();
+}
+
 void DataArrayDouble::writeVTK(std::ostream& ofs, int indent, const std::string& nameInFile, DataArrayByte *byteArr) const
 {
   static const char SPACE[4]={' ',' ',' ',' '};
@@ -1169,6 +1183,15 @@ void DataArrayDouble::writeVTK(std::ostream& ofs, int indent, const std::string&
   std::string idt(indent,' ');
   ofs.precision(17);
   ofs << idt << "<DataArray type=\"Float32\" Name=\"" << nameInFile << "\" NumberOfComponents=\"" << getNumberOfComponents() << "\"";
+  //
+  bool areAllEmpty(true);
+  for(std::vector<std::string>::const_iterator it=_info_on_compo.begin();it!=_info_on_compo.end();it++)
+    if(!(*it).empty())
+      areAllEmpty=false;
+  if(!areAllEmpty)
+    for(std::size_t i=0;i<_info_on_compo.size();i++)
+      ofs << " ComponentName" << i << "=\"" << _info_on_compo[i] << "\"";
+  //
   if(byteArr)
     {
       ofs << " format=\"appended\" offset=\"" << byteArr->getNumberOfTuples() << "\">";
@@ -1202,6 +1225,12 @@ void DataArrayDouble::reprZipStream(std::ostream& stream) const
   reprZipWithoutNameStream(stream);
 }
 
+void DataArrayDouble::reprNotTooLongStream(std::ostream& stream) const
+{
+  stream << "Name of double array : \"" << _name << "\"\n";
+  reprNotTooLongWithoutNameStream(stream);
+}
+
 void DataArrayDouble::reprWithoutNameStream(std::ostream& stream) const
 {
   DataArray::reprWithoutNameStream(stream);
@@ -1216,6 +1245,13 @@ void DataArrayDouble::reprZipWithoutNameStream(std::ostream& stream) const
   _mem.reprZip(getNumberOfComponents(),stream);
 }
 
+void DataArrayDouble::reprNotTooLongWithoutNameStream(std::ostream& stream) const
+{
+  DataArray::reprWithoutNameStream(stream);
+  stream.precision(17);
+  _mem.reprNotTooLong(getNumberOfComponents(),stream);
+}
+
 void DataArrayDouble::reprCppStream(const std::string& varName, std::ostream& stream) const
 {
   int nbTuples=getNumberOfTuples(),nbComp=getNumberOfComponents();
@@ -1411,9 +1447,9 @@ DataArrayDouble *DataArrayDouble::toNoInterlace() const
 /*!
  * Permutes values of \a this array as required by \a old2New array. The values are
  * permuted so that \c new[ \a old2New[ i ]] = \c old[ i ]. Number of tuples remains
- * the same as in \this one.
+ * the same as in \this one.
  * If a permutation reduction is needed, substr() or selectByTupleId() should be used.
- * For more info on renumbering see \ref MEDCouplingArrayRenumbering.
+ * For more info on renumbering see \ref numbering.
  *  \param [in] old2New - C array of length equal to \a this->getNumberOfTuples()
  *     giving a new position for i-th old value.
  */
@@ -1443,8 +1479,8 @@ void DataArrayDouble::renumberInPlace(const int *old2New)
 /*!
  * Permutes values of \a this array as required by \a new2Old array. The values are
  * permuted so that \c new[ i ] = \c old[ \a new2Old[ i ]]. Number of tuples remains
- * the same as in \this one.
- * For more info on renumbering see \ref MEDCouplingArrayRenumbering.
+ * the same as in \this one.
+ * For more info on renumbering see \ref numbering.
  *  \param [in] new2Old - C array of length equal to \a this->getNumberOfTuples()
  *     giving a previous position of i-th new value.
  *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
@@ -1476,9 +1512,9 @@ void DataArrayDouble::renumberInPlaceR(const int *new2Old)
 /*!
  * Returns a copy of \a this array with values permuted as required by \a old2New array.
  * The values are permuted so that  \c new[ \a old2New[ i ]] = \c old[ i ].
- * Number of tuples in the result array remains the same as in \this one.
+ * Number of tuples in the result array remains the same as in \this one.
  * If a permutation reduction is needed, renumberAndReduce() should be used.
- * For more info on renumbering see \ref MEDCouplingArrayRenumbering.
+ * For more info on renumbering see \ref numbering.
  *  \param [in] old2New - C array of length equal to \a this->getNumberOfTuples()
  *          giving a new position for i-th old value.
  *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
@@ -1504,9 +1540,9 @@ DataArrayDouble *DataArrayDouble::renumber(const int *old2New) const
 /*!
  * Returns a copy of \a this array with values permuted as required by \a new2Old array.
  * The values are permuted so that  \c new[ i ] = \c old[ \a new2Old[ i ]]. Number of
- * tuples in the result array remains the same as in \this one.
+ * tuples in the result array remains the same as in \this one.
  * If a permutation reduction is needed, substr() or selectByTupleId() should be used.
- * For more info on renumbering see \ref MEDCouplingArrayRenumbering.
+ * For more info on renumbering see \ref numbering.
  *  \param [in] new2Old - C array of length equal to \a this->getNumberOfTuples()
  *     giving a previous position of i-th new value.
  *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
@@ -1534,7 +1570,7 @@ DataArrayDouble *DataArrayDouble::renumberR(const int *new2Old) const
  * The values are permuted so that  \c new[ \a old2New[ i ]] = \c old[ i ] for all
  * \a old2New[ i ] >= 0. In other words every i-th tuple in \a this array, for which 
  * \a old2New[ i ] is negative, is missing from the result array.
- * For more info on renumbering see \ref MEDCouplingArrayRenumbering.
+ * For more info on renumbering see \ref numbering.
  *  \param [in] old2New - C array of length equal to \a this->getNumberOfTuples()
  *     giving a new position for i-th old tuple and giving negative position for
  *     for i-th old tuple that should be omitted.
@@ -1567,7 +1603,7 @@ DataArrayDouble *DataArrayDouble::renumberAndReduce(const int *old2New, int newN
  * The values are permuted so that  \c new[ i ] = \c old[ \a new2OldBg[ i ]].
  * This method is equivalent to renumberAndReduce() except that convention in input is
  * \c new2old and \b not \c old2new.
- * For more info on renumbering see \ref MEDCouplingArrayRenumbering.
+ * For more info on renumbering see \ref numbering.
  *  \param [in] new2OldBg - pointer to the beginning of a permutation array that gives a
  *              tuple index in \a this array to fill the i-th tuple in the new array.
  *  \param [in] new2OldEnd - specifies the end of the permutation array that starts at
@@ -1592,6 +1628,11 @@ DataArrayDouble *DataArrayDouble::selectByTupleId(const int *new2OldBg, const in
   return ret.retn();
 }
 
+DataArrayDouble *DataArrayDouble::selectByTupleId(const DataArrayInt & di) const
+{
+  return selectByTupleId(di.getConstPointer(), di.getConstPointer()+di.getNumberOfTuples());
+}
+
 /*!
  * Returns a shorten and permuted copy of \a this array. The new DataArrayDouble is
  * of size \a new2OldEnd - \a new2OldBg and it's values are permuted as required by
@@ -1601,7 +1642,7 @@ DataArrayDouble *DataArrayDouble::selectByTupleId(const int *new2OldBg, const in
  * \c new2old and \b not \c old2new.
  * This method is equivalent to selectByTupleId() except that it prevents coping data
  * from behind the end of \a this array.
- * For more info on renumbering see \ref MEDCouplingArrayRenumbering.
+ * For more info on renumbering see \ref numbering.
  *  \param [in] new2OldBg - pointer to the beginning of a permutation array that gives a
  *              tuple index in \a this array to fill the i-th tuple in the new array.
  *  \param [in] new2OldEnd - specifies the end of the permutation array that starts at
@@ -1638,7 +1679,7 @@ DataArrayDouble *DataArrayDouble::selectByTupleIdSafe(const int *new2OldBg, cons
  * command \c range( \a bg, \a end2, \a step ).
  * This method is equivalent to selectByTupleIdSafe() except that the input array is
  * not constructed explicitly.
- * For more info on renumbering see \ref MEDCouplingArrayRenumbering.
+ * For more info on renumbering see \ref numbering.
  *  \param [in] bg - index of the first tuple to copy from \a this array.
  *  \param [in] end2 - index of the tuple before which the tuples to copy are located.
  *  \param [in] step - index increment to get index of the next tuple to copy.
@@ -1664,7 +1705,7 @@ DataArrayDouble *DataArrayDouble::selectByTupleId2(int bg, int end2, int step) c
 /*!
  * Returns a shorten copy of \a this array. The new DataArrayDouble contains ranges
  * of tuples specified by \a ranges parameter.
- * For more info on renumbering see \ref MEDCouplingArrayRenumbering.
+ * For more info on renumbering see \ref numbering.
  *  \param [in] ranges - std::vector of std::pair's each of which defines a range
  *              of tuples in [\c begin,\c end) format.
  *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
@@ -1862,7 +1903,7 @@ void DataArrayDouble::transpose()
  *  \ref py_mcdataarraydouble_KeepSelectedComponents "Here is a Python example".
  *  \endif
  */
-DataArray *DataArrayDouble::keepSelectedComponents(const std::vector<int>& compoIds) const
+DataArrayDouble *DataArrayDouble::keepSelectedComponents(const std::vector<int>& compoIds) const
 {
   checkAllocated();
   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
@@ -2349,7 +2390,7 @@ void DataArrayDouble::setPartOfValues1(const DataArrayDouble *a, int bgTuples, i
  *  \throw If \a this is not allocated.
  *  \throw If parameters specifying tuples and components to assign to, do not give a
  *            non-empty range of increasing indices or indices are out of a valid range
- *            for \this array.
+ *            for \this array.
  *
  *  \if ENABLE_EXAMPLES
  *  \ref py_mcdataarraydouble_setpartofvaluessimple1 "Here is a Python example".
@@ -2540,7 +2581,7 @@ void DataArrayDouble::setPartOfValuesSimple2(double a, const int *bgTuples, cons
  *         defined by <em>(bgComp,endComp,stepComp)</em>.
  *  \throw If parameters specifying components to assign to, do not give a
  *            non-empty range of increasing indices or indices are out of a valid range
- *            for \this array.
+ *            for \this array.
  *
  *  \if ENABLE_EXAMPLES
  *  \ref py_mcdataarraydouble_setpartofvalues3 "Here is a Python example".
@@ -2614,7 +2655,7 @@ void DataArrayDouble::setPartOfValues3(const DataArrayDouble *a, const int *bgTu
  *         \a this array.
  *  \throw If parameters specifying components to assign to, do not give a
  *            non-empty range of increasing indices or indices are out of a valid range
- *            for \this array.
+ *            for \this array.
  *
  *  \if ENABLE_EXAMPLES
  *  \ref py_mcdataarraydouble_setpartofvaluessimple3 "Here is a Python example".
@@ -3526,14 +3567,14 @@ DataArrayDouble *DataArrayDouble::accumulatePerChunck(const int *bgOfIndex, cons
 DataArrayDouble *DataArrayDouble::fromPolarToCart() const
 {
   checkAllocated();
-  int nbOfComp=getNumberOfComponents();
+  int nbOfComp(getNumberOfComponents());
   if(nbOfComp!=2)
     throw INTERP_KERNEL::Exception("DataArrayDouble::fromPolarToCart : must be an array with exactly 2 components !");
-  int nbOfTuple=getNumberOfTuples();
-  DataArrayDouble *ret=DataArrayDouble::New();
+  int nbOfTuple(getNumberOfTuples());
+  DataArrayDouble *ret(DataArrayDouble::New());
   ret->alloc(nbOfTuple,2);
-  double *w=ret->getPointer();
-  const double *wIn=getConstPointer();
+  double *w(ret->getPointer());
+  const double *wIn(getConstPointer());
   for(int i=0;i<nbOfTuple;i++,w+=2,wIn+=2)
     {
       w[0]=wIn[0]*cos(wIn[1]);
@@ -3556,14 +3597,14 @@ DataArrayDouble *DataArrayDouble::fromPolarToCart() const
 DataArrayDouble *DataArrayDouble::fromCylToCart() const
 {
   checkAllocated();
-  int nbOfComp=getNumberOfComponents();
+  int nbOfComp(getNumberOfComponents());
   if(nbOfComp!=3)
     throw INTERP_KERNEL::Exception("DataArrayDouble::fromCylToCart : must be an array with exactly 3 components !");
-  int nbOfTuple=getNumberOfTuples();
-  DataArrayDouble *ret=DataArrayDouble::New();
+  int nbOfTuple(getNumberOfTuples());
+  DataArrayDouble *ret(DataArrayDouble::New());
   ret->alloc(getNumberOfTuples(),3);
-  double *w=ret->getPointer();
-  const double *wIn=getConstPointer();
+  double *w(ret->getPointer());
+  const double *wIn(getConstPointer());
   for(int i=0;i<nbOfTuple;i++,w+=3,wIn+=3)
     {
       w[0]=wIn[0]*cos(wIn[1]);
@@ -3588,14 +3629,14 @@ DataArrayDouble *DataArrayDouble::fromCylToCart() const
 DataArrayDouble *DataArrayDouble::fromSpherToCart() const
 {
   checkAllocated();
-  int nbOfComp=getNumberOfComponents();
+  int nbOfComp(getNumberOfComponents());
   if(nbOfComp!=3)
     throw INTERP_KERNEL::Exception("DataArrayDouble::fromSpherToCart : must be an array with exactly 3 components !");
-  int nbOfTuple=getNumberOfTuples();
-  DataArrayDouble *ret=DataArrayDouble::New();
+  int nbOfTuple(getNumberOfTuples());
+  DataArrayDouble *ret(DataArrayDouble::New());
   ret->alloc(getNumberOfTuples(),3);
-  double *w=ret->getPointer();
-  const double *wIn=getConstPointer();
+  double *w(ret->getPointer());
+  const double *wIn(getConstPointer());
   for(int i=0;i<nbOfTuple;i++,w+=3,wIn+=3)
     {
       w[0]=wIn[0]*cos(wIn[2])*sin(wIn[1]);
@@ -3605,6 +3646,56 @@ DataArrayDouble *DataArrayDouble::fromSpherToCart() const
   return ret;
 }
 
+/*!
+ * This method returns a new array containing the same number of tuples than \a this. To do this, this method needs \a at parameter to specify the convention of \a this.
+ * All the tuples of the returned array will be in cartesian sense. So if \a at equals to AX_CART the returned array is basically a deep copy of \a this.
+ * If \a at equals to AX_CYL the returned array will be the result of operation cylindric to cartesian of \a this...
+ *
+ * \param [in] atOfThis - The axis type of \a this.
+ * \return DataArrayDouble * - the new instance of DataArrayDouble (that must be dealed by caller) containing the result of the cartesianizification of \a this.
+ */
+DataArrayDouble *DataArrayDouble::cartesianize(MEDCouplingAxisType atOfThis) const
+{
+  checkAllocated();
+  int nbOfComp(getNumberOfComponents());
+  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret;
+  switch(atOfThis)
+    {
+    case AX_CART:
+      ret=deepCpy();
+    case AX_CYL:
+      if(nbOfComp==3)
+        {
+          ret=fromCylToCart();
+          break;
+        }
+      if(nbOfComp==2)
+        {
+          ret=fromPolarToCart();
+          break;
+        }
+      else
+        throw INTERP_KERNEL::Exception("DataArrayDouble::cartesianize : For AX_CYL, number of components must be in [2,3] !");
+    case AX_SPHER:
+      if(nbOfComp==3)
+        {
+          ret=fromSpherToCart();
+          break;
+        }
+      if(nbOfComp==2)
+        {
+          ret=fromPolarToCart();
+          break;
+        }
+      else
+        throw INTERP_KERNEL::Exception("DataArrayDouble::cartesianize : For AX_CYL, number of components must be in [2,3] !");
+    default:
+      throw INTERP_KERNEL::Exception("DataArrayDouble::cartesianize : not recognized axis type ! Only AX_CART, AX_CYL and AX_SPHER supported !");
+    }
+  ret->copyStringInfoFrom(*this);
+  return ret.retn();
+}
+
 /*!
  * Computes the doubly contracted product of every tensor defined by the tuple of \a this
  * array contating 6 components.
@@ -3617,7 +3708,7 @@ DataArrayDouble *DataArrayDouble::fromSpherToCart() const
 DataArrayDouble *DataArrayDouble::doublyContractedProduct() const
 {
   checkAllocated();
-  int nbOfComp=getNumberOfComponents();
+  int nbOfComp(getNumberOfComponents());
   if(nbOfComp!=6)
     throw INTERP_KERNEL::Exception("DataArrayDouble::doublyContractedProduct : must be an array with exactly 6 components !");
   DataArrayDouble *ret=DataArrayDouble::New();
@@ -4307,6 +4398,8 @@ DataArrayDouble *DataArrayDouble::applyFunc(int nbOfComp, FunctionToEvaluate fun
  *  \param [in] nbOfComp - number of components in the result array.
  *  \param [in] func - the expression defining how to transform a tuple of \a this array.
  *              Supported expressions are described \ref MEDCouplingArrayApplyFuncExpr "here".
+ *  \param [in] isSafe - By default true. If true invalid operation (division by 0. acos of value > 1. ...) leads to a throw of an exception.
+ *              If false the computation is carried on without any notification. When false the evaluation is a little faster.
  *  \return DataArrayDouble * - the new instance of DataArrayDouble containing the
  *          same number of tuples as \a this array and \a nbOfComp components.
  *          The caller is to delete this result array using decrRef() as it is no more
@@ -4314,144 +4407,210 @@ DataArrayDouble *DataArrayDouble::applyFunc(int nbOfComp, FunctionToEvaluate fun
  *  \throw If \a this is not allocated.
  *  \throw If computing \a func fails.
  */
-DataArrayDouble *DataArrayDouble::applyFunc(int nbOfComp, const std::string& func) const
+DataArrayDouble *DataArrayDouble::applyFunc(int nbOfComp, const std::string& func, bool isSafe) const
 {
-  checkAllocated();
   INTERP_KERNEL::ExprParser expr(func);
   expr.parse();
   std::set<std::string> vars;
   expr.getTrueSetOfVars(vars);
-  int oldNbOfComp=getNumberOfComponents();
-  if((int)vars.size()>oldNbOfComp)
-    {
-      std::ostringstream oss; oss << "The field has " << oldNbOfComp << " components and there are ";
-      oss << vars.size() << " variables : ";
-      std::copy(vars.begin(),vars.end(),std::ostream_iterator<std::string>(oss," "));
-      throw INTERP_KERNEL::Exception(oss.str().c_str());
-    }
   std::vector<std::string> varsV(vars.begin(),vars.end());
-  expr.prepareExprEvaluation(varsV,oldNbOfComp,nbOfComp);
-  //
-  DataArrayDouble *newArr=DataArrayDouble::New();
-  int nbOfTuples=getNumberOfTuples();
-  newArr->alloc(nbOfTuples,nbOfComp);
-  const double *ptr=getConstPointer();
-  double *ptrToFill=newArr->getPointer();
-  for(int i=0;i<nbOfTuples;i++)
-    {
-      try
-      {
-          expr.evaluateExpr(nbOfComp,ptr+i*oldNbOfComp,ptrToFill+i*nbOfComp);
-      }
-      catch(INTERP_KERNEL::Exception& e)
-      {
-          std::ostringstream oss; oss << "For tuple # " << i << " with value (";
-          std::copy(ptr+oldNbOfComp*i,ptr+oldNbOfComp*(i+1),std::ostream_iterator<double>(oss,", "));
-          oss << ") : Evaluation of function failed !" << e.what();
-          newArr->decrRef();
-          throw INTERP_KERNEL::Exception(oss.str().c_str());
-      }
-    }
-  return newArr;
+  return applyFunc3(nbOfComp,varsV,func,isSafe);
 }
 
 /*!
  * Returns a new DataArrayDouble created from \a this one by applying a function to every
- * tuple of \a this array. Textual data is not copied.
+ * tuple of \a this array. Textual data is not copied. This method works by tuples (whatever its size).
+ * If \a this is a one component array, call applyFuncOnThis instead that performs the same work faster.
+ *
  * For more info see \ref MEDCouplingArrayApplyFunc0.
  *  \param [in] func - the expression defining how to transform a tuple of \a this array.
  *              Supported expressions are described \ref MEDCouplingArrayApplyFuncExpr "here".
+ *  \param [in] isSafe - By default true. If true invalid operation (division by 0. acos of value > 1. ...) leads to a throw of an exception.
+ *                       If false the computation is carried on without any notification. When false the evaluation is a little faster.
  *  \return DataArrayDouble * - the new instance of DataArrayDouble containing the
  *          same number of tuples and components as \a this array.
  *          The caller is to delete this result array using decrRef() as it is no more
  *          needed.
+ *  \sa applyFuncOnThis
  *  \throw If \a this is not allocated.
  *  \throw If computing \a func fails.
  */
-DataArrayDouble *DataArrayDouble::applyFunc(const std::string& func) const
+DataArrayDouble *DataArrayDouble::applyFunc(const std::string& func, bool isSafe) const
 {
+  int nbOfComp(getNumberOfComponents());
+  if(nbOfComp<=0)
+    throw INTERP_KERNEL::Exception("DataArrayDouble::applyFunc : output number of component must be > 0 !");
   checkAllocated();
+  int nbOfTuples(getNumberOfTuples());
+  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newArr(DataArrayDouble::New());
+  newArr->alloc(nbOfTuples,nbOfComp);
   INTERP_KERNEL::ExprParser expr(func);
   expr.parse();
-  expr.prepareExprEvaluationVec();
-  //
-  DataArrayDouble *newArr=DataArrayDouble::New();
-  int nbOfTuples=getNumberOfTuples();
-  int nbOfComp=getNumberOfComponents();
-  newArr->alloc(nbOfTuples,nbOfComp);
-  const double *ptr=getConstPointer();
-  double *ptrToFill=newArr->getPointer();
-  for(int i=0;i<nbOfTuples;i++)
+  std::set<std::string> vars;
+  expr.getTrueSetOfVars(vars);
+  if((int)vars.size()>1)
     {
-      try
-      {
-          expr.evaluateExpr(nbOfComp,ptr+i*nbOfComp,ptrToFill+i*nbOfComp);
-      }
-      catch(INTERP_KERNEL::Exception& e)
-      {
-          std::ostringstream oss; oss << "For tuple # " << i << " with value (";
-          std::copy(ptr+nbOfComp*i,ptr+nbOfComp*(i+1),std::ostream_iterator<double>(oss,", "));
-          oss << ") : Evaluation of function failed ! " << e.what();
-          newArr->decrRef();
-          throw INTERP_KERNEL::Exception(oss.str().c_str());
-      }
+      std::ostringstream oss; oss << "DataArrayDouble::applyFunc : this method works only with at most one var func expression ! If you need to map comps on variables please use applyFunc2 or applyFunc3 instead ! Vars in expr are : ";
+      std::copy(vars.begin(),vars.end(),std::ostream_iterator<std::string>(oss," "));
+      throw INTERP_KERNEL::Exception(oss.str().c_str());
     }
-  return newArr;
+  if(vars.empty())
+    {
+      expr.prepareFastEvaluator();
+      newArr->rearrange(1);
+      newArr->fillWithValue(expr.evaluateDouble());
+      newArr->rearrange(nbOfComp);
+      return newArr.retn();
+    }
+  std::vector<std::string> vars2(vars.begin(),vars.end());
+  double buff,*ptrToFill(newArr->getPointer());
+  const double *ptr(begin());
+  std::vector<double> stck;
+  expr.prepareExprEvaluationDouble(vars2,1,1,0,&buff,&buff+1);
+  expr.prepareFastEvaluator();
+  if(!isSafe)
+    {
+      for(int i=0;i<nbOfTuples;i++)
+        {
+          for(int iComp=0;iComp<nbOfComp;iComp++,ptr++,ptrToFill++)
+            {
+              buff=*ptr;
+              expr.evaluateDoubleInternal(stck);
+              *ptrToFill=stck.back();
+              stck.pop_back();
+            }
+        }
+    }
+  else
+    {
+      for(int i=0;i<nbOfTuples;i++)
+        {
+          for(int iComp=0;iComp<nbOfComp;iComp++,ptr++,ptrToFill++)
+            {
+              buff=*ptr;
+              try
+              {
+                  expr.evaluateDoubleInternalSafe(stck);
+              }
+              catch(INTERP_KERNEL::Exception& e)
+              {
+                  std::ostringstream oss; oss << "For tuple # " << i << " component # " << iComp << " with value (";
+                  oss << buff;
+                  oss << ") : Evaluation of function failed !" << e.what();
+                  throw INTERP_KERNEL::Exception(oss.str().c_str());
+              }
+              *ptrToFill=stck.back();
+              stck.pop_back();
+            }
+        }
+    }
+  return newArr.retn();
 }
 
 /*!
- * Returns a new DataArrayDouble created from \a this one by applying a function to every
- * tuple of \a this array. Textual data is not copied.
- * For more info see \ref MEDCouplingArrayApplyFunc2.
- *  \param [in] nbOfComp - number of components in the result array.
+ * This method is a non const method that modify the array in \a this.
+ * This method only works on one component array. It means that function \a func must
+ * contain at most one variable.
+ * This method is a specialization of applyFunc method with one parameter on one component array.
+ *
  *  \param [in] func - the expression defining how to transform a tuple of \a this array.
  *              Supported expressions are described \ref MEDCouplingArrayApplyFuncExpr "here".
- *  \return DataArrayDouble * - the new instance of DataArrayDouble containing the
- *          same number of tuples 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.
- *  \throw If \a func contains vars that are not in \a this->getInfoOnComponent().
- *  \throw If computing \a func fails.
+ *  \param [in] isSafe - By default true. If true invalid operation (division by 0. acos of value > 1. ...) leads to a throw of an exception.
+ *              If false the computation is carried on without any notification. When false the evaluation is a little faster.
+ *
+ * \sa applyFunc
  */
-DataArrayDouble *DataArrayDouble::applyFunc2(int nbOfComp, const std::string& func) const
+void DataArrayDouble::applyFuncOnThis(const std::string& func, bool isSafe)
 {
+  int nbOfComp(getNumberOfComponents());
+  if(nbOfComp<=0)
+    throw INTERP_KERNEL::Exception("DataArrayDouble::applyFuncOnThis : output number of component must be > 0 !");
   checkAllocated();
+  int nbOfTuples(getNumberOfTuples());
   INTERP_KERNEL::ExprParser expr(func);
   expr.parse();
   std::set<std::string> vars;
   expr.getTrueSetOfVars(vars);
-  int oldNbOfComp=getNumberOfComponents();
-  if((int)vars.size()>oldNbOfComp)
+  if((int)vars.size()>1)
     {
-      std::ostringstream oss; oss << "The field has " << oldNbOfComp << " components and there are ";
-      oss << vars.size() << " variables : ";
+      std::ostringstream oss; oss << "DataArrayDouble::applyFuncOnThis : this method works only with at most one var func expression ! If you need to map comps on variables please use applyFunc2 or applyFunc3 instead ! Vars in expr are : ";
       std::copy(vars.begin(),vars.end(),std::ostream_iterator<std::string>(oss," "));
       throw INTERP_KERNEL::Exception(oss.str().c_str());
     }
-  expr.prepareExprEvaluation(getVarsOnComponent(),oldNbOfComp,nbOfComp);
-  //
-  DataArrayDouble *newArr=DataArrayDouble::New();
-  int nbOfTuples=getNumberOfTuples();
-  newArr->alloc(nbOfTuples,nbOfComp);
-  const double *ptr=getConstPointer();
-  double *ptrToFill=newArr->getPointer();
-  for(int i=0;i<nbOfTuples;i++)
+  if(vars.empty())
     {
-      try
-      {
-          expr.evaluateExpr(nbOfComp,ptr+i*oldNbOfComp,ptrToFill+i*nbOfComp);
-      }
-      catch(INTERP_KERNEL::Exception& e)
-      {
-          std::ostringstream oss; oss << "For tuple # " << i << " with value (";
-          std::copy(ptr+oldNbOfComp*i,ptr+oldNbOfComp*(i+1),std::ostream_iterator<double>(oss,", "));
-          oss << ") : Evaluation of function failed !" << e.what();
-          newArr->decrRef();
-          throw INTERP_KERNEL::Exception(oss.str().c_str());
-      }
+      expr.prepareFastEvaluator();
+      std::vector<std::string> compInfo(getInfoOnComponents());
+      rearrange(1);
+      fillWithValue(expr.evaluateDouble());
+      rearrange(nbOfComp);
+      setInfoOnComponents(compInfo);
+      return ;
     }
-  return newArr;
+  std::vector<std::string> vars2(vars.begin(),vars.end());
+  double buff,*ptrToFill(getPointer());
+  const double *ptr(begin());
+  std::vector<double> stck;
+  expr.prepareExprEvaluationDouble(vars2,1,1,0,&buff,&buff+1);
+  expr.prepareFastEvaluator();
+  if(!isSafe)
+    {
+      for(int i=0;i<nbOfTuples;i++)
+        {
+          for(int iComp=0;iComp<nbOfComp;iComp++,ptr++,ptrToFill++)
+            {
+              buff=*ptr;
+              expr.evaluateDoubleInternal(stck);
+              *ptrToFill=stck.back();
+              stck.pop_back();
+            }
+        }
+    }
+  else
+    {
+      for(int i=0;i<nbOfTuples;i++)
+        {
+          for(int iComp=0;iComp<nbOfComp;iComp++,ptr++,ptrToFill++)
+            {
+              buff=*ptr;
+              try
+              {
+                  expr.evaluateDoubleInternalSafe(stck);
+              }
+              catch(INTERP_KERNEL::Exception& e)
+              {
+                  std::ostringstream oss; oss << "For tuple # " << i << " component # " << iComp << " with value (";
+                  oss << buff;
+                  oss << ") : Evaluation of function failed !" << e.what();
+                  throw INTERP_KERNEL::Exception(oss.str().c_str());
+              }
+              *ptrToFill=stck.back();
+              stck.pop_back();
+            }
+        }
+    }
+}
+
+/*!
+ * Returns a new DataArrayDouble created from \a this one by applying a function to every
+ * tuple of \a this array. Textual data is not copied.
+ * For more info see \ref MEDCouplingArrayApplyFunc2.
+ *  \param [in] nbOfComp - number of components in the result array.
+ *  \param [in] func - the expression defining how to transform a tuple of \a this array.
+ *              Supported expressions are described \ref MEDCouplingArrayApplyFuncExpr "here".
+ *  \param [in] isSafe - By default true. If true invalid operation (division by 0. acos of value > 1. ...) leads to a throw of an exception.
+ *              If false the computation is carried on without any notification. When false the evaluation is a little faster.
+ *  \return DataArrayDouble * - the new instance of DataArrayDouble containing the
+ *          same number of tuples 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.
+ *  \throw If \a func contains vars that are not in \a this->getInfoOnComponent().
+ *  \throw If computing \a func fails.
+ */
+DataArrayDouble *DataArrayDouble::applyFunc2(int nbOfComp, const std::string& func, bool isSafe) const
+{
+  return applyFunc3(nbOfComp,getVarsOnComponent(),func,isSafe);
 }
 
 /*!
@@ -4462,6 +4621,8 @@ DataArrayDouble *DataArrayDouble::applyFunc2(int nbOfComp, const std::string& fu
  *  \param [in] varsOrder - sequence of vars defining their order.
  *  \param [in] func - the expression defining how to transform a tuple of \a this array.
  *              Supported expressions are described \ref MEDCouplingArrayApplyFuncExpr "here".
+ *  \param [in] isSafe - By default true. If true invalid operation (division by 0. acos of value > 1. ...) leads to a throw of an exception.
+ *              If false the computation is carried on without any notification. When false the evaluation is a little faster.
  *  \return DataArrayDouble * - the new instance of DataArrayDouble containing the
  *          same number of tuples as \a this array.
  *          The caller is to delete this result array using decrRef() as it is no more
@@ -4470,14 +4631,20 @@ DataArrayDouble *DataArrayDouble::applyFunc2(int nbOfComp, const std::string& fu
  *  \throw If \a func contains vars not in \a varsOrder.
  *  \throw If computing \a func fails.
  */
-DataArrayDouble *DataArrayDouble::applyFunc3(int nbOfComp, const std::vector<std::string>& varsOrder, const std::string& func) const
+DataArrayDouble *DataArrayDouble::applyFunc3(int nbOfComp, const std::vector<std::string>& varsOrder, const std::string& func, bool isSafe) const
 {
+  if(nbOfComp<=0)
+    throw INTERP_KERNEL::Exception("DataArrayDouble::applyFunc3 : output number of component must be > 0 !");
+  std::vector<std::string> varsOrder2(varsOrder);
+  int oldNbOfComp(getNumberOfComponents());
+  for(int i=(int)varsOrder.size();i<oldNbOfComp;i++)
+    varsOrder2.push_back(std::string());
   checkAllocated();
+  int nbOfTuples(getNumberOfTuples());
   INTERP_KERNEL::ExprParser expr(func);
   expr.parse();
   std::set<std::string> vars;
   expr.getTrueSetOfVars(vars);
-  int oldNbOfComp=getNumberOfComponents();
   if((int)vars.size()>oldNbOfComp)
     {
       std::ostringstream oss; oss << "The field has " << oldNbOfComp << " components and there are ";
@@ -4485,29 +4652,49 @@ DataArrayDouble *DataArrayDouble::applyFunc3(int nbOfComp, const std::vector<std
       std::copy(vars.begin(),vars.end(),std::ostream_iterator<std::string>(oss," "));
       throw INTERP_KERNEL::Exception(oss.str().c_str());
     }
-  expr.prepareExprEvaluation(varsOrder,oldNbOfComp,nbOfComp);
-  //
-  DataArrayDouble *newArr=DataArrayDouble::New();
-  int nbOfTuples=getNumberOfTuples();
+  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newArr(DataArrayDouble::New());
   newArr->alloc(nbOfTuples,nbOfComp);
-  const double *ptr=getConstPointer();
-  double *ptrToFill=newArr->getPointer();
-  for(int i=0;i<nbOfTuples;i++)
-    {
-      try
-      {
-          expr.evaluateExpr(nbOfComp,ptr+i*oldNbOfComp,ptrToFill+i*nbOfComp);
-      }
-      catch(INTERP_KERNEL::Exception& e)
-      {
-          std::ostringstream oss; oss << "For tuple # " << i << " with value (";
-          std::copy(ptr+oldNbOfComp*i,ptr+oldNbOfComp*(i+1),std::ostream_iterator<double>(oss,", "));
-          oss << ") : Evaluation of function failed !" << e.what();
-          newArr->decrRef();
-          throw INTERP_KERNEL::Exception(oss.str().c_str());
-      }
+  INTERP_KERNEL::AutoPtr<double> buff(new double[oldNbOfComp]);
+  double *buffPtr(buff),*ptrToFill;
+  std::vector<double> stck;
+  for(int iComp=0;iComp<nbOfComp;iComp++)
+    {
+      expr.prepareExprEvaluationDouble(varsOrder2,oldNbOfComp,nbOfComp,iComp,buffPtr,buffPtr+oldNbOfComp);
+      expr.prepareFastEvaluator();
+      const double *ptr(getConstPointer());
+      ptrToFill=newArr->getPointer()+iComp;
+      if(!isSafe)
+        {
+          for(int i=0;i<nbOfTuples;i++,ptrToFill+=nbOfComp,ptr+=oldNbOfComp)
+            {
+              std::copy(ptr,ptr+oldNbOfComp,buffPtr);
+              expr.evaluateDoubleInternal(stck);
+              *ptrToFill=stck.back();
+              stck.pop_back();
+            }
+        }
+      else
+        {
+          for(int i=0;i<nbOfTuples;i++,ptrToFill+=nbOfComp,ptr+=oldNbOfComp)
+            {
+              std::copy(ptr,ptr+oldNbOfComp,buffPtr);
+              try
+              {
+                  expr.evaluateDoubleInternalSafe(stck);
+                  *ptrToFill=stck.back();
+                  stck.pop_back();
+              }
+              catch(INTERP_KERNEL::Exception& e)
+              {
+                  std::ostringstream oss; oss << "For tuple # " << i << " with value (";
+                  std::copy(ptr+oldNbOfComp*i,ptr+oldNbOfComp*(i+1),std::ostream_iterator<double>(oss,", "));
+                  oss << ") : Evaluation of function failed !" << e.what();
+                  throw INTERP_KERNEL::Exception(oss.str().c_str());
+              }
+            }
+        }
     }
-  return newArr;
+  return newArr.retn();
 }
 
 void DataArrayDouble::applyFuncFast32(const std::string& func)
@@ -5958,7 +6145,7 @@ void DataArrayInt::pushBackSilent(int val)
  * This method adds at the end of \a this a serie of values [\c valsBg,\c valsEnd). This method do \b not update its time label to avoid useless incrementation
  * of counter. So the caller is expected to call TimeLabel::declareAsNew on \a this at the end of the push session.
  *
- *  \param [in] valsBg - an array of values to push at the end of \this.
+ *  \param [in] valsBg - an array of values to push at the end of \this.
  *  \param [in] valsEnd - specifies the end of the array \a valsBg, so that
  *              the last value of \a valsBg is \a valsEnd[ -1 ].
  * \throw If \a this has already been allocated with number of components different from one.
@@ -6083,7 +6270,9 @@ void DataArrayInt::iota(int init)
 /*!
  * Returns a textual and human readable representation of \a this instance of
  * DataArrayInt. This text is shown when a DataArrayInt is printed in Python.
- *  \return std::string - text describing \a this DataArrayInt.
+ * \return std::string - text describing \a this DataArrayInt.
+ * 
+ * \sa reprNotTooLong, reprZip
  */
 std::string DataArrayInt::repr() const
 {
@@ -6099,6 +6288,18 @@ std::string DataArrayInt::reprZip() const
   return ret.str();
 }
 
+/*!
+ * This method is close to repr method except that when \a this has more than 1000 tuples, all tuples are not
+ * printed out to avoid to consume too much space in interpretor.
+ * \sa repr
+ */
+std::string DataArrayInt::reprNotTooLong() const
+{
+  std::ostringstream ret;
+  reprNotTooLongStream(ret);
+  return ret.str();
+}
+
 void DataArrayInt::writeVTK(std::ostream& ofs, int indent, const std::string& type, const std::string& nameInFile, DataArrayByte *byteArr) const
 {
   static const char SPACE[4]={' ',' ',' ',' '};
@@ -6152,6 +6353,12 @@ void DataArrayInt::reprZipStream(std::ostream& stream) const
   reprZipWithoutNameStream(stream);
 }
 
+void DataArrayInt::reprNotTooLongStream(std::ostream& stream) const
+{
+  stream << "Name of int array : \"" << _name << "\"\n";
+  reprNotTooLongWithoutNameStream(stream);
+}
+
 void DataArrayInt::reprWithoutNameStream(std::ostream& stream) const
 {
   DataArray::reprWithoutNameStream(stream);
@@ -6164,6 +6371,13 @@ void DataArrayInt::reprZipWithoutNameStream(std::ostream& stream) const
   _mem.reprZip(getNumberOfComponents(),stream);
 }
 
+void DataArrayInt::reprNotTooLongWithoutNameStream(std::ostream& stream) const
+{
+  DataArray::reprWithoutNameStream(stream);
+  stream.precision(17);
+  _mem.reprNotTooLong(getNumberOfComponents(),stream);
+}
+
 void DataArrayInt::reprCppStream(const std::string& varName, std::ostream& stream) const
 {
   int nbTuples=getNumberOfTuples(),nbComp=getNumberOfComponents();
@@ -6240,7 +6454,7 @@ void DataArrayInt::reprQuickOverviewData(std::ostream& stream, std::size_t maxNb
 }
 
 /*!
- * Modifies \a this one-dimensional array so that each value \a v = \a indArrBg[ \a v ],
+ * 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.
@@ -6249,15 +6463,15 @@ void DataArrayInt::reprQuickOverviewData(std::ostream& stream, std::size_t maxNb
  *  \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 replaceOneValByInThis
  */
 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);
-  int nbOfTuples=getNumberOfTuples();
-  int *pt=getPointer();
+  int nbElemsIn((int)std::distance(indArrBg,indArrEnd)),nbOfTuples(getNumberOfTuples()),*pt(getPointer());
   for(int i=0;i<nbOfTuples;i++,pt++)
     {
       if(*pt>=0 && *pt<nbElemsIn)
@@ -6271,6 +6485,29 @@ void DataArrayInt::transformWithIndArr(const int *indArrBg, const int *indArrEnd
   declareAsNew();
 }
 
+/*!
+ * Modifies in place \a this one-dimensional array like this : each id in \a this so that this[id] equal to \a valToBeReplaced will be replaced at the same place by \a replacedBy.
+ *
+ * \param [in] valToBeReplaced - the value in \a this to be replaced.
+ * \param [in] replacedBy - the value taken by each tuple previously equal to \a valToBeReplaced.
+ *
+ * \sa DataArrayInt::transformWithIndArr
+ */
+void DataArrayInt::replaceOneValByInThis(int valToBeReplaced, int replacedBy)
+{
+  checkAllocated();
+  if(getNumberOfComponents()!=1)
+    throw INTERP_KERNEL::Exception("Call replaceOneValByInThis method on DataArrayInt with only one component, you can call 'rearrange' method before !");
+  if(valToBeReplaced==replacedBy)
+    return ;
+  int nbOfTuples(getNumberOfTuples()),*pt(getPointer());
+  for(int i=0;i<nbOfTuples;i++,pt++)
+    {
+      if(*pt==valToBeReplaced)
+        *pt=replacedBy;
+    }
+}
+
 /*!
  * 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,
@@ -6319,7 +6556,7 @@ void DataArrayInt::transformWithIndArr(const int *indArrBg, const int *indArrEnd
  */
 void DataArrayInt::splitByValueRange(const int *arrBg, const int *arrEnd,
                                      DataArrayInt *& castArr, DataArrayInt *& rankInsideCast, DataArrayInt *& castsPresent) const
-    {
+{
   checkAllocated();
   if(getNumberOfComponents()!=1)
     throw INTERP_KERNEL::Exception("Call splitByValueRange  method on DataArrayInt with only one component, you can call 'rearrange' method before !");
@@ -6362,7 +6599,60 @@ void DataArrayInt::splitByValueRange(const int *arrBg, const int *arrEnd,
   castArr=ret1.retn();
   rankInsideCast=ret2.retn();
   castsPresent=ret3.retn();
+}
+
+/*!
+ * This method look at \a this if it can be considered as a range defined by the 3-tuple ( \a strt , \a sttoopp , \a stteepp ).
+ * If false is returned the tuple must be ignored. If true is returned \a this can be considered by a range( \a strt , \a sttoopp , \a stteepp ).
+ * This method works only if \a this is allocated and single component. If not an exception will be thrown.
+ *
+ * \param [out] strt - the start of the range (included) if true is returned.
+ * \param [out] sttoopp - the end of the range (not included) if true is returned.
+ * \param [out] stteepp - the step of the range if true is returned.
+ * \return the verdict of the check.
+ *
+ * \sa DataArray::GetNumberOfItemGivenBES
+ */
+bool DataArrayInt::isRange(int& strt, int& sttoopp, int& stteepp) const
+{
+  checkAllocated();
+  if(getNumberOfComponents()!=1)
+    throw INTERP_KERNEL::Exception("DataArrayInt::isRange : this must be single component array !");
+  int nbTuples(getNumberOfTuples());
+  if(nbTuples==0)
+    { strt=0; sttoopp=0; stteepp=1; return true; }
+  const int *pt(begin());
+  strt=*pt; 
+  if(nbTuples==1)
+    { sttoopp=strt+1; stteepp=1; return true; }
+  strt=*pt; sttoopp=pt[nbTuples-1];
+  if(strt==sttoopp)
+    return false;
+  if(sttoopp>strt)
+    {
+      sttoopp++;
+      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;
     }
+}
 
 /*!
  * Creates a one-dimensional DataArrayInt (\a res) whose contents are computed from 
@@ -6418,7 +6708,7 @@ DataArrayInt *DataArrayInt::transformWithIndArrR(const int *indArrBg, const int
  * Creates a one-dimensional DataArrayInt of given length, whose contents are computed
  * from values of \a this array, which is supposed to contain a renumbering map in 
  * "Old to New" mode. The result array contains a renumbering map in "New to Old" mode.
- * To know how to use the renumbering maps see \ref MEDCouplingArrayRenumbering.
+ * 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
@@ -6485,7 +6775,7 @@ DataArrayInt *DataArrayInt::invertArrayO2N2N2OBis(int newNbOfElem) const
  * 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 MEDCouplingArrayRenumbering.
+ * 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
@@ -6621,6 +6911,25 @@ bool DataArrayInt::isFittingWith(const std::vector<bool>& v) const
   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.
+ */
+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;
+}
+
 /*!
  * Sorts values of the array.
  *  \param [in] asc - \a true means ascending order, \a false, descending.
@@ -6903,9 +7212,9 @@ DataArrayInt *DataArrayInt::toNoInterlace() const
 /*!
  * Permutes values of \a this array as required by \a old2New array. The values are
  * permuted so that \c new[ \a old2New[ i ]] = \c old[ i ]. Number of tuples remains
- * the same as in \this one.
+ * the same as in \this one.
  * If a permutation reduction is needed, substr() or selectByTupleId() should be used.
- * For more info on renumbering see \ref MEDCouplingArrayRenumbering.
+ * For more info on renumbering see \ref numbering.
  *  \param [in] old2New - C array of length equal to \a this->getNumberOfTuples()
  *     giving a new position for i-th old value.
  */
@@ -6935,8 +7244,8 @@ void DataArrayInt::renumberInPlace(const int *old2New)
 /*!
  * Permutes values of \a this array as required by \a new2Old array. The values are
  * permuted so that \c new[ i ] = \c old[ \a new2Old[ i ]]. Number of tuples remains
- * the same as in \this one.
- * For more info on renumbering see \ref MEDCouplingArrayRenumbering.
+ * the same as in \this one.
+ * For more info on renumbering see \ref numbering.
  *  \param [in] new2Old - C array of length equal to \a this->getNumberOfTuples()
  *     giving a previous position of i-th new value.
  *  \return DataArrayInt * - the new instance of DataArrayInt that the caller
@@ -6968,9 +7277,9 @@ void DataArrayInt::renumberInPlaceR(const int *new2Old)
 /*!
  * Returns a copy of \a this array with values permuted as required by \a old2New array.
  * The values are permuted so that  \c new[ \a old2New[ i ]] = \c old[ i ].
- * Number of tuples in the result array remains the same as in \this one.
+ * Number of tuples in the result array remains the same as in \this one.
  * If a permutation reduction is needed, renumberAndReduce() should be used.
- * For more info on renumbering see \ref MEDCouplingArrayRenumbering.
+ * For more info on renumbering see \ref numbering.
  *  \param [in] old2New - C array of length equal to \a this->getNumberOfTuples()
  *          giving a new position for i-th old value.
  *  \return DataArrayInt * - the new instance of DataArrayInt that the caller
@@ -6996,9 +7305,9 @@ DataArrayInt *DataArrayInt::renumber(const int *old2New) const
 /*!
  * Returns a copy of \a this array with values permuted as required by \a new2Old array.
  * The values are permuted so that  \c new[ i ] = \c old[ \a new2Old[ i ]]. Number of
- * tuples in the result array remains the same as in \this one.
+ * tuples in the result array remains the same as in \this one.
  * If a permutation reduction is needed, substr() or selectByTupleId() should be used.
- * For more info on renumbering see \ref MEDCouplingArrayRenumbering.
+ * For more info on renumbering see \ref numbering.
  *  \param [in] new2Old - C array of length equal to \a this->getNumberOfTuples()
  *     giving a previous position of i-th new value.
  *  \return DataArrayInt * - the new instance of DataArrayInt that the caller
@@ -7026,7 +7335,7 @@ DataArrayInt *DataArrayInt::renumberR(const int *new2Old) const
  * The values are permuted so that  \c new[ \a old2New[ i ]] = \c old[ i ] for all
  * \a old2New[ i ] >= 0. In other words every i-th tuple in \a this array, for which 
  * \a old2New[ i ] is negative, is missing from the result array.
- * For more info on renumbering see \ref MEDCouplingArrayRenumbering.
+ * For more info on renumbering see \ref numbering.
  *  \param [in] old2New - C array of length equal to \a this->getNumberOfTuples()
  *     giving a new position for i-th old tuple and giving negative position for
  *     for i-th old tuple that should be omitted.
@@ -7059,7 +7368,7 @@ DataArrayInt *DataArrayInt::renumberAndReduce(const int *old2New, int newNbOfTup
  * The values are permuted so that  \c new[ i ] = \c old[ \a new2OldBg[ i ]].
  * This method is equivalent to renumberAndReduce() except that convention in input is
  * \c new2old and \b not \c old2new.
- * For more info on renumbering see \ref MEDCouplingArrayRenumbering.
+ * For more info on renumbering see \ref numbering.
  *  \param [in] new2OldBg - pointer to the beginning of a permutation array that gives a
  *              tuple index in \a this array to fill the i-th tuple in the new array.
  *  \param [in] new2OldEnd - specifies the end of the permutation array that starts at
@@ -7093,7 +7402,7 @@ DataArrayInt *DataArrayInt::selectByTupleId(const int *new2OldBg, const int *new
  * \c new2old and \b not \c old2new.
  * This method is equivalent to selectByTupleId() except that it prevents coping data
  * from behind the end of \a this array.
- * For more info on renumbering see \ref MEDCouplingArrayRenumbering.
+ * For more info on renumbering see \ref numbering.
  *  \param [in] new2OldBg - pointer to the beginning of a permutation array that gives a
  *              tuple index in \a this array to fill the i-th tuple in the new array.
  *  \param [in] new2OldEnd - specifies the end of the permutation array that starts at
@@ -7130,7 +7439,7 @@ DataArrayInt *DataArrayInt::selectByTupleIdSafe(const int *new2OldBg, const int
  * command \c range( \a bg, \a end2, \a step ).
  * This method is equivalent to selectByTupleIdSafe() except that the input array is
  * not constructed explicitly.
- * For more info on renumbering see \ref MEDCouplingArrayRenumbering.
+ * For more info on renumbering see \ref numbering.
  *  \param [in] bg - index of the first tuple to copy from \a this array.
  *  \param [in] end2 - index of the tuple before which the tuples to copy are located.
  *  \param [in] step - index increment to get index of the next tuple to copy.
@@ -7156,7 +7465,7 @@ DataArrayInt *DataArrayInt::selectByTupleId2(int bg, int end2, int step) const
 /*!
  * Returns a shorten copy of \a this array. The new DataArrayInt contains ranges
  * of tuples specified by \a ranges parameter.
- * For more info on renumbering see \ref MEDCouplingArrayRenumbering.
+ * For more info on renumbering see \ref numbering.
  *  \param [in] ranges - std::vector of std::pair's each of which defines a range
  *              of tuples in [\c begin,\c end) format.
  *  \return DataArrayInt * - the new instance of DataArrayInt that the caller
@@ -7224,7 +7533,7 @@ DataArray *DataArrayInt::selectByTupleRanges(const std::vector<std::pair<int,int
  * are [5,6,0,3,2,7,1,4]; if this result array (\a res) is used as an argument in call
  * \a this->renumber(\a res) then the returned array contains [0,3,4,6,7,9,10,11].
  * This method is useful for renumbering (in MED file for example). For more info
- * on renumbering see \ref MEDCouplingArrayRenumbering.
+ * on renumbering see \ref numbering.
  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
  *          array using decrRef() as it is no more needed.
  *  \throw If \a this is not allocated.
@@ -7292,7 +7601,7 @@ DataArrayInt *DataArrayInt::FindPermutationFromFirstToSecond(const DataArrayInt
  * place in the set \a B. The second out array is the index of the first one; it shows how
  * many elements of \a A are mapped into each element of \a B. <br>
  * For more info on
- * mapping and its usage in renumbering see \ref MEDCouplingArrayRenumbering. <br>
+ * mapping and its usage in renumbering see \ref numbering. <br>
  * \b Example:
  * - \a this: [0,3,2,3,2,2,1,2]
  * - \a targetNb: 4
@@ -7359,7 +7668,7 @@ void DataArrayInt::changeSurjectiveFormat(int targetNb, DataArrayInt *&arr, Data
  * from a zip representation of a surjective format (returned e.g. by
  * \ref ParaMEDMEM::DataArrayDouble::findCommonTuples() "DataArrayDouble::findCommonTuples()"
  * for example). The result array minimizes the permutation. <br>
- * For more info on renumbering see \ref MEDCouplingArrayRenumbering. <br>
+ * For more info on renumbering see \ref numbering. <br>
  * \b Example: <br>
  * - \a nbOfOldTuples: 10 
  * - \a arr          : [0,3, 5,7,9]
@@ -7420,7 +7729,7 @@ DataArrayInt *DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(int nbOfOldTu
 /*!
  * Returns a new DataArrayInt containing a renumbering map in "New to Old" mode,
  * which if applied to \a this array would make it sorted ascendingly.
- * For more info on renumbering see \ref MEDCouplingArrayRenumbering. <br>
+ * For more info on renumbering see \ref numbering. <br>
  * \b Example: <br>
  * - \a this: [2,0,1,1,0,1,2,0,1,1,0,0]
  * - result: [10,0,5,6,1,7,11,2,8,9,3,4]
@@ -7475,17 +7784,20 @@ DataArrayInt *DataArrayInt::buildPermArrPerLevel() const
 /*!
  * Checks if contents of \a this array are equal to that of an array filled with
  * iota(). This method is particularly useful for DataArrayInt instances that represent
- * a renumbering array to check the real need in renumbering. 
+ * a renumbering array to check the real need in renumbering. In this case it is better to use isIdentity2
+ * method of isIdentity method.
+ *
  *  \return bool - \a true if \a this array contents == \a range( \a this->getNumberOfTuples())
  *  \throw If \a this is not allocated.
  *  \throw If \a this->getNumberOfComponents() != 1.
+ *  \sa isIdentity2
  */
 bool DataArrayInt::isIdentity() const
 {
   checkAllocated();
   if(getNumberOfComponents()!=1)
     return false;
-  int nbOfTuples=getNumberOfTuples();
+  int nbOfTuples(getNumberOfTuples());
   const int *pt=getConstPointer();
   for(int i=0;i<nbOfTuples;i++,pt++)
     if(*pt!=i)
@@ -7493,6 +7805,25 @@ bool DataArrayInt::isIdentity() const
   return true;
 }
 
+/*!
+ * This method is stronger than isIdentity method. This method checks than \a this can be considered as an identity function
+ * of a set having \a sizeExpected elements into itself.
+ *
+ * \param [in] sizeExpected - The number of elements
+ * \return bool - \a true if \a this array contents == \a range( \a this->getNumberOfTuples()) and if \a this has \a sizeExpected tuples in it.
+ *
+ *  \throw If \a this is not allocated.
+ *  \throw If \a this->getNumberOfComponents() != 1.
+ * \sa isIdentity
+ */
+bool DataArrayInt::isIdentity2(int sizeExpected) const
+{
+  bool ret0(isIdentity());
+  if(!ret0)
+    return false;
+  return getNumberOfTuples()==sizeExpected;
+}
+
 /*!
  * Checks if all values in \a this array are equal to \a val.
  *  \param [in] val - value to check equality of array values to.
@@ -7686,7 +8017,7 @@ void DataArrayInt::reAlloc(int nbOfTuples)
  *  \ref py_mcdataarrayint_keepselectedcomponents "Here is a Python example".
  *  \endif
  */
-DataArray *DataArrayInt::keepSelectedComponents(const std::vector<int>& compoIds) const
+DataArrayInt *DataArrayInt::keepSelectedComponents(const std::vector<int>& compoIds) const
 {
   checkAllocated();
   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New());
@@ -7874,7 +8205,7 @@ void DataArrayInt::setPartOfValues1(const DataArrayInt *a, int bgTuples, int end
  *  \throw If \a this is not allocated.
  *  \throw If parameters specifying tuples and components to assign to, do not give a
  *            non-empty range of increasing indices or indices are out of a valid range
- *            for \this array.
+ *            for \this array.
  *
  *  \if ENABLE_EXAMPLES
  *  \ref py_mcdataarrayint_setpartofvaluessimple1 "Here is a Python example".
@@ -8066,7 +8397,7 @@ void DataArrayInt::setPartOfValuesSimple2(int a, const int *bgTuples, const int
  *         defined by <em>(bgComp,endComp,stepComp)</em>.
  *  \throw If parameters specifying components to assign to, do not give a
  *            non-empty range of increasing indices or indices are out of a valid range
- *            for \this array.
+ *            for \this array.
  *
  *  \if ENABLE_EXAMPLES
  *  \ref py_mcdataarrayint_setpartofvalues3 "Here is a Python example".
@@ -8140,7 +8471,7 @@ void DataArrayInt::setPartOfValues3(const DataArrayInt *a, const int *bgTuples,
  *         \a this array.
  *  \throw If parameters specifying components to assign to, do not give a
  *            non-empty range of increasing indices or indices are out of a valid range
- *            for \this array.
+ *            for \this array.
  *
  *  \if ENABLE_EXAMPLES
  *  \ref py_mcdataarrayint_setpartofvaluessimple3 "Here is a Python example".
@@ -8484,7 +8815,7 @@ DataArrayIntIterator *DataArrayInt::iterator()
 
 /*!
  * Creates a new DataArrayInt containing IDs (indices) of tuples holding value equal to a
- * given one.
+ * given one. The ids are sorted in the ascending order.
  *  \param [in] val - the value to find within \a this.
  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this
  *          array using decrRef() as it is no more needed.
@@ -9091,6 +9422,32 @@ int DataArrayInt::getMinValueInArray() const
   return *loc;
 }
 
+/*!
+ * Returns in a single walk in \a this the min value and the max value in \a this.
+ * \a this is expected to be single component array.
+ *
+ * \param [out] minValue - the min value in \a this.
+ * \param [out] maxValue - the max value in \a this.
+ *
+ * \sa getMinValueInArray, getMinValue, getMaxValueInArray, getMaxValue
+ */
+void DataArrayInt::getMinMaxValues(int& minValue, int& maxValue) const
+{
+  checkAllocated();
+  if(getNumberOfComponents()!=1)
+    throw INTERP_KERNEL::Exception("DataArrayInt::getMinMaxValues : must be applied on DataArrayInt with only one component !");
+  int nbTuples(getNumberOfTuples());
+  const int *pt(begin());
+  minValue=std::numeric_limits<int>::max(); maxValue=-std::numeric_limits<int>::max();
+  for(int i=0;i<nbTuples;i++,pt++)
+    {
+      if(*pt<minValue)
+        minValue=*pt;
+      if(*pt>maxValue)
+        maxValue=*pt;
+    }
+}
+
 /*!
  * 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
@@ -9264,7 +9621,7 @@ void DataArrayInt::applyModulus(int val)
  * \param [in] vmax end of range. This value is \b not included in range (excluded).
  * \return a newly allocated data array that the caller should deal with.
  *
- * \sa DataArrayInt::getIdsNotInRange
+ * \sa DataArrayInt::getIdsNotInRange , DataArrayInt::getIdsStrictlyNegative
  */
 DataArrayInt *DataArrayInt::getIdsInRange(int vmin, int vmax) const
 {
@@ -9289,7 +9646,7 @@ DataArrayInt *DataArrayInt::getIdsInRange(int vmin, int vmax) const
  * \param [in] vmax end of range. This value is included in range (included).
  * \return a newly allocated data array that the caller should deal with.
  * 
- * \sa DataArrayInt::getIdsInRange
+ * \sa DataArrayInt::getIdsInRange , DataArrayInt::getIdsStrictlyNegative
  */
 DataArrayInt *DataArrayInt::getIdsNotInRange(int vmin, int vmax) const
 {
@@ -9305,6 +9662,26 @@ DataArrayInt *DataArrayInt::getIdsNotInRange(int vmin, int vmax) const
   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::getIdsInRange
+ */
+DataArrayInt *DataArrayInt::getIdsStrictlyNegative() const
+{
+  checkAllocated();
+  if(getNumberOfComponents()!=1)
+    throw INTERP_KERNEL::Exception("DataArrayInt::getIdsStrictlyNegative : this must have exactly one component !");
+  const int *cptr(getConstPointer());
+  MEDCouplingAutoRefCountObjectPtr<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);
+  return ret.retn();
+}
+
 /*!
  * This method works only on data array with one component.
  * This method checks that all ids in \b this are in [ \b vmin, \b vmax ). If there is at least one element in \a this not in [ \b vmin, \b vmax ) an exception will be thrown.
@@ -9823,7 +10200,8 @@ DataArrayInt *DataArrayInt::buildSubstractionOptimized(const DataArrayInt *other
   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()),*work1(pt1Bg),*work2(pt2Bg);
+  const int *pt1Bg(begin()),*pt1End(end()),*pt2Bg(other->begin()),*pt2End(other->end());
+  const int *work1(pt1Bg),*work2(pt2Bg);
   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
   for(;work1!=pt1End;work1++)
     {
@@ -9880,6 +10258,7 @@ DataArrayInt *DataArrayInt::buildIntersection(const DataArrayInt *other) const
  * 
  * \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
 {
@@ -9896,6 +10275,38 @@ DataArrayInt *DataArrayInt::buildUnique() const
   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());
+  MEDCouplingAutoRefCountObjectPtr<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 
@@ -9995,8 +10406,6 @@ void DataArrayInt::computeOffsets2()
     throw INTERP_KERNEL::Exception("DataArrayInt::computeOffsets2 : only single component allowed !");
   int nbOfTuples=getNumberOfTuples();
   int *ret=(int *)malloc((nbOfTuples+1)*sizeof(int));
-  if(nbOfTuples==0)
-    return ;
   const int *work=getConstPointer();
   ret[0]=0;
   for(int i=0;i<nbOfTuples;i++)
@@ -10292,6 +10701,68 @@ DataArrayInt *DataArrayInt::findIdInRangeForEachTuple(const DataArrayInt *ranges
   return ret.retn();
 }
 
+/*!
+ * \b WARNING this method is a \b non \a const \b method. This method works tuple by tuple. Each tuple is expected to be pairs (number of components must be equal to 2).
+ * This method rearrange each pair in \a this so that, tuple with id \b tid will be after the call \c this->getIJ(tid,0)==this->getIJ(tid-1,1) and \c this->getIJ(tid,1)==this->getIJ(tid+1,0).
+ * If it is impossible to reach such condition an exception will be thrown ! \b WARNING In case of throw \a this can be partially modified !
+ * If this method has correctly worked, \a this will be able to be considered as a linked list.
+ * This method does nothing if number of tuples is lower of equal to 1.
+ *
+ * This method is useful for users having an unstructured mesh having only SEG2 to rearrange internaly the connectibity without any coordinates consideration.
+ *
+ * \sa MEDCouplingUMesh::orderConsecutiveCells1D
+ */
+void DataArrayInt::sortEachPairToMakeALinkedList()
+{
+  checkAllocated();
+  if(getNumberOfComponents()!=2)
+    throw INTERP_KERNEL::Exception("DataArrayInt::sortEachPairToMakeALinkedList : Only works on DataArrayInt instance with nb of components equal to 2 !");
+  int nbOfTuples(getNumberOfTuples());
+  if(nbOfTuples<=1)
+    return ;
+  int *conn(getPointer());
+  for(int i=1;i<nbOfTuples;i++,conn+=2)
+    {
+      if(i>1)
+        {
+          if(conn[2]==conn[3])
+            {
+              std::ostringstream oss; oss << "DataArrayInt::sortEachPairToMakeALinkedList : In the tuple #" << i << " presence of a pair filled with same ids !";
+              throw INTERP_KERNEL::Exception(oss.str().c_str());
+            }
+          if(conn[2]!=conn[1] && conn[3]==conn[1] && conn[2]!=conn[0])
+            std::swap(conn[2],conn[3]);
+          //not(conn[2]==conn[1] && conn[3]!=conn[1] && conn[3]!=conn[0])
+          if(conn[2]!=conn[1] || conn[3]==conn[1] || conn[3]==conn[0])
+            {
+              std::ostringstream oss; oss << "DataArrayInt::sortEachPairToMakeALinkedList : In the tuple #" << i << " something is invalid !";
+              throw INTERP_KERNEL::Exception(oss.str().c_str());
+            }
+        }
+      else
+        {
+          if(conn[0]==conn[1] || conn[2]==conn[3])
+            throw INTERP_KERNEL::Exception("DataArrayInt::sortEachPairToMakeALinkedList : In the 2 first tuples presence of a pair filled with same ids !");
+          int tmp[4];
+          std::set<int> s;
+          s.insert(conn,conn+4);
+          if(s.size()!=3)
+            throw INTERP_KERNEL::Exception("DataArrayInt::sortEachPairToMakeALinkedList : This can't be considered as a linked list regarding 2 first tuples !");
+          if(std::count(conn,conn+4,conn[0])==2)
+            {
+              tmp[0]=conn[1];
+              tmp[1]=conn[0];
+              tmp[2]=conn[0];
+              if(conn[2]==conn[0])
+                { tmp[3]=conn[3]; }
+              else
+                { tmp[3]=conn[2];}
+              std::copy(tmp,tmp+4,conn);
+            }
+        }
+    }
+}
+
 /*!
  * 
  * \param [in] nbTimes specifies the nb of times each tuples in \a this will be duplicated contiguouly in returned DataArrayInt instance.