mò
«jwEc           @   s>   d  k  Z d k l Z d  k Z d „  Z e ƒ  Z d „  Z d  S(   N(   s	   ext_toolsc       	   C   s  t  i d d d ƒ} t i d d d ƒ i t i ƒ }  |  i d } t i
 d d g t i ƒ } | i d } d	 } d } d } d
 } d } d } t  i d | d d d d d d g ƒ } | i | ƒ | i i | ƒ d }	 t i i i |	 ƒ \ } } d }
 } d h  d g  } t i" | ƒ D] } | | q~ d d !<d g  } | D] } | | qH~ d d !<d |	 <} d } t  i d | d d d d g ƒ } | i i | ƒ | i | ƒ t i' d& t i ƒ } d! } d" } t  i d# | d$ g ƒ } | i i | ƒ | i | ƒ | S('   sT   
    Builds an extension module with Bspline basis calculators using
    weave.
    t   _bsplinet   compilert   gcci    i   i   f0.40000000000000002f0.5i   i   s5  
    double *bspline(double **output, double *x, int nx, 
                    double *knots, int nknots,
                    int m, int d, int lower, int upper)
    {                   
       int nbasis;
       int index, i, j, k;
       double *result, *b, *b0, *b1;
       double *f0, *f1;
       double denom;

       nbasis = upper - lower;

       result = *((double **) output);
       f0 = (double *) malloc(sizeof(*f0) * nx);
       f1 = (double *) malloc(sizeof(*f1) * nx);

       if (m == 1) {
           for(i=0; i<nbasis; i++) {
               index = i + lower;

               if(index < nknots - 1) {
                   if ((knots[index] != knots[index+1]) && (d <= 0)) {
                       for (k=0; k<nx; k++) {

                           *result = (double) (x[k] >= knots[index]) * (x[k] < knots[index+1]);
                           result++;
                       }
                   } 
                   else {
                       for (k=0; k<nx; k++) {
                           *result = 0.;
                           result++;
                       }
                   }
                }
                else {
                   for (k=0; k<nx; k++) {
                       *result = 0.;
                       result++;
                   }
               }
            }
        }    
        else {
            b = (double *) malloc(sizeof(*b) * (nbasis+1) * nx);
            bspline(&b, x, nx, knots, nknots, m-1, d-1, lower, upper+1);

            for(i=0; i<nbasis; i++) {
                b0 = b + nx*i;
                b1 = b + nx*(i+1);

                index = i+lower;

                if ((knots[index] != knots[index+m-1]) && (index+m-1 < nknots)) {
                    denom = knots[index+m-1] - knots[index];   
                    if (d <= 0) {
                        for (k=0; k<nx; k++) {
                            f0[k] = (x[k] - knots[index]) / denom;
                        }
                    }
                    else {
                        for (k=0; k<nx; k++) {
                            f0[k] = (m-1) / (knots[index+m-1] - knots[index]);
                        }
                    }
                }
                else {
                    for (k=0; k<nx; k++) {
                        f0[k] = 0.;
                    }
                }

                index = i+lower+1;
                if ((knots[index] != knots[index+m-1]) && (index+m-1 < nknots)) {
                    denom = knots[index+m-1] - knots[index];
                    if (d <= 0) {
                        for (k=0; k<nx; k++) { 
                            f1[k] = (knots[index+m-1] - x[k]) / denom;
                        }
                    }
                    else {
                        for (k=0; k<nx; k++) { 
                            f1[k] = -(m-1) / (knots[index+m-1] - knots[index]);
                        }
                    }
                }  
                else {
                    for (k=0; k<nx; k++) {
                        f1[k] = 0.;
                    }
                }

                for (k=0; k<nx; k++) {
                    *result = f0[k]*(*b0) + f1[k]*(*b1);
                    b0++; b1++; result++;
                }
            }
            free(b);
        }    
        free(f0); free(f1); 
        result = result - nx * nbasis;

        return(result);
    }
    s1  

    int dim[2] = {upper-lower, Nx[0]};
    PyArrayObject *basis;
    double *data;


    basis = (PyArrayObject *) PyArray_SimpleNew(2, dim, PyArray_DOUBLE);
    data = (double *) basis->data;
    bspline(&data, x, Nx[0], knots, Nknots[0], m, d, lower, upper);
    return_val = (PyObject *) basis;

    t   evaluatet   xt   knotst   mt   dt   lowert   upperi   i   sƒ
  

    double *bspline_prod(double *x, int nx, double *knots, int nknots,
                        int m, int l, int r, int dl, int dr) 
    {
        double *result, *bl, *br;
        int k;

        if (fabs(r - l) <= m) {
            result = (double *) malloc(sizeof(*result) * nx);
            bl = (double *) malloc(sizeof(*bl) * nx);
            br = (double *) malloc(sizeof(*br) * nx);

            bl = bspline(&bl, x, nx, knots, nknots, m, dl, l, l+1);
            br = bspline(&br, x, nx, knots, nknots, m, dr, r, r+1);

            for (k=0; k<nx; k++) {
                result[k] = bl[k] * br[k];
            }
            free(bl); free(br);
        }
        else {
            for (k=0; k<nx; k++) {
                result[k] = 0.;
            }
        }    

        return(result);
    }

    
    double bspline_quad(double *knots, int nknots,
                        int m, int l, int r, int dl, int dr) 
        /* This is based on scipy.integrate.fixed_quad */
    {
        double *y;
        double qx[%(nq)d]={%(qx)s};
        double qw[%(nq)d]={%(qw)s};
        double x[%(nq)d];
        int nq=%(nq)d;
        int k, kk;
        int lower, upper;
        double result, a, b, partial;

        result = 0;

	/* TO DO: figure out knot span more efficiently */

        lower = l - m - 1; 
	if (lower < 0) { lower = 0;}
	upper = lower + 2 * m + 4;
	if (upper > nknots - 1) {upper = nknots-1;}
/*	upper = nknots - m; */
        for (k=lower; k<upper; k++) {
            partial = 0.;
            a = knots[k]; b=knots[k+1];
            for (kk=0; kk<nq; kk++) {
               x[kk] = (b - a) * (qx[kk] + 1) / 2. + a;
            }

            y = bspline_prod(x, nq, knots, nknots, m, l, r, dl, dr);

            for (kk=0; kk<nq; kk++) {
                partial += y[kk] * qw[kk];
            }
            result += (b - a) * partial / 2.;
        }

        return(result);
    }    

    void bspline_gram(double **output, double *knots, int nknots,
                        int m, int dl, int dr) 

    /* Presumes that the first m and last m knots are to be ignored, i.e.
    the interior knots are knots[(m+1):-(m+1)] and the boundary knots are
    knots[m] and knots[-m]. In this setting the first basis element of interest
    is the 1st not the 0th. Should maybe be fixed? */

    {
        double *result;
        int l, r, i, j;
        int nbasis;

        nbasis = nknots - m;

        result = *((double **) output);
        for (i=0; i<nbasis; i++) {
	    for (j=0; j<m; j++) {
                l = i;
                r = l+j;
                *result = bspline_quad(knots, nknots, m, l, r, dl, dr);
		result++;
            }
        } 
    }    

    t   qxiÿÿÿÿt   qwt   nqs  

    int dim[2] = {Nknots[0]-m, m};
    double *data;
    PyArrayObject *gram;

    gram = (PyArrayObject *) PyArray_SimpleNew(2, dim, PyArray_DOUBLE);
    data = (double *) gram->data;
    bspline_gram(&data, knots, Nknots[0], m, dl, dr);
    return_val = (PyObject *) gram;

    t   gramt   dlt   dri   i
   sÁ  

    void invband_compute(double **dataptr, double *L, int n, int m) {

        /* Note: m is number of bands not including the diagonal so L is of size (m+1)xn */

        int i,j,k;
        int idx, idy;
	double *data, *odata;
	double diag;

	data = *((double **) dataptr);

	for (i=0; i<n; i++) {
             diag = L[i];
	     data[i] = 1.0 / (diag*diag) ;

	     for (j=0; j<=m; j++) {
                 L[j*n+i] /= diag;
		 if (j > 0) { data[j*n+i] = 0;}
             }
         }

        for (i=n-1; i>=0; i--) {
             for (j=1; j <= (m<n-1-i ? m:n-1-i); j++) {
                  for (k=1; k<=(n-1-i<m ? n-1-i:m); k++) {
                      idx = (j<k ? k-j:j-k); idy = (j<k ? i+j:i+k);
                      data[j*n+i] -= L[k*n+i] * data[idx*n+idy];
                  }
             }

             for (k=1; k<=(n-1-i<m ? n-1-i:m); k++) {
                  data[i] -= L[k*n+i] * data[k*n+i];
             }
        }

    return;
    }
    s-  

    int dim[2] = {NL[0], NL[1]};
    int i, j;
    double *data;
    PyArrayObject *invband;

    invband = (PyArrayObject *) PyArray_SimpleNew(2, dim, PyArray_DOUBLE);
    data = (double *) invband->data;
    invband_compute(&data, L, NL[1], NL[0]-1);

     return_val = (PyObject *) invband;

    t   invbandt   LN(   i   i
   (,   t	   ext_toolst
   ext_modulet   modt   Nt   linspacet   astypet   float64R   t   shapet   nknotst   arrayR   t   nxR   R   R   R	   t	   eval_codet   eval_ext_codet   ext_functiont   bspline_evalt   add_functiont	   customizet   add_support_codeR   t   scipyt   specialt
   orthogonalt   p_rootsR
   R   R   R   t   _[1]t   realt   qt	   gram_codet   gram_ext_codet   bspline_gramt   zerosR   t   invband_support_codet   invband_ext_codeR   (   R   R	   R   R-   R   R*   R   R+   R   R   R   R/   R   R,   R   R   R   R0   R   R   R
   R   R(   R   R   R    (    (    t$   Lib/sandbox/models/bspline_module.pyt   setup_bspline_module   sH     !k	
tc	(	c           C   s   t  i ƒ  d  S(   N(   R   t   compile(    (    (    R1   t   build_bspline_moduleU  s    (	   t   numpyR   t   scipy.weaveR   t   scipy.special.orthogonalR$   R2   R   R4   (   R2   R   R$   R   R4   R   (    (    R1   t   ?   s   			ÿ O	