changeset 5683:be2ec0458410 octave-forge

separate oct files for low level functions
author cdf
date Mon, 25 May 2009 08:04:36 +0000
parents 2c94879b0a84
children e692af2b7645
files extra/nurbs/src/Makefile extra/nurbs/src/basisfun.cc extra/nurbs/src/basisfunder.cc extra/nurbs/src/bspderiv.cc extra/nurbs/src/bspeval.cc extra/nurbs/src/findspan.cc extra/nurbs/src/low_level_functions.cc extra/nurbs/src/low_level_functions.h extra/nurbs/src/nrb_srf_basisfun__.cc extra/nurbs/src/nrb_srf_basisfun_der__.cc
diffstat 10 files changed, 717 insertions(+), 636 deletions(-) [+]
line wrap: on
line diff
--- a/extra/nurbs/src/Makefile	Sun May 24 11:17:26 2009 +0000
+++ b/extra/nurbs/src/Makefile	Mon May 25 08:04:36 2009 +0000
@@ -1,7 +1,13 @@
-all: low_level_functions.oct
+OCTFILES = bspderiv.oct nrb_srf_basisfun_der__.oct\
+basisfun.oct bspeval.oct basisfunder.oct findspan.oct nrb_srf_basisfun__.oct
+
+all: $(OCTFILES)
 
-%.oct: %.cc
-	mkoctfile $<
+low_level_functions.o: low_level_functions.cc
+	mkoctfile -c $<
+
+%.oct:  %.cc low_level_functions.o
+	mkoctfile $< low_level_functions.o
 
 clean:
