diff --git a/Geo/MHexahedron.cpp b/Geo/MHexahedron.cpp
index ccc3796e99f565ff0b5cb8d50c8d4bd72cfb10b4..630daee66ad02052922226fc114ef08299613217 100644
--- a/Geo/MHexahedron.cpp
+++ b/Geo/MHexahedron.cpp
@@ -181,9 +181,7 @@ int MHexahedronN::getNumEdgesRep(bool curved)
 const JacobianBasis* MHexahedron::getJacobianFuncSpace(int order) const
 {
   if (order == -1) return BasisFactory::getJacobianBasis(getTypeForMSH());
-
-  int tag = ElementType::getTag(TYPE_HEX, order);
-  return tag ? BasisFactory::getJacobianBasis(tag) : NULL;
+  return BasisFactory::getJacobianBasis(FuncSpaceData(this, order));
 }
 
 void _myGetFaceRep(MHexahedron *hex, int num, double *x, double *y, double *z,
diff --git a/Geo/MLine.cpp b/Geo/MLine.cpp
index ae11a4428389fb64a915b4efcce7c4efb0dfe440..73e4c7978263fad4fd41057d45800a435427e63c 100644
--- a/Geo/MLine.cpp
+++ b/Geo/MLine.cpp
@@ -11,13 +11,12 @@
 #include "Context.h"
 #include "qualityMeasures.h"
 #include "decasteljau.h"
+#include "bezierBasis.h"
 
 const JacobianBasis* MLine::getJacobianFuncSpace(int order) const
 {
   if (order == -1) return BasisFactory::getJacobianBasis(getTypeForMSH());
-
-  int tag = ElementType::getTag(TYPE_LIN, order);
-  return tag ? BasisFactory::getJacobianBasis(tag) : NULL;
+  return BasisFactory::getJacobianBasis(FuncSpaceData(this, order));
 }
 
 void MLine::getIntegrationPoints(int pOrder, int *npts, IntPt **pts)
diff --git a/Geo/MPrism.cpp b/Geo/MPrism.cpp
index 3ac5ae27e5dee2c7d766fc580e5fe2cbd4d6140a..12655cc28575610ca1e4f7c55907092e7c47d383 100644
--- a/Geo/MPrism.cpp
+++ b/Geo/MPrism.cpp
@@ -39,9 +39,7 @@ void MPrism::getIntegrationPoints(int pOrder, int *npts, IntPt **pts)
 const JacobianBasis* MPrism::getJacobianFuncSpace(int order) const
 {
   if (order == -1) return BasisFactory::getJacobianBasis(getTypeForMSH());
-
-  int tag = ElementType::getTag(TYPE_PRI, order);
-  return tag ? BasisFactory::getJacobianBasis(tag) : NULL;
+  return BasisFactory::getJacobianBasis(FuncSpaceData(this, order));
 }
 
 double MPrism::getInnerRadius()
diff --git a/Geo/MPyramid.cpp b/Geo/MPyramid.cpp
index ea27a2a795fc51cd9fb53ce38f089a77df0886b8..b16f096029444411cacc7480c4ecb73f8e745fb5 100644
--- a/Geo/MPyramid.cpp
+++ b/Geo/MPyramid.cpp
@@ -36,9 +36,7 @@ void MPyramid::getIntegrationPoints(int pOrder, int *npts, IntPt **pts)
 const JacobianBasis* MPyramid::getJacobianFuncSpace(int order) const
 {
   if (order == -1) return BasisFactory::getJacobianBasis(getTypeForMSH());
-
-  int tag = ElementType::getTag(TYPE_PYR, order);
-  return tag ? BasisFactory::getJacobianBasis(tag) : NULL;
+  return BasisFactory::getJacobianBasis(FuncSpaceData(this, order));
 }
 
 MPyramidN::~MPyramidN() {}
diff --git a/Geo/MQuadrangle.cpp b/Geo/MQuadrangle.cpp
index 468fd5306d75ab5a37f7e686ca6ed46b21894230..1e68dda69fd5b6cd2e8997944cadac1517b31e06 100644
--- a/Geo/MQuadrangle.cpp
+++ b/Geo/MQuadrangle.cpp
@@ -19,9 +19,7 @@
 const JacobianBasis* MQuadrangle::getJacobianFuncSpace(int order) const
 {
   if (order == -1) return BasisFactory::getJacobianBasis(getTypeForMSH());
-
-  int tag = ElementType::getTag(TYPE_QUA, order);
-  return tag ? BasisFactory::getJacobianBasis(tag) : NULL;
+  return BasisFactory::getJacobianBasis(FuncSpaceData(this, order));
 }
 
 int MQuadrangleN::getNumEdgesRep(bool curved)
diff --git a/Geo/MTetrahedron.cpp b/Geo/MTetrahedron.cpp
index 9bda9f6b5d1c47673e416e3f08926731252969b3..14fd75c1a6f6483e210046165eafea035ba813c7 100644
--- a/Geo/MTetrahedron.cpp
+++ b/Geo/MTetrahedron.cpp
@@ -103,9 +103,7 @@ void MTetrahedron::xyz2uvw(double xyz[3], double uvw[3]) const
 const JacobianBasis* MTetrahedron::getJacobianFuncSpace(int order) const
 {
   if (order == -1) return BasisFactory::getJacobianBasis(getTypeForMSH());
-
-  int tag = ElementType::getTag(TYPE_TET, order);
-  return tag ? BasisFactory::getJacobianBasis(tag) : NULL;
+  return BasisFactory::getJacobianBasis(FuncSpaceData(this, order));
 }
 
 int MTetrahedron10::getNumEdgesRep(bool curved){
diff --git a/Geo/MTriangle.cpp b/Geo/MTriangle.cpp
index 90ebc5d228c4f93f4d2a99f1e4ae2a37d66032d7..3b5638591b9b58b9acf56cf3c293b8561447ee20 100644
--- a/Geo/MTriangle.cpp
+++ b/Geo/MTriangle.cpp
@@ -117,9 +117,7 @@ void MTriangle::xyz2uvw(double xyz[3], double uvw[3]) const
 const JacobianBasis* MTriangle::getJacobianFuncSpace(int order) const
 {
   if (order == -1) return BasisFactory::getJacobianBasis(getTypeForMSH());
-
-  int tag = ElementType::getTag(TYPE_TRI, order);
-  return tag ? BasisFactory::getJacobianBasis(tag) : NULL;
+  return BasisFactory::getJacobianBasis(FuncSpaceData(this, order));
 }
 
 int MTriangleN::getNumEdgesRep(bool curved) {
diff --git a/Mesh/CMakeLists.txt b/Mesh/CMakeLists.txt
index aba1b46fb2b466d6f1271679ec1fd49746ab62d3..7cf93c40fc481880ba36b735f5e78906e95d157d 100644
--- a/Mesh/CMakeLists.txt
+++ b/Mesh/CMakeLists.txt
@@ -30,7 +30,7 @@ meshGRegionRelocateVertex.cpp
     BackgroundMeshManager.cpp 
     pointInsertionRTreeTools.cpp 
     pointInsertion.cpp 
-    qualityMeasures.cpp 
+    qualityMeasures.cpp qualityMeasuresJacobian.cpp
     BoundaryLayers.cpp 
     BDS.cpp 
     HighOrder.cpp 
diff --git a/Mesh/qualityMeasuresJacobian.cpp b/Mesh/qualityMeasuresJacobian.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e0978976583ba6a259835388cd3beac928f7779c
--- /dev/null
+++ b/Mesh/qualityMeasuresJacobian.cpp
@@ -0,0 +1,361 @@
+// Gmsh - Copyright (C) 1997-2015 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to the public mailing list <gmsh@geuz.org>.
+
+#include "qualityMeasuresJacobian.h"
+#include "MElement.h"
+#include "BasisFactory.h"
+#include "bezierBasis.h"
+#include "JacobianBasis.h"
+
+
+namespace jacobianBasedQuality {
+
+bool _lessMinB::operator()(_CoeffData *cd1, _CoeffData *cd2) const
+{
+  return cd1->minB() > cd2->minB();
+}
+
+bool _lessMaxB::operator()(_CoeffData *cd1, _CoeffData *cd2) const
+{
+  return cd1->maxB() < cd2->maxB();
+}
+
+_CoeffDataJac::_CoeffDataJac(fullVector<double> &v,
+                           const bezierBasis *bfs,
+                           int depth)
+: _CoeffData(depth), _coeffs(v.getDataPtr(), v.size()), _bfs(bfs)
+{
+  if (!v.getOwnData()) {
+    Msg::Fatal("Cannot create an instance of _CoeffDataJac from a "
+               "fullVector that does not own its data.");
+  }
+  // _coeffs reuses the data of v, this avoid to allocate a new array and to
+  // copy data that are not used outside of this object.
+  // It remains to swap ownership:
+  v.setOwnData(false);
+  ((fullVector<double>)_coeffs).setOwnData(true);
+
+  _minL = _maxL = v(0);
+  int i = 1;
+  for (; i < bfs->getNumLagCoeff(); i++) {
+    _minL = std::min(_minL, v(i));
+    _maxL = std::max(_maxL, v(i));
+  }
+  _minB = _minL;
+  _maxB = _maxL;
+  for (; i < v.size(); i++) {
+    _minB = std::min(_minB, v(i));
+    _maxB = std::max(_maxB, v(i));
+  }
+}
+
+bool _CoeffDataJac::boundsOk(double minL, double maxL) const
+{
+  double tol = std::max(std::abs(minL), std::abs(maxL)) * 1e-3;
+  return (minL <= 0 || _minB > 0) &&
+         minL - _minB < tol &&
+         _maxB - maxL < tol;
+}
+
+void _CoeffDataJac::getSubCoeff(std::vector<_CoeffData*> &v) const
+{
+  v.clear();
+  v.reserve(_bfs->getNumDivision());
+  fullVector<double> subCoeff;
+  _bfs->subdivideBezCoeff(_coeffs, subCoeff);
+
+  int sz = _coeffs.size();
+  for (int i = 0; i < _bfs->getNumDivision(); i++) {
+    fullVector<double> coeff(sz);
+    coeff.copy(subCoeff, i * sz, sz, 0);
+    _CoeffDataJac *newData = new _CoeffDataJac(coeff, _bfs, _depth+1);
+    v.push_back(newData);
+  }
+}
+
+_CoeffDataScaledJac::_CoeffDataScaledJac(fullVector<double> &det,
+                                         fullMatrix<double> &mat,
+                                         const bezierBasis *bfsDet,
+                                         const bezierBasis *bfsMat,
+                                         int depth)
+: _CoeffData(depth), _coeffsJacDet(det.getDataPtr(), det.size()),
+  _coeffsJacMat(mat.getDataPtr(), mat.size1(), mat.size2()),
+  _bfsDet(bfsDet), _bfsMat(bfsMat)
+{
+  if (!det.getOwnData() || !mat.getOwnData()) {
+    Msg::Fatal("Cannot create an instance of _CoeffDataScaledJac from a "
+               "fullVector or a fullMatrix that does not own its data.");
+  }
+  // _coeffsJacDet and _coeffsJacMat reuse data, this avoid to allocate new
+  // arrays and to copy data that are not used outside of this object.
+  // It remains to swap ownerships:
+  det.setOwnData(false);
+  mat.setOwnData(false);
+  const fullVector<double> *p1 = &_coeffsJacDet;
+  const fullMatrix<double> *p2 = &_coeffsJacMat;
+  ((fullVector<double>*)p1)->setOwnData(true);
+  ((fullMatrix<double>*)p2)->setOwnData(true);
+
+  _computeAtCorner(_minL, _maxL);
+  _minB = _computeLowerBound();
+  // computation of _maxB not implemented for now
+}
+
+void _CoeffDataScaledJac::_computeAtCorner(double &min, double &max) const
+{
+  min = std::numeric_limits<double>::infinity();
+  max = -min;
+
+  for (int i = 0; i < _bfsDet->getNumLagCoeff(); i++) {
+    double den = 1;
+    for (int j = 0; j < _coeffsJacMat.size2()/3; ++j) {
+      den *= std::sqrt(_coeffsJacMat(0+3*j, i) * _coeffsJacMat(0+3*j, i)+
+                       _coeffsJacMat(1+3*j, i) * _coeffsJacMat(1+3*j, i)+
+                       _coeffsJacMat(2+3*j, i) * _coeffsJacMat(2+3*j, i));
+    }
+    min = std::min(min, _coeffsJacDet(i) / den);
+    max = std::max(max, _coeffsJacDet(i) / den);
+  }
+}
+
+double _CoeffDataScaledJac::_computeLowerBound() const
+{
+  fullVector<double> coeffNumerator;
+  _bfsDet->getRaiser()->reorder(_coeffsJacDet, coeffNumerator);
+
+  fullVector<double> coeffDenominator;
+  {
+    fullVector<double> v[3];
+    for (int i = 0; i < _coeffsJacMat.size2()/3; ++i) {
+      v[i].resize(_coeffsJacMat.size1());
+      for (int j = 0; j < _coeffsJacMat.size1(); ++j) {
+        v[i](j) = std::sqrt(_coeffsJacMat(j, 0+3*i) * _coeffsJacMat(j, 0+3*i)+
+                            _coeffsJacMat(j, 1+3*i) * _coeffsJacMat(j, 1+3*i)+
+                            _coeffsJacMat(j, 2+3*i) * _coeffsJacMat(j, 2+3*i));
+      }
+    }
+    if (_coeffsJacMat.size2()/3 == 3) {
+      _bfsMat->getRaiser()->computeCoeff(v[0], v[1], v[2], coeffDenominator);
+    }
+    else {
+      _bfsMat->getRaiser()->computeCoeff(v[0], v[1], coeffDenominator);
+    }
+  }
+
+  return _computeBoundRational(coeffNumerator, coeffDenominator, true);
+}
+
+bool _CoeffDataScaledJac::boundsOk(double minL, double maxL) const
+{
+  double tol = 1e-3;
+  return minL - _minB < tol;
+}
+
+void _CoeffDataScaledJac::getSubCoeff(std::vector<_CoeffData*> &v) const
+{
+  v.clear();
+  v.reserve(_bfsDet->getNumDivision());
+  fullVector<double> subCoeffD;
+  fullMatrix<double> subCoeffM;
+  _bfsDet->subdivideBezCoeff(_coeffsJacDet, subCoeffD);
+  _bfsMat->subdivideBezCoeff(_coeffsJacMat, subCoeffM);
+
+  int szD = _coeffsJacDet.size();
+  int szM1 = _coeffsJacMat.size1();
+  int szM2 = _coeffsJacMat.size2();
+  for (int i = 0; i < _bfsDet->getNumDivision(); i++) {
+    fullVector<double> coeffD(szD);
+    fullMatrix<double> coeffM(szM1, szM2);
+    coeffD.copy(subCoeffD, i * szD, szD, 0);
+    coeffM.copy(subCoeffM, i * szM1, szM1, 0, szM2, 0, 0);
+    _CoeffDataScaledJac *newData;
+    newData = new _CoeffDataScaledJac(coeffD, coeffM, _bfsDet, _bfsMat, _depth+1);
+    v.push_back(newData);
+  }
+}
+
+template<typename Comp>
+void _subdivideDomainsMinOrMax(std::vector<_CoeffData*> &domains,
+                               double &minL,
+                               double &maxL)
+{
+  std::vector<_CoeffData*> subs;
+  make_heap(domains.begin(), domains.end(), Comp());
+  while (!domains[0]->boundsOk(minL, maxL)) {
+    _CoeffData *cd = domains[0];
+    pop_heap(domains.begin(), domains.end(), Comp());
+    domains.pop_back();
+    cd->getSubCoeff(subs);
+    delete cd;
+
+    for (unsigned int i = 0; i < subs.size(); i++) {
+      minL = std::min(minL, subs[i]->minL());
+      maxL = std::max(maxL, subs[i]->maxL());
+      domains.push_back(subs[i]);
+      push_heap(domains.begin(), domains.end(), Comp());
+    }
+  }
+}
+
+void _subdivideDomains(std::vector<_CoeffData*> &domains)
+{
+  if (domains.empty()) {
+    Msg::Warning("empty vector in Bezier subdivision, nothing to do");
+    return;
+  }
+  double minL = domains[0]->minL();
+  double maxL = domains[0]->maxL();
+  for (unsigned int i = 1; i < domains.size(); ++i) {
+    minL = std::min(minL, domains[i]->minL());
+    maxL = std::max(maxL, domains[i]->maxL());
+  }
+
+  _subdivideDomainsMinOrMax<_lessMinB>(domains, minL, maxL);
+  _subdivideDomainsMinOrMax<_lessMaxB>(domains, minL, maxL);
+}
+
+void minMaxJacobianDeterminant(MElement *el, double &min, double &max)
+{
+  const JacobianBasis *jfs = el->getJacobianFuncSpace();
+  if (!jfs) {
+    Msg::Error("Jacobian function space not implemented for type of element %d", el->getTypeForMSH());
+    return;
+  }
+
+  fullMatrix<double> nodesXYZ(jfs->getNumMapNodes(), 3);
+  el->getNodesCoord(nodesXYZ);
+
+  fullVector<double> coeffLag(jfs->getNumJacNodes());
+  fullVector<double> coeffBez(jfs->getNumJacNodes());
+  jfs->getSignedJacobian(nodesXYZ, coeffLag);
+  jfs->lag2Bez(coeffLag, coeffBez);
+
+  std::vector<_CoeffData*> domains;
+  domains.push_back(new _CoeffDataJac(coeffBez, jfs->getBezier(), 0));
+
+  _subdivideDomains(domains);
+
+  min = domains[0]->minB();
+  max = domains[0]->maxB();
+  delete domains[0];
+  for (unsigned int i = 1; i < domains.size(); ++i) {
+    min = std::min(min, domains[i]->minB());
+    max = std::max(max, domains[i]->maxB());
+    delete domains[i];
+  }
+}
+
+void minScaledJacobian(MElement *el, double &min)
+{
+  const int jacOrder = el->getPolynomialOrder() * el->getDim();
+  const JacobianBasis *jfs = el->getJacobianFuncSpace(jacOrder);
+  if (!jfs) {
+    Msg::Error("Jacobian function space not implemented for type of element %d", el->getTypeForMSH());
+    return;
+  }
+
+  fullMatrix<double> nodesXYZ(jfs->getNumMapNodes(), 3);
+  el->getNodesCoord(nodesXYZ);
+
+  fullVector<double> coeffDetLag(jfs->getNumJacNodes());
+  fullVector<double> coeffDetBez(jfs->getNumJacNodes());
+  jfs->getSignedJacobian(nodesXYZ, coeffDetLag);
+  jfs->lag2Bez(coeffDetLag, coeffDetBez);
+
+  const GradientBasis *gfs = BasisFactory::getGradientBasis(el->getTypeForMSH());
+
+  fullMatrix<double> coeffMatLag(gfs->getNumSamplingPoints(), 9);
+  fullMatrix<double> coeffMatBez(gfs->getNumSamplingPoints(), 9);
+  gfs->getAllGradientsFromNodes(nodesXYZ, coeffMatLag);
+  gfs->lag2Bez(coeffMatLag, coeffMatBez);
+
+  if (el->getDim() == 2) coeffMatBez.resize(coeffMatBez.size1(), 6);
+
+  std::vector<_CoeffData*> domains;
+  domains.push_back(
+      new _CoeffDataScaledJac(coeffDetBez, coeffMatBez, jfs->getBezier(),
+                             gfs->getBezier(), 0)
+  );
+
+  _subdivideDomains(domains);
+
+  min = domains[0]->minB();
+  delete domains[0];
+  for (unsigned int i = 1; i < domains.size(); ++i) {
+    min = std::min(min, domains[i]->minB());
+    delete domains[i];
+  }
+
+  Msg::Info("=====================================================min %g", min);
+}
+
+double minScaledJacobian(MElement *el)
+{
+  double min;
+  minScaledJacobian(el, min);
+  return min;
+}
+
+double _computeBoundRational(const fullVector<double> &numerator,
+                             const fullVector<double> &denominator,
+                             bool lower, bool positiveDenom)
+{
+  //sleep(1);
+  //numerator.print("numerator");
+  //denominator.print("denominator");
+  if (numerator.size() != denominator.size()) {
+    Msg::Error("In order to compute a bound on a rational function, I need "
+               "vectors of the same size!");
+    return 0;
+  }
+
+  // upper and lower bound of the desired bound:
+  const double inf = std::numeric_limits<double>::infinity();
+  double upperBound = inf;
+  double lowerBound = -inf;
+
+  if (!positiveDenom) {
+    lower = lower ? false : true;
+  }
+
+  if (lower) {
+    // if lower is true, we seek: bound * den <= num
+    for (int i = 0; i < numerator.size(); ++i) {
+      if (denominator(i) == 0) {
+        if (numerator(i) < 0) return -inf;
+      }
+      else if (denominator(i) > 0) {
+        upperBound = std::min(upperBound, numerator(i)/denominator(i));
+      }
+      else {
+        lowerBound = std::max(lowerBound, numerator(i)/denominator(i));
+      }
+    }
+    if (lowerBound > upperBound)
+      return -inf;
+    else
+      return upperBound;
+  }
+  else {
+    // otherwise, we seek: bound * den >= num
+    for (int i = 0; i < numerator.size(); ++i) {
+      if (denominator(i) == 0) {
+        if (numerator(i) > 0) return inf;
+      }
+      else if (denominator(i) > 0) {
+        lowerBound = std::max(lowerBound, numerator(i)/denominator(i));
+      }
+      else {
+        upperBound = std::min(upperBound, numerator(i)/denominator(i));
+      }
+    }
+    if (lowerBound > upperBound)
+      return inf;
+    else
+      return lowerBound;
+  }
+}
+
+} // end namespace jacobianBasedQuality
diff --git a/Mesh/qualityMeasuresJacobian.h b/Mesh/qualityMeasuresJacobian.h
new file mode 100644
index 0000000000000000000000000000000000000000..242deb31dcd75fd26b33670983b927b2414f4dd9
--- /dev/null
+++ b/Mesh/qualityMeasuresJacobian.h
@@ -0,0 +1,98 @@
+// Gmsh - Copyright (C) 1997-2015 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to the public mailing list <gmsh@geuz.org>.
+
+#ifndef _QUALITY_MEASURES_JACOBIAN_H_
+#define _QUALITY_MEASURES_JACOBIAN_H_
+
+#include <vector>
+#include "fullMatrix.h"
+
+class bezierBasis;
+class MElement;
+
+namespace jacobianBasedQuality {
+
+void minMaxJacobianDeterminant(MElement *el, double &min, double &max);
+void minScaledJacobian(MElement *el, double &min);
+double minScaledJacobian(MElement *el);
+
+class _CoeffData
+{
+protected:
+  double _minL, _maxL; //Extremum of Jac at corners
+  double _minB, _maxB; //Extremum of bezier coefficients
+  int _depth;
+
+public:
+  _CoeffData(int depth) : _minL(0), _maxL(0), _minB(0), _maxB(0),
+                         _depth(depth) {}
+  virtual ~_CoeffData() {}
+
+  //inline int depth() const {return _depthSub;}
+  inline double minL() const {return _minL;}
+  inline double maxL() const {return _maxL;}
+  inline double minB() const {return _minB;}
+  inline double maxB() const {return _maxB;}
+
+  virtual bool boundsOk(double minL, double maxL) const = 0;
+  virtual void getSubCoeff(std::vector<_CoeffData*>&) const = 0;
+};
+
+struct _lessMinB {
+  bool operator()(_CoeffData*, _CoeffData*) const;
+};
+struct _lessMaxB {
+  bool operator()(_CoeffData*, _CoeffData*) const;
+};
+
+class _CoeffDataJac: public _CoeffData
+{
+private:
+  const fullVector<double> _coeffs;
+  const bezierBasis *_bfs;
+
+public:
+  _CoeffDataJac(fullVector<double> &v, const bezierBasis *bfs, int depth);
+  ~_CoeffDataJac() {}
+
+  bool boundsOk(double minL, double maxL) const;
+  void getSubCoeff(std::vector<_CoeffData*>&) const;
+};
+
+class _CoeffDataScaledJac: public _CoeffData
+{
+private:
+  const fullVector<double> _coeffsJacDet;
+  const fullMatrix<double> _coeffsJacMat;
+  const bezierBasis *_bfsDet, *_bfsMat;
+
+public:
+  _CoeffDataScaledJac(fullVector<double> &det,
+                     fullMatrix<double> &mat,
+                     const bezierBasis *bfsDet,
+                     const bezierBasis *bfsMat,
+                     int depth);
+  ~_CoeffDataScaledJac() {}
+
+  bool boundsOk(double minL, double maxL) const;
+  void getSubCoeff(std::vector<_CoeffData*>&) const;
+
+private:
+  void _computeAtCorner(double &min, double &max) const;
+  double _computeLowerBound() const;
+};
+
+//inline bool isValid(MElement *el) {
+//  double min, max;
+//  minMaxJacobianDeterminant(el, min, max);
+//  return min > 0;
+//}
+
+double _computeBoundRational(const fullVector<double> &numerator,
+                             const fullVector<double> &denominator,
+                             bool lower, bool positiveDenom = true);
+}
+
+#endif
diff --git a/Numeric/JacobianBasis.cpp b/Numeric/JacobianBasis.cpp
index 1b3ef74eae642479b08719cb4bbd353acb985141..5978c1916a73cd0d557b3da25214292c504735d1 100644
--- a/Numeric/JacobianBasis.cpp
+++ b/Numeric/JacobianBasis.cpp
@@ -6,6 +6,7 @@
 #include "JacobianBasis.h"
 #include "pointsGenerators.h"
 #include "nodalBasis.h"
+#include "bezierBasis.h"
 #include "BasisFactory.h"
 #include "Numeric.h"
 #include <cmath>
@@ -150,11 +151,11 @@ inline void calcJDJ3D(double dxdX, double dxdY, double dxdZ,
                                     dzdX, dzdY, dzdZ);
 }
 
-}
+} //namespace
 
 GradientBasis::GradientBasis(FuncSpaceData data)
