diff --git a/Geo/Geo.cpp b/Geo/Geo.cpp
index 3c02029ca90a6794912af4574ab7ba85d1199bba..ddf640c0d31d4550e56a16b0fd89ba1aa938fabf 100644
--- a/Geo/Geo.cpp
+++ b/Geo/Geo.cpp
@@ -2877,51 +2877,40 @@ void ReplaceAllDuplicates()
   ReplaceDuplicateSurfaces();
 }
 
-
 // Projection of a point on a surface
 
-static Vertex *VERTEX;
-static Curve *CURVE;
-static Surface *SURFACE;
-
-static void projectPS(int N, double x[], double res[])
-{
-  //x[1] = u x[2] = v
-  Vertex du, dv, c;
-  c = InterpolateSurface(SURFACE, x[1], x[2], 0, 0);
-  du = InterpolateSurface(SURFACE, x[1], x[2], 1, 1);
-  dv = InterpolateSurface(SURFACE, x[1], x[2], 1, 2);
-  res[1] =
-    (c.Pos.X - VERTEX->Pos.X) * du.Pos.X +
-    (c.Pos.Y - VERTEX->Pos.Y) * du.Pos.Y +
-    (c.Pos.Z - VERTEX->Pos.Z) * du.Pos.Z;
-  res[2] =
-    (c.Pos.X - VERTEX->Pos.X) * dv.Pos.X +
-    (c.Pos.Y - VERTEX->Pos.Y) * dv.Pos.Y +
-    (c.Pos.Z - VERTEX->Pos.Z) * dv.Pos.Z;
-}
-
-bool ProjectPointOnSurface(Surface *s, Vertex &p, double u[2])
-{
-  double x[3] = { 0.5, u[0], u[1] };
-  int check;
-  SURFACE = s;
-  VERTEX = &p;
-  newt(x, 2, &check, projectPS);
-
-  Vertex vv = InterpolateSurface(s, x[1], x[2], 0, 0);
-  double res[3];
-  projectPS(2, x, res);
-  double resid = sqrt(res[1] * res[1] + res[2] * res[2]);
-
-  p.Pos.X = vv.Pos.X;
-  p.Pos.Y = vv.Pos.Y;
-  p.Pos.Z = vv.Pos.Z;
-  u[0] = x[1];
-  u[1] = x[2];
-  if(resid > 1.e-6)
-    return false;  
-  return true;
+struct PointSurface{
+  Vertex *p;
+  Surface *s;
+};
+
+static void projectPS(Double_Vector &x, Double_Vector &res, void *data)
+{
+  PointSurface *ps = (PointSurface*)data;
+  Vertex c = InterpolateSurface(ps->s, x(0), x(1), 0, 0);
+  Vertex du = InterpolateSurface(ps->s, x(0), x(1), 1, 1);
+  Vertex dv = InterpolateSurface(ps->s, x(0), x(1), 1, 2);
+  res(0) =
+    (c.Pos.X - ps->p->Pos.X) * du.Pos.X +
+    (c.Pos.Y - ps->p->Pos.Y) * du.Pos.Y +
+    (c.Pos.Z - ps->p->Pos.Z) * du.Pos.Z;
+  res(1) =
+    (c.Pos.X - ps->p->Pos.X) * dv.Pos.X +
+    (c.Pos.Y - ps->p->Pos.Y) * dv.Pos.Y +
+    (c.Pos.Z - ps->p->Pos.Z) * dv.Pos.Z;
+}
+
+bool ProjectPointOnSurface(Surface *s, Vertex &p, double uv[2])
+{
+  Double_Vector x(2);
+  x(0) = uv[0];
+  x(1) = uv[1];
+  PointSurface ps = {&p, s};
+  if(newton_fd(projectPS, x, &ps, 1.)){
+    p = InterpolateSurface(s, x(0), x(1), 0, 0);
+    return true;
+  }
+  return false;
 }
 
 // Split line
@@ -3039,25 +3028,19 @@ bool SplitCurve(int line_id, List_T *vertices_id, List_T *shapes)
 
 // Intersect a curve with a surface
 
-static void intersectCS(int N, double x[], double res[])
-{
-  // (x[1], x[2]) = surface params, x[3] = curve param
-  Vertex s = InterpolateSurface(SURFACE, x[1], x[2], 0, 0);
-  Vertex c = InterpolateCurve(CURVE, x[3], 0);
-  res[1] = s.Pos.X - c.Pos.X;
-  res[2] = s.Pos.Y - c.Pos.Y;
-  res[3] = s.Pos.Z - c.Pos.Z;
-}
+struct CurveSurface{
+  Curve *c;
+  Surface *s;
+};
 
-static bool IntersectCurveSurface(Curve *c, Surface *s, double x[4])
+static void intersectCS(Double_Vector &uvt, Double_Vector &res, void *data)
 {
-  int check;
-  SURFACE = s;
-  CURVE = c;
-  newt(x, 3, &check, intersectCS);
-
-  if(check) return false;
-  return true;
+  CurveSurface *cs = (CurveSurface*)data;
+  Vertex vs = InterpolateSurface(cs->s, uvt(0), uvt(1), 0, 0);
+  Vertex vc = InterpolateCurve(cs->c, uvt(2), 0);
+  res(0) = vs.Pos.X - vc.Pos.X;
+  res(1) = vs.Pos.Y - vc.Pos.Y;
+  res(2) = vs.Pos.Z - vc.Pos.Z;
 }
 
 bool IntersectCurvesWithSurface(List_T *curve_ids, int surface_id, List_T *shapes)
@@ -3072,15 +3055,19 @@ bool IntersectCurvesWithSurface(List_T *curve_ids, int surface_id, List_T *shape
     List_Read(curve_ids, i, &curve_id);
     Curve *c = FindCurve((int)curve_id);
     if(c){
-      double x[4] = {0., 0.5, 0.5, 0.5};
-      if(IntersectCurveSurface(c, s, x)){
-        Vertex p = InterpolateCurve(c, x[3], 0);
+      CurveSurface cs = {c, s};
+      Double_Vector uvt(3);
+      uvt(0) = 0.5;
+      uvt(1) = 0.5;
+      uvt(2) = 0.5;
+      if(newton_fd(intersectCS, uvt, &cs, 1.)){
+        Vertex p = InterpolateCurve(c, uvt(2), 0);
         Vertex *v = Create_Vertex(NEWPOINT(), p.Pos.X, p.Pos.Y, p.Pos.Z, p.lc, p.u);
         Tree_Insert(GModel::current()->getGEOInternals()->Points, &v);
-        Shape s;
-        s.Type = MSH_POINT;
-        s.Num = v->Num;
-        List_Add(shapes, &s);
+        Shape sh;
+        sh.Type = MSH_POINT;
+        sh.Num = v->Num;
+        List_Add(shapes, &sh);
       }
     }
     else{
diff --git a/Geo/Geo.h b/Geo/Geo.h
index d210c9b46f6910b3ab69514394f709cab23378a3..c9456c96be64df98c3ae4318ecbff735013c6cb2 100644
--- a/Geo/Geo.h
+++ b/Geo/Geo.h
@@ -275,8 +275,7 @@ void ProtudeXYZ(double &x, double &y, double &z, ExtrudeParams *e);
 
 void ReplaceAllDuplicates();
 
-bool ProjectPointOnCurve(Curve *c, Vertex *v, Vertex *RES, Vertex *DER);
-bool ProjectPointOnSurface(Surface *s, Vertex &p, double u[2]);
+bool ProjectPointOnSurface(Surface *s, Vertex &p, double uv[2]);
 
 bool IntersectCurvesWithSurface(List_T *curve_ids, int surface_id, List_T *shapes);
 bool SplitCurve(int line_id, List_T *vertices_id, List_T *shapes);
diff --git a/Numeric/Numeric.cpp b/Numeric/Numeric.cpp
index 9b293baf9872c148c87ad7dec6c3077d41ddea4d..b130fabf67cadc2c0e72660e27a8f5bd9d8bdcf1 100644
--- a/Numeric/Numeric.cpp
+++ b/Numeric/Numeric.cpp
@@ -36,90 +36,6 @@ int Init_Numeric()
   return 1;
 }
 
-#define MAX_DIM_NEWT 10
-#define MAXITER 100
-#define PREC 1.e-8
-
-static int nrdim;
-static double nru[MAX_DIM_NEWT], nrv[MAX_DIM_NEWT];
-static void (*nrfunc) (int n, double x[], double y[]);
-struct gsl_dummy{ int i; };
-
-static void convert_vector_from_gsl(const gsl_vector * gv, double *v)
-{
-  int i, m;
-  m = gv->size;
-  for(i = 0; i < m; i++) {
-    v[i + 1] = gsl_vector_get(gv, i);
-  }
-}
-
-static void convert_vector_to_gsl(double *v, int n, gsl_vector * gv)
-{
-  int i;
-  for(i = 0; i < n; i++) {
-    gsl_vector_set(gv, i, v[i + 1]);
-  }
-}
-
-static int gslfunc(const gsl_vector * xx, void *params, gsl_vector * f)
-{
-  convert_vector_from_gsl(xx, nru);
-  (*nrfunc) (nrdim, nru, nrv);
-  // Msg::Info("f(%lf,%lf) = %lf %lf\n",nru[1],nru[2],nrv[1],nrv[2]);
-  convert_vector_to_gsl(nrv, nrdim, f);
-  return GSL_SUCCESS;
-}
-
-// Warning: for compatibility with the old newt from NR, x[] and the
-// arguments of func() are indexed from 1 to n...
-void newt(double x[], int n, int *check,
-          void (*func) (int, double[], double[]))
-{
-  const gsl_multiroot_fsolver_type *T;
-  gsl_multiroot_fsolver *s;
-  int status;
-  size_t iter = 0;
-  struct gsl_dummy p = { 1 };
-  gsl_multiroot_function f = { &gslfunc, n, &p };
-  gsl_vector *xx = gsl_vector_alloc(n);
-
-  if(n > MAX_DIM_NEWT - 1)
-    Msg::Fatal("Maximum Newton dimension exceeded\n");
-  nrdim = n;
-
-  nrfunc = func;
-  convert_vector_to_gsl(x, n, xx);
-
-  T = gsl_multiroot_fsolver_hybrid;
-  s = gsl_multiroot_fsolver_alloc(T, n);
-  gsl_multiroot_fsolver_set(s, &f, xx);
-
-  do {
-    iter++;
-    status = gsl_multiroot_fsolver_iterate(s);
-    // Msg::Info("status %d %d %d %lf %lf\n",
-    //     status,n,iter,gsl_vector_get(s->x,0),gsl_vector_get(s->x,1));
-     if(status)
-       break;    // solver problem
-    status = gsl_multiroot_test_residual(s->f, n * PREC);
-  }
-  while(status == GSL_CONTINUE && iter < MAXITER);
-
-  if(status == GSL_CONTINUE) {
-    *check = 1; // problem !!!
-  }
-  else {
-    // Msg::Info("status %d %d %d %lf %lf\n",
-    //     status,n,iter,gsl_vector_get(s->x,0),gsl_vector_get(s->x,1));
-    convert_vector_from_gsl(s->x, x);
-    *check = 0; // converged
-  }
-
-  gsl_multiroot_fsolver_free(s);
-  gsl_vector_free(xx);
-}
-
 static double (*f_statN) (double*, void *data); 
 
 static void (*df_statN) (double*, double*, double &, void *data);
@@ -196,18 +112,6 @@ int Init_Numeric()
   return 1;
 }
 
-double brent(double ax, double bx, double cx,
-             double (*f) (double), double tol, double *xmin)
-{
-  Msg::Error("Gmsh must be compiled with GSL support for brent");
-}
-
-void newt(double x[], int n, int *check,
-          void (*func) (int, double[], double[]))
-{
-  Msg::Error("Gmsh must be compiled with GSL support for newt");
-}
-
 void minimize_N(int N, double (*f) (double*, void *data), 
                 void (*df) (double*, double*, double &, void *data) ,
                 void *data,int niter,
diff --git a/Numeric/Numeric.h b/Numeric/Numeric.h
index aebc115d68282ea09100e8bc33ff1da85e942c89..0348210f6e65af796ba7ee74852fa48970346bb4 100644
--- a/Numeric/Numeric.h
+++ b/Numeric/Numeric.h
@@ -9,8 +9,6 @@
 #include "NumericEmbedded.h"
 
 int Init_Numeric();
-void newt(double x[], int n, int *check,
-          void (*func) (int, double[], double[]));
 void minimize_N(int N, double (*f) (double*, void *data), 
                 void (*df) (double*, double*, double &, void *data),
                 void *data,int niter,
diff --git a/Numeric/NumericEmbedded.cpp b/Numeric/NumericEmbedded.cpp
index c625836a55866847fe6065109536eeb1f6a9c197..219d1167a913e4818084713e32774e560023aaa9 100644
--- a/Numeric/NumericEmbedded.cpp
+++ b/Numeric/NumericEmbedded.cpp
@@ -8,7 +8,6 @@
 // Msg)
 
 #include "NumericEmbedded.h"
-#include "GmshMatrix.h"
 #include "GmshMessage.h"
 
 #define SQU(a)      ((a)*(a))
@@ -435,7 +434,7 @@ void FindCubicRoots(const double coef[4], double real[3], double imag[3])
   real[2] = -term1 + r13*cos((dum1 + 4.0*M_PI)/3.0);
 }
 
-void  eigsort(double d[3])
+void eigsort(double d[3])
 {
   int k, j, i;
   double p;
@@ -487,3 +486,42 @@ void invert_singular_matrix3x3(double MM[3][3], double II[3][3])
     }
   }
 }
+
+bool newton_fd(void (*func)(Double_Vector &, Double_Vector &, void *),
+               Double_Vector &x, void *data, double relax)
+{
+  const double PRECISION = 1.e-6;
+  const int MAXIT = 10;
+  const double EPS = 1.e-4;
+  const int N = x.size();
+  
+  Double_Matrix J(N, N);
+  Double_Vector r(N), rp(N), dx(N);
+  
+  int iter = 1;
+  while (iter < MAXIT){
+    iter++;
+    func(x, r, data);
+
+    for (int j = 0; j < N; j++){
+      double h = EPS * fabs(x(j));
+      if(h == 0.) h = EPS;
+      x(j) += h;
+      func(x, rp, data);
+      for (int i = 0; i < N; i++)
+        J(i, j) = (rp(i) - r(i)) / h;
+      x(j) -= h;
+    }
+    
+    if (N == 1)
+      dx(0) = r(0) / J(0, 0);
+    else
+      J.lu_solve(r, dx);
+    
+    for (int i = 0; i < N; i++)
+      x(i) -= relax * dx(i);
+
+    if(dx.norm() < PRECISION) return true; 
+  }
+  return false;
+}
diff --git a/Numeric/NumericEmbedded.h b/Numeric/NumericEmbedded.h
index ceba0e734ba6f32e3a494f9e511613aa0d64b2d3..fb457310ff5a5dbbc529125ae438de23adc90143 100644
--- a/Numeric/NumericEmbedded.h
+++ b/Numeric/NumericEmbedded.h
@@ -7,6 +7,7 @@
 #define _NUMERIC_EMBEDDED_H_
 
 #include <math.h>
+#include "GmshMatrix.h"
 
 #define myhypot(a,b) (sqrt((a)*(a)+(b)*(b)))
 #define sign(x)      (((x)>=0)?1:-1)
@@ -69,5 +70,7 @@ void gradSimplex(double *x, double *y, double *z, double *v, double *grad);
 double ComputeVonMises(double *val);
 double ComputeScalarRep(int numComp, double *val);
 void invert_singular_matrix3x3(double MM[3][3], double II[3][3]);
-
+bool newton_fd(void (*func)(Double_Vector &, Double_Vector &, void *),
+               Double_Vector &x, void *data, double relax);
+  
 #endif