-	-rm *.o core octave-core *.oct *~
+	-rm -f *.o core octave-core *.oct *~
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extra/nurbs/src/basisfun.cc	Mon May 25 08:04:36 2009 +0000
@@ -0,0 +1,82 @@
+/* Copyright (C) 2009 Carlo de Falco
+  
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+ 
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include <octave/oct.h>
+#include "low_level_functions.h"
+
+DEFUN_DLD(basisfun, args, nargout, "\n\
+ BASISFUN: Compute B-Spline Basis Functions \n\
+\n\
+ INPUT:\n\
+\n\
+   i - knot span  ( from FindSpan() )\n\
+   u - parametric point\n\
+   p - spline degree\n\
+   U - knot sequence\n\
+\n\
+ OUTPUT:\n\
+\n\
+   N - Basis functions vector[p+1]\n\
+\n\
+ Algorithm A2.2 from 'The NURBS BOOK' pg70.\n\
+")
+{
+
+  octave_value_list retval;
+  const NDArray   i = args(0).array_value();
+  const NDArray   u = args(1).array_value();
+  int       p = args(2).idx_type_value();
+  const RowVector U = args(3).row_vector_value();
+  RowVector N(p+1, 0.0);
+  Matrix    B(u.length(), p+1, 0.0);
+  
+  if (!error_state)
+    {
+      for (octave_idx_type ii(0); ii < u.length(); ii++)
+	{
+	  basisfun(int(i(ii)), u(ii), p, U, N);
+	  B.insert(N, ii, 0);
+	}
+      
+      retval(0) = octave_value(B);
+    }
+  return retval;
+} 
+
+/*
+%!shared n, U, p, u, s
+%!test
+%!  n = 3; 
+%!  U = [0 0 0 1/2 1 1 1]; 
+%!  p = 2; 
+%!  u = linspace(0, 1, 10);  
+%!  s = findspan(n, p, u, U); 
+%!  assert (s, [2*ones(1, 5) 3*ones(1, 5)]);
+%!test
+%!  Bref = [1.00000   0.00000   0.00000
+%!          0.60494   0.37037   0.02469
+%!          0.30864   0.59259   0.09877
+%!          0.11111   0.66667   0.22222
+%!          0.01235   0.59259   0.39506
+%!          0.39506   0.59259   0.01235
+%!          0.22222   0.66667   0.11111
+%!          0.09877   0.59259   0.30864
+%!          0.02469   0.37037   0.60494
+%!          0.00000   0.00000   1.00000];
+%!  B = basisfun(s, u, p, U);
+%!  assert (B, Bref, 1e-5);
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extra/nurbs/src/basisfunder.cc	Mon May 25 08:04:36 2009 +0000
@@ -0,0 +1,69 @@
+/* Copyright (C) 2009 Carlo de Falco
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+ 
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include <octave/oct.h>
+#include "low_level_functions.h"
+
+DEFUN_DLD(basisfunder, args, nargout,"\n\
+ BASISFUNDER:  B-Spline Basis function derivatives\n\
+\n\
+ Calling Sequence:\n\
+\n\
+   ders = basisfunder (i, pl, u, k, nd)\n\
+\n\
+    INPUT:\n\
+\n\
+      i   - knot span\n\
+      pl  - degree of curve\n\
+      u   - parametric points\n\
+      k   - knot vector\n\
+      nd  - number of derivatives to compute\n\
+\n\
+    OUTPUT:\n\
+\n\
+      ders - ders(n, i, :) (i-1)-th derivative at n-th point\n\
+")
+{
+  octave_value_list retval;
+
+  const NDArray i = args(0).array_value ();
+  int pl = args(1).int_value ();
+  const NDArray u = args(2).array_value ();
+  const RowVector U = args(3).row_vector_value ();
+  int nd = args(4).int_value ();
+
+  if (!error_state)
+    {
+      if (i.length () != u.length ())
+	print_usage ();
+ 
+      NDArray dersv (dim_vector (i.length (), nd+1, pl+1), 0.0);
+      NDArray ders(dim_vector(nd+1, pl+1), 0.0);
+      for ( octave_idx_type jj(0); jj < i.length (); jj++)
+	{
+	  basisfunder (int (i(jj)), pl, u(jj), U, nd, ders);
+
+	  for (octave_idx_type kk(0); kk < nd+1; kk++)
+	    for (octave_idx_type ll(0); ll < pl+1; ll++)
+	      {
+		dersv(jj, kk, ll) = ders(kk, ll);
+	      }
+	}
+      retval(0) = dersv;
+    }
+  return retval;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extra/nurbs/src/bspderiv.cc	Mon May 25 08:04:36 2009 +0000
@@ -0,0 +1,74 @@
+/* Copyright (C) 2009 Carlo de Falco
+  
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+ 
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include <octave/oct.h>
+#include "low_level_functions.h"
+
+DEFUN_DLD(bspderiv, args, nargout,"\n\
+ BSPDERIV:  B-Spline derivative\n\
+\n\
+\n\
+ Calling Sequence:\n\
+\n\
+          [dc,dk] = bspderiv(d,c,k)\n\
+\n\
+  INPUT:\n\
+ \n\
+    d - degree of the B-Spline\n\
+    c - control points double  matrix(mc,nc)\n\
+    k - knot sequence  double  vector(nk)\n\
+ \n\
+  OUTPUT:\n\
+ \n\
+    dc - control points of the derivative     double  matrix(mc,nc)\n\
+    dk - knot sequence of the derivative      double  vector(nk)\n\
+ \n\
+  Modified version of Algorithm A3.3 from 'The NURBS BOOK' pg98.\n\
+")
+{
+  //if (bspderiv_bad_arguments(args, nargout)) 
+  //  return octave_value_list(); 
+  
+  int       d = args(0).int_value();
+  const Matrix    c = args(1).matrix_value();
+  const RowVector k = args(2).row_vector_value();
+  octave_value_list retval;
+  octave_idx_type mc = c.rows(), nc = c.cols(), nk = k.numel();
+  Matrix dc (mc, nc-1, 0.0);
+  RowVector dk(nk-2, 0.0);
+
+  if (!error_state)
+    {      
+      double tmp;
+      
+      for (octave_idx_type i(0); i<=nc-2; i++)
+	{
+	  tmp = (double)d / (k(i+d+1) - k(i+1));
+	  for ( octave_idx_type j(0); j<=mc-1; j++)
+	    dc(j,i) = tmp*(c(j,i+1) - c(j,i));        
+	}
+      
+      for ( octave_idx_type i(1); i <= nk-2; i++)
+	dk(i-1) = k(i);
+      
+      if (nargout>1)
+	retval(1) = octave_value(dk);
+      retval(0) = octave_value(dc);
+    }
+
+  return(retval);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extra/nurbs/src/bspeval.cc	Mon May 25 08:04:36 2009 +0000
@@ -0,0 +1,117 @@
+/* Copyright (C) 2009 Carlo de Falco
+  
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+ 
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include <octave/oct.h>
+#include "low_level_functions.h"
+
+static bool bspeval_bad_arguments(const octave_value_list& args);
+
+DEFUN_DLD(bspeval, args, nargout,"\
+ BSPEVAL:  Evaluate B-Spline at parametric points\n\
+\n\
+\n\
+ Calling Sequence:\n\
+\n\
+   p = bspeval(d,c,k,u)\n\
+\n\
+    INPUT:\n\
+\n\
+       d - Degree of the B-Spline.\n\
+       c - Control Points, matrix of size (dim,nc).\n\
+       k - Knot sequence, row vector of size nk.\n\
+       u - Parametric evaluation points, row vector of size nu.\n\
+ \n\
+    OUTPUT:\n\
+\n\
+       p - Evaluated points, matrix of size (dim,nu)\n\
+")
+{
+  
+  
+
+  int       d = args(0).int_value();
+  const Matrix    c = args(1).matrix_value();
+  const RowVector k = args(2).row_vector_value();
+  const NDArray   u = args(3).array_value();
+  
+  octave_idx_type nu = u.length();
+  octave_idx_type mc = c.rows(),
+    nc = c.cols();
+
+  Matrix p(mc, nu, 0.0);
+  RowVector N(d+1,0.0);
+
+  octave_value_list retval;
+  if (!error_state)
+    {
+      if (nc + d == k.length() - 1) 
+	{	 
+	  int s, tmp1;
+	  double tmp2;
+	  
+	  for (octave_idx_type col(0); col<nu; col++)
+	    {	
+	      s = findspan(nc-1, d, u(col), k);
+	      basisfun(s, u(col), d, k, N);    
+	      tmp1 = s - d;                
+	      for (octave_idx_type row(0); row<mc; row++)
+		{
+		  double tmp2 = 0.0;
+		  for ( octave_idx_type i(0); i<=d; i++)                   
+		    tmp2 +=  N(i)*c(row,tmp1+i);	  
+		  p(row,col) = tmp2;
+		}             
+	    }   
+	} 
+      else 
+	{
+	  error("inconsistent bspline data, d + columns(c) != length(k) - 1.");
+	}
+    }
+  retval(0) = octave_value(p);
+  return retval;
+} 
+
+static bool bspeval_bad_arguments(const octave_value_list& args) 
+{ 
+  if (args.length() != 4)
+    {
+      error("wrong number of input arguments.");
+      return true;
+    }
+  if (!args(0).is_real_scalar()) 
+    { 
+      error("degree should be a scalar."); 
+      return true; 
+    } 
+  if (!args(1).is_real_matrix()) 
+    { 
+      error("the control net should be a matrix of doubles."); 
+      return true; 
+    } 
+  if (!args(2).is_real_matrix()) 
+    { 
+      error("the knot vector should be a real vector."); 
+      return true; 
+    } 
+  if (!args(3).is_real_type()) 
+    { 
+      error("the set of parametric points should be an array of doubles."); 
+      return true; 
+    } 
+  return false; 
+} 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extra/nurbs/src/findspan.cc	Mon May 25 08:04:36 2009 +0000
@@ -0,0 +1,62 @@
+/* Copyright (C) 2009 Carlo de Falco
+  
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+ 
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include <octave/oct.h>
+#include "low_level_functions.h"
+
+DEFUN_DLD(findspan, args, nargout,"\
+FINDSPAN: Find the span of a B-Spline knot vector at a parametric point\n\
+\n\
+\n\
+Calling Sequence:\n\
+\n\
+   s = findspan(n,p,u,U)\n\
+\n\
+  INPUT:\n\
+\n\
+    n - number of control points - 1\n\
+    p - spline degree\n\
+    u - parametric point\n\
+    U - knot sequence\n\
+\n\
+    U(1) <= u <= U(end)\n\
+  RETURN:\n\
+ \n\
+    s - knot span\n\
+ \n\
+  Algorithm A2.1 from 'The NURBS BOOK' pg68\n\
+")
+{
+
+  octave_value_list retval;
+  int       n = args(0).idx_type_value();
+  int       p = args(1).idx_type_value();
+  const NDArray   u = args(2).array_value();
+  const RowVector U = args(3).row_vector_value();
+  NDArray   s(u);
+
+  if (!error_state)
+    {
+      for (octave_idx_type ii(0); ii < u.length(); ii++)
+	{
+	  s(ii) = findspan(n, p, u(ii), U);
+	}
+      retval(0) = octave_value(s);
+    }
+  return retval;
+} 
+
--- a/extra/nurbs/src/low_level_functions.cc	Sun May 24 11:17:26 2009 +0000
+++ b/extra/nurbs/src/low_level_functions.cc	Mon May 25 08:04:36 2009 +0000
@@ -18,443 +18,10 @@
 */
 
 
-#include <iostream>
 #include <octave/oct.h>