-    : _data(data) {
-
+    : _data(data)
+{
   fullMatrix<double> samplingPoints;
   gmshGeneratePoints(data, samplingPoints);
   const int numSampPnts = samplingPoints.size1();
@@ -183,6 +184,11 @@ GradientBasis::GradientBasis(FuncSpaceData data)
                       gradShapeIdealMatY, gradShapeIdealMatZ);
 }
 
+const bezierBasis* GradientBasis::getBezier() const
+{
+  return BasisFactory::getBezierBasis(_data);
+}
+
 void GradientBasis::getGradientsFromNodes(const fullMatrix<double> &nodes,
                                           fullMatrix<double> *dxyzdX,
                                           fullMatrix<double> *dxyzdY,
@@ -193,6 +199,20 @@ void GradientBasis::getGradientsFromNodes(const fullMatrix<double> &nodes,
   if (dxyzdZ) gradShapeMatZ.mult(nodes, *dxyzdZ);
 }
 
+void GradientBasis::getAllGradientsFromNodes(const fullMatrix<double> &nodes,
+                                             fullMatrix<double> &dxyzdXYZ) const
+{
+  fullMatrix<double> prox;
+  prox.setAsProxy(dxyzdXYZ, 0, 3);
+  gradShapeMatX.mult(nodes, prox);
+
+  prox.setAsProxy(dxyzdXYZ, 3, 3);
+  gradShapeMatY.mult(nodes, prox);
+
+  prox.setAsProxy(dxyzdXYZ, 6, 3);
+  gradShapeMatZ.mult(nodes, prox);
+}
+
 void GradientBasis::getIdealGradientsFromNodes(const fullMatrix<double> &nodes,
                                                fullMatrix<double> *dxyzdX,
                                                fullMatrix<double> *dxyzdY,
@@ -225,8 +245,14 @@ void GradientBasis::mapFromIdealElement(int type, double jac[3][3])
   mapFromIdealElement(type, dxyzdX, dxyzdY, dxyzdZ);
 }
 
+void GradientBasis::lag2Bez(const fullMatrix<double> &lag,
+                            fullMatrix<double> &bez) const
+{
+  getBezier()->matrixLag2Bez.mult(lag,bez);
+}
+
 JacobianBasis::JacobianBasis(FuncSpaceData data)
-    : _bezier(NULL), _data(data), _dim(data.dimension())
+    : _data(data), _dim(data.dimension())
 {
   const int parentType = data.elementType();
   const int primJacobianOrder = jacobianOrder(parentType, 1);
@@ -311,10 +337,7 @@ JacobianBasis::JacobianBasis(FuncSpaceData data)
 
 const bezierBasis* JacobianBasis::getBezier() const
 {
-  if (!_bezier) {
-    const_cast<JacobianBasis*>(this)->_bezier = BasisFactory::getBezierBasis(_data);
-  }
-  return _bezier;
+  return BasisFactory::getBezierBasis(_data);
 }
 
 // Computes (unit) normals to straight line element at barycenter (with norm of gradient as return value)
@@ -444,11 +467,11 @@ void JacobianBasis::getJacobianGeneral(int nJacNodes,
     case 2 : {
       fullMatrix<double> normal(1,3);
       const double invScale = getPrimNormal2D(nodesXYZ, normal, idealNorm);
-      if (invScale == 0) {
-        for (int i = 0; i < nJacNodes; i++) jacobian(i) = 0;
-        return;
-      }
       if (scaling) {
+        if (invScale == 0) {
+          for (int i = 0; i < nJacNodes; i++) jacobian(i) = 0;
+          return;
+        }
         const double scale = 1./invScale;
         normal(0,0) *= scale; normal(0,1) *= scale; normal(0,2) *= scale;               // Faster to scale normal than afterwards
       }
@@ -751,6 +774,18 @@ void JacobianBasis::getMetricMinAndGradients(const fullMatrix<double> &nodesXYZ,
   }
 }
 
+void JacobianBasis::lag2Bez(const fullVector<double> &lag,
+                                   fullVector<double> &bez) const
+{
+  getBezier()->matrixLag2Bez.mult(lag, bez);
+}
+
+void JacobianBasis::lag2Bez(const fullMatrix<double> &lag,
+                                   fullMatrix<double> &bez) const
+{
+  getBezier()->matrixLag2Bez.mult(lag, bez);
+}
+
 // Research purpose (to be removed ?)
 void JacobianBasis::interpolate(const fullVector<double> &jacobian,
                                 const fullMatrix<double> &uvw,
diff --git a/Numeric/JacobianBasis.h b/Numeric/JacobianBasis.h
index 501f7abf39806c0e0f81bb61d4ca1e93e59225d1..d3bc5261acb909d5976759fe47a06f4a9fc4a50d 100644
--- a/Numeric/JacobianBasis.h
+++ b/Numeric/JacobianBasis.h
@@ -8,7 +8,8 @@
 
 #include "fullMatrix.h"
 #include "FuncSpaceData.h"
-#include "bezierBasis.h"
+
+class bezierBasis;
 
 class GradientBasis {
 public:
@@ -23,11 +24,14 @@ public:
 
   int getNumSamplingPoints() const {return gradShapeMatX.size1();}
   int getNumMapNodes() const {return gradShapeMatX.size2();}
+  const bezierBasis* getBezier() const;
 
   void getGradientsFromNodes(const fullMatrix<double> &nodes,
                              fullMatrix<double> *dxyzdX,
                              fullMatrix<double> *dxyzdY,
                              fullMatrix<double> *dxyzdZ) const;
+  void getAllGradientsFromNodes(const fullMatrix<double> &nodes,
+                                fullMatrix<double> &dxyzdXYZ) const;
   void getIdealGradientsFromNodes(const fullMatrix<double> &nodes,
                                   fullMatrix<double> *dxyzdX,
                                   fullMatrix<double> *dxyzdY,
@@ -51,13 +55,13 @@ public:
                                   fullVector<double> &gSVecY,
                                   fullVector<double> &gSVecZ);
   static void mapFromIdealElement(int type, double jac[3][3]);
+
+  void lag2Bez(const fullMatrix<double> &lag, fullMatrix<double> &bez) const;
 };
 
 class JacobianBasis {
 private:
   const GradientBasis *_gradBasis;
-  const bezierBasis *_bezier;
-
   const FuncSpaceData _data;
   const int _dim;
 
@@ -65,7 +69,7 @@ private:
   fullVector<double> primGradShapeBaryX, primGradShapeBaryY, primGradShapeBaryZ;
   fullVector<double> primIdealGradShapeBaryX, primIdealGradShapeBaryY,
                      primIdealGradShapeBaryZ;
-  fullMatrix<double> matrixPrimJac2Jac;                                           // Lifts Lagrange basis of primary Jac. to Lagrange basis of Jac.
+  fullMatrix<double> matrixPrimJac2Jac; // Lifts Lagrange basis of primary Jac. to Lagrange basis of Jac.
 
   int numJacNodes, numPrimJacNodes;
   int numMapNodes, numPrimMapNodes;
@@ -177,16 +181,13 @@ public:
                        nodesXYZ, false, true, jacobian);
   }
 
-  inline void lag2Bez(const fullVector<double> &jac, fullVector<double> &bez) const {
-    getBezier()->matrixLag2Bez.mult(jac,bez);
-  }
-  inline void lag2Bez(const fullMatrix<double> &jac, fullMatrix<double> &bez) const {
-    getBezier()->matrixLag2Bez.mult(jac,bez);
-  }
+  void lag2Bez(const fullVector<double> &lag, fullVector<double> &bez) const;
+  void lag2Bez(const fullMatrix<double> &lag, fullMatrix<double> &bez) const;
   inline void primJac2Jac(const fullVector<double> &primJac, fullVector<double> &jac) const {
     matrixPrimJac2Jac.mult(primJac,jac);
   }
 
+  // Research purpose (to be removed ?)
   void interpolate(const fullVector<double> &jacobian,
                    const fullMatrix<double> &uvw,
                    fullMatrix<double> &result, bool areBezier = false) const;
diff --git a/Numeric/bezierBasis.cpp b/Numeric/bezierBasis.cpp
index 34e916b8082c3171bd3b2a1c7bc44ff1e82042d8..13c2d61c694d724307fe0ad8f0c6d5d33f99b484 100644
--- a/Numeric/bezierBasis.cpp
+++ b/Numeric/bezierBasis.cpp
@@ -4,9 +4,10 @@
 // bugs and problems to the public mailing list <gmsh@onelab.info>.
 
 #include <algorithm>
+#include <vector>
+#include "bezierBasis.h"
 #include "GmshDefines.h"
 #include "GmshMessage.h"
-#include <vector>
 #include "polynomialBasis.h"
 #include "pyramidalBasis.h"
 #include "pointsGenerators.h"
@@ -668,3 +669,286 @@ void bezierBasis::_constructPyr()
   }
   return;
 }
+
+bezierBasisRaiser* bezierBasis::getRaiser() const
+{
+  if (!_raiser) {
+    const_cast<bezierBasis*>(this)->_raiser = new bezierBasisRaiser(this);
+  }
+  return _raiser;
+}
+
+void bezierBasisRaiser::_fillRaiserData()
+{
+  if (_bfs->getType() == TYPE_PYR) {
+    _fillRaiserDataPyr();
+    return;
+  }
+
+  const fullMatrix<double> &expD = _bfs->_exponents;
+  fullMatrix<int> exp(expD.size1(), expD.size2());
+  for (int i = 0; i < expD.size1(); ++i) {
+    for (int j = 0; j < expD.size2(); ++j) {
+      exp(i, j) = static_cast<int>(expD(i, j) + .5);
+    }
+  }
+
+  int order = _bfs->getOrder();
+  int ncoeff = exp.size1();
+  int dim = _bfs->getDim();
+  int dimSimplex = _bfs->getDimSimplex();
+
+  for (int i = 0; i < ncoeff; i++) {
+    int hash = 0;
+    for (int l = 0; l < dim; l++) {
+      hash += exp(i, l) * pow_int(order+1, l);
+    }
+    _raiser1[hash].push_back(_Data(1, i));
+  }
+
+  for (int i = 0; i < ncoeff; i++) {
+    for (int j = 0; j < ncoeff; j++) {
+      double num = 1, den = 1;
+      {
+        int compl1 = order;
+        int compl2 = order;
+        int compltot = 2*order;
+        for (int l = 0; l < dimSimplex; l++) {
+          num *= nChoosek(compl1, exp(i, l))
+               * nChoosek(compl2, exp(j, l));
+          den *= nChoosek(compltot, exp(i, l) + exp(j, l));
+          compl1 -= exp(i, l);
+          compl2 -= exp(j, l);
+          compltot -= exp(i, l) + exp(j, l);
+        }
+        for (int l = dimSimplex; l < dim; l++) {
+          num *= nChoosek(order, exp(i, l))
+               * nChoosek(order, exp(j, l));
+          den *= nChoosek(2*order, exp(i, l) + exp(j, l));
+        }
+      }
+
+      int hash = 0;
+      for (int l = 0; l < dim; l++) {
+        hash += (exp(i, l)+exp(j, l)) * pow_int(2*order+1, l);
+      }
+      _raiser2[hash].push_back(_Data(num/den, i, j));
+    }
+  }
+
+  for (int i = 0; i < ncoeff; i++) {
+    for (int j = 0; j < ncoeff; j++) {
+      for (int k = 0; k < ncoeff; ++k) {
+        double num = 1, den = 1;
+        {
+          int compl1 = order;
+          int compl2 = order;
+          int compl3 = order;
+          int compltot = 3*order;
+          for (int l = 0; l < dimSimplex; l++) {
+            num *= nChoosek(compl1, exp(i, l))
+                 * nChoosek(compl2, exp(j, l))
+                 * nChoosek(compl3, exp(k, l));
+            den *= nChoosek(compltot, exp(i, l) + exp(j, l) + exp(k, l));
+            compl1 -= exp(i, l);
+            compl2 -= exp(j, l);
+            compl3 -= exp(k, l);
+            compltot -= exp(i, l) + exp(j, l) + exp(k, l);
+          }
+          for (int l = dimSimplex; l < dim; l++) {
+            num *= nChoosek(order, exp(i, l))
+                 * nChoosek(order, exp(j, l))
+                 * nChoosek(order, exp(k, l));
+            den *= nChoosek(3*order, exp(i, l) + exp(j, l) + exp(k, l));
+          }
+        }
+
+        int hash = 0;
+        for (int l = 0; l < dim; l++) {
+          hash += (exp(i, l)+exp(j, l)+exp(k, l)) * pow_int(3*order+1, l);
+        }
+        _raiser3[hash].push_back(_Data(num/den, i, j, k));
+      }
+    }
+  }
+}
+
+void bezierBasisRaiser::_fillRaiserDataPyr()
+{
+  FuncSpaceData fsdata = _bfs->getFuncSpaceData();
+  if (fsdata.elementType() != TYPE_PYR) {
+    _fillRaiserData();
+    return;
+  }
+  if (fsdata.isPyramidalSpace()) {
+    Msg::Error("Bezier raiser not implemented for pyramidal space");
+    return;
+  }
+
+  const fullMatrix<double> &expD = _bfs->_exponents;
+  fullMatrix<int> exp(expD.size1(), expD.size2());
+  for (int i = 0; i < expD.size1(); ++i) {
+    for (int j = 0; j < expD.size2(); ++j) {
+      exp(i, j) = static_cast<int>(expD(i, j) + .5);
+    }
+  }
+
+  int ncoeff = exp.size1();
+  int order[3] = {fsdata.nij(), fsdata.nij(), fsdata.nk()};
+
+  for (int i = 0; i < ncoeff; i++) {
+    int hash = 0;
+    for (int l = 0; l < 3; l++) {
+      hash += exp(i, l) * pow_int(order[l]+1, l);
+    }
+    _raiser1[hash].push_back(_Data(1, i));
+  }
+
+  for (int i = 0; i < ncoeff; i++) {
+    for (int j = 0; j < ncoeff; j++) {
+      double num = 1, den = 1;
+      for (int l = 0; l < 3; l++) {
+        num *= nChoosek(order[l], exp(i, l))
+             * nChoosek(order[l], exp(j, l));
+        den *= nChoosek(2*order[l], exp(i, l) + exp(j, l));
+      }
+
+      int hash = 0;
+      for (int l = 0; l < 3; l++) {
+        hash += (exp(i, l)+exp(j, l)) * pow_int(2*order[l]+1, l);
+      }
+      _raiser2[hash].push_back(_Data(num/den, i, j));
+    }
+  }
+
+  for (int i = 0; i < ncoeff; i++) {
+    for (int j = 0; j < ncoeff; j++) {
+      for (int k = 0; k < ncoeff; ++k) {
+        double num = 1, den = 1;
+        for (int l = 0; l < 3; l++) {
+          num *= nChoosek(order[l], exp(i, l))
+               * nChoosek(order[l], exp(j, l))
+               * nChoosek(order[l], exp(k, l));
+          den *= nChoosek(3*order[l], exp(i, l) + exp(j, l) + exp(k, l));
+        }
+
+        int hash = 0;
+        for (int l = 0; l < 3; l++) {
+          hash += (exp(i, l)+exp(j, l)+exp(k, l)) * pow_int(3*order[l]+1, l);
+        }
+        _raiser3[hash].push_back(_Data(num/den, i, j, k));
+      }
+    }
+  }
+}
+
+void bezierBasisRaiser::computeCoeff(const fullVector<double> &coeffA,
+                                     const fullVector<double> &coeffB,
+                                     fullVector<double> &coeffSquare)
+{
+  coeffSquare.resize(_raiser2.size(), true);
+  std::map<int, std::vector<_Data> >::const_iterator it;
+
+  int ind = 0;
+  for (it = _raiser2.begin(); it != _raiser2.end(); ++it, ++ind) {
+    for (unsigned int l = 0; l < it->second.size(); ++l) {
+      const int i = it->second[l].i;
+      const int j = it->second[l].j;
+      coeffSquare(ind) += it->second[l].val * coeffA(i) * coeffB(j);
+    }
+  }
+}
+
+void bezierBasisRaiser::computeCoeff(const fullVector<double> &coeffA,
+                                     const fullVector<double> &coeffB,
+                                     const fullVector<double> &coeffC,
+                                     fullVector<double> &coeffCubic)
+{
+  coeffCubic.resize(_raiser3.size(), true);
+  std::map<int, std::vector<_Data> >::const_iterator it;
+
+  int ind = 0;
+  for (it = _raiser3.begin(); it != _raiser3.end(); ++it, ++ind) {
+    for (unsigned int l = 0; l < it->second.size(); ++l) {
+      const int i = it->second[l].i;
+      const int j = it->second[l].j;
+      const int k = it->second[l].k;
+      coeffCubic(ind) += it->second[l].val * coeffA(i) * coeffB(j) * coeffC(k);
+    }
+  }
+}
+
+void bezierBasisRaiser::computeCoeff(const fullMatrix<double> &coeffA,
+                                     const fullMatrix<double> &coeffB,
+                                     fullMatrix<double> &coeffSquare)
+{
+  coeffSquare.resize(_raiser2.size(), coeffA.size2(), true);
+  std::map<int, std::vector<_Data> >::const_iterator it;
+
+  int ind = 0;
+  for (it = _raiser2.begin(); it != _raiser2.end(); ++it, ++ind) {
+    for (unsigned int l = 0; l < it->second.size(); ++l) {
+      const int i = it->second[l].i;
+      const int j = it->second[l].j;
+      for (int ind2 = 0; ind2 < coeffA.size2(); ++ind2) {
+        coeffSquare(ind, ind2) += it->second[l].val * coeffA(i, ind2)
+                                                    * coeffB(j, ind2);
+      }
+    }
+  }
+}
+
+void bezierBasisRaiser::computeCoeff(const fullMatrix<double> &coeffA,
+                                     const fullMatrix<double> &coeffB,
+                                     const fullMatrix<double> &coeffC,
+                                     fullMatrix<double> &coeffCubic)
+{
+  coeffCubic.resize(_raiser3.size(), coeffA.size2(), true);
+  std::map<int, std::vector<_Data> >::const_iterator it;
+
+  int ind = 0;
+  for (it = _raiser3.begin(); it != _raiser3.end(); ++it, ++ind) {
+    for (unsigned int l = 0; l < it->second.size(); ++l) {
+      const int i = it->second[l].i;
+      const int j = it->second[l].j;
+      const int k = it->second[l].k;
+      for (int ind2 = 0; ind2 < coeffA.size2(); ++ind2) {
+        coeffCubic(ind, ind2) += it->second[l].val * coeffA(i, ind2)
+                                                   * coeffB(j, ind2)
+                                                   * coeffC(k, ind2);
+      }
+    }
+  }
+}
+
+void bezierBasisRaiser::reorder(const fullVector<double> &orig,
+                                fullVector<double> &reordered)
+{
+  reordered.resize(_raiser1.size(), false);
+  std::map<int, std::vector<_Data> >::const_iterator it;
+
+  int ind = 0;
+  for (it = _raiser1.begin(); it != _raiser1.end(); ++it, ++ind) {
+    for (unsigned int l = 0; l < it->second.size(); ++l) {
+      reordered(ind) = orig(it->second[l].i);
+    }
+  }
+}
+
+void bezierBasisRaiser::reorder(const fullMatrix<double> &orig,
+                                fullMatrix<double> &reordered)
+{
+  reordered.resize(_raiser1.size(), orig.size2());
+  std::map<int, std::vector<_Data> >::const_iterator it;
+
+  int ind = 0;
+  for (it = _raiser1.begin(); it != _raiser1.end(); ++it, ++ind) {
+    for (unsigned int l = 0; l < it->second.size(); ++l) {
+      const int i = it->second[l].i;
+      for (int ind2 = 0; ind2 < orig.size2(); ++ind2) {
+        reordered(ind, ind2) = orig(i, ind2);
+      }
+    }
+  }
+}
+
diff --git a/Numeric/bezierBasis.h b/Numeric/bezierBasis.h
index 19ef6a5bdec77babd30fc306750e0d1c038dc330..5495f7a9433b4740021492172b4b52981da8c44d 100644
--- a/Numeric/bezierBasis.h
+++ b/Numeric/bezierBasis.h
@@ -9,19 +9,21 @@
 #include <map>
 #include <vector>
 #include "fullMatrix.h"
-#include "ElementType.h"
 #include "FuncSpaceData.h"
 
 class MElement;
+class bezierBasisRaiser;
 
 class bezierBasis {
  private :
-  // the 'numLagCoeff' first exponents are related to 'Lagrangian' values
+  // the 'numLagCoeff' first exponents are related to 'real' values
   int _numLagCoeff;
   int _numDivisions, _dimSimplex;
   const FuncSpaceData _data;
+  bezierBasisRaiser *_raiser;
 
   friend class MetricBasis;
+  friend class bezierBasisRaiser;
   fullMatrix<double> _exponents;
 
  public :
@@ -30,7 +32,7 @@ class bezierBasis {
   fullMatrix<double> subDivisor;
 
   // Constructors
-  inline bezierBasis(FuncSpaceData data) : _data(data) {
+  inline bezierBasis(FuncSpaceData data) : _data(data), _raiser(NULL) {
     if (_data.elementType() == TYPE_PYR)
       _constructPyr();
     else
@@ -39,11 +41,14 @@ class bezierBasis {
 
   // get methods
   inline int getDim() const {return _exponents.size2();}
+  inline int getType() const {return _data.elementType();}
   inline int getOrder() const {return _data.spaceOrder();}
   inline int getDimSimplex() const {return _dimSimplex;}
   inline int getNumLagCoeff() const {return _numLagCoeff;}
   inline int getNumDivision() const {return _numDivisions;}
   inline int getNumSubNodes() const {return subDivisor.size1();}
+  inline FuncSpaceData getFuncSpaceData() const {return _data;}
+  bezierBasisRaiser* getRaiser() const;
 
   // generate Bezier points
   void generateBezierPoints(fullMatrix<double>&) const;
@@ -81,6 +86,59 @@ class bezierBasis {
   void _FEpoints2BezPoints(fullMatrix<double>&) const;
 };
 
+class bezierBasisRaiser {
+  // Let f, g, h be three function whose Bezier coefficients are given.
+  // This class allows to compute the Bezier coefficients of f*g and f*g*h.
+private :
+  class _Data;
+  std::map<int, std::vector<_Data> > _raiser1, _raiser2, _raiser3;
+  const bezierBasis *_bfs;
+
+  class _Data {
+    friend class bezierBasisRaiser;
+  private:
+    const int i, j, k;
+    const double val;
+  public:
+    _Data(double val, int i, int j = -1, int k = -1) :
+      i(i), j(j), k(k), val(val) {}
+  };
+
+public:
+  bezierBasisRaiser(const bezierBasis *bezier) : _bfs(bezier) {
+    _fillRaiserData();
+  };
+
+  // Warning: Those method return a vector or a matrix of Bezier coefficients
+  // that are not stocked in the same order than what is expected as input.
+  void computeCoeff(const fullVector<double> &coeffA,
+                    const fullVector<double> &coeffB,
+                    fullVector<double> &coeffSquare);
+  void computeCoeff(const fullMatrix<double> &coeffA,
+                    const fullMatrix<double> &coeffB,
+                    fullMatrix<double> &coeffSquare);
+  void computeCoeff(const fullVector<double> &coeffA,
+                    const fullVector<double> &coeffB,
+                    const fullVector<double> &coeffC,
+                    fullVector<double> &coeffCubic);
+  void computeCoeff(const fullMatrix<double> &coeffA,
+                    const fullMatrix<double> &coeffB,
+                    const fullMatrix<double> &coeffC,
+                    fullMatrix<double> &coeffCubic);
+
+  // Method returning a vector/matrix whose coeff are in the order defined in
+  // this class:
+  void reorder(const fullVector<double> &orig,
+               fullVector<double> &reordered);
+  void reorder(const fullMatrix<double> &orig,
+               fullMatrix<double> &reordered);
+
+private:
+  void _fillRaiserData();
+  void _fillRaiserDataPyr();
+};
+
+
 #endif
 
 
diff --git a/Numeric/fullMatrix.h b/Numeric/fullMatrix.h
index bdee20667ed88fa12f12746c38f119685477c559..2bfd6f767caf849a63aa99e29a640dba919a0f19 100644
--- a/Numeric/fullMatrix.h
+++ b/Numeric/fullMatrix.h
@@ -392,6 +392,9 @@ class fullVector
   {
     if(fread (_data, sizeof(scalar), _r, f) != (size_t)_r) return;
   }
+
+  bool getOwnData() const {return _own_data;};
+  void setOwnData(bool ownData) {_own_data = ownData;};
 };
 
 // An abstract interface for dense matrix of scalar
@@ -836,7 +839,7 @@ class fullMatrix
      _data[cind+i] = x(i);
   }
 
-  bool getOwnData() {return _own_data;};
+  bool getOwnData() const {return _own_data;};
   void setOwnData(bool ownData) {_own_data = ownData;};
 };
 #endif