-#include <octave/oct-map.h>
-#include <octave/parse.h>
-
-static int findspan(int n, int p, double u, const RowVector& U);
-static void basisfun(int i, double u, int p, const RowVector& U, RowVector& N);
-static void basisfunder (int i, int pl, double uu, const RowVector& u_knotl, int nders, NDArray& dersv);
-static double factln(int n);
-static double gammaln(double xx);
-static double bincoeff(int n, int k);
-static bool bspeval_bad_arguments(const octave_value_list& args);
-
-// Exported functions:
-// bspeval, bspderiv, findspan, basisfun, nrb_srf_basisfun__, nrb_srf_basisfun_der__
-
-// PKG_ADD: autoload ("basisfunder", "low_level_functions.oct");
-DEFUN_DLD(basisfunder, args, nargout,"\n\
- BASISFUNDER:  B-Spline Basis function derivatives\n\
-\n\
- Calling Sequence:\n\
-\n\
-   ders = basisfunder (i, pl, u, k, nd)\n\
-\n\
-    INPUT:\n\
-\n\
-      i   - knot span\n\
-      pl  - degree of curve\n\
-      u   - parametric points\n\
-      k   - knot vector\n\
-      nd  - number of derivatives to compute\n\
-\n\
-    OUTPUT:\n\
-\n\
-      ders - ders(n, i, :) (i-1)-th derivative at n-th point\n\
-")
-{
-  octave_value_list retval;
-
-  const NDArray i = args(0).array_value ();
-  int pl = args(1).int_value ();
-  const NDArray u = args(2).array_value ();
-  const RowVector U = args(3).row_vector_value ();
-  int nd = args(4).int_value ();
-
-  if (!error_state)
-    {
-      if (i.length () != u.length ())
-	print_usage ();
- 
-      NDArray dersv (dim_vector (i.length (), nd+1, pl+1), 0.0);
-      NDArray ders(dim_vector(nd+1, pl+1), 0.0);
-      for ( octave_idx_type jj(0); jj < i.length (); jj++)
-	{
-	  basisfunder (int (i(jj)), pl, u(jj), U, nd, ders);
-
-	  for (octave_idx_type kk(0); kk < nd+1; kk++)
-	    for (octave_idx_type ll(0); ll < pl+1; ll++)
-	      {
-		dersv(jj, kk, ll) = ders(kk, ll);
-	      }
-	}
-      retval(0) = dersv;
-    }
-  return retval;
-}
-
-
-// PKG_ADD: autoload ("nrb_srf_basisfun_der__", "low_level_functions.oct");
-DEFUN_DLD(nrb_srf_basisfun_der__, args, nargout,"\
- NRB_SRF_BASISFUN_DER__:  Undocumented private function	\
-")
-{
-  //function [Bu, Bv, N] = nrb_srf_basisfun_der__ (points, nrb);
-
-  octave_value_list retval, newargs;
-
-  const NDArray points = args(0).array_value();
-  const Octave_map nrb = args(1).map_value();
-
-  if (!error_state) 
-    {
-      const Cell knots = nrb.contents("knots")(0).cell_value();
-      const NDArray coefs = nrb.contents("coefs")(0).array_value();
-      octave_idx_type m   = (nrb.contents("number")(0).vector_value())(0) - 1; // m    = size (nrb.coefs, 2) -1;
-      octave_idx_type n   = (nrb.contents("number")(0).vector_value())(1) - 1; // n    = size (nrb.coefs, 3) -1;
-      octave_idx_type p = (nrb.contents("order")(0).vector_value())(0) - 1;    // p    = nrb.order(1) -1;
-      octave_idx_type q = (nrb.contents("order")(0).vector_value())(1) - 1;    // q    = nrb.order(2) -1;
-
-      Array<idx_vector> idx(2, idx_vector(':')); 
-      idx(0) = 1;
-      const NDArray u(points.index (idx).squeeze ()); // u = points(1,:);
-      
-      idx(0) = 2;
-      const NDArray v(points.index (idx).squeeze ()); // v = points(2,:);      
-      
-      octave_idx_type npt = u.length (); // npt = length(u);
-
-      RowVector M(p+1, 0.0), N (q+1, 0.0);
-      Matrix Nout(npt, (p+1)*(q+1), 0.0);
-      Matrix Bu(npt, (p+1)*(q+1), 0.0);
-      Matrix Bv(npt, (p+1)*(q+1), 0.0);
-      RowVector Denom(npt, 0.0);
-      RowVector Denom_du(npt, 0.0);
-      RowVector Denom_dv(npt, 0.0);
-      Matrix Num(npt, (p+1)*(q+1), 0.0);
-      Matrix Num_du(npt, (p+1)*(q+1), 0.0);
-      Matrix Num_dv(npt, (p+1)*(q+1), 0.0);
-
-      const RowVector U(knots(0).row_vector_value ()); // U = nrb.knots{1};
-
-      const RowVector V(knots(1).row_vector_value ()); // V = nrb.knots{2};
-      
-      Array<idx_vector> idx2(3, idx_vector(':')); idx2(0) = 4;
-      NDArray w (coefs.index (idx2).squeeze ()); // w = squeeze(nrb.coefs(4,:,:));
-      
-      RowVector spu(u);
-      for (octave_idx_type ii(0); ii < npt; ii++)
-	{
-	  spu(ii) = findspan(m, p, u(ii), U);
-	} // spu  =  findspan (m, p, u, U); 
-
-      newargs(3) = U; newargs(2) = p; newargs(1) = u; newargs(0) = spu;
-      Matrix Ik = feval (std::string("numbasisfun"), newargs, 1)(0).matrix_value (); // Ik = numbasisfun (spu, u, p, U);
-
-      RowVector spv(v);
-      for (octave_idx_type ii(0); ii < v.length(); ii++)
-	{
-	  spv(ii) = findspan(n, q, v(ii), V);
-	} // spv  =  findspan (n, q, v, V);
-
-      newargs(3) = V; newargs(2) = q; newargs(1) = v; newargs(0) = spv;
-      Matrix Jk = feval (std::string("numbasisfun"), newargs, 1)(0).matrix_value (); // Jk = numbasisfun (spv, v, q, V);
-
-      Matrix NuIkuk(npt, p+1, 0.0);
-      for (octave_idx_type ii(0); ii < npt; ii++)
-	{
-	  basisfun (int(spu(ii)), u(ii), p, U, M);
-	  NuIkuk.insert (M, ii, 0);
-	} // NuIkuk = basisfun (spu, u, p, U);
-
-      Matrix NvJkvk(v.length (), q+1, 0.0);
-      for (octave_idx_type ii(0); ii < npt; ii++)
-	{
-	  basisfun(int(spv(ii)), v(ii), q, V, N);
-	  NvJkvk.insert (N, ii, 0);
-	} // NvJkvk = basisfun (spv, v, q, V);
-
-     
-      newargs(4) = 1; newargs(3) = U; newargs(2) = u; newargs(1) = p; newargs(0) = spu;
-      NDArray NuIkukprime = feval (std::string("basisfunder"), newargs, 1)(0).array_value (); //   NuIkukprime = basisfunder (spu, p, u, U, 1);
-                                                                                              //   NuIkukprime = squeeze(NuJkukprime(:,2,:));
-      
-      newargs(4) = 1; newargs(3) = V; newargs(2) = v; newargs(1) = q; newargs(0) = spv;
-      NDArray NvJkvkprime = feval (std::string("basisfunder"), newargs, 1)(0).array_value (); //   NvJkvkprime = basisfunder (spv, q, v, V, 1);
-                                                                                              //   NvJkvkprime = squeeze(NvJkvkprime(:,2,:));
-      
-      for (octave_idx_type k(0); k < npt; k++) 
-	for (octave_idx_type ii(0); ii < p+1; ii++) 
-	  for (octave_idx_type jj(0); jj < q+1; jj++) 
-	    {
-	      Num(k, ii+jj*(p+1)) = NuIkuk(k, ii) * NvJkvk(k, jj) * w(Ik(k, ii), Jk(k, jj));
-	      Denom(k) += Num(k, ii+jj*(p+1));
-
-	      Num_du(k, ii+jj*(p+1)) = NuIkukprime(k, 1, ii) * NvJkvk(k, jj) * w(Ik(k, ii), Jk(k, jj));
-	      Denom_du(k) += Num_du(k, ii+jj*(p+1));
-
-	      Num_dv(k, ii+jj*(p+1)) = NuIkuk(k, ii) * NvJkvkprime(k, 1, jj) * w(Ik(k, ii), Jk(k, jj));
-	      Denom_dv(k) += Num_dv(k, ii+jj*(p+1));
-	    }
-
-      for (octave_idx_type k(0); k < npt; k++) 
-	for (octave_idx_type ii(0); ii < p+1; ii++) 
-	  for (octave_idx_type jj(0); jj < q+1; jj++) 
-	    {
-	      Bu(k, octave_idx_type(ii+(p+1)*jj))  = (Num_du(k, ii+jj*(p+1))/Denom(k) - Denom_du(k)*Num(k, ii+jj*(p+1))/(Denom(k)*Denom(k))); 
-	      Bv(k, octave_idx_type(ii+(p+1)*jj))  = (Num_dv(k, ii+jj*(p+1))/Denom(k) - Denom_dv(k)*Num(k, ii+jj*(p+1))/(Denom(k)*Denom(k))); 
-	      Nout(k, octave_idx_type(ii+(p+1)*jj))= Ik(k, ii)+(m+1)*Jk(k, jj)+1;
-	    }
-
-      //   for k=1:npt
-      //     [Ika, Jkb] = meshgrid(Ik(k, :), Jk(k, :)); 
-      
-      //     N(k, :)    = sub2ind([m+1, n+1], Ika(:)+1, Jkb(:)+1);
-      //     wIkaJkb(1:p+1, 1:q+1) = reshape (w(N(k, :)), p+1, q+1); 
-      
-      //     Num    = (NuIkuk(k, :).' * NvJkvk(k, :)) .* wIkaJkb;
-      //     Num_du = (NuIkukprime(k, :).' * NvJkvk(k, :)) .* wIkaJkb;
-      //     Num_dv = (NuIkuk(k, :).' * NvJkvkprime(k, :)) .* wIkaJkb;
-      //     Denom  = sum(sum(Num));
-      //     Denom_du = sum(sum(Num_du));
-      //     Denom_dv = sum(sum(Num_dv));
-      
-      //     Bu(k, :) = (Num_du/Denom - Denom_du.*Num/Denom.^2)(:).';
-      //     Bv(k, :) = (Num_dv/Denom - Denom_dv.*Num/Denom.^2)(:).';
-      //   end
-      
-
-      retval(2) = Nout;
-      retval(1) = Bv;
-      retval(0) = Bu;
-
-    }
-  return retval;
-}
-
-// PKG_ADD: autoload ("nrb_srf_basisfun__", "low_level_functions.oct");
-DEFUN_DLD(nrb_srf_basisfun__, args, nargout,"\
- NRB_SRF_BASISFUN__:  Undocumented private function\
-")
-{
-
-  octave_value_list retval, newargs;
-
-  const NDArray points = args(0).array_value();
-  const Octave_map nrb = args(1).map_value();
+#include "low_level_functions.h"
 
-  if (!error_state) 
-    {
-
-      const Cell knots = nrb.contents("knots")(0).cell_value();
-      const NDArray coefs = nrb.contents("coefs")(0).array_value();
-      octave_idx_type m   = (nrb.contents("number")(0).vector_value())(0) - 1; // m    = size (nrb.coefs, 2) -1;
-      octave_idx_type n   = (nrb.contents("number")(0).vector_value())(1) - 1; // n    = size (nrb.coefs, 3) -1;
-      octave_idx_type p = (nrb.contents("order")(0).vector_value())(0) - 1;    // p    = nrb.order(1) -1;
-      octave_idx_type q = (nrb.contents("order")(0).vector_value())(1) - 1;    // q    = nrb.order(2) -1;
-
-      Array<idx_vector> idx(2, idx_vector(':')); 
-      idx(0) = 1;
-      const NDArray u(points.index (idx).squeeze ()); // u = points(1,:);
-
-      idx(0) = 2;
-      const NDArray v(points.index (idx).squeeze ()); // v = points(2,:);      
-
-      octave_idx_type npt = u.length (); // npt = length(u);
-      RowVector M(p+1, 0.0), N (q+1, 0.0);
-      Matrix RIkJk(npt, (p+1)*(q+1), 0.0);
-      Matrix indIkJk(npt, (p+1)*(q+1), 0.0);
-      RowVector denom(npt, 0.0);
-
-      const RowVector U(knots(0).row_vector_value ()); // U = nrb.knots{1};
-
-      const RowVector V(knots(1).row_vector_value ()); // V = nrb.knots{2};
-      
-      Array<idx_vector> idx2(3, idx_vector(':')); idx2(0) = 4;
-      NDArray w (coefs.index (idx2).squeeze ()); // w = squeeze(nrb.coefs(4,:,:));
-      
-      RowVector spu(u);
-      for (octave_idx_type ii(0); ii < npt; ii++)
-	{
-	  spu(ii) = findspan(m, p, u(ii), U);
-	} // spu  =  findspan (m, p, u, U); 
-
-      newargs(3) = U; newargs(2) = p; newargs(1) = u; newargs(0) = spu;
-      Matrix Ik = feval (std::string("numbasisfun"), newargs, 1)(0).matrix_value (); // Ik = numbasisfun (spu, u, p, U);
-
-      RowVector spv(v);
-      for (octave_idx_type ii(0); ii < v.length(); ii++)
-	{
-	  spv(ii) = findspan(n, q, v(ii), V);
-	} // spv  =  findspan (n, q, v, V);
-
-      newargs(3) = V; newargs(2) = q; newargs(1) = v; newargs(0) = spv;
-      Matrix Jk = feval (std::string("numbasisfun"), newargs, 1)(0).matrix_value (); // Jk = numbasisfun (spv, v, q, V);
-
-      Matrix NuIkuk(npt, p+1, 0.0);
-      for (octave_idx_type ii(0); ii < npt; ii++)
-	{
-	  basisfun (int(spu(ii)), u(ii), p, U, M);
-	  NuIkuk.insert (M, ii, 0);
-	} // NuIkuk = basisfun (spu, u, p, U);
-
-      Matrix NvJkvk(v.length (), q+1, 0.0);
-      for (octave_idx_type ii(0); ii < npt; ii++)
-	{
-	  basisfun(int(spv(ii)), v(ii), q, V, N);
-	  NvJkvk.insert (N, ii, 0);
-	} // NvJkvk = basisfun (spv, v, q, V);
-
-
-      for (octave_idx_type k(0); k < npt; k++) 
-	for (octave_idx_type ii(0); ii < p+1; ii++) 
-	  for (octave_idx_type jj(0); jj < q+1; jj++) 
-	    denom(k) += NuIkuk(k, ii) * NvJkvk(k, jj) * w(Ik(k, ii), Jk(k, jj));
-
-      
-      for (octave_idx_type k(0); k < npt; k++) 
-	for (octave_idx_type ii(0); ii < p+1; ii++) 
-	  for (octave_idx_type jj(0); jj < q+1; jj++) 
-	    {
-	      RIkJk(k, octave_idx_type(ii+(p+1)*jj))  = NuIkuk(k, ii)*NvJkvk(k, jj) * w(Ik(k, ii), Jk(k, jj))/denom(k); 
-	      indIkJk(k, octave_idx_type(ii+(p+1)*jj))= Ik(k, ii)+(m+1)*Jk(k, jj)+1;
-	    }
-
-      // for k=1:npt
-      //       [Jkb, Ika] = meshgrid(Jk(k, :), Ik(k, :)); 
-      //       indIkJk(k, :)    = sub2ind([m+1, n+1], Ika(:)+1, Jkb(:)+1);
-      //       wIkaJkb(1:p+1, 1:q+1) = reshape (w(indIkJk(k, :)), p+1, q+1); 
-      
-      //       NuIkukaNvJkvk(1:p+1, 1:q+1) = (NuIkuk(k, :).' * NvJkvk(k, :));
-      //       RIkJk(k, :) = (NuIkukaNvJkvk .* wIkaJkb ./ sum(sum(NuIkukaNvJkvk .* wIkaJkb)))(:).';
-      //     end
-      
-      retval(0) = RIkJk; // B = RIkJk;
-      retval(1) = indIkJk; // N = indIkJk;
-
-    }
-  return retval;
-}
-
-
-// PKG_ADD: autoload ("bspeval", "low_level_functions.oct");
-DEFUN_DLD(bspeval, args, nargout,"\
- BSPEVAL:  Evaluate B-Spline at parametric points\n\
-\n\
-\n\
- Calling Sequence:\n\
-\n\
-   p = bspeval(d,c,k,u)\n\
-\n\
-    INPUT:\n\
-\n\
-       d - Degree of the B-Spline.\n\
-       c - Control Points, matrix of size (dim,nc).\n\
-       k - Knot sequence, row vector of size nk.\n\
-       u - Parametric evaluation points, row vector of size nu.\n\
- \n\
-    OUTPUT:\n\
-\n\
-       p - Evaluated points, matrix of size (dim,nu)\n\
-")
-{
-  
-  
-
-  int       d = args(0).int_value();
-  const Matrix    c = args(1).matrix_value();
-  const RowVector k = args(2).row_vector_value();
-  const NDArray   u = args(3).array_value();
-  
-  octave_idx_type nu = u.length();
-  octave_idx_type mc = c.rows(),
-    nc = c.cols();
-
-  Matrix p(mc, nu, 0.0);
-  RowVector N(d+1,0.0);
-
-  octave_value_list retval;
-  if (!error_state)
-    {
-      if (nc + d == k.length() - 1) 
-	{	 
-	  int s, tmp1;
-	  double tmp2;
-	  
-	  for (octave_idx_type col(0); col<nu; col++)
-	    {	
-	      s = findspan(nc-1, d, u(col), k);
-	      basisfun(s, u(col), d, k, N);    
-	      tmp1 = s - d;                
-	      for (octave_idx_type row(0); row<mc; row++)
-		{
-		  double tmp2 = 0.0;
-		  for ( octave_idx_type i(0); i<=d; i++)                   
-		    tmp2 +=  N(i)*c(row,tmp1+i);	  
-		  p(row,col) = tmp2;
-		}             
-	    }   
-	} 
-      else 
-	{
-	  error("inconsistent bspline data, d + columns(c) != length(k) - 1.");
-	}
-    }
-  retval(0) = octave_value(p);
-  return retval;
-} 
-
-
-// PKG_ADD: autoload ("bspderiv", "low_level_functions.oct");
-DEFUN_DLD(bspderiv, args, nargout,"\n\
- BSPDERIV:  B-Spline derivative\n\
-\n\
-\n\
- Calling Sequence:\n\
-\n\
-          [dc,dk] = bspderiv(d,c,k)\n\
-\n\
-  INPUT:\n\
- \n\
-    d - degree of the B-Spline\n\
-    c - control points double  matrix(mc,nc)\n\
-    k - knot sequence  double  vector(nk)\n\
- \n\
-  OUTPUT:\n\
- \n\
-    dc - control points of the derivative     double  matrix(mc,nc)\n\
-    dk - knot sequence of the derivative      double  vector(nk)\n\
- \n\
-  Modified version of Algorithm A3.3 from 'The NURBS BOOK' pg98.\n\
-")
-{
-  //if (bspderiv_bad_arguments(args, nargout)) 
-  //  return octave_value_list(); 
-  
-  int       d = args(0).int_value();
-  const Matrix    c = args(1).matrix_value();
-  const RowVector k = args(2).row_vector_value();
-  octave_value_list retval;
-  octave_idx_type mc = c.rows(), nc = c.cols(), nk = k.numel();
-  Matrix dc (mc, nc-1, 0.0);
-  RowVector dk(nk-2, 0.0);
-
-  if (!error_state)
-    {      
-      double tmp;
-      
-      for (octave_idx_type i(0); i<=nc-2; i++)
-	{
-	  tmp = (double)d / (k(i+d+1) - k(i+1));
-	  for ( octave_idx_type j(0); j<=mc-1; j++)
-	    dc(j,i) = tmp*(c(j,i+1) - c(j,i));        
-	}
-      
-      for ( octave_idx_type i(1); i <= nk-2; i++)
-	dk(i-1) = k(i);
-      
-      if (nargout>1)
-	retval(1) = octave_value(dk);
-      retval(0) = octave_value(dc);
-    }
-
-  return(retval);
-}
-
-
-static int findspan(int n, int p, double u, const RowVector& U)
+int findspan(int n, int p, double u, const RowVector& U)
 
 // Find the knot span of the parametric point u. 
 //
@@ -493,52 +60,10 @@
   return(mid);
 }
 
-// PKG_ADD: autoload ("findspan", "low_level_functions.oct");
-DEFUN_DLD(findspan, args, nargout,"\
-FINDSPAN: Find the span of a B-Spline knot vector at a parametric point\n\
-\n\
-\n\
-Calling Sequence:\n\
-\n\
-   s = findspan(n,p,u,U)\n\
-\n\
-  INPUT:\n\
-\n\
-    n - number of control points - 1\n\
-    p - spline degree\n\
-    u - parametric point\n\
-    U - knot sequence\n\
-\n\
-    U(1) <= u <= U(end)\n\
-  RETURN:\n\
- \n\
-    s - knot span\n\
- \n\
-  Algorithm A2.1 from 'The NURBS BOOK' pg68\n\
-")
-{
-
-  octave_value_list retval;
-  int       n = args(0).idx_type_value();
-  int       p = args(1).idx_type_value();
-  const NDArray   u = args(2).array_value();
-  const RowVector U = args(3).row_vector_value();
-  NDArray   s(u);
-
-  if (!error_state)
-    {
-      for (octave_idx_type ii(0); ii < u.length(); ii++)
-	{
-	  s(ii) = findspan(n, p, u(ii), U);
-	}
-      retval(0) = octave_value(s);
-    }
-  return retval;
-} 
 
 
+void basisfun(int i, double u, int p, const RowVector& U, RowVector& N)
 
-static void basisfun(int i, double u, int p, const RowVector& U, RowVector& N)
 // Basis Function. 
 //
 // INPUT:
@@ -580,128 +105,25 @@
 
 }
 
-// PKG_ADD: autoload ("basisfun", "low_level_functions.oct");
-DEFUN_DLD(basisfun, args, nargout, "\n\
- BASISFUN: Compute B-Spline Basis Functions \n\
-\n\
- INPUT:\n\
-\n\
-   i - knot span  ( from FindSpan() )\n\
-   u - parametric point\n\
-   p - spline degree\n\
-   U - knot sequence\n\
-\n\
- OUTPUT:\n\
-\n\
-   N - Basis functions vector[p+1]\n\
-\n\
- Algorithm A2.2 from 'The NURBS BOOK' pg70.\n\
-")
+
+void basisfunder (int i, int pl, double u, const RowVector& u_knotl, int nders, NDArray& ders)
 {
-
-  octave_value_list retval;
-  const NDArray   i = args(0).array_value();
-  const NDArray   u = args(1).array_value();
-  int       p = args(2).idx_type_value();
-  const RowVector U = args(3).row_vector_value();
-  RowVector N(p+1, 0.0);
-  Matrix    B(u.length(), p+1, 0.0);
   
-  if (!error_state)
-    {
-      for (octave_idx_type ii(0); ii < u.length(); ii++)
-	{
-	  basisfun(int(i(ii)), u(ii), p, U, N);
-	  B.insert(N, ii, 0);
-	}
-      
-      retval(0) = octave_value(B);
-    }
-  return retval;
-} 
+//    BASISFUNDER:  B-Spline Basis function derivatives
+//
+//     INPUT:
+//
+//       i   - knot span
+//       pl  - degree of curve
+//       u   - parametric points
+//       k   - knot vector
+//       nd  - number of derivatives to compute
+//
+//     OUTPUT:
+//
+//       ders - ders(n, i, :) (i-1)-th derivative at n-th point
 
 
-static double gammaln(double xx)
-// Compute logarithm of the gamma function
-// Algorithm from 'Numerical Recipes in C, 2nd Edition' pg214.
-{
-  double x,y,tmp,ser;
-  static double cof[6] = {76.18009172947146,-86.50532032291677,
-                          24.01409824083091,-1.231739572450155,
-                          0.12086650973866179e-2, -0.5395239384953e-5};
-  int j;
-  y = x = xx;
-  tmp = x + 5.5;
-  tmp -= (x+0.5) * log(tmp);
-  ser = 1.000000000190015;
-  for (j=0; j<=5; j++) ser += cof[j]/++y;
-  return -tmp+log(2.5066282746310005*ser/x);
-}
-
-static double factln(int n)
-// computes ln(n!)
-// Numerical Recipes in C
-// Algorithm from 'Numerical Recipes in C, 2nd Edition' pg215.
-{
-  static int ntop = 0;
-  static double a[101];
-  
-  if (n <= 1) return 0.0;
-  while (n > ntop)
-    {
-      ++ntop;
-      a[ntop] = gammaln(ntop+1.0);
-    }
-  return a[n];
-}
-
-static double bincoeff(int n, int k)
-// Computes the binomial coefficient.
-//
-//     ( n )      n!
-//     (   ) = --------   
-//     ( k )   k!(n-k)!
-//
-// Algorithm from 'Numerical Recipes in C, 2nd Edition' pg215.
-{
-  return floor(0.5+exp(factln(n)-factln(k)-factln(n-k)));
-}
-
-
-static bool bspeval_bad_arguments(const octave_value_list& args) 
-{ 
-  if (args.length() != 4)
-    {
-      error("wrong number of input arguments.");
-      return true;
-    }
-  if (!args(0).is_real_scalar()) 
-    { 
-      error("degree should be a scalar."); 
-      return true; 
-    } 
-  if (!args(1).is_real_matrix()) 
-    { 
-      error("the control net should be a matrix of doubles."); 
-      return true; 
-    } 
-  if (!args(2).is_real_matrix()) 
-    { 
-      error("the knot vector should be a real vector."); 
-      return true; 
-    } 
-  if (!args(3).is_real_type()) 
-    { 
-      error("the set of parametric points should be an array of doubles."); 
-      return true; 
-    } 
-  return false; 
-} 
-
-
-static void basisfunder (int i, int pl, double u, const RowVector& u_knotl, int nders, NDArray& ders)
-{
-  
   //     ders = zeros(nders+1,pl+1);
   Matrix ndu(octave_idx_type(pl+1), octave_idx_type(pl+1), 0.0); // ndu = zeros(pl+1,pl+1);
   RowVector left(octave_idx_type(pl+1), 0.0);                    // left = zeros(pl+1);
@@ -793,26 +215,3 @@
 }
 
 
-/*
-%!shared n, U, p, u, s
-%!test
-%!  n = 3; 
-%!  U = [0 0 0 1/2 1 1 1]; 
-%!  p = 2; 
-%!  u = linspace(0, 1, 10);  
-%!  s = findspan(n, p, u, U); 
-%!  assert (s, [2*ones(1, 5) 3*ones(1, 5)]);
-%!test
-%!  Bref = [1.00000   0.00000   0.00000
-%!          0.60494   0.37037   0.02469
-%!          0.30864   0.59259   0.09877
-%!          0.11111   0.66667   0.22222
-%!          0.01235   0.59259   0.39506
-%!          0.39506   0.59259   0.01235
-%!          0.22222   0.66667   0.11111
-%!          0.09877   0.59259   0.30864
-%!          0.02469   0.37037   0.60494
-%!          0.00000   0.00000   1.00000];
-%!  B = basisfun(s, u, p, U);
-%!  assert (B, Bref, 1e-5);
-*/
--- a/extra/nurbs/src/low_level_functions.h	Sun May 24 11:17:26 2009 +0000
+++ b/extra/nurbs/src/low_level_functions.h	Mon May 25 08:04:36 2009 +0000
@@ -15,16 +15,6 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */
 
-static int findspan(int n, int p, double u, 
-		    const RowVector& U);
-
-static void basisfun(int i, double u, int p, 
-		     const RowVector& U, RowVector& N);
-
-static double factln(int n);
-
-static double gammaln(double xx);
-
-static bool bspeval_bad_arguments(const octave_value_list& args);
-
-static double bincoeff(int n, int k);
+int findspan(int n, int p, double u, const RowVector& U);
+void basisfun(int i, double u, int p, const RowVector& U, RowVector& N);
+void basisfunder (int i, int pl, double uu, const RowVector& u_knotl, int nders, NDArray& dersv);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extra/nurbs/src/nrb_srf_basisfun__.cc	Mon May 25 08:04:36 2009 +0000
@@ -0,0 +1,124 @@
+/* Copyright (C) 2009 Carlo de Falco
+  
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+ 
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include <octave/oct.h>
+#include <octave/oct-map.h>
+#include <octave/parse.h>
+#include "low_level_functions.h"
+
+DEFUN_DLD(nrb_srf_basisfun__, args, nargout,"\
+ NRB_SRF_BASISFUN__:  Undocumented private function\
+")
+{
+
+  octave_value_list retval, newargs;
+
+  const NDArray points = args(0).array_value();
+  const Octave_map nrb = args(1).map_value();
+
+  if (!error_state) 
+    {
+
+      const Cell knots = nrb.contents("knots")(0).cell_value();
+      const NDArray coefs = nrb.contents("coefs")(0).array_value();
+      octave_idx_type m   = (nrb.contents("number")(0).vector_value())(0) - 1; // m    = size (nrb.coefs, 2) -1;
+      octave_idx_type n   = (nrb.contents("number")(0).vector_value())(1) - 1; // n    = size (nrb.coefs, 3) -1;
+      octave_idx_type p = (nrb.contents("order")(0).vector_value())(0) - 1;    // p    = nrb.order(1) -1;
+      octave_idx_type q = (nrb.contents("order")(0).vector_value())(1) - 1;    // q    = nrb.order(2) -1;
+
+      Array<idx_vector> idx(2, idx_vector(':')); 
+      idx(0) = 1;
+      const NDArray u(points.index (idx).squeeze ()); // u = points(1,:);
+
+      idx(0) = 2;
+      const NDArray v(points.index (idx).squeeze ()); // v = points(2,:);      
+
+      octave_idx_type npt = u.length (); // npt = length(u);
+      RowVector M(p+1, 0.0), N (q+1, 0.0);
+      Matrix RIkJk(npt, (p+1)*(q+1), 0.0);
+      Matrix indIkJk(npt, (p+1)*(q+1), 0.0);
+      RowVector denom(npt, 0.0);
+
+      const RowVector U(knots(0).row_vector_value ()); // U = nrb.knots{1};
+
+      const RowVector V(knots(1).row_vector_value ()); // V = nrb.knots{2};
+      
+      Array<idx_vector> idx2(3, idx_vector(':')); idx2(0) = 4;
+      NDArray w (coefs.index (idx2).squeeze ()); // w = squeeze(nrb.coefs(4,:,:));
+      
+      RowVector spu(u);
+      for (octave_idx_type ii(0); ii < npt; ii++)
+	{
+	  spu(ii) = findspan(m, p, u(ii), U);
+	} // spu  =  findspan (m, p, u, U); 
+
+      newargs(3) = U; newargs(2) = p; newargs(1) = u; newargs(0) = spu;
+      Matrix Ik = feval (std::string("numbasisfun"), newargs, 1)(0).matrix_value (); // Ik = numbasisfun (spu, u, p, U);
+
+      RowVector spv(v);
+      for (octave_idx_type ii(0); ii < v.length(); ii++)
+	{
+	  spv(ii) = findspan(n, q, v(ii), V);
+	} // spv  =  findspan (n, q, v, V);
+
+      newargs(3) = V; newargs(2) = q; newargs(1) = v; newargs(0) = spv;
+      Matrix Jk = feval (std::string("numbasisfun"), newargs, 1)(0).matrix_value (); // Jk = numbasisfun (spv, v, q, V);
+
+      Matrix NuIkuk(npt, p+1, 0.0);
+      for (octave_idx_type ii(0); ii < npt; ii++)
+	{
+	  basisfun (int(spu(ii)), u(ii), p, U, M);
+	  NuIkuk.insert (M, ii, 0);
+	} // NuIkuk = basisfun (spu, u, p, U);
+
+      Matrix NvJkvk(v.length (), q+1, 0.0);
+      for (octave_idx_type ii(0); ii < npt; ii++)
+	{
+	  basisfun(int(spv(ii)), v(ii), q, V, N);
+	  NvJkvk.insert (N, ii, 0);
+	} // NvJkvk = basisfun (spv, v, q, V);
+
+
+      for (octave_idx_type k(0); k < npt; k++) 
+	for (octave_idx_type ii(0); ii < p+1; ii++) 
+	  for (octave_idx_type jj(0); jj < q+1; jj++) 
+	    denom(k) += NuIkuk(k, ii) * NvJkvk(k, jj) * w(Ik(k, ii), Jk(k, jj));
+
+      
+      for (octave_idx_type k(0); k < npt; k++) 
+	for (octave_idx_type ii(0); ii < p+1; ii++) 
+	  for (octave_idx_type jj(0); jj < q+1; jj++) 
+	    {
+	      RIkJk(k, octave_idx_type(ii+(p+1)*jj))  = NuIkuk(k, ii)*NvJkvk(k, jj) * w(Ik(k, ii), Jk(k, jj))/denom(k); 
+	      indIkJk(k, octave_idx_type(ii+(p+1)*jj))= Ik(k, ii)+(m+1)*Jk(k, jj)+1;
+	    }
+
+      // for k=1:npt
+      //       [Jkb, Ika] = meshgrid(Jk(k, :), Ik(k, :)); 
+      //       indIkJk(k, :)    = sub2ind([m+1, n+1], Ika(:)+1, Jkb(:)+1);
+      //       wIkaJkb(1:p+1, 1:q+1) = reshape (w(indIkJk(k, :)), p+1, q+1); 
+      
+      //       NuIkukaNvJkvk(1:p+1, 1:q+1) = (NuIkuk(k, :).' * NvJkvk(k, :));
+      //       RIkJk(k, :) = (NuIkukaNvJkvk .* wIkaJkb ./ sum(sum(NuIkukaNvJkvk .* wIkaJkb)))(:).';
+      //     end
+      
+      retval(0) = RIkJk; // B = RIkJk;
+      retval(1) = indIkJk; // N = indIkJk;
+
+    }
+  return retval;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extra/nurbs/src/nrb_srf_basisfun_der__.cc	Mon May 25 08:04:36 2009 +0000
@@ -0,0 +1,158 @@
+/* Copyright (C) 2009 Carlo de Falco
+  
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+ 
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include <octave/oct.h>
+#include <octave/oct-map.h>
+#include <octave/parse.h>
+#include "low_level_functions.h"
+
+DEFUN_DLD(nrb_srf_basisfun_der__, args, nargout,"\
+ NRB_SRF_BASISFUN_DER__:  Undocumented private function	\
+")
+{
+  //function [Bu, Bv, N] = nrb_srf_basisfun_der__ (points, nrb);
+
+  octave_value_list retval, newargs;
+
+  const NDArray points = args(0).array_value();
+  const Octave_map nrb = args(1).map_value();
+
+  if (!error_state) 
+    {
+      const Cell knots = nrb.contents("knots")(0).cell_value();
+      const NDArray coefs = nrb.contents("coefs")(0).array_value();
+      octave_idx_type m   = (nrb.contents("number")(0).vector_value())(0) - 1; // m    = size (nrb.coefs, 2) -1;
+      octave_idx_type n   = (nrb.contents("number")(0).vector_value())(1) - 1; // n    = size (nrb.coefs, 3) -1;
+      octave_idx_type p = (nrb.contents("order")(0).vector_value())(0) - 1;    // p    = nrb.order(1) -1;
+      octave_idx_type q = (nrb.contents("order")(0).vector_value())(1) - 1;    // q    = nrb.order(2) -1;
+
+      Array<idx_vector> idx(2, idx_vector(':')); 
+      idx(0) = 1;
+      const NDArray u(points.index (idx).squeeze ()); // u = points(1,:);
+      
+      idx(0) = 2;
+      const NDArray v(points.index (idx).squeeze ()); // v = points(2,:);      
+      
+      octave_idx_type npt = u.length (); // npt = length(u);
+
+      RowVector M(p+1, 0.0), N (q+1, 0.0);
+      Matrix Nout(npt, (p+1)*(q+1), 0.0);
+      Matrix Bu(npt, (p+1)*(q+1), 0.0);
+      Matrix Bv(npt, (p+1)*(q+1), 0.0);
+      RowVector Denom(npt, 0.0);
+      RowVector Denom_du(npt, 0.0);
+      RowVector Denom_dv(npt, 0.0);
+      Matrix Num(npt, (p+1)*(q+1), 0.0);
+      Matrix Num_du(npt, (p+1)*(q+1), 0.0);
+      Matrix Num_dv(npt, (p+1)*(q+1), 0.0);
+
+      const RowVector U(knots(0).row_vector_value ()); // U = nrb.knots{1};
+
+      const RowVector V(knots(1).row_vector_value ()); // V = nrb.knots{2};
+      
+      Array<idx_vector> idx2(3, idx_vector(':')); idx2(0) = 4;
+      NDArray w (coefs.index (idx2).squeeze ()); // w = squeeze(nrb.coefs(4,:,:));
+      
+      RowVector spu(u);
+      for (octave_idx_type ii(0); ii < npt; ii++)
+	{
+	  spu(ii) = findspan(m, p, u(ii), U);
+	} // spu  =  findspan (m, p, u, U); 
+
+      newargs(3) = U; newargs(2) = p; newargs(1) = u; newargs(0) = spu;
+      Matrix Ik = feval (std::string("numbasisfun"), newargs, 1)(0).matrix_value (); // Ik = numbasisfun (spu, u, p, U);
+
+      RowVector spv(v);
+      for (octave_idx_type ii(0); ii < v.length(); ii++)
+	{
+	  spv(ii) = findspan(n, q, v(ii), V);
+	} // spv  =  findspan (n, q, v, V);
+
+      newargs(3) = V; newargs(2) = q; newargs(1) = v; newargs(0) = spv;
+      Matrix Jk = feval (std::string("numbasisfun"), newargs, 1)(0).matrix_value (); // Jk = numbasisfun (spv, v, q, V);
+
+      Matrix NuIkuk(npt, p+1, 0.0);
+      for (octave_idx_type ii(0); ii < npt; ii++)
+	{
+	  basisfun (int(spu(ii)), u(ii), p, U, M);
+	  NuIkuk.insert (M, ii, 0);
+	} // NuIkuk = basisfun (spu, u, p, U);
+
+      Matrix NvJkvk(v.length (), q+1, 0.0);
+      for (octave_idx_type ii(0); ii < npt; ii++)
+	{
+	  basisfun(int(spv(ii)), v(ii), q, V, N);
+	  NvJkvk.insert (N, ii, 0);
+	} // NvJkvk = basisfun (spv, v, q, V);
+
+     
+      newargs(4) = 1; newargs(3) = U; newargs(2) = u; newargs(1) = p; newargs(0) = spu;
+      NDArray NuIkukprime = feval (std::string("basisfunder"), newargs, 1)(0).array_value (); //   NuIkukprime = basisfunder (spu, p, u, U, 1);
+                                                                                              //   NuIkukprime = squeeze(NuJkukprime(:,2,:));
+      
+      newargs(4) = 1; newargs(3) = V; newargs(2) = v; newargs(1) = q; newargs(0) = spv;
+      NDArray NvJkvkprime = feval (std::string("basisfunder"), newargs, 1)(0).array_value (); //   NvJkvkprime = basisfunder (spv, q, v, V, 1);
+                                                                                              //   NvJkvkprime = squeeze(NvJkvkprime(:,2,:));
+      
+      for (octave_idx_type k(0); k < npt; k++) 
+	for (octave_idx_type ii(0); ii < p+1; ii++) 
+	  for (octave_idx_type jj(0); jj < q+1; jj++) 
+	    {
+	      Num(k, ii+jj*(p+1)) = NuIkuk(k, ii) * NvJkvk(k, jj) * w(Ik(k, ii), Jk(k, jj));
+	      Denom(k) += Num(k, ii+jj*(p+1));
+
+	      Num_du(k, ii+jj*(p+1)) = NuIkukprime(k, 1, ii) * NvJkvk(k, jj) * w(Ik(k, ii), Jk(k, jj));
+	      Denom_du(k) += Num_du(k, ii+jj*(p+1));
+
+	      Num_dv(k, ii+jj*(p+1)) = NuIkuk(k, ii) * NvJkvkprime(k, 1, jj) * w(Ik(k, ii), Jk(k, jj));
+	      Denom_dv(k) += Num_dv(k, ii+jj*(p+1));
+	    }
+
+      for (octave_idx_type k(0); k < npt; k++) 
+	for (octave_idx_type ii(0); ii < p+1; ii++) 
+	  for (octave_idx_type jj(0); jj < q+1; jj++) 
+	    {
+	      Bu(k, octave_idx_type(ii+(p+1)*jj))  = (Num_du(k, ii+jj*(p+1))/Denom(k) - Denom_du(k)*Num(k, ii+jj*(p+1))/(Denom(k)*Denom(k))); 
+	      Bv(k, octave_idx_type(ii+(p+1)*jj))  = (Num_dv(k, ii+jj*(p+1))/Denom(k) - Denom_dv(k)*Num(k, ii+jj*(p+1))/(Denom(k)*Denom(k))); 
+	      Nout(k, octave_idx_type(ii+(p+1)*jj))= Ik(k, ii)+(m+1)*Jk(k, jj)+1;
+	    }
+
+      //   for k=1:npt
+      //     [Ika, Jkb] = meshgrid(Ik(k, :), Jk(k, :)); 
+      
+      //     N(k, :)    = sub2ind([m+1, n+1], Ika(:)+1, Jkb(:)+1);
+      //     wIkaJkb(1:p+1, 1:q+1) = reshape (w(N(k, :)), p+1, q+1); 
+      
+      //     Num    = (NuIkuk(k, :).' * NvJkvk(k, :)) .* wIkaJkb;
+      //     Num_du = (NuIkukprime(k, :).' * NvJkvk(k, :)) .* wIkaJkb;
+      //     Num_dv = (NuIkuk(k, :).' * NvJkvkprime(k, :)) .* wIkaJkb;
+      //     Denom  = sum(sum(Num));
+      //     Denom_du = sum(sum(Num_du));
+      //     Denom_dv = sum(sum(Num_dv));
+      
+      //     Bu(k, :) = (Num_du/Denom - Denom_du.*Num/Denom.^2)(:).';
+      //     Bv(k, :) = (Num_dv/Denom - Denom_dv.*Num/Denom.^2)(:).';
+      //   end
+      
+
+      retval(2) = Nout;
+      retval(1) = Bv;
+      retval(0) = Bu;
+
+    }
+  return retval;
+}