[Scipy-svn] r3691 - in trunk/scipy/sparse: . sparsetools tests

scipy-svn at scipy.org scipy-svn at scipy.org
Thu Dec 20 14:22:31 EST 2007


Author: wnbell
Date: 2007-12-20 13:22:18 -0600 (Thu, 20 Dec 2007)
New Revision: 3691

Added:
   trunk/scipy/sparse/sparsetools/fixed_size.h
Modified:
   trunk/scipy/sparse/__init__.py
   trunk/scipy/sparse/base.py
   trunk/scipy/sparse/compressed.py
   trunk/scipy/sparse/coo.py
   trunk/scipy/sparse/csc.py
   trunk/scipy/sparse/csr.py
   trunk/scipy/sparse/data.py
   trunk/scipy/sparse/dia.py
   trunk/scipy/sparse/sparsetools/sparsetools.h
   trunk/scipy/sparse/sparsetools/sparsetools.i
   trunk/scipy/sparse/sparsetools/sparsetools.py
   trunk/scipy/sparse/sparsetools/sparsetools_wrap.cxx
   trunk/scipy/sparse/tests/test_base.py
Log:
separated coo_tocsr() and csr_sum_duplicates()
added special repr for dia_matrix
working towards block CSR/CSC


Modified: trunk/scipy/sparse/__init__.py
===================================================================
--- trunk/scipy/sparse/__init__.py	2007-12-20 09:16:26 UTC (rev 3690)
+++ trunk/scipy/sparse/__init__.py	2007-12-20 19:22:18 UTC (rev 3691)
@@ -9,6 +9,8 @@
 from dok import *
 from coo import *
 from dia import *
+#from bsr import *
+#from bsc import *
 
 from construct import *
 from spfuncs import *

Modified: trunk/scipy/sparse/base.py
===================================================================
--- trunk/scipy/sparse/base.py	2007-12-20 09:16:26 UTC (rev 3690)
+++ trunk/scipy/sparse/base.py	2007-12-20 19:22:18 UTC (rev 3691)
@@ -407,6 +407,12 @@
     def todia(self):
         return self.tocoo().todia()
     
+#    def tobsr(self,blocksize=None):
+#        return self.tocoo().tobsr(blocksize=blocksize)
+#    
+#    def tobsc(self,blocksize=None):
+#        return self.tocoo().tobsc(blocksize=blocksize)
+
     def copy(self):
         return self.__class__(self,copy=True)
 

Modified: trunk/scipy/sparse/compressed.py
===================================================================
--- trunk/scipy/sparse/compressed.py	2007-12-20 09:16:26 UTC (rev 3690)
+++ trunk/scipy/sparse/compressed.py	2007-12-20 19:22:18 UTC (rev 3691)
@@ -42,7 +42,7 @@
             if arg1.format == self.format and copy:
                 arg1 = arg1.copy()
             else:
-                arg1 = getattr(arg1,'to' + self.format)()
+                arg1 = arg1.asformat(self.format)
             self._set_self( arg1 )
 
         elif isinstance(arg1, tuple):
@@ -121,6 +121,7 @@
                     False - basic check, O(1) operations
 
         """
+        #TODO does spmatrix take care of this?
         self.shape = tuple([int(x) for x in self.shape])  # for floats etc.
 
         #use _swap to determine proper bounds
@@ -446,6 +447,18 @@
 
     
     # methods that modify the internal data structure
+    def sum_duplicates(self):
+        """Eliminate duplicate matrix entries by adding them together
+
+        The is an *in place* operation
+        """
+        fn = getattr(sparsetools,self.format + '_sum_duplicates')
+
+        M,N = self.shape
+        fn( M, N, self.indptr, self.indices, self.data)
+
+        self.prune() #nnz may have changed
+
     def sorted_indices(self):
         """Return a copy of this matrix with sorted indices
         """

Modified: trunk/scipy/sparse/coo.py
===================================================================
--- trunk/scipy/sparse/coo.py	2007-12-20 09:16:26 UTC (rev 3690)
+++ trunk/scipy/sparse/coo.py	2007-12-20 19:22:18 UTC (rev 3691)
@@ -6,13 +6,15 @@
 from warnings import warn 
 
 from numpy import array, asarray, empty, intc, zeros, bincount, \
-        unique, searchsorted, atleast_2d
+        unique, searchsorted, atleast_2d, lexsort, cumsum, concatenate, \
+        empty_like, arange
 
 from sparsetools import coo_tocsr, coo_tocsc
-from base import spmatrix, isspmatrix
+from base import isspmatrix
+from data import _data_matrix
 from sputils import upcast, to_native, isshape, getdtype
 
-class coo_matrix(spmatrix):
+class coo_matrix(_data_matrix):
     """A sparse matrix in COOrdinate format.
     Also known as the 'ijv' or 'triplet' format.
 
@@ -76,7 +78,7 @@
     """
 
     def __init__(self, arg1, shape=None, dtype=None, copy=False, dims=None):
-        spmatrix.__init__(self)
+        _data_matrix.__init__(self)
 
         if dims is not None:
             warn("dims is deprecated, use shape instead", DeprecationWarning)
@@ -154,11 +156,6 @@
 
         self._check()
 
-    def _get_dtype(self):
-        return self.data.dtype
-    def _set_dtype(self,newtype):
-        self.data.dtype = newtype
-    dtype = property(fget=_get_dtype,fset=_set_dtype)
 
     def _check(self):
         """ Checks for consistency and stores the number of non-zeros as
@@ -212,7 +209,13 @@
         M[A.row, A.col] = A.data
         return M
 
-    def tocsc(self):
+    def tocsc(self,sum_duplicates=True):
+        """Return a copy of this matrix in Compressed Sparse Column format
+
+            By default sum_duplicates=True and any duplicate 
+            matrix entries are added together.
+
+        """
         from csc import csc_matrix
         if self.nnz == 0:
             return csc_matrix(self.shape, dtype=self.dtype)
@@ -225,9 +228,17 @@
                       self.row, self.col, self.data, \
                       indptr, indices, data)
 
-            return csc_matrix((data, indices, indptr), self.shape)
+            A = csc_matrix((data, indices, indptr), self.shape)
+            A.sum_duplicates()
+            return A
 
-    def tocsr(self):
+    def tocsr(self,sum_duplicates=True):
+        """Return a copy of this matrix in Compressed Sparse Row format
+
+            By default sum_duplicates=True and any duplicate 
+            matrix entries are added together.
+
+        """
         from csr import csr_matrix
         if self.nnz == 0:
             return csr_matrix(self.shape, dtype=self.dtype)
@@ -240,7 +251,9 @@
                       self.row, self.col, self.data, \
                       indptr, indices, data)
 
-            return csr_matrix((data, indices, indptr), self.shape)
+            A = csr_matrix((data, indices, indptr), self.shape)
+            A.sum_duplicates()
+            return A
     
 
     def tocoo(self, copy=False):
@@ -256,7 +269,9 @@
         diags = unique(ks)
 
         if len(diags) > 100:
-            pass #do something?
+            #probably undesired, should we do something?
+            #should todia() have a maxdiags parameter?
+            pass
 
         #initialize and fill in data array
         data = zeros( (len(diags), self.col.max()+1), dtype=self.dtype)
@@ -278,24 +293,17 @@
 
         return dok
 
-#    def tobsr(self,blocksize=None):
+
+#    def tobsc(self,blocksize=None):
 #        if blocksize in [None, (1,1)]:
-#            return self.tocsr().tobsr()
+#            return self.tocsc().tobsc(blocksize)
 #        else:
-#            from bsr import bsr_matrix
-#            data,indices,indptr = self._toblock(blocksize,'bsr')
-#            return bsr_matrix((data,indices,indptr),shape=self.shape)
+#            return self.transpose().tobsr().transpose()
 #
-#    def tobsc(self,blocksize=None):
+#    def tobsr(self,blocksize=None):
 #        if blocksize in [None, (1,1)]:
-#            return self.tocsc().tobsc()
-#        else:
-#            from bsc import bsc_matrix
-#            data,indices,indptr = self._toblock(blocksize,'bsc')
-#            return bsc_matrix((data,indices,indptr),shape=self.shape)
+#            return self.tocsr().tobsr(blocksize)
 #
-#    def _toblock(self,blocksize,format):
-#        """generic function to convert to BSR/BSC/BOO formats"""
 #        M,N = self.shape
 #        X,Y = blocksize
 #    
@@ -305,10 +313,7 @@
 #        i_block,i_sub = divmod(self.row, X)
 #        j_block,j_sub = divmod(self.col, Y)
 #    
-#        if format in ['bsr','boo']:
-#            perm = lexsort( keys=[j_block,i_block] )
-#        else:
-#            perm = lexsort( keys=[i_block,j_block] )
+#        perm = lexsort( keys=[j_block,i_block] )
 #    
 #        i_block = i_block[perm]
 #        j_block = j_block[perm]
@@ -330,24 +335,30 @@
 #        row = i_block[mask]
 #        col = j_block[mask]
 #    
-#        #row,col,data form BOO format 
+#        # now row,col,data form BOO format 
 #    
-#        if format == 'boo':
-#            return data,(row,col)
-#        elif format == 'bsr':
-#            temp = cumsum(bincount(row))
-#            indptr = zeros( M/X + 1, dtype=intc )
-#            indptr[1:len(temp)+1] = temp
-#            indptr[len(temp)+1:] = temp[-1]
-#            return data,col,indptr
-#        else:
-#            temp = cumsum(bincount(col))
-#            indptr = zeros( N/Y + 1, dtype=intc )
-#            indptr[1:len(temp)+1] = temp
-#            indptr[len(temp)+1:] = temp[-1]
-#            return data,row,indptr
+#        temp = cumsum(bincount(row))
+#        indptr = zeros( M/X + 1, dtype=intc )
+#        indptr[1:len(temp)+1] = temp
+#        indptr[len(temp)+1:] = temp[-1]
+#       
+#        from bsr import bsr_matrix
+#        return bsr_matrix((data,col,indptr),shape=self.shape)
 
+    # needed by _data_matrix
+    def _with_data(self,data,copy=True):
+        """Returns a matrix with the same sparsity structure as self,
+        but with different data.  By default the index arrays
+        (i.e. .row and .col) are copied.
+        """
+        if copy:
+            return coo_matrix( (data, (self.row.copy(), self.col.copy()) ), \
+                                   shape=self.shape, dtype=data.dtype)
+        else:
+            return coo_matrix( (data, (self.row, self.col) ), \
+                                   shape=self.shape, dtype=data.dtype)
 
+
 from sputils import _isinstance
 
 def isspmatrix_coo( x ):

Modified: trunk/scipy/sparse/csc.py
===================================================================
--- trunk/scipy/sparse/csc.py	2007-12-20 09:16:26 UTC (rev 3690)
+++ trunk/scipy/sparse/csc.py	2007-12-20 19:22:18 UTC (rev 3691)
@@ -1,4 +1,4 @@
-"""Compressed Sparse Column sparse matrix format
+"""Compressed Sparse Column matrix format
 """
 
 __all__ = ['csc_matrix', 'isspmatrix_csc']
@@ -217,7 +217,26 @@
 
         from csr import csr_matrix
         return csr_matrix((data, indices, indptr), self.shape)
-    
+
+#    def tobsc(self,blocksize=None, copy=True):
+#        if blocksize in [None, (1,1)]:
+#            from bsc import bsc_matrix
+#            arg1 = (self.data.reshape(-1,1,1),self.indices,self.indptr)  
+#            return bsc_matrix( arg1, shape=self.shape, copy=copy )
+#        else:
+#            #TODO make this more efficient
+#            return self.tocoo(copy=False).tobsr(blocksize=blocksize)
+#    
+#    def tobsr(self, blocksize=None):
+#        if blocksize in [None, (1,1)]:
+#            from bsr import bsr_matrix
+#            csr = self.tocsr()
+#            arg1 = (csr.data.reshape(-1,1,1),csr.indices,csr.indptr)  
+#            return bsr_matrix( arg1, shape=self.shape )
+#        else:
+#            #TODO make this more efficient
+#            return self.tocoo(copy=False).tobsr(blocksize=blocksize)
+
     def get_submatrix( self, slice0, slice1 ):
         """Return a submatrix of this matrix (new matrix is created).
         Contigous range of rows and columns can be selected using:

Modified: trunk/scipy/sparse/csr.py
===================================================================
--- trunk/scipy/sparse/csr.py	2007-12-20 09:16:26 UTC (rev 3690)
+++ trunk/scipy/sparse/csr.py	2007-12-20 19:22:18 UTC (rev 3691)
@@ -1,4 +1,4 @@
-"""Compressed Sparse Row sparse matrix format
+"""Compressed Sparse Row matrix format
 """
 
 __all__ = ['csr_matrix', 'isspmatrix_csr']
@@ -223,6 +223,25 @@
 
         from csc import csc_matrix
         return csc_matrix((data, indices, indptr), self.shape)
+
+#    def tobsr(self,blocksize=None,copy=True):
+#        if blocksize in [None, (1,1)]:
+#            from bsr import bsr_matrix
+#            arg1 = (self.data.reshape(-1,1,1),self.indices,self.indptr)  
+#            return bsr_matrix( arg1, shape=self.shape, copy=copy )
+#        else:
+#            #TODO make this more efficient
+#            return self.tocoo(copy=False).tobsr(blocksize=blocksize)
+#    
+#    def tobsc(self,blocksize=None):
+#        if blocksize in [None, (1,1)]:
+#            from bsc import bsc_matrix
+#            csc = self.tocsc()
+#            arg1 = (csc.data.reshape(-1,1,1),csc.indices,csc.indptr)  
+#            return bsc_matrix( arg1, shape=self.shape )
+#        else:
+#            #TODO make this more efficient
+#            return self.tocoo(copy=False).tobsc(blocksize=blocksize)
     
     def get_submatrix( self, slice0, slice1 ):
         """Return a submatrix of this matrix (new matrix is created).

Modified: trunk/scipy/sparse/data.py
===================================================================
--- trunk/scipy/sparse/data.py	2007-12-20 09:16:26 UTC (rev 3690)
+++ trunk/scipy/sparse/data.py	2007-12-20 19:22:18 UTC (rev 3691)
@@ -11,6 +11,8 @@
 from base import spmatrix
 from sputils import isscalarlike
 
+#TODO implement all relevant operations
+#use .data.__methods__() instead of /=, *=, etc.
 class _data_matrix(spmatrix):
     def __init__(self):
         spmatrix.__init__(self)

Modified: trunk/scipy/sparse/dia.py
===================================================================
--- trunk/scipy/sparse/dia.py	2007-12-20 09:16:26 UTC (rev 3690)
+++ trunk/scipy/sparse/dia.py	2007-12-20 19:22:18 UTC (rev 3691)
@@ -6,7 +6,7 @@
         empty_like, intc, atleast_1d, atleast_2d, add, multiply, \
         unique
 
-from base import isspmatrix
+from base import isspmatrix, _formats
 from data import _data_matrix
 from sputils import isscalarlike, isshape, upcast, getdtype, isdense
 
@@ -114,6 +114,13 @@
         if len(unique(self.diags)) != len(self.diags):
             raise ValueError,'offset array contains duplicate values'
 
+    def __repr__(self):
+        nnz = self.getnnz()
+        format = self.getformat()
+        return "<%dx%d sparse matrix of type '%s'\n" \
+               "\twith %d stored elements (%d diagonals) in %s format>" % \
+               ( self.shape +  (self.dtype.type, nnz, self.data.shape[0], \
+                 _formats[format][1],) )
 
     def getnnz(self):
         """number of nonzero values

Added: trunk/scipy/sparse/sparsetools/fixed_size.h
===================================================================
--- trunk/scipy/sparse/sparsetools/fixed_size.h	2007-12-20 09:16:26 UTC (rev 3690)
+++ trunk/scipy/sparse/sparsetools/fixed_size.h	2007-12-20 19:22:18 UTC (rev 3691)
@@ -0,0 +1,39 @@
+#ifndef FIXED_SIZE_H
+#define FIXED_SIZE_H
+
+/*
+ * templates for fixed size array and vector arithmetic
+ * 
+ */
+
+template<int N, class T>
+class Dot
+{
+    public:
+        inline T operator()(const T * lhs, const T * rhs)
+        {
+            Dot<N-1,T> d;
+            return (*lhs * *rhs) + d(++lhs, ++rhs);
+        }
+};
+
+template<class T>
+class Dot<0,T>
+{
+    public:
+        inline T operator()(const T * lhs, const T * rhs)
+        {
+            return 0;
+        }
+};
+
+    template<int N, class T>
+inline T dot(const T * lhs, const T * rhs)
+{
+    Dot<N,T> d;
+    return d(lhs, rhs);
+}
+
+
+
+#endif

Modified: trunk/scipy/sparse/sparsetools/sparsetools.h
===================================================================
--- trunk/scipy/sparse/sparsetools/sparsetools.h	2007-12-20 09:16:26 UTC (rev 3690)
+++ trunk/scipy/sparse/sparsetools/sparsetools.h	2007-12-20 19:22:18 UTC (rev 3691)
@@ -10,7 +10,7 @@
  *    Nathan Bell
  *
  * Revisions:
- *    07/14/2007 - added sum_csr_duplicates
+ *    07/14/2007 - added csr_sum_duplicates
  *    07/12/2007 - added templated function for binary arithmetic ops
  *    01/09/2007 - index type is now templated
  *    01/06/2007 - initial inclusion into SciPy
@@ -24,6 +24,10 @@
 #include <algorithm>
 #include <functional>
 
+
+#include "fixed_size.h"
+
+
 /*
  * Extract main diagonal of CSR matrix A
  *
@@ -38,7 +42,8 @@
  *   T  Yx[min(n_row,n_col)] - diagonal entries
  *
  * Note:
- *   Output array Yx should be preallocated
+ *   Output array Yx must be preallocated
+ *
  *   Duplicate entries will be summed.
  *
  *   Complexity: Linear.  Specifically O(nnz(A) + min(n_row,n_col))
@@ -52,20 +57,20 @@
 	              const T Ax[],
 	                    T Yx[])
 {
-  const I N = std::min(n_row, n_col);
-  
-  for(I i = 0; i < N; i++){
-    I row_start = Ap[i];
-    I row_end   = Ap[i+1];
-    
-    T diag = 0;
-    for(I jj = row_start; jj < row_end; jj++){
-        if (Aj[jj] == i)
-            diag += Ax[jj];
+    const I N = std::min(n_row, n_col);
+
+    for(I i = 0; i < N; i++){
+        I row_start = Ap[i];
+        I row_end   = Ap[i+1];
+
+        T diag = 0;
+        for(I jj = row_start; jj < row_end; jj++){
+            if (Aj[jj] == i)
+                diag += Ax[jj];
+        }
+
+        Yx[i] = diag;
     }
-    
-    Yx[i] = diag;
-  }
 }
 
 
@@ -80,7 +85,7 @@
  *   Bi  - row indices
  *
  * Note:
- *   Output array Bi needs to be preallocated
+ *   Output array Bi must be preallocated
  *
  * Note: 
  *   Complexity: Linear.
@@ -92,9 +97,7 @@
                      I Bi[])
 {
   for(I i = 0; i < n_row; i++){
-    I row_start = Ap[i];
-    I row_end   = Ap[i+1];
-    for(I jj = row_start; jj < row_end; jj++){
+    for(I jj = Ap[i]; jj < Ap[i+1]; jj++){
       Bi[jj] = i;
     }
   }
@@ -122,7 +125,7 @@
  *   T  Bx[nnz(A)]  - nonzeros
  *
  * Note:
- *   Output arrays Bp,Bj,Bx should be preallocated
+ *   Output arrays Bp, Bj, Bx must be preallocated
  *
  * Note: 
  *   Input:  column indices *are not* assumed to be in sorted order
@@ -141,96 +144,91 @@
 	                 I Bi[],
 	                 T Bx[])
 {  
-  I nnz = Ap[n_row];
-  
-  std::vector<I> temp(n_col,0); //temp array
+  const I nnz = Ap[n_row];
  
   //compute number of non-zero entries per column of A 
-  for (I i = 0; i < nnz; i++){            
-    temp[Aj[i]]++;
+  std::fill(Bp, Bp + n_col, 0);
+
+  for (I n = 0; n < nnz; n++){            
+    Bp[Aj[n]]++;
   }
         
   //cumsum the nnz per column to get Bp[]
-  for(I i = 0, cumsum = 0; i < n_col; i++){     
-    Bp[i] = cumsum;
-    cumsum += temp[i];
+  for(I col = 0, cumsum = 0; col < n_col; col++){     
+    I temp  = Bp[col];
+    Bp[col] = cumsum;
+    cumsum += temp;
   }
   Bp[n_col] = nnz; 
-  std::copy(Bp, Bp + n_col, temp.begin());
-
   
-  for(I i = 0; i < n_row; i++){
-    I row_start = Ap[i];
-    I row_end   = Ap[i+1];
-    for(I j = row_start; j < row_end; j++){
-      I col = Aj[j];
-      I k   = temp[col];
+  for(I row = 0; row < n_row; row++){
+    for(I jj = Ap[row]; jj < Ap[row+1]; jj++){
+      I col  = Aj[jj];
+      I dest = Bp[col];
 
-      Bi[k] = i;
-      Bx[k] = Ax[j];
+      Bi[dest] = row;
+      Bx[dest] = Ax[jj];
 
-      temp[col]++;
+      Bp[col]++;
     }
   }  
+
+  for(I col = 0, last = 0; col <= n_col; col++){
+      I temp  = Bp[col];
+      Bp[col] = last;
+      last    = temp;
+  }
 }   
 
 
 
 
+
+
+
 /*
- * Compute B = A for CSR matrix A, COO matrix B
+ * Compute C = A*B for CSR matrices A,B
  *
- * Also, with the appropriate arguments can also be used to:
- *   - convert CSC->COO
  *
  * Input Arguments:
- *   I  n_row         - number of rows in A
- *   I  n_col         - number of columns in A
- *   I  Ap[n_row+1]   - row pointer
- *   I  Aj[nnz(A)]    - column indices
- *   T  Ax[nnz(A)]    - nonzeros
- *
+ *   I  n_row       - number of rows in A
+ *   I  n_col       - number of columns in B (hence C is n_row by n_col)
+ *   I  Ap[n_row+1] - row pointer
+ *   I  Aj[nnz(A)]  - column indices
+ *   T  Ax[nnz(A)]  - nonzeros
+ *   I  Bp[?]       - row pointer
+ *   I  Bj[nnz(B)]  - column indices
+ *   T  Bx[nnz(B)]  - nonzeros
  * Output Arguments:
- *   vec<I> Bi  - row indices
- *   vec<I> Bj  - column indices
- *   vec<T> Bx  - nonzeros
- *
+ *   vec<I> Cp - row pointer
+ *   vec<I> Cj - column indices
+ *   vec<T> Cx - nonzeros
+ *   
  * Note:
- *   Output arrays Bi,Bj,Bx will be allocated within in the method
+ *   Output arrays Cp, Cj, and Cx must be preallocated
  *
  * Note: 
- *   Complexity: Linear.
- * 
+ *   Input:  A and B column indices *are not* assumed to be in sorted order 
+ *   Output: C column indices *are not* assumed to be in sorted order
+ *           Cx will not contain any zero entries
+ *
+ *   Complexity: O(n_row*K^2 + max(n_row,n_col)) 
+ *                 where K is the maximum nnz in a row of A
+ *                 and column of B.
+ *
+ *
+ *  This is an implementation of the SMMP algorithm:
+ *
+ *    "Sparse Matrix Multiplication Package (SMMP)"
+ *      Randolph E. Bank and Craig C. Douglas
+ *
+ *    http://citeseer.ist.psu.edu/445062.html
+ *    http://www.mgnet.org/~douglas/ccd-codes.html
+ *
  */
-template <class I, class T>
-void csr_tocoo(const I n_row,
-	           const I n_col, 
-               const I Ap[], 
-               const I Aj[], 
-               const T Ax[],
-               std::vector<I>* Bi,
-               std::vector<I>* Bj,
-               std::vector<T>* Bx)
-{
-  I nnz = Ap[n_row];
-  Bi->reserve(nnz);
-  Bi->reserve(nnz);
-  Bx->reserve(nnz);
-  for(I i = 0; i < n_row; i++){
-    I row_start = Ap[i];
-    I row_end   = Ap[i+1];
-    for(I jj = row_start; jj < row_end; jj++){
-      Bi->push_back(i);
-      Bj->push_back(Aj[jj]);
-      Bx->push_back(Ax[jj]);
-    }
-  }
-}
 
-
-
 /*
- * Compute CSR row pointer for the matrix product C = A * B
+ * Pass 1 computes CSR row pointer for the matrix product C = A * B
  *
  */
 template <class I>
@@ -276,6 +274,10 @@
     }
 }
 
+/*
+ * Pass 2 computes CSR entries for C using the row pointer computed in Pass 1
+ *
+ */
 template <class I, class T>
 void csr_matmat_pass2(const I n_row,
       	              const I n_col, 
@@ -343,108 +345,10 @@
 
 
 
-/*
- * Compute C = A*B for CSR matrices A,B
- *
- *
- * Input Arguments:
- *   I  n_row       - number of rows in A
- *   I  n_col       - number of columns in B (hence C is n_row by n_col)
- *   I  Ap[n_row+1] - row pointer
- *   I  Aj[nnz(A)]  - column indices
- *   T  Ax[nnz(A)]  - nonzeros
- *   I  Bp[?]       - row pointer
- *   I  Bj[nnz(B)]  - column indices
- *   T  Bx[nnz(B)]  - nonzeros
- * Output Arguments:
- *   vec<I> Cp - row pointer
- *   vec<I> Cj - column indices
- *   vec<T> Cx - nonzeros
- *   
- * Note:
- *   Output arrays Cp,Cj, and Cx will be allocated within in the method
- *
- * Note: 
- *   Input:  A and B column indices *are not* assumed to be in sorted order 
- *   Output: C column indices *are not* assumed to be in sorted order
- *           Cx will not contain any zero entries
- *
- *   Complexity: O(n_row*K^2 + max(n_row,n_col)) 
- *                 where K is the maximum nnz in a row of A
- *                 and column of B.
- *
- *
- *  This implementation closely follows the SMMP algorithm:
- *
- *    "Sparse Matrix Multiplication Package (SMMP)"
- *      Randolph E. Bank and Craig C. Douglas
- *
- *    http://citeseer.ist.psu.edu/445062.html
- *    http://www.mgnet.org/~douglas/ccd-codes.html
- *
- */
-template <class I, class T>
-void csrmucsr(const I n_row,
-      	      const I n_col, 
-      	      const I Ap[], 
-      	      const I Aj[], 
-      	      const T Ax[],
-      	      const I Bp[],
-      	      const I Bj[],
-      	      const T Bx[],
-      	      std::vector<I>* Cp,
-      	      std::vector<I>* Cj,
-      	      std::vector<T>* Cx)
-{
-    Cp->resize(n_row+1,0);
 
-    std::vector<I> next(n_col,-1);
-    std::vector<T> sums(n_col, 0);
 
-    for(I i = 0; i < n_row; i++){
-        I head = -2;
-        I length =  0;
 
-        I jj_start = Ap[i];
-        I jj_end   = Ap[i+1];
-        for(I jj = jj_start; jj < jj_end; jj++){
-            I j = Aj[jj];
 
-            I kk_start = Bp[j];
-            I kk_end   = Bp[j+1];
-            for(I kk = kk_start; kk < kk_end; kk++){
-                I k = Bj[kk];
-
-                sums[k] += Ax[jj]*Bx[kk];
-
-                if(next[k] == -1){
-                    next[k] = head;                        
-                    head = k;
-                    length++;
-                }
-            }
-        }         
-
-        for(I jj = 0; jj < length; jj++){
-            if(sums[head] != 0){
-                Cj->push_back(head);
-                Cx->push_back(sums[head]);
-            }
-
-            I temp = head;                
-            head = next[head];
-
-            next[temp] = -1; //clear arrays
-            sums[temp]  =  0;                              
-        }
-
-        (*Cp)[i+1] = Cx->size();
-    }
-}
-
-
-
-
 /*
  * Compute C = A (bin_op) B for CSR matrices A,B
  *
@@ -466,7 +370,7 @@
  *   vec<T> Cx  - nonzeros
  *   
  * Note:
- *   Output arrays Cp,Cj, and Cx will be allocated within in the method
+ *   Output arrays Cp, Cj, and Cx will be allocated within in the method
  *
  * Note: 
  *   Input:  A and B column indices *are not* assumed to be in sorted order 
@@ -488,14 +392,14 @@
                    std::vector<T>* Cx,
                    const bin_op& op)
 {
-  Cp->resize(n_row+1,0);
+  Cp->resize(n_row + 1, 0);
   
-  std::vector<I>   next(n_col,-1);
-  std::vector<T> A_row(n_col,0);
-  std::vector<T> B_row(n_col,0);
+  std::vector<I>  next(n_col,-1);
+  std::vector<T> A_row(n_col, 0);
+  std::vector<T> B_row(n_col, 0);
 
   for(I i = 0; i < n_row; i++){
-    I head = -2;
+    I head   = -2;
     I length =  0;
     
     //add a row of A to A_row
@@ -605,7 +509,7 @@
  *
  */
 template <class I, class T>
-void sum_csr_duplicates(const I n_row,
+void csr_sum_duplicates(const I n_row,
                         const I n_col, 
                               I Ap[], 
                               I Aj[], 
@@ -672,15 +576,15 @@
  *   T Bx  - nonzeros
  *
  * Note:
- *   Output arrays Bp,Bj,Bx should be preallocated
+ *   Output arrays Bp, Bj, and Bx must be preallocated
  *
  * Note: 
  *   Input:  row and column indices *are not* assumed to be ordered
- *           duplicate (i,j) entries will be summed together
  *           
  *   Output: CSR column indices *will be* in sorted order
- *           Bp[n_row] will store the number of nonzeros
  *
+ *   Note: duplicate entries are carried over to the CSR represention
+ *
  *   Complexity: Linear.  Specifically O(nnz(A) + max(n_row,n_col))
  * 
  */
@@ -695,39 +599,46 @@
                      I Bj[],
                      T Bx[])
 {
-  std::vector<I> temp(n_row,0);
+    //compute number of non-zero entries per row of A 
+    std::fill(Bp, Bp + n_row, 0);
 
-  //compute nnz per row, then compute Bp
-  for(I i = 0; i < nnz; i++){
-    temp[Ai[i]]++;
-  }
-  //cumsum the nnz per row to get Bp[]
-  for(I i = 0, cumsum = 0; i < n_row; i++){     
-    Bp[i] = cumsum;
-    cumsum += temp[i];
-  }
-  Bp[n_row] = nnz; 
-  std::copy(Bp, Bp + n_row, temp.begin());
+    for (I n = 0; n < nnz; n++){            
+        Bp[Ai[n]]++;
+    }
 
-  //write Aj,Ax into Bj,Bx
-  for(I i = 0; i < nnz; i++){
-    I row = Ai[i];
-    I n   = temp[row];
+    //cumsum the nnz per row to get Bp[]
+    for(I i = 0, cumsum = 0; i < n_row; i++){     
+        I temp = Bp[i];
+        Bp[i] = cumsum;
+        cumsum += temp;
+    }
+    Bp[n_row] = nnz; 
 
-    Bj[n] = Aj[i];
-    Bx[n] = Ax[i];
+    //write Aj,Ax into Bj,Bx
+    for(I n = 0; n < nnz; n++){
+        I row  = Ai[n];
+        I dest = Bp[row];
 
-    temp[row]++;
-  }
-  //now Bp,Bj,Bx form a CSR representation (with duplicates)
+        Bj[dest] = Aj[n];
+        Bx[dest] = Ax[n];
 
-  sum_csr_duplicates(n_row,n_col,Bp,Bj,Bx);
+        Bp[row]++;
+    }
+
+    for(I i = 0, last = 0; i <= n_row; i++){
+        I temp = Bp[i];
+        Bp[i]  = last;
+        last   = temp;
+    }
+
+    //now Bp,Bj,Bx form a CSR representation (with possible duplicates)
 }
-	    
 
 
 
 
+
+
 /*
  * Compute Y = A*X for CSR matrix A and dense vectors X,Y
  *
@@ -737,16 +648,16 @@
  *   I  n_col         - number of columns in A
  *   I  Ap[n_row+1]   - row pointer
  *   I  Aj[nnz(A)]    - column indices
- *   T  Ax[n_col]     - nonzeros
- *   T  Xx[n_col]     - nonzeros
+ *   T  Ax[nnz(A)]    - nonzeros
+ *   T  Xx[n_col]     - input vector
  *
  * Output Arguments:
- *   vec<T> Yx - nonzeros 
+ *   T  Yx[n_row]     - output vector
  *
  * Note:
- *   Output array Xx will be allocated within in the method
+ *   Output array Yx must be preallocated
  *
- *   Complexity: Linear.  Specifically O(nnz(A) + max(n_row,n_col))
+ *   Complexity: Linear.  Specifically O(nnz(A) + n_row)
  * 
  */
 template <class I, class T>
@@ -758,16 +669,13 @@
 	            const T Xx[],
 	                  T Yx[])
 {
-  for(I i = 0; i < n_row; i++){
-    I row_start = Ap[i];
-    I row_end   = Ap[i+1];
-    
-    T sum = 0;
-    for(I jj = row_start; jj < row_end; jj++){
-      sum += Ax[jj] * Xx[Aj[jj]];
+    for(I i = 0; i < n_row; i++){
+        T sum = 0;
+        for(I jj = Ap[i]; jj < Ap[i+1]; jj++){
+            sum += Ax[jj] * Xx[Aj[jj]];
+        }
+        Yx[i] = sum;
     }
-    Yx[i] = sum;
-  }
 }
 
 
@@ -785,13 +693,12 @@
  *   T  Xx[n_col]     - input vector
  *
  * Output Arguments:
- *   T  Yx[n_row] - output vector 
+ *   T  Yx[n_row]     - output vector 
  *
  * Note:
- *   Output arrays Xx should be be preallocated
- *
+ *   Output array Yx must be preallocated
  *   
- *   Complexity: Linear.  Specifically O(nnz(A) + max(n_row,n_col))
+ *   Complexity: Linear.  Specifically O(nnz(A) + n_col)
  * 
  */
 template <class I, class T>
@@ -803,162 +710,135 @@
 	            const T Xx[],
 	                  T Yx[])
 { 
- for(I i = 0; i < n_row; i++){
-      Yx[i] = 0;
-  }
+    for(I i = 0; i < n_row; i++){
+        Yx[i] = 0;
+    }
 
-  for(I j = 0; j < n_col; j++){
-    I col_start = Ap[j];
-    I col_end   = Ap[j+1];
-    
-    for(I ii = col_start; ii < col_end; ii++){
-      I row  = Ai[ii];
-      Yx[row] += Ax[ii] * Xx[j];
+    for(I j = 0; j < n_col; j++){
+        I col_start = Ap[j];
+        I col_end   = Ap[j+1];
+
+        for(I ii = col_start; ii < col_end; ii++){
+            I row  = Ai[ii];
+            Yx[row] += Ax[ii] * Xx[j];
+        }
     }
-  }
 }
 
 
 
 
-/*
- * Construct CSC matrix A from diagonals
- *
- * Input Arguments:
- *   I  n_row                            - number of rows in A
- *   I  n_col                            - number of columns in A
- *   I  n_diags                          - number of diagonals
- *   I  diags_indx[n_diags]              - where to place each diagonal 
- *   T  diags[n_diags][min(n_row,n_col)] - diagonals
- *
- * Output Arguments:
- *   vec<I> Ap  - row pointer
- *   vec<I> Aj  - column indices
- *   vec<T> Ax  - nonzeros
- *
- * Note:
- *   Output arrays Ap,Aj,Ax will be allocated within in the method
- *
- * Note: 
- *   Output: row indices are not in sorted order
- *
- *   Complexity: Linear
- * 
- */
-template <class I, class T>
-void spdiags(const I n_row,
-             const I n_col,
-             const I n_diag,
-             const I offsets[],
-             const T diags[],
-             std::vector<I> * Ap,
-             std::vector<I> * Ai,
-             std::vector<T> * Ax)
+template <class I, class T, int R, int C>
+void bsr_matvec_fixed(const I n_row,
+	                  const I n_col, 
+	                  const I Ap[], 
+	                  const I Aj[], 
+	                  const T Ax[],
+	                  const T Xx[],
+	                        T Yx[])
 {
-  const I diags_length = std::min(n_row,n_col);
-  Ap->push_back(0);
+    for(I i = 0; i < n_row; i++) {
+        T r0 = 0;
+        T r1 = 0;
+        T r2 = 0;
+        T r3 = 0;
+        T r4 = 0;
+        T r5 = 0;
 
-  for(I i = 0; i < n_col; i++){
-    for(I j = 0; j < n_diag; j++){
-      if(offsets[j] <= 0){              //sub-diagonal
-    	I row = i - offsets[j];
-	    if (row >= n_row){ continue; }
-        
-	    Ai->push_back(row);
-        Ax->push_back(diags[j*diags_length + i]);
-      } else {                          //super-diagonal
-	    I row = i - offsets[j];
-	    if (row < 0 || row >= n_row){ continue; }
-        Ai->push_back(row);
-        Ax->push_back(diags[j*diags_length + row]);
-      }
+        for(I jj = Ap[i]; jj < Ap[i+1]; jj++) {
+            I j = Aj[jj];
+            const T * base = Ax + jj*(R*C);
+            if (R >= 1) r0 += dot<C,T>(base + 0*C, Xx + j*C);
+            if (R >= 2) r1 += dot<C,T>(base + 1*C, Xx + j*C);
+            if (R >= 3) r2 += dot<C,T>(base + 2*C, Xx + j*C);
+            if (R >= 4) r3 += dot<C,T>(base + 3*C, Xx + j*C);
+            if (R >= 5) r4 += dot<C,T>(base + 4*C, Xx + j*C);
+            if (R >= 6) r5 += dot<C,T>(base + 5*C, Xx + j*C);
+        }
+
+        if (R >= 1) Yx[R*i+0] = r0; 
+        if (R >= 2) Yx[R*i+1] = r1;
+        if (R >= 3) Yx[R*i+2] = r2;
+        if (R >= 4) Yx[R*i+3] = r3;
+        if (R >= 5) Yx[R*i+4] = r4;
+        if (R >= 6) Yx[R*i+5] = r5;
     }
-    Ap->push_back(Ai->size());
-  }
 }
 
 
 
-/*
- * Compute M = A for CSR matrix A, dense matrix M
- *
- * Input Arguments:
- *   I  n_row           - number of rows in A
- *   I  n_col           - number of columns in A
- *   I  Ap[n_row+1]     - row pointer
- *   I  Aj[nnz(A)]      - column indices
- *   T    Ax[nnz(A)]      - nonzeros 
- *   T    Mx[n_row*n_col] - dense matrix
- *
- * Note:
- *   Output array Mx is assumed to be allocated and
- *   initialized to 0 by the caller.
- *
- */
 template <class I, class T>
-void csr_todense(const I  n_row,
-                 const I  n_col,
-                 const I  Ap[],
-                 const I  Aj[],
-                 const T  Ax[],
-                       T  Mx[])
+void bsr_matvec(const I n_row,
+	            const I n_col, 
+	            const I R, 
+	            const I C, 
+	            const I Ap[], 
+	            const I Aj[], 
+	            const T Ax[],
+	            const T Xx[],
+	                  T Yx[])
 {
-  I row_base = 0;
-  for(I i = 0; i < n_row; i++){
-    I row_start = Ap[i];
-    I row_end   = Ap[i+1];
-    for(I jj = row_start; jj < row_end; jj++){
-      I j = Aj[jj];
-      Mx[row_base + j] = Ax[jj];
-    }	
-    row_base += n_col;
-  }
-}
+    /*
+    //use fixed version for R,C <= 4,4
+    if (R == 1){
+        if (C == 1) { bsr_matvec_fixed<I,T,1,1>(n_row,n_col,Ap,Aj,Ax,Xx,Yx); return; }
+        if (C == 2) { bsr_matvec_fixed<I,T,1,2>(n_row,n_col,Ap,Aj,Ax,Xx,Yx); return; } 
+        if (C == 3) { bsr_matvec_fixed<I,T,1,3>(n_row,n_col,Ap,Aj,Ax,Xx,Yx); return; }
+        if (C == 4) { bsr_matvec_fixed<I,T,1,4>(n_row,n_col,Ap,Aj,Ax,Xx,Yx); return; }
+    }
+    if (R == 2){
+        if (C == 1) { bsr_matvec_fixed<I,T,2,1>(n_row,n_col,Ap,Aj,Ax,Xx,Yx); return; }
+        if (C == 2) { bsr_matvec_fixed<I,T,2,2>(n_row,n_col,Ap,Aj,Ax,Xx,Yx); return; } 
+        if (C == 3) { bsr_matvec_fixed<I,T,2,3>(n_row,n_col,Ap,Aj,Ax,Xx,Yx); return; }
+        if (C == 4) { bsr_matvec_fixed<I,T,2,4>(n_row,n_col,Ap,Aj,Ax,Xx,Yx); return; }
+    }
+    if (R == 3){
+        if (C == 1) { bsr_matvec_fixed<I,T,3,1>(n_row,n_col,Ap,Aj,Ax,Xx,Yx); return; }
+        if (C == 2) { bsr_matvec_fixed<I,T,3,2>(n_row,n_col,Ap,Aj,Ax,Xx,Yx); return; } 
+        if (C == 3) { bsr_matvec_fixed<I,T,3,3>(n_row,n_col,Ap,Aj,Ax,Xx,Yx); return; }
+        if (C == 4) { bsr_matvec_fixed<I,T,3,4>(n_row,n_col,Ap,Aj,Ax,Xx,Yx); return; }
+    }
+    if (R == 4){
+        if (C == 1) { bsr_matvec_fixed<I,T,4,1>(n_row,n_col,Ap,Aj,Ax,Xx,Yx); return; }
+        if (C == 2) { bsr_matvec_fixed<I,T,4,2>(n_row,n_col,Ap,Aj,Ax,Xx,Yx); return; } 
+        if (C == 3) { bsr_matvec_fixed<I,T,4,3>(n_row,n_col,Ap,Aj,Ax,Xx,Yx); return; }
+        if (C == 4) { bsr_matvec_fixed<I,T,4,4>(n_row,n_col,Ap,Aj,Ax,Xx,Yx); return; }
+    } */
 
 
+    //otherwise use general method
+    for(I i = 0; i < n_row; i++){
+        Yx[i] = 0;
+    }
 
-/*
- * Compute A = M for CSR matrix A, dense matrix M
- *
- * Input Arguments:
- *   I  n_row           - number of rows in A
- *   I  n_col           - number of columns in A
- *   T  Mx[n_row*n_col] - dense matrix
- *   I  Ap[n_row+1]     - row pointer
- *   I  Aj[nnz(A)]      - column indices
- *   T  Ax[nnz(A)]      - nonzeros 
- *
- * Note:
- *    Output arrays Ap,Aj,Ax will be allocated within the method
- *
- */
-template <class I, class T>
-void dense_tocsr(const I n_row,
-                 const I n_col,
-                 const T Mx[],
-                 std::vector<I>* Ap,
-                 std::vector<I>* Aj,
-                 std::vector<T>* Ax)
-{
-  const T* x_ptr = Mx;
+    for(I i = 0; i < n_row; i++){
+        const T * A = Ax + R * C * Ap[i];
+              T * y = Yx + R * i;
+        for(I jj = Ap[i]; jj < Ap[i+1]; jj++){
+            const T * x = Xx + C*Aj[jj];
 
-  Ap->push_back(0);
-  for(I i = 0; i < n_row; i++){
-    for(I j = 0; j < n_col; j++){
-      if(*x_ptr != 0){
-	    Aj->push_back(j);
-	    Ax->push_back(*x_ptr);
-      }
-      x_ptr++;
+            for( I r = 0; r < R; r++ ){
+                T sum = 0;
+                for( I c = 0; c < C; c++ ){
+                    sum += (*A) * x[c];
+                    A++;
+                }
+                y[r] += sum;
+            }
+
+        }
     }
-    Ap->push_back(Aj->size());
-  }
 }
 
 
 
 
 
+
+
+
+
+
 /*
  * Sort CSR column indices inplace
  *
@@ -979,8 +859,8 @@
 void csr_sort_indices(const I n_row,
                       const I n_col,
                       const I Ap[], 
-                      I       Aj[], 
-                      T       Ax[])
+                            I Aj[], 
+                            T Ax[])
 {
   std::vector< std::pair<I,T> > temp;
 
@@ -1003,57 +883,58 @@
     }    
 }
 
+
 template<class I, class T>
 void get_csr_submatrix(const I n_row,
-		       const I n_col,
-		       const I Ap[], 
-		       const I Aj[], 
-		       const T Ax[],
-		       const I ir0,
-		       const I ir1,
-		       const I ic0,
-		       const I ic1,
-		       std::vector<I>* Bp,
-		       std::vector<I>* Bj,
-		       std::vector<T>* Bx)
+		               const I n_col,
+		               const I Ap[], 
+		               const I Aj[], 
+		               const T Ax[],
+		               const I ir0,
+		               const I ir1,
+		               const I ic0,
+		               const I ic1,
+		               std::vector<I>* Bp,
+		               std::vector<I>* Bj,
+		               std::vector<T>* Bx)
 {
-  I new_n_row = ir1 - ir0;
-  //I new_n_col = ic1 - ic0;  //currently unused
-  I new_nnz = 0;
-  I kk = 0;
+    I new_n_row = ir1 - ir0;
+    //I new_n_col = ic1 - ic0;  //currently unused
+    I new_nnz = 0;
+    I kk = 0;
 
-  // Count nonzeros total/per row.
-  for(I i = 0; i < new_n_row; i++){
-    I row_start = Ap[ir0+i];
-    I row_end   = Ap[ir0+i+1];
+    // Count nonzeros total/per row.
+    for(I i = 0; i < new_n_row; i++){
+        I row_start = Ap[ir0+i];
+        I row_end   = Ap[ir0+i+1];
 
-    for(I jj = row_start; jj < row_end; jj++){
-      if ((Aj[jj] >= ic0) && (Aj[jj] < ic1)) {
-	    new_nnz++;
-      }
+        for(I jj = row_start; jj < row_end; jj++){
+            if ((Aj[jj] >= ic0) && (Aj[jj] < ic1)) {
+                new_nnz++;
+            }
+        }
     }
-  }
 
-  // Allocate.
-  Bp->resize(new_n_row+1);
-  Bj->resize(new_nnz);
-  Bx->resize(new_nnz);
+    // Allocate.
+    Bp->resize(new_n_row+1);
+    Bj->resize(new_nnz);
+    Bx->resize(new_nnz);
 
-  // Assign.
-  (*Bp)[0] = 0;
-  for(I i = 0; i < new_n_row; i++){
-    I row_start = Ap[ir0+i];
-    I row_end   = Ap[ir0+i+1];
+    // Assign.
+    (*Bp)[0] = 0;
+    for(I i = 0; i < new_n_row; i++){
+        I row_start = Ap[ir0+i];
+        I row_end   = Ap[ir0+i+1];
 
-    for(I jj = row_start; jj < row_end; jj++){
-      if ((Aj[jj] >= ic0) && (Aj[jj] < ic1)) {
-	(*Bj)[kk] = Aj[jj] - ic0;
-	(*Bx)[kk] = Ax[jj];
-	kk++;
-      }
+        for(I jj = row_start; jj < row_end; jj++){
+            if ((Aj[jj] >= ic0) && (Aj[jj] < ic1)) {
+                (*Bj)[kk] = Aj[jj] - ic0;
+                (*Bx)[kk] = Ax[jj];
+                kk++;
+            }
+        }
+        (*Bp)[i+1] = kk;
     }
-    (*Bp)[i+1] = kk;
-  }
 }
 
 
@@ -1084,16 +965,6 @@
                      T Bx[])
 { csr_tocsc<I,T>(n_col, n_row, Ap, Ai, Ax, Bp, Bj, Bx); }
 
-template <class I, class T>
-void csc_tocoo(const I n_row,
-              const I n_col, 
-              const I Ap[], 
-              const I Ai[], 
-              const T Ax[],
-              std::vector<I>* Bi,
-              std::vector<I>* Bj,
-              std::vector<T>* Bx)
-{ csr_tocoo<I,T>(n_col, n_row, Ap, Ai, Ax, Bj, Bi, Bx); }
     
 template <class I>
 void csc_matmat_pass1(const I n_row,
@@ -1119,19 +990,6 @@
       	                    T Cx[])
 { csr_matmat_pass2(n_col, n_row, Bp, Bi, Bx, Ap, Ai, Ax, Cp, Ci, Cx); }
 
-template <class I, class T>
-void cscmucsc(const I n_row,
-              const I n_col, 
-              const I Ap[], 
-              const I Ai[], 
-              const T Ax[],
-              const I Bp[],
-              const I Bi[],
-              const T Bx[],
-              std::vector<I>* Cp,
-              std::vector<I>* Ci,
-              std::vector<T>* Cx)
-{ csrmucsr<I,T>(n_col, n_row, Bp, Bi, Bx, Ap, Ai, Ax, Cp, Ci, Cx); }
 
 template<class I, class T>
 void coo_tocsc(const I n_row,
@@ -1187,12 +1045,12 @@
 
 
 template <class I, class T>
-void sum_csc_duplicates(const I n_row,
+void csc_sum_duplicates(const I n_row,
                         const I n_col, 
                               I Ap[], 
                               I Ai[], 
                               T Ax[])
-{ sum_csr_duplicates(n_col, n_row, Ap, Ai, Ax); }
+{ csr_sum_duplicates(n_col, n_row, Ap, Ai, Ax); }
 
 
 template<class I, class T>
@@ -1203,4 +1061,306 @@
                       T       Ax[])
 { csr_sort_indices(n_col, n_row, Ap, Ai, Ax); }
 
+
+
+
+
+
+/* 
+ * These are sparsetools functions that are not currently used
+ * 
+ */
+
+///*
+// * Compute C = A*B for CSR matrices A,B
+// *
+// *
+// * Input Arguments:
+// *   I  n_row       - number of rows in A
+// *   I  n_col       - number of columns in B (hence C is n_row by n_col)
+// *   I  Ap[n_row+1] - row pointer
+// *   I  Aj[nnz(A)]  - column indices
+// *   T  Ax[nnz(A)]  - nonzeros
+// *   I  Bp[?]       - row pointer
+// *   I  Bj[nnz(B)]  - column indices
+// *   T  Bx[nnz(B)]  - nonzeros
+// * Output Arguments:
+// *   vec<I> Cp - row pointer
+// *   vec<I> Cj - column indices
+// *   vec<T> Cx - nonzeros
+// *   
+// * Note:
+// *   Output arrays Cp, Cj, and Cx will be allocated within in the method
+// *
+// * Note: 
+// *   Input:  A and B column indices *are not* assumed to be in sorted order 
+// *   Output: C column indices *are not* assumed to be in sorted order
+// *           Cx will not contain any zero entries
+// *
+// *   Complexity: O(n_row*K^2 + max(n_row,n_col)) 
+// *                 where K is the maximum nnz in a row of A
+// *                 and column of B.
+// *
+// *
+// *  This implementation closely follows the SMMP algorithm:
+// *
+// *    "Sparse Matrix Multiplication Package (SMMP)"
+// *      Randolph E. Bank and Craig C. Douglas
+// *
+// *    http://citeseer.ist.psu.edu/445062.html
+// *    http://www.mgnet.org/~douglas/ccd-codes.html
+// *
+// */
+//template <class I, class T>
+//void csrmucsr(const I n_row,
+//      	      const I n_col, 
+//      	      const I Ap[], 
+//      	      const I Aj[], 
+//      	      const T Ax[],
+//      	      const I Bp[],
+//      	      const I Bj[],
+//      	      const T Bx[],
+//      	      std::vector<I>* Cp,
+//      	      std::vector<I>* Cj,
+//      	      std::vector<T>* Cx)
+//{
+//    Cp->resize(n_row+1,0);
+//
+//    std::vector<I> next(n_col,-1);
+//    std::vector<T> sums(n_col, 0);
+//
+//    for(I i = 0; i < n_row; i++){
+//        I head = -2;
+//        I length =  0;
+//
+//        I jj_start = Ap[i];
+//        I jj_end   = Ap[i+1];
+//        for(I jj = jj_start; jj < jj_end; jj++){
+//            I j = Aj[jj];
+//
+//            I kk_start = Bp[j];
+//            I kk_end   = Bp[j+1];
+//            for(I kk = kk_start; kk < kk_end; kk++){
+//                I k = Bj[kk];
+//
+//                sums[k] += Ax[jj]*Bx[kk];
+//
+//                if(next[k] == -1){
+//                    next[k] = head;                        
+//                    head = k;
+//                    length++;
+//                }
+//            }
+//        }         
+//
+//        for(I jj = 0; jj < length; jj++){
+//            if(sums[head] != 0){
+//                Cj->push_back(head);
+//                Cx->push_back(sums[head]);
+//            }
+//
+//            I temp = head;                
+//            head = next[head];
+//
+//            next[temp] = -1; //clear arrays
+//            sums[temp]  =  0;                              
+//        }
+//
+//        (*Cp)[i+1] = Cx->size();
+//    }
+//}
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+///*
+// * Compute A = M for CSR matrix A, dense matrix M
+// *
+// * Input Arguments:
+// *   I  n_row           - number of rows in A
+// *   I  n_col           - number of columns in A
+// *   T  Mx[n_row*n_col] - dense matrix
+// *   I  Ap[n_row+1]     - row pointer
+// *   I  Aj[nnz(A)]      - column indices
+// *   T  Ax[nnz(A)]      - nonzeros 
+// *
+// * Note:
+// *    Output arrays Ap, Aj, and Ax will be allocated within the method
+// *
+// */
+//template <class I, class T>
+//void dense_tocsr(const I n_row,
+//                 const I n_col,
+//                 const T Mx[],
+//                 std::vector<I>* Ap,
+//                 std::vector<I>* Aj,
+//                 std::vector<T>* Ax)
+//{
+//  const T* x_ptr = Mx;
+//
+//  Ap->push_back(0);
+//  for(I i = 0; i < n_row; i++){
+//    for(I j = 0; j < n_col; j++){
+//      if(*x_ptr != 0){
+//	    Aj->push_back(j);
+//	    Ax->push_back(*x_ptr);
+//      }
+//      x_ptr++;
+//    }
+//    Ap->push_back(Aj->size());
+//  }
+//}
+//
+//
+///*
+// * Compute M = A for CSR matrix A, dense matrix M
+// *
+// * Input Arguments:
+// *   I  n_row           - number of rows in A
+// *   I  n_col           - number of columns in A
+// *   I  Ap[n_row+1]     - row pointer
+// *   I  Aj[nnz(A)]      - column indices
+// *   T  Ax[nnz(A)]      - nonzeros 
+// *   T  Mx[n_row*n_col] - dense matrix
+// *
+// * Note:
+// *   Output array Mx is assumed to be allocated and
+// *   initialized to 0 by the caller.
+// *
+// */
+//template <class I, class T>
+//void csr_todense(const I  n_row,
+//                 const I  n_col,
+//                 const I  Ap[],
+//                 const I  Aj[],
+//                 const T  Ax[],
+//                       T  Mx[])
+//{
+//    I row_base = 0;
+//    for(I i = 0; i < n_row; i++){
+//        I row_start = Ap[i];
+//        I row_end   = Ap[i+1];
+//        for(I jj = row_start; jj < row_end; jj++){
+//            I j = Aj[jj];
+//            Mx[row_base + j] = Ax[jj];
+//        }	
+//        row_base += n_col;
+//    }
+//}
+///*
+// * Compute B = A for CSR matrix A, COO matrix B
+// *
+// * Also, with the appropriate arguments can also be used to:
+// *   - convert CSC->COO
+// *
+// * Input Arguments:
+// *   I  n_row         - number of rows in A
+// *   I  n_col         - number of columns in A
+// *   I  Ap[n_row+1]   - row pointer
+// *   I  Aj[nnz(A)]    - column indices
+// *   T  Ax[nnz(A)]    - nonzeros
+// *
+// * Output Arguments:
+// *   vec<I> Bi  - row indices
+// *   vec<I> Bj  - column indices
+// *   vec<T> Bx  - nonzeros
+// *
+// * Note:
+// *   Output arrays Bi, Bj, Bx will be allocated within in the method
+// *
+// * Note: 
+// *   Complexity: Linear.
+// * 
+// */
+//template <class I, class T>
+//void csr_tocoo(const I n_row,
+//	           const I n_col, 
+//               const I Ap[], 
+//               const I Aj[], 
+//               const T Ax[],
+//               std::vector<I>* Bi,
+//               std::vector<I>* Bj,
+//               std::vector<T>* Bx)
+//{
+//  I nnz = Ap[n_row];
+//  Bi->reserve(nnz);
+//  Bi->reserve(nnz);
+//  Bx->reserve(nnz);
+//  for(I i = 0; i < n_row; i++){
+//    I row_start = Ap[i];
+//    I row_end   = Ap[i+1];
+//    for(I jj = row_start; jj < row_end; jj++){
+//      Bi->push_back(i);
+//      Bj->push_back(Aj[jj]);
+//      Bx->push_back(Ax[jj]);
+//    }
+//  }
+//}
+//
+//
+///*
+// * Construct CSC matrix A from diagonals
+// *
+// * Input Arguments:
+// *   I  n_row                            - number of rows in A
+// *   I  n_col                            - number of columns in A
+// *   I  n_diags                          - number of diagonals
+// *   I  diags_indx[n_diags]              - where to place each diagonal 
+// *   T  diags[n_diags][min(n_row,n_col)] - diagonals
+// *
+// * Output Arguments:
+// *   vec<I> Ap  - row pointer
+// *   vec<I> Aj  - column indices
+// *   vec<T> Ax  - nonzeros
+// *
+// * Note:
+// *   Output arrays Ap, Aj, Ax will be allocated within in the method
+// *
+// * Note: 
+// *   Output: row indices are not in sorted order
+// *
+// *   Complexity: Linear
+// * 
+// */
+//template <class I, class T>
+//void spdiags(const I n_row,
+//             const I n_col,
+//             const I n_diag,
+//             const I offsets[],
+//             const T diags[],
+//             std::vector<I> * Ap,
+//             std::vector<I> * Ai,
+//             std::vector<T> * Ax)
+//{
+//    const I diags_length = std::min(n_row,n_col);
+//    Ap->push_back(0);
+//
+//    for(I i = 0; i < n_col; i++){
+//        for(I j = 0; j < n_diag; j++){
+//            if(offsets[j] <= 0){              //sub-diagonal
+//                I row = i - offsets[j];
+//                if (row >= n_row){ continue; }
+//
+//                Ai->push_back(row);
+//                Ax->push_back(diags[j*diags_length + i]);
+//            } else {                          //super-diagonal
+//                I row = i - offsets[j];
+//                if (row < 0 || row >= n_row){ continue; }
+//                Ai->push_back(row);
+//                Ax->push_back(diags[j*diags_length + row]);
+//            }
+//        }
+//        Ap->push_back(Ai->size());
+//    }
+//}
+//
+
 #endif

Modified: trunk/scipy/sparse/sparsetools/sparsetools.i
===================================================================
--- trunk/scipy/sparse/sparsetools/sparsetools.i	2007-12-20 09:16:26 UTC (rev 3690)
+++ trunk/scipy/sparse/sparsetools/sparsetools.i	2007-12-20 19:22:18 UTC (rev 3691)
@@ -197,8 +197,6 @@
  * CSR<->COO and CSC<->COO
  */
 %template(expandptr)   expandptr<int>;
-/*INSTANTIATE_ALL(csrtocoo)*/
-/*INSTANTIATE_ALL(csctocoo)*/
 INSTANTIATE_ALL(coo_tocsr)
 INSTANTIATE_ALL(coo_tocsc)
 
@@ -210,14 +208,13 @@
 %template(csc_matmat_pass1)   csc_matmat_pass1<int>;
 INSTANTIATE_ALL(csr_matmat_pass2)
 INSTANTIATE_ALL(csc_matmat_pass2)
-/*INSTANTIATE_ALL(csrmucsr)*/
-/*INSTANTIATE_ALL(cscmucsc)*/
 
 /*
  * CSR*x and CSC*x
  */
 INSTANTIATE_ALL(csr_matvec)
 INSTANTIATE_ALL(csc_matvec)
+INSTANTIATE_ALL(bsr_matvec)
 
 /*
  * CSR (binary op) CSR and CSC (binary op) CSC
@@ -233,19 +230,7 @@
 INSTANTIATE_ALL(csc_minus_csc)
 
 
-
 /*
- * spdiags->CSC
- */
-/*INSTANTIATE_ALL(spdiags)*/
-
-/*
- * CSR<->Dense
- */
-/*INSTANTIATE_ALL(csr_todense)*/
-/*INSTANTIATE_ALL(densetocsr)*/ 
-
-/*
  * Sort CSR/CSC indices.
  */
 INSTANTIATE_ALL(csr_sort_indices)
@@ -255,8 +240,8 @@
 /*
  * Sum duplicate CSR/CSC entries.
  */
-INSTANTIATE_ALL(sum_csr_duplicates)
-INSTANTIATE_ALL(sum_csc_duplicates)
+INSTANTIATE_ALL(csr_sum_duplicates)
+INSTANTIATE_ALL(csc_sum_duplicates)
 
 /*
  * Extract submatrices

Modified: trunk/scipy/sparse/sparsetools/sparsetools.py
===================================================================
--- trunk/scipy/sparse/sparsetools/sparsetools.py	2007-12-20 09:16:26 UTC (rev 3690)
+++ trunk/scipy/sparse/sparsetools/sparsetools.py	2007-12-20 19:22:18 UTC (rev 3691)
@@ -300,6 +300,31 @@
     """
   return _sparsetools.csc_matvec(*args)
 
+def bsr_matvec(*args):
+  """
+    bsr_matvec(int n_row, int n_col, int R, int C, int Ap, int Aj, 
+        signed char Ax, signed char Xx, signed char Yx)
+    bsr_matvec(int n_row, int n_col, int R, int C, int Ap, int Aj, 
+        unsigned char Ax, unsigned char Xx, unsigned char Yx)
+    bsr_matvec(int n_row, int n_col, int R, int C, int Ap, int Aj, 
+        short Ax, short Xx, short Yx)
+    bsr_matvec(int n_row, int n_col, int R, int C, int Ap, int Aj, 
+        int Ax, int Xx, int Yx)
+    bsr_matvec(int n_row, int n_col, int R, int C, int Ap, int Aj, 
+        long long Ax, long long Xx, long long Yx)
+    bsr_matvec(int n_row, int n_col, int R, int C, int Ap, int Aj, 
+        float Ax, float Xx, float Yx)
+    bsr_matvec(int n_row, int n_col, int R, int C, int Ap, int Aj, 
+        double Ax, double Xx, double Yx)
+    bsr_matvec(int n_row, int n_col, int R, int C, int Ap, int Aj, 
+        npy_cfloat_wrapper Ax, npy_cfloat_wrapper Xx, 
+        npy_cfloat_wrapper Yx)
+    bsr_matvec(int n_row, int n_col, int R, int C, int Ap, int Aj, 
+        npy_cdouble_wrapper Ax, npy_cdouble_wrapper Xx, 
+        npy_cdouble_wrapper Yx)
+    """
+  return _sparsetools.bsr_matvec(*args)
+
 def csr_elmul_csr(*args):
   """
     csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, signed char Ax, 
@@ -600,33 +625,33 @@
     """
   return _sparsetools.csc_sort_indices(*args)
 
-def sum_csr_duplicates(*args):
+def csr_sum_duplicates(*args):
   """
-    sum_csr_duplicates(int n_row, int n_col, int Ap, int Aj, signed char Ax)
-    sum_csr_duplicates(int n_row, int n_col, int Ap, int Aj, unsigned char Ax)
-    sum_csr_duplicates(int n_row, int n_col, int Ap, int Aj, short Ax)
-    sum_csr_duplicates(int n_row, int n_col, int Ap, int Aj, int Ax)
-    sum_csr_duplicates(int n_row, int n_col, int Ap, int Aj, long long Ax)
-    sum_csr_duplicates(int n_row, int n_col, int Ap, int Aj, float Ax)
-    sum_csr_duplicates(int n_row, int n_col, int Ap, int Aj, double Ax)
-    sum_csr_duplicates(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax)
-    sum_csr_duplicates(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax)
+    csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, signed char Ax)
+    csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, unsigned char Ax)
+    csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, short Ax)
+    csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, int Ax)
+    csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, long long Ax)
+    csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, float Ax)
+    csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, double Ax)
+    csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax)
+    csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax)
     """
-  return _sparsetools.sum_csr_duplicates(*args)
+  return _sparsetools.csr_sum_duplicates(*args)
 
-def sum_csc_duplicates(*args):
+def csc_sum_duplicates(*args):
   """
-    sum_csc_duplicates(int n_row, int n_col, int Ap, int Ai, signed char Ax)
-    sum_csc_duplicates(int n_row, int n_col, int Ap, int Ai, unsigned char Ax)
-    sum_csc_duplicates(int n_row, int n_col, int Ap, int Ai, short Ax)
-    sum_csc_duplicates(int n_row, int n_col, int Ap, int Ai, int Ax)
-    sum_csc_duplicates(int n_row, int n_col, int Ap, int Ai, long long Ax)
-    sum_csc_duplicates(int n_row, int n_col, int Ap, int Ai, float Ax)
-    sum_csc_duplicates(int n_row, int n_col, int Ap, int Ai, double Ax)
-    sum_csc_duplicates(int n_row, int n_col, int Ap, int Ai, npy_cfloat_wrapper Ax)
-    sum_csc_duplicates(int n_row, int n_col, int Ap, int Ai, npy_cdouble_wrapper Ax)
+    csc_sum_duplicates(int n_row, int n_col, int Ap, int Ai, signed char Ax)
+    csc_sum_duplicates(int n_row, int n_col, int Ap, int Ai, unsigned char Ax)
+    csc_sum_duplicates(int n_row, int n_col, int Ap, int Ai, short Ax)
+    csc_sum_duplicates(int n_row, int n_col, int Ap, int Ai, int Ax)
+    csc_sum_duplicates(int n_row, int n_col, int Ap, int Ai, long long Ax)
+    csc_sum_duplicates(int n_row, int n_col, int Ap, int Ai, float Ax)
+    csc_sum_duplicates(int n_row, int n_col, int Ap, int Ai, double Ax)
+    csc_sum_duplicates(int n_row, int n_col, int Ap, int Ai, npy_cfloat_wrapper Ax)
+    csc_sum_duplicates(int n_row, int n_col, int Ap, int Ai, npy_cdouble_wrapper Ax)
     """
-  return _sparsetools.sum_csc_duplicates(*args)
+  return _sparsetools.csc_sum_duplicates(*args)
 
 def get_csr_submatrix(*args):
   """

Modified: trunk/scipy/sparse/sparsetools/sparsetools_wrap.cxx
===================================================================
--- trunk/scipy/sparse/sparsetools/sparsetools_wrap.cxx	2007-12-20 09:16:26 UTC (rev 3690)
+++ trunk/scipy/sparse/sparsetools/sparsetools_wrap.cxx	2007-12-20 19:22:18 UTC (rev 3691)
@@ -19069,6 +19069,1724 @@
 }
 
 
+SWIGINTERN PyObject *_wrap_bsr_matvec__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  int arg1 ;
+  int arg2 ;
+  int arg3 ;
+  int arg4 ;
+  int *arg5 ;
+  int *arg6 ;
+  signed char *arg7 ;
+  signed char *arg8 ;
+  signed char *arg9 ;
+  int val1 ;
+  int ecode1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  int val3 ;
+  int ecode3 = 0 ;
+  int val4 ;
+  int ecode4 = 0 ;
+  PyArrayObject *array5 = NULL ;
+  int is_new_object5 ;
+  PyArrayObject *array6 = NULL ;
+  int is_new_object6 ;
+  PyArrayObject *array7 = NULL ;
+  int is_new_object7 ;
+  PyArrayObject *array8 = NULL ;
+  int is_new_object8 ;
+  PyArrayObject *temp9 = NULL ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  PyObject * obj5 = 0 ;
+  PyObject * obj6 = 0 ;
+  PyObject * obj7 = 0 ;
+  PyObject * obj8 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOOOOOOOO:bsr_matvec",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6,&obj7,&obj8)) SWIG_fail;
+  ecode1 = SWIG_AsVal_int(obj0, &val1);
+  if (!SWIG_IsOK(ecode1)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "bsr_matvec" "', argument " "1"" of type '" "int""'");
+  } 
+  arg1 = static_cast< int >(val1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "bsr_matvec" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  ecode3 = SWIG_AsVal_int(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "bsr_matvec" "', argument " "3"" of type '" "int""'");
+  } 
+  arg3 = static_cast< int >(val3);
+  ecode4 = SWIG_AsVal_int(obj3, &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "bsr_matvec" "', argument " "4"" of type '" "int""'");
+  } 
+  arg4 = static_cast< int >(val4);
+  {
+    npy_intp size[1] = {
+      -1
+    };
+    array5 = obj_to_array_contiguous_allow_conversion(obj4, PyArray_INT, &is_new_object5);
+    if (!array5 || !require_dimensions(array5,1) || !require_size(array5,size,1)
+      || !require_contiguous(array5)   || !require_native(array5)) SWIG_fail;
+    
+    arg5 = (int*) array5->data;
+  }
+  {
+    npy_intp size[1] = {
+      -1
+    };
+    array6 = obj_to_array_contiguous_allow_conversion(obj5, PyArray_INT, &is_new_object6);
+    if (!array6 || !require_dimensions(array6,1) || !require_size(array6,size,1)
+      || !require_contiguous(array6)   || !require_native(array6)) SWIG_fail;
+    
+    arg6 = (int*) array6->data;
+  }
+  {
+    npy_intp size[1] = {
+      -1
+    };
+    array7 = obj_to_array_contiguous_allow_conversion(obj6, PyArray_BYTE, &is_new_object7);
+    if (!array7 || !require_dimensions(array7,1) || !require_size(array7,size,1)
+      || !require_contiguous(array7)   || !require_native(array7)) SWIG_fail;
+    
+    arg7 = (signed char*) array7->data;
+  }
+  {
+    npy_intp size[1] = {
+      -1
+    };
+    array8 = obj_to_array_contiguous_allow_conversion(obj7, PyArray_BYTE, &is_new_object8);
+    if (!array8 || !require_dimensions(array8,1) || !require_size(array8,size,1)
+      || !require_contiguous(array8)   || !require_native(array8)) SWIG_fail;
+    
+    arg8 = (signed char*) array8->data;
+  }
+  {
+    temp9 = obj_to_array_no_conversion(obj8,PyArray_BYTE);
+    if (!temp9  || !require_contiguous(temp9) || !require_native(temp9)) SWIG_fail;
+    arg9 = (signed char*) array_data(temp9);
+  }
+  bsr_matvec<int,signed char >(arg1,arg2,arg3,arg4,(int const (*))arg5,(int const (*))arg6,(signed char const (*))arg7,(signed char const (*))arg8,arg9);
+  resultobj = SWIG_Py_Void();
+  {
+    if (is_new_object5 && array5) Py_DECREF(array5);
+  }
+  {
+    if (is_new_object6 && array6) Py_DECREF(array6);
+  }
+  {
+    if (is_new_object7 && array7) Py_DECREF(array7);
+  }
+  {
+    if (is_new_object8 && array8) Py_DECREF(array8);
+  }
+  return resultobj;
+fail:
+  {
+    if (is_new_object5 && array5) Py_DECREF(array5);
+  }
+  {
+    if (is_new_object6 && array6) Py_DECREF(array6);
+  }
+  {
+    if (is_new_object7 && array7) Py_DECREF(array7);
+  }
+  {
+    if (is_new_object8 && array8) Py_DECREF(array8);
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_bsr_matvec__SWIG_2(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  int arg1 ;
+  int arg2 ;
+  int arg3 ;
+  int arg4 ;
+  int *arg5 ;
+  int *arg6 ;
+  unsigned char *arg7 ;
+  unsigned char *arg8 ;
+  unsigned char *arg9 ;
+  int val1 ;
+  int ecode1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  int val3 ;
+  int ecode3 = 0 ;
+  int val4 ;
+  int ecode4 = 0 ;
+  PyArrayObject *array5 = NULL ;
+  int is_new_object5 ;
+  PyArrayObject *array6 = NULL ;
+  int is_new_object6 ;
+  PyArrayObject *array7 = NULL ;
+  int is_new_object7 ;
+  PyArrayObject *array8 = NULL ;
+  int is_new_object8 ;
+  PyArrayObject *temp9 = NULL ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  PyObject * obj5 = 0 ;
+  PyObject * obj6 = 0 ;
+  PyObject * obj7 = 0 ;
+  PyObject * obj8 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOOOOOOOO:bsr_matvec",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6,&obj7,&obj8)) SWIG_fail;
+  ecode1 = SWIG_AsVal_int(obj0, &val1);
+  if (!SWIG_IsOK(ecode1)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "bsr_matvec" "', argument " "1"" of type '" "int""'");
+  } 
+  arg1 = static_cast< int >(val1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "bsr_matvec" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  ecode3 = SWIG_AsVal_int(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "bsr_matvec" "', argument " "3"" of type '" "int""'");
+  } 
+  arg3 = static_cast< int >(val3);
+  ecode4 = SWIG_AsVal_int(obj3, &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "bsr_matvec" "', argument " "4"" of type '" "int""'");
+  } 
+  arg4 = static_cast< int >(val4);
+  {
+    npy_intp size[1] = {
+      -1
+    };
+    array5 = obj_to_array_contiguous_allow_conversion(obj4, PyArray_INT, &is_new_object5);
+    if (!array5 || !require_dimensions(array5,1) || !require_size(array5,size,1)
+      || !require_contiguous(array5)   || !require_native(array5)) SWIG_fail;
+    
+    arg5 = (int*) array5->data;
+  }
+  {
+    npy_intp size[1] = {
+      -1
+    };
+    array6 = obj_to_array_contiguous_allow_conversion(obj5, PyArray_INT, &is_new_object6);
+    if (!array6 || !require_dimensions(array6,1) || !require_size(array6,size,1)
+      || !require_contiguous(array6)   || !require_native(array6)) SWIG_fail;
+    
+    arg6 = (int*) array6->data;
+  }
+  {
+    npy_intp size[1] = {
+      -1
+    };
+    array7 = obj_to_array_contiguous_allow_conversion(obj6, PyArray_UBYTE, &is_new_object7);
+    if (!array7 || !require_dimensions(array7,1) || !require_size(array7,size,1)
+      || !require_contiguous(array7)   || !require_native(array7)) SWIG_fail;
+    
+    arg7 = (unsigned char*) array7->data;
+  }
+  {
+    npy_intp size[1] = {
+      -1
+    };
+    array8 = obj_to_array_contiguous_allow_conversion(obj7, PyArray_UBYTE, &is_new_object8);
+    if (!array8 || !require_dimensions(array8,1) || !require_size(array8,size,1)
+      || !require_contiguous(array8)   || !require_native(array8)) SWIG_fail;
+    
+    arg8 = (unsigned char*) array8->data;
+  }
+  {
+    temp9 = obj_to_array_no_conversion(obj8,PyArray_UBYTE);
+    if (!temp9  || !require_contiguous(temp9) || !require_native(temp9)) SWIG_fail;
+    arg9 = (unsigned char*) array_data(temp9);
+  }
+  bsr_matvec<int,unsigned char >(arg1,arg2,arg3,arg4,(int const (*))arg5,(int const (*))arg6,(unsigned char const (*))arg7,(unsigned char const (*))arg8,arg9);
+  resultobj = SWIG_Py_Void();
+  {
+    if (is_new_object5 && array5) Py_DECREF(array5);
+  }
+  {
+    if (is_new_object6 && array6) Py_DECREF(array6);
+  }
+  {
+    if (is_new_object7 && array7) Py_DECREF(array7);
+  }
+  {
+    if (is_new_object8 && array8) Py_DECREF(array8);
+  }
+  return resultobj;
+fail:
+  {
+    if (is_new_object5 && array5) Py_DECREF(array5);
+  }
+  {
+    if (is_new_object6 && array6) Py_DECREF(array6);
+  }
+  {
+    if (is_new_object7 && array7) Py_DECREF(array7);
+  }
+  {
+    if (is_new_object8 && array8) Py_DECREF(array8);
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_bsr_matvec__SWIG_3(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  int arg1 ;
+  int arg2 ;
+  int arg3 ;
+  int arg4 ;
+  int *arg5 ;
+  int *arg6 ;
+  short *arg7 ;
+  short *arg8 ;
+  short *arg9 ;
+  int val1 ;
+  int ecode1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  int val3 ;
+  int ecode3 = 0 ;
+  int val4 ;
+  int ecode4 = 0 ;
+  PyArrayObject *array5 = NULL ;
+  int is_new_object5 ;
+  PyArrayObject *array6 = NULL ;
+  int is_new_object6 ;
+  PyArrayObject *array7 = NULL ;
+  int is_new_object7 ;
+  PyArrayObject *array8 = NULL ;
+  int is_new_object8 ;
+  PyArrayObject *temp9 = NULL ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  PyObject * obj5 = 0 ;
+  PyObject * obj6 = 0 ;
+  PyObject * obj7 = 0 ;
+  PyObject * obj8 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOOOOOOOO:bsr_matvec",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6,&obj7,&obj8)) SWIG_fail;
+  ecode1 = SWIG_AsVal_int(obj0, &val1);
+  if (!SWIG_IsOK(ecode1)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "bsr_matvec" "', argument " "1"" of type '" "int""'");
+  } 
+  arg1 = static_cast< int >(val1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "bsr_matvec" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  ecode3 = SWIG_AsVal_int(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "bsr_matvec" "', argument " "3"" of type '" "int""'");
+  } 
+  arg3 = static_cast< int >(val3);
+  ecode4 = SWIG_AsVal_int(obj3, &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "bsr_matvec" "', argument " "4"" of type '" "int""'");
+  } 
+  arg4 = static_cast< int >(val4);
+  {
+    npy_intp size[1] = {
+      -1
+    };
+    array5 = obj_to_array_contiguous_allow_conversion(obj4, PyArray_INT, &is_new_object5);
+    if (!array5 || !require_dimensions(array5,1) || !require_size(array5,size,1)
+      || !require_contiguous(array5)   || !require_native(array5)) SWIG_fail;
+    
+    arg5 = (int*) array5->data;
+  }
+  {
+    npy_intp size[1] = {
+      -1
+    };
+    array6 = obj_to_array_contiguous_allow_conversion(obj5, PyArray_INT, &is_new_object6);
+    if (!array6 || !require_dimensions(array6,1) || !require_size(array6,size,1)
+      || !require_contiguous(array6)   || !require_native(array6)) SWIG_fail;
+    
+    arg6 = (int*) array6->data;
+  }
+  {
+    npy_intp size[1] = {
+      -1
+    };
+    array7 = obj_to_array_contiguous_allow_conversion(obj6, PyArray_SHORT, &is_new_object7);
+    if (!array7 || !require_dimensions(array7,1) || !require_size(array7,size,1)
+      || !require_contiguous(array7)   || !require_native(array7)) SWIG_fail;
+    
+    arg7 = (short*) array7->data;
+  }
+  {
+    npy_intp size[1] = {
+      -1
+    };
+    array8 = obj_to_array_contiguous_allow_conversion(obj7, PyArray_SHORT, &is_new_object8);
+    if (!array8 || !require_dimensions(array8,1) || !require_size(array8,size,1)
+      || !require_contiguous(array8)   || !require_native(array8)) SWIG_fail;
+    
+    arg8 = (short*) array8->data;
+  }
+  {
+    temp9 = obj_to_array_no_conversion(obj8,PyArray_SHORT);
+    if (!temp9  || !require_contiguous(temp9) || !require_native(temp9)) SWIG_fail;
+    arg9 = (short*) array_data(temp9);
+  }
+  bsr_matvec<int,short >(arg1,arg2,arg3,arg4,(int const (*))arg5,(int const (*))arg6,(short const (*))arg7,(short const (*))arg8,arg9);
+  resultobj = SWIG_Py_Void();
+  {
+    if (is_new_object5 && array5) Py_DECREF(array5);
+  }
+  {
+    if (is_new_object6 && array6) Py_DECREF(array6);
+  }
+  {
+    if (is_new_object7 && array7) Py_DECREF(array7);
+  }
+  {
+    if (is_new_object8 && array8) Py_DECREF(array8);
+  }
+  return resultobj;
+fail:
+  {
+    if (is_new_object5 && array5) Py_DECREF(array5);
+  }
+  {
+    if (is_new_object6 && array6) Py_DECREF(array6);
+  }
+  {
+    if (is_new_object7 && array7) Py_DECREF(array7);
+  }
+  {
+    if (is_new_object8 && array8) Py_DECREF(array8);
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_bsr_matvec__SWIG_4(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  int arg1 ;
+  int arg2 ;
+  int arg3 ;
+  int arg4 ;
+  int *arg5 ;
+  int *arg6 ;
+  int *arg7 ;
+  int *arg8 ;
+  int *arg9 ;
+  int val1 ;
+  int ecode1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  int val3 ;
+  int ecode3 = 0 ;
+  int val4 ;
+  int ecode4 = 0 ;
+  PyArrayObject *array5 = NULL ;
+  int is_new_object5 ;
+  PyArrayObject *array6 = NULL ;
+  int is_new_object6 ;
+  PyArrayObject *array7 = NULL ;
+  int is_new_object7 ;
+  PyArrayObject *array8 = NULL ;
+  int is_new_object8 ;
+  PyArrayObject *temp9 = NULL ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  PyObject * obj5 = 0 ;
+  PyObject * obj6 = 0 ;
+  PyObject * obj7 = 0 ;
+  PyObject * obj8 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOOOOOOOO:bsr_matvec",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6,&obj7,&obj8)) SWIG_fail;
+  ecode1 = SWIG_AsVal_int(obj0, &val1);
+  if (!SWIG_IsOK(ecode1)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "bsr_matvec" "', argument " "1"" of type '" "int""'");
+  } 
+  arg1 = static_cast< int >(val1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "bsr_matvec" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  ecode3 = SWIG_AsVal_int(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "bsr_matvec" "', argument " "3"" of type '" "int""'");
+  } 
+  arg3 = static_cast< int >(val3);
+  ecode4 = SWIG_AsVal_int(obj3, &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "bsr_matvec" "', argument " "4"" of type '" "int""'");
+  } 
+  arg4 = static_cast< int >(val4);
+  {
+    npy_intp size[1] = {
+      -1
+    };
+    array5 = obj_to_array_contiguous_allow_conversion(obj4, PyArray_INT, &is_new_object5);
+    if (!array5 || !require_dimensions(array5,1) || !require_size(array5,size,1)
+      || !require_contiguous(array5)   || !require_native(array5)) SWIG_fail;
+    
+    arg5 = (int*) array5->data;
+  }
+  {
+    npy_intp size[1] = {
+      -1
+    };
+    array6 = obj_to_array_contiguous_allow_conversion(obj5, PyArray_INT, &is_new_object6);
+    if (!array6 || !require_dimensions(array6,1) || !require_size(array6,size,1)
+      || !require_contiguous(array6)   || !require_native(array6)) SWIG_fail;
+    
+    arg6 = (int*) array6->data;
+  }
+  {
+    npy_intp size[1] = {
+      -1
+    };
+    array7 = obj_to_array_contiguous_allow_conversion(obj6, PyArray_INT, &is_new_object7);
+    if (!array7 || !require_dimensions(array7,1) || !require_size(array7,size,1)
+      || !require_contiguous(array7)   || !require_native(array7)) SWIG_fail;
+    
+    arg7 = (int*) array7->data;
+  }
+  {
+    npy_intp size[1] = {
+      -1
+    };
+    array8 = obj_to_array_contiguous_allow_conversion(obj7, PyArray_INT, &is_new_object8);
+    if (!array8 || !require_dimensions(array8,1) || !require_size(array8,size,1)
+      || !require_contiguous(array8)   || !require_native(array8)) SWIG_fail;
+    
+    arg8 = (int*) array8->data;
+  }
+  {
+    temp9 = obj_to_array_no_conversion(obj8,PyArray_INT);
+    if (!temp9  || !require_contiguous(temp9) || !require_native(temp9)) SWIG_fail;
+    arg9 = (int*) array_data(temp9);
+  }
+  bsr_matvec<int,int >(arg1,arg2,arg3,arg4,(int const (*))arg5,(int const (*))arg6,(int const (*))arg7,(int const (*))arg8,arg9);
+  resultobj = SWIG_Py_Void();
+  {
+    if (is_new_object5 && array5) Py_DECREF(array5);
+  }
+  {
+    if (is_new_object6 && array6) Py_DECREF(array6);
+  }
+  {
+    if (is_new_object7 && array7) Py_DECREF(array7);
+  }
+  {
+    if (is_new_object8 && array8) Py_DECREF(array8);
+  }
+  return resultobj;
+fail:
+  {
+    if (is_new_object5 && array5) Py_DECREF(array5);
+  }
+  {
+    if (is_new_object6 && array6) Py_DECREF(array6);
+  }
+  {
+    if (is_new_object7 && array7) Py_DECREF(array7);
+  }
+  {
+    if (is_new_object8 && array8) Py_DECREF(array8);
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_bsr_matvec__SWIG_5(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  int arg1 ;
+  int arg2 ;
+  int arg3 ;
+  int arg4 ;
+  int *arg5 ;
+  int *arg6 ;
+  long long *arg7 ;
+  long long *arg8 ;
+  long long *arg9 ;
+  int val1 ;
+  int ecode1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  int val3 ;
+  int ecode3 = 0 ;
+  int val4 ;
+  int ecode4 = 0 ;
+  PyArrayObject *array5 = NULL ;
+  int is_new_object5 ;
+  PyArrayObject *array6 = NULL ;
+  int is_new_object6 ;
+  PyArrayObject *array7 = NULL ;
+  int is_new_object7 ;
+  PyArrayObject *array8 = NULL ;
+  int is_new_object8 ;
+  PyArrayObject *temp9 = NULL ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  PyObject * obj5 = 0 ;
+  PyObject * obj6 = 0 ;
+  PyObject * obj7 = 0 ;
+  PyObject * obj8 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOOOOOOOO:bsr_matvec",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6,&obj7,&obj8)) SWIG_fail;
+  ecode1 = SWIG_AsVal_int(obj0, &val1);
+  if (!SWIG_IsOK(ecode1)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "bsr_matvec" "', argument " "1"" of type '" "int""'");
+  } 
+  arg1 = static_cast< int >(val1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "bsr_matvec" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  ecode3 = SWIG_AsVal_int(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "bsr_matvec" "', argument " "3"" of type '" "int""'");
+  } 
+  arg3 = static_cast< int >(val3);
+  ecode4 = SWIG_AsVal_int(obj3, &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "bsr_matvec" "', argument " "4"" of type '" "int""'");
+  } 
+  arg4 = static_cast< int >(val4);
+  {
+    npy_intp size[1] = {
+      -1
+    };
+    array5 = obj_to_array_contiguous_allow_conversion(obj4, PyArray_INT, &is_new_object5);
+    if (!array5 || !require_dimensions(array5,1) || !require_size(array5,size,1)
+      || !require_contiguous(array5)   || !require_native(array5)) SWIG_fail;
+    
+    arg5 = (int*) array5->data;
+  }
+  {
+    npy_intp size[1] = {
+      -1
+    };
+    array6 = obj_to_array_contiguous_allow_conversion(obj5, PyArray_INT, &is_new_object6);
+    if (!array6 || !require_dimensions(array6,1) || !require_size(array6,size,1)
+      || !require_contiguous(array6)   || !require_native(array6)) SWIG_fail;
+    
+    arg6 = (int*) array6->data;
+  }
+  {
+    npy_intp size[1] = {
+      -1
+    };
+    array7 = obj_to_array_contiguous_allow_conversion(obj6, PyArray_LONGLONG, &is_new_object7);
+    if (!array7 || !require_dimensions(array7,1) || !require_size(array7,size,1)
+      || !require_contiguous(array7)   || !require_native(array7)) SWIG_fail;
+    
+    arg7 = (long long*) array7->data;
+  }
+  {
+    npy_intp size[1] = {
+      -1
+    };
+    array8 = obj_to_array_contiguous_allow_conversion(obj7, PyArray_LONGLONG, &is_new_object8);
+    if (!array8 || !require_dimensions(array8,1) || !require_size(array8,size,1)
+      || !require_contiguous(array8)   || !require_native(array8)) SWIG_fail;
+    
+    arg8 = (long long*) array8->data;
+  }
+  {
+    temp9 = obj_to_array_no_conversion(obj8,PyArray_LONGLONG);
+    if (!temp9  || !require_contiguous(temp9) || !require_native(temp9)) SWIG_fail;
+    arg9 = (long long*) array_data(temp9);
+  }
+  bsr_matvec<int,long long >(arg1,arg2,arg3,arg4,(int const (*))arg5,(int const (*))arg6,(long long const (*))arg7,(long long const (*))arg8,arg9);
+  resultobj = SWIG_Py_Void();
+  {
+    if (is_new_object5 && array5) Py_DECREF(array5);
+  }
+  {
+    if (is_new_object6 && array6) Py_DECREF(array6);
+  }
+  {
+    if (is_new_object7 && array7) Py_DECREF(array7);
+  }
+  {
+    if (is_new_object8 && array8) Py_DECREF(array8);
+  }
+  return resultobj;
+fail:
+  {
+    if (is_new_object5 && array5) Py_DECREF(array5);
+  }
+  {
+    if (is_new_object6 && array6) Py_DECREF(array6);
+  }
+  {
+    if (is_new_object7 && array7) Py_DECREF(array7);
+  }
+  {
+    if (is_new_object8 && array8) Py_DECREF(array8);
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_bsr_matvec__SWIG_6(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  int arg1 ;
+  int arg2 ;
+  int arg3 ;
+  int arg4 ;
+  int *arg5 ;
+  int *arg6 ;
+  float *arg7 ;
+  float *arg8 ;
+  float *arg9 ;
+  int val1 ;
+  int ecode1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  int val3 ;
+  int ecode3 = 0 ;
+  int val4 ;
+  int ecode4 = 0 ;
+  PyArrayObject *array5 = NULL ;
+  int is_new_object5 ;
+  PyArrayObject *array6 = NULL ;
+  int is_new_object6 ;
+  PyArrayObject *array7 = NULL ;
+  int is_new_object7 ;
+  PyArrayObject *array8 = NULL ;
+  int is_new_object8 ;
+  PyArrayObject *temp9 = NULL ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  PyObject * obj5 = 0 ;
+  PyObject * obj6 = 0 ;
+  PyObject * obj7 = 0 ;
+  PyObject * obj8 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOOOOOOOO:bsr_matvec",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6,&obj7,&obj8)) SWIG_fail;
+  ecode1 = SWIG_AsVal_int(obj0, &val1);
+  if (!SWIG_IsOK(ecode1)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "bsr_matvec" "', argument " "1"" of type '" "int""'");
+  } 
+  arg1 = static_cast< int >(val1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "bsr_matvec" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  ecode3 = SWIG_AsVal_int(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "bsr_matvec" "', argument " "3"" of type '" "int""'");
+  } 
+  arg3 = static_cast< int >(val3);
+  ecode4 = SWIG_AsVal_int(obj3, &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "bsr_matvec" "', argument " "4"" of type '" "int""'");
+  } 
+  arg4 = static_cast< int >(val4);
+  {
+    npy_intp size[1] = {
+      -1
+    };
+    array5 = obj_to_array_contiguous_allow_conversion(obj4, PyArray_INT, &is_new_object5);
+    if (!array5 || !require_dimensions(array5,1) || !require_size(array5,size,1)
+      || !require_contiguous(array5)   || !require_native(array5)) SWIG_fail;
+    
+    arg5 = (int*) array5->data;
+  }
+  {
+    npy_intp size[1] = {
+      -1
+    };
+    array6 = obj_to_array_contiguous_allow_conversion(obj5, PyArray_INT, &is_new_object6);
+    if (!array6 || !require_dimensions(array6,1) || !require_size(array6,size,1)
+      || !require_contiguous(array6)   || !require_native(array6)) SWIG_fail;
+    
+    arg6 = (int*) array6->data;
+  }
+  {
+    npy_intp size[1] = {
+      -1
+    };
+    array7 = obj_to_array_contiguous_allow_conversion(obj6, PyArray_FLOAT, &is_new_object7);
+    if (!array7 || !require_dimensions(array7,1) || !require_size(array7,size,1)
+      || !require_contiguous(array7)   || !require_native(array7)) SWIG_fail;
+    
+    arg7 = (float*) array7->data;
+  }
+  {
+    npy_intp size[1] = {
+      -1
+    };
+    array8 = obj_to_array_contiguous_allow_conversion(obj7, PyArray_FLOAT, &is_new_object8);
+    if (!array8 || !require_dimensions(array8,1) || !require_size(array8,size,1)
+      || !require_contiguous(array8)   || !require_native(array8)) SWIG_fail;
+    
+    arg8 = (float*) array8->data;
+  }
+  {
+    temp9 = obj_to_array_no_conversion(obj8,PyArray_FLOAT);
+    if (!temp9  || !require_contiguous(temp9) || !require_native(temp9)) SWIG_fail;
+    arg9 = (float*) array_data(temp9);
+  }
+  bsr_matvec<int,float >(arg1,arg2,arg3,arg4,(int const (*))arg5,(int const (*))arg6,(float const (*))arg7,(float const (*))arg8,arg9);
+  resultobj = SWIG_Py_Void();
+  {
+    if (is_new_object5 && array5) Py_DECREF(array5);
+  }
+  {
+    if (is_new_object6 && array6) Py_DECREF(array6);
+  }
+  {
+    if (is_new_object7 && array7) Py_DECREF(array7);
+  }
+  {
+    if (is_new_object8 && array8) Py_DECREF(array8);
+  }
+  return resultobj;
+fail:
+  {
+    if (is_new_object5 && array5) Py_DECREF(array5);
+  }
+  {
+    if (is_new_object6 && array6) Py_DECREF(array6);
+  }
+  {
+    if (is_new_object7 && array7) Py_DECREF(array7);
+  }
+  {
+    if (is_new_object8 && array8) Py_DECREF(array8);
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_bsr_matvec__SWIG_7(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  int arg1 ;
+  int arg2 ;
+  int arg3 ;
+  int arg4 ;
+  int *arg5 ;
+  int *arg6 ;
+  double *arg7 ;
+  double *arg8 ;
+  double *arg9 ;
+  int val1 ;
+  int ecode1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  int val3 ;
+  int ecode3 = 0 ;
+  int val4 ;
+  int ecode4 = 0 ;
+  PyArrayObject *array5 = NULL ;
+  int is_new_object5 ;
+  PyArrayObject *array6 = NULL ;
+  int is_new_object6 ;
+  PyArrayObject *array7 = NULL ;
+  int is_new_object7 ;
+  PyArrayObject *array8 = NULL ;
+  int is_new_object8 ;
+  PyArrayObject *temp9 = NULL ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  PyObject * obj5 = 0 ;
+  PyObject * obj6 = 0 ;
+  PyObject * obj7 = 0 ;
+  PyObject * obj8 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOOOOOOOO:bsr_matvec",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6,&obj7,&obj8)) SWIG_fail;
+  ecode1 = SWIG_AsVal_int(obj0, &val1);
+  if (!SWIG_IsOK(ecode1)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "bsr_matvec" "', argument " "1"" of type '" "int""'");
+  } 
+  arg1 = static_cast< int >(val1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "bsr_matvec" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  ecode3 = SWIG_AsVal_int(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "bsr_matvec" "', argument " "3"" of type '" "int""'");
+  } 
+  arg3 = static_cast< int >(val3);
+  ecode4 = SWIG_AsVal_int(obj3, &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "bsr_matvec" "', argument " "4"" of type '" "int""'");
+  } 
+  arg4 = static_cast< int >(val4);
+  {
+    npy_intp size[1] = {
+      -1
+    };
+    array5 = obj_to_array_contiguous_allow_conversion(obj4, PyArray_INT, &is_new_object5);
+    if (!array5 || !require_dimensions(array5,1) || !require_size(array5,size,1)
+      || !require_contiguous(array5)   || !require_native(array5)) SWIG_fail;
+    
+    arg5 = (int*) array5->data;
+  }
+  {
+    npy_intp size[1] = {
+      -1
+    };
+    array6 = obj_to_array_contiguous_allow_conversion(obj5, PyArray_INT, &is_new_object6);
+    if (!array6 || !require_dimensions(array6,1) || !require_size(array6,size,1)
+      || !require_contiguous(array6)   || !require_native(array6)) SWIG_fail;
+    
+    arg6 = (int*) array6->data;
+  }
+  {
+    npy_intp size[1] = {
+      -1
+    };
+    array7 = obj_to_array_contiguous_allow_conversion(obj6, PyArray_DOUBLE, &is_new_object7);
+    if (!array7 || !require_dimensions(array7,1) || !require_size(array7,size,1)
+      || !require_contiguous(array7)   || !require_native(array7)) SWIG_fail;
+    
+    arg7 = (double*) array7->data;
+  }
+  {
+    npy_intp size[1] = {
+      -1
+    };
+    array8 = obj_to_array_contiguous_allow_conversion(obj7, PyArray_DOUBLE, &is_new_object8);
+    if (!array8 || !require_dimensions(array8,1) || !require_size(array8,size,1)
+      || !require_contiguous(array8)   || !require_native(array8)) SWIG_fail;
+    
+    arg8 = (double*) array8->data;
+  }
+  {
+    temp9 = obj_to_array_no_conversion(obj8,PyArray_DOUBLE);
+    if (!temp9  || !require_contiguous(temp9) || !require_native(temp9)) SWIG_fail;
+    arg9 = (double*) array_data(temp9);
+  }
+  bsr_matvec<int,double >(arg1,arg2,arg3,arg4,(int const (*))arg5,(int const (*))arg6,(double const (*))arg7,(double const (*))arg8,arg9);
+  resultobj = SWIG_Py_Void();
+  {
+    if (is_new_object5 && array5) Py_DECREF(array5);
+  }
+  {
+    if (is_new_object6 && array6) Py_DECREF(array6);
+  }
+  {
+    if (is_new_object7 && array7) Py_DECREF(array7);
+  }
+  {
+    if (is_new_object8 && array8) Py_DECREF(array8);
+  }
+  return resultobj;
+fail:
+  {
+    if (is_new_object5 && array5) Py_DECREF(array5);
+  }
+  {
+    if (is_new_object6 && array6) Py_DECREF(array6);
+  }
+  {
+    if (is_new_object7 && array7) Py_DECREF(array7);
+  }
+  {
+    if (is_new_object8 && array8) Py_DECREF(array8);
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_bsr_matvec__SWIG_8(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  int arg1 ;
+  int arg2 ;
+  int arg3 ;
+  int arg4 ;
+  int *arg5 ;
+  int *arg6 ;
+  npy_cfloat_wrapper *arg7 ;
+  npy_cfloat_wrapper *arg8 ;
+  npy_cfloat_wrapper *arg9 ;
+  int val1 ;
+  int ecode1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  int val3 ;
+  int ecode3 = 0 ;
+  int val4 ;
+  int ecode4 = 0 ;
+  PyArrayObject *array5 = NULL ;
+  int is_new_object5 ;
+  PyArrayObject *array6 = NULL ;
+  int is_new_object6 ;
+  PyArrayObject *array7 = NULL ;
+  int is_new_object7 ;
+  PyArrayObject *array8 = NULL ;
+  int is_new_object8 ;
+  PyArrayObject *temp9 = NULL ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  PyObject * obj5 = 0 ;
+  PyObject * obj6 = 0 ;
+  PyObject * obj7 = 0 ;
+  PyObject * obj8 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOOOOOOOO:bsr_matvec",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6,&obj7,&obj8)) SWIG_fail;
+  ecode1 = SWIG_AsVal_int(obj0, &val1);
+  if (!SWIG_IsOK(ecode1)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "bsr_matvec" "', argument " "1"" of type '" "int""'");
+  } 
+  arg1 = static_cast< int >(val1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "bsr_matvec" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  ecode3 = SWIG_AsVal_int(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "bsr_matvec" "', argument " "3"" of type '" "int""'");
+  } 
+  arg3 = static_cast< int >(val3);
+  ecode4 = SWIG_AsVal_int(obj3, &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "bsr_matvec" "', argument " "4"" of type '" "int""'");
+  } 
+  arg4 = static_cast< int >(val4);
+  {
+    npy_intp size[1] = {
+      -1
+    };
+    array5 = obj_to_array_contiguous_allow_conversion(obj4, PyArray_INT, &is_new_object5);
+    if (!array5 || !require_dimensions(array5,1) || !require_size(array5,size,1)
+      || !require_contiguous(array5)   || !require_native(array5)) SWIG_fail;
+    
+    arg5 = (int*) array5->data;
+  }
+  {
+    npy_intp size[1] = {
+      -1
+    };
+    array6 = obj_to_array_contiguous_allow_conversion(obj5, PyArray_INT, &is_new_object6);
+    if (!array6 || !require_dimensions(array6,1) || !require_size(array6,size,1)
+      || !require_contiguous(array6)   || !require_native(array6)) SWIG_fail;
+    
+    arg6 = (int*) array6->data;
+  }
+  {
+    npy_intp size[1] = {
+      -1
+    };
+    array7 = obj_to_array_contiguous_allow_conversion(obj6, PyArray_CFLOAT, &is_new_object7);
+    if (!array7 || !require_dimensions(array7,1) || !require_size(array7,size,1)
+      || !require_contiguous(array7)   || !require_native(array7)) SWIG_fail;
+    
+    arg7 = (npy_cfloat_wrapper*) array7->data;
+  }
+  {
+    npy_intp size[1] = {
+      -1
+    };
+    array8 = obj_to_array_contiguous_allow_conversion(obj7, PyArray_CFLOAT, &is_new_object8);
+    if (!array8 || !require_dimensions(array8,1) || !require_size(array8,size,1)
+      || !require_contiguous(array8)   || !require_native(array8)) SWIG_fail;
+    
+    arg8 = (npy_cfloat_wrapper*) array8->data;
+  }
+  {
+    temp9 = obj_to_array_no_conversion(obj8,PyArray_CFLOAT);
+    if (!temp9  || !require_contiguous(temp9) || !require_native(temp9)) SWIG_fail;
+    arg9 = (npy_cfloat_wrapper*) array_data(temp9);
+  }
+  bsr_matvec<int,npy_cfloat_wrapper >(arg1,arg2,arg3,arg4,(int const (*))arg5,(int const (*))arg6,(npy_cfloat_wrapper const (*))arg7,(npy_cfloat_wrapper const (*))arg8,arg9);
+  resultobj = SWIG_Py_Void();
+  {
+    if (is_new_object5 && array5) Py_DECREF(array5);
+  }
+  {
+    if (is_new_object6 && array6) Py_DECREF(array6);
+  }
+  {
+    if (is_new_object7 && array7) Py_DECREF(array7);
+  }
+  {
+    if (is_new_object8 && array8) Py_DECREF(array8);
+  }
+  return resultobj;
+fail:
+  {
+    if (is_new_object5 && array5) Py_DECREF(array5);
+  }
+  {
+    if (is_new_object6 && array6) Py_DECREF(array6);
+  }
+  {
+    if (is_new_object7 && array7) Py_DECREF(array7);
+  }
+  {
+    if (is_new_object8 && array8) Py_DECREF(array8);
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_bsr_matvec__SWIG_9(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  int arg1 ;
+  int arg2 ;
+  int arg3 ;
+  int arg4 ;
+  int *arg5 ;
+  int *arg6 ;
+  npy_cdouble_wrapper *arg7 ;
+  npy_cdouble_wrapper *arg8 ;
+  npy_cdouble_wrapper *arg9 ;
+  int val1 ;
+  int ecode1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  int val3 ;
+  int ecode3 = 0 ;
+  int val4 ;
+  int ecode4 = 0 ;
+  PyArrayObject *array5 = NULL ;
+  int is_new_object5 ;
+  PyArrayObject *array6 = NULL ;
+  int is_new_object6 ;
+  PyArrayObject *array7 = NULL ;
+  int is_new_object7 ;
+  PyArrayObject *array8 = NULL ;
+  int is_new_object8 ;
+  PyArrayObject *temp9 = NULL ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  PyObject * obj5 = 0 ;
+  PyObject * obj6 = 0 ;
+  PyObject * obj7 = 0 ;
+  PyObject * obj8 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOOOOOOOO:bsr_matvec",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6,&obj7,&obj8)) SWIG_fail;
+  ecode1 = SWIG_AsVal_int(obj0, &val1);
+  if (!SWIG_IsOK(ecode1)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "bsr_matvec" "', argument " "1"" of type '" "int""'");
+  } 
+  arg1 = static_cast< int >(val1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "bsr_matvec" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  ecode3 = SWIG_AsVal_int(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "bsr_matvec" "', argument " "3"" of type '" "int""'");
+  } 
+  arg3 = static_cast< int >(val3);
+  ecode4 = SWIG_AsVal_int(obj3, &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "bsr_matvec" "', argument " "4"" of type '" "int""'");
+  } 
+  arg4 = static_cast< int >(val4);
+  {
+    npy_intp size[1] = {
+      -1
+    };
+    array5 = obj_to_array_contiguous_allow_conversion(obj4, PyArray_INT, &is_new_object5);
+    if (!array5 || !require_dimensions(array5,1) || !require_size(array5,size,1)
+      || !require_contiguous(array5)   || !require_native(array5)) SWIG_fail;
+    
+    arg5 = (int*) array5->data;
+  }
+  {
+    npy_intp size[1] = {
+      -1
+    };
+    array6 = obj_to_array_contiguous_allow_conversion(obj5, PyArray_INT, &is_new_object6);
+    if (!array6 || !require_dimensions(array6,1) || !require_size(array6,size,1)
+      || !require_contiguous(array6)   || !require_native(array6)) SWIG_fail;
+    
+    arg6 = (int*) array6->data;
+  }
+  {
+    npy_intp size[1] = {
+      -1
+    };
+    array7 = obj_to_array_contiguous_allow_conversion(obj6, PyArray_CDOUBLE, &is_new_object7);
+    if (!array7 || !require_dimensions(array7,1) || !require_size(array7,size,1)
+      || !require_contiguous(array7)   || !require_native(array7)) SWIG_fail;
+    
+    arg7 = (npy_cdouble_wrapper*) array7->data;
+  }
+  {
+    npy_intp size[1] = {
+      -1
+    };
+    array8 = obj_to_array_contiguous_allow_conversion(obj7, PyArray_CDOUBLE, &is_new_object8);
+    if (!array8 || !require_dimensions(array8,1) || !require_size(array8,size,1)
+      || !require_contiguous(array8)   || !require_native(array8)) SWIG_fail;
+    
+    arg8 = (npy_cdouble_wrapper*) array8->data;
+  }
+  {
+    temp9 = obj_to_array_no_conversion(obj8,PyArray_CDOUBLE);
+    if (!temp9  || !require_contiguous(temp9) || !require_native(temp9)) SWIG_fail;
+    arg9 = (npy_cdouble_wrapper*) array_data(temp9);
+  }
+  bsr_matvec<int,npy_cdouble_wrapper >(arg1,arg2,arg3,arg4,(int const (*))arg5,(int const (*))arg6,(npy_cdouble_wrapper const (*))arg7,(npy_cdouble_wrapper const (*))arg8,arg9);
+  resultobj = SWIG_Py_Void();
+  {
+    if (is_new_object5 && array5) Py_DECREF(array5);
+  }
+  {
+    if (is_new_object6 && array6) Py_DECREF(array6);
+  }
+  {
+    if (is_new_object7 && array7) Py_DECREF(array7);
+  }
+  {
+    if (is_new_object8 && array8) Py_DECREF(array8);
+  }
+  return resultobj;
+fail:
+  {
+    if (is_new_object5 && array5) Py_DECREF(array5);
+  }
+  {
+    if (is_new_object6 && array6) Py_DECREF(array6);
+  }
+  {
+    if (is_new_object7 && array7) Py_DECREF(array7);
+  }
+  {
+    if (is_new_object8 && array8) Py_DECREF(array8);
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_bsr_matvec(PyObject *self, PyObject *args) {
+  int argc;
+  PyObject *argv[10];
+  int ii;
+  
+  if (!PyTuple_Check(args)) SWIG_fail;
+  argc = (int)PyObject_Length(args);
+  for (ii = 0; (ii < argc) && (ii < 9); ii++) {
+    argv[ii] = PyTuple_GET_ITEM(args,ii);
+  }
+  if (argc == 9) {
+    int _v;
+    {
+      int res = SWIG_AsVal_int(argv[0], NULL);
+      _v = SWIG_CheckState(res);
+    }
+    if (_v) {
+      {
+        int res = SWIG_AsVal_int(argv[1], NULL);
+        _v = SWIG_CheckState(res);
+      }
+      if (_v) {
+        {
+          int res = SWIG_AsVal_int(argv[2], NULL);
+          _v = SWIG_CheckState(res);
+        }
+        if (_v) {
+          {
+            int res = SWIG_AsVal_int(argv[3], NULL);
+            _v = SWIG_CheckState(res);
+          }
+          if (_v) {
+            {
+              _v = (is_array(argv[4]) && PyArray_CanCastSafely(PyArray_TYPE(argv[4]),PyArray_INT)) ? 1 : 0;
+            }
+            if (_v) {
+              {
+                _v = (is_array(argv[5]) && PyArray_CanCastSafely(PyArray_TYPE(argv[5]),PyArray_INT)) ? 1 : 0;
+              }
+              if (_v) {
+                {
+                  _v = (is_array(argv[6]) && PyArray_CanCastSafely(PyArray_TYPE(argv[6]),PyArray_BYTE)) ? 1 : 0;
+                }
+                if (_v) {
+                  {
+                    _v = (is_array(argv[7]) && PyArray_CanCastSafely(PyArray_TYPE(argv[7]),PyArray_BYTE)) ? 1 : 0;
+                  }
+                  if (_v) {
+                    {
+                      _v = (is_array(argv[8]) && PyArray_CanCastSafely(PyArray_TYPE(argv[8]),PyArray_BYTE)) ? 1 : 0;
+                    }
+                    if (_v) {
+                      return _wrap_bsr_matvec__SWIG_1(self, args);
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  if (argc == 9) {
+    int _v;
+    {
+      int res = SWIG_AsVal_int(argv[0], NULL);
+      _v = SWIG_CheckState(res);
+    }
+    if (_v) {
+      {
+        int res = SWIG_AsVal_int(argv[1], NULL);
+        _v = SWIG_CheckState(res);
+      }
+      if (_v) {
+        {
+          int res = SWIG_AsVal_int(argv[2], NULL);
+          _v = SWIG_CheckState(res);
+        }
+        if (_v) {
+          {
+            int res = SWIG_AsVal_int(argv[3], NULL);
+            _v = SWIG_CheckState(res);
+          }
+          if (_v) {
+            {
+              _v = (is_array(argv[4]) && PyArray_CanCastSafely(PyArray_TYPE(argv[4]),PyArray_INT)) ? 1 : 0;
+            }
+            if (_v) {
+              {
+                _v = (is_array(argv[5]) && PyArray_CanCastSafely(PyArray_TYPE(argv[5]),PyArray_INT)) ? 1 : 0;
+              }
+              if (_v) {
+                {
+                  _v = (is_array(argv[6]) && PyArray_CanCastSafely(PyArray_TYPE(argv[6]),PyArray_UBYTE)) ? 1 : 0;
+                }
+                if (_v) {
+                  {
+                    _v = (is_array(argv[7]) && PyArray_CanCastSafely(PyArray_TYPE(argv[7]),PyArray_UBYTE)) ? 1 : 0;
+                  }
+                  if (_v) {
+                    {
+                      _v = (is_array(argv[8]) && PyArray_CanCastSafely(PyArray_TYPE(argv[8]),PyArray_UBYTE)) ? 1 : 0;
+                    }
+                    if (_v) {
+                      return _wrap_bsr_matvec__SWIG_2(self, args);
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  if (argc == 9) {
+    int _v;
+    {
+      int res = SWIG_AsVal_int(argv[0], NULL);
+      _v = SWIG_CheckState(res);
+    }
+    if (_v) {
+      {
+        int res = SWIG_AsVal_int(argv[1], NULL);
+        _v = SWIG_CheckState(res);
+      }
+      if (_v) {
+        {
+          int res = SWIG_AsVal_int(argv[2], NULL);
+          _v = SWIG_CheckState(res);
+        }
+        if (_v) {
+          {
+            int res = SWIG_AsVal_int(argv[3], NULL);
+            _v = SWIG_CheckState(res);
+          }
+          if (_v) {
+            {
+              _v = (is_array(argv[4]) && PyArray_CanCastSafely(PyArray_TYPE(argv[4]),PyArray_INT)) ? 1 : 0;
+            }
+            if (_v) {
+              {
+                _v = (is_array(argv[5]) && PyArray_CanCastSafely(PyArray_TYPE(argv[5]),PyArray_INT)) ? 1 : 0;
+              }
+              if (_v) {
+                {
+                  _v = (is_array(argv[6]) && PyArray_CanCastSafely(PyArray_TYPE(argv[6]),PyArray_SHORT)) ? 1 : 0;
+                }
+                if (_v) {
+                  {
+                    _v = (is_array(argv[7]) && PyArray_CanCastSafely(PyArray_TYPE(argv[7]),PyArray_SHORT)) ? 1 : 0;
+                  }
+                  if (_v) {
+                    {
+                      _v = (is_array(argv[8]) && PyArray_CanCastSafely(PyArray_TYPE(argv[8]),PyArray_SHORT)) ? 1 : 0;
+                    }
+                    if (_v) {
+                      return _wrap_bsr_matvec__SWIG_3(self, args);
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  if (argc == 9) {
+    int _v;
+    {
+      int res = SWIG_AsVal_int(argv[0], NULL);
+      _v = SWIG_CheckState(res);
+    }
+    if (_v) {
+      {
+        int res = SWIG_AsVal_int(argv[1], NULL);
+        _v = SWIG_CheckState(res);
+      }
+      if (_v) {
+        {
+          int res = SWIG_AsVal_int(argv[2], NULL);
+          _v = SWIG_CheckState(res);
+        }
+        if (_v) {
+          {
+            int res = SWIG_AsVal_int(argv[3], NULL);
+            _v = SWIG_CheckState(res);
+          }
+          if (_v) {
+            {
+              _v = (is_array(argv[4]) && PyArray_CanCastSafely(PyArray_TYPE(argv[4]),PyArray_INT)) ? 1 : 0;
+            }
+            if (_v) {
+              {
+                _v = (is_array(argv[5]) && PyArray_CanCastSafely(PyArray_TYPE(argv[5]),PyArray_INT)) ? 1 : 0;
+              }
+              if (_v) {
+                {
+                  _v = (is_array(argv[6]) && PyArray_CanCastSafely(PyArray_TYPE(argv[6]),PyArray_INT)) ? 1 : 0;
+                }
+                if (_v) {
+                  {
+                    _v = (is_array(argv[7]) && PyArray_CanCastSafely(PyArray_TYPE(argv[7]),PyArray_INT)) ? 1 : 0;
+                  }
+                  if (_v) {
+                    {
+                      _v = (is_array(argv[8]) && PyArray_CanCastSafely(PyArray_TYPE(argv[8]),PyArray_INT)) ? 1 : 0;
+                    }
+                    if (_v) {
+                      return _wrap_bsr_matvec__SWIG_4(self, args);
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  if (argc == 9) {
+    int _v;
+    {
+      int res = SWIG_AsVal_int(argv[0], NULL);
+      _v = SWIG_CheckState(res);
+    }
+    if (_v) {
+      {
+        int res = SWIG_AsVal_int(argv[1], NULL);
+        _v = SWIG_CheckState(res);
+      }
+      if (_v) {
+        {
+          int res = SWIG_AsVal_int(argv[2], NULL);
+          _v = SWIG_CheckState(res);
+        }
+        if (_v) {
+          {
+            int res = SWIG_AsVal_int(argv[3], NULL);
+            _v = SWIG_CheckState(res);
+          }
+          if (_v) {
+            {
+              _v = (is_array(argv[4]) && PyArray_CanCastSafely(PyArray_TYPE(argv[4]),PyArray_INT)) ? 1 : 0;
+            }
+            if (_v) {
+              {
+                _v = (is_array(argv[5]) && PyArray_CanCastSafely(PyArray_TYPE(argv[5]),PyArray_INT)) ? 1 : 0;
+              }
+              if (_v) {
+                {
+                  _v = (is_array(argv[6]) && PyArray_CanCastSafely(PyArray_TYPE(argv[6]),PyArray_LONGLONG)) ? 1 : 0;
+                }
+                if (_v) {
+                  {
+                    _v = (is_array(argv[7]) && PyArray_CanCastSafely(PyArray_TYPE(argv[7]),PyArray_LONGLONG)) ? 1 : 0;
+                  }
+                  if (_v) {
+                    {
+                      _v = (is_array(argv[8]) && PyArray_CanCastSafely(PyArray_TYPE(argv[8]),PyArray_LONGLONG)) ? 1 : 0;
+                    }
+                    if (_v) {
+                      return _wrap_bsr_matvec__SWIG_5(self, args);
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  if (argc == 9) {
+    int _v;
+    {
+      int res = SWIG_AsVal_int(argv[0], NULL);
+      _v = SWIG_CheckState(res);
+    }
+    if (_v) {
+      {
+        int res = SWIG_AsVal_int(argv[1], NULL);
+        _v = SWIG_CheckState(res);
+      }
+      if (_v) {
+        {
+          int res = SWIG_AsVal_int(argv[2], NULL);
+          _v = SWIG_CheckState(res);
+        }
+        if (_v) {
+          {
+            int res = SWIG_AsVal_int(argv[3], NULL);
+            _v = SWIG_CheckState(res);
+          }
+          if (_v) {
+            {
+              _v = (is_array(argv[4]) && PyArray_CanCastSafely(PyArray_TYPE(argv[4]),PyArray_INT)) ? 1 : 0;
+            }
+            if (_v) {
+              {
+                _v = (is_array(argv[5]) && PyArray_CanCastSafely(PyArray_TYPE(argv[5]),PyArray_INT)) ? 1 : 0;
+              }
+              if (_v) {
+                {
+                  _v = (is_array(argv[6]) && PyArray_CanCastSafely(PyArray_TYPE(argv[6]),PyArray_FLOAT)) ? 1 : 0;
+                }
+                if (_v) {
+                  {
+                    _v = (is_array(argv[7]) && PyArray_CanCastSafely(PyArray_TYPE(argv[7]),PyArray_FLOAT)) ? 1 : 0;
+                  }
+                  if (_v) {
+                    {
+                      _v = (is_array(argv[8]) && PyArray_CanCastSafely(PyArray_TYPE(argv[8]),PyArray_FLOAT)) ? 1 : 0;
+                    }
+                    if (_v) {
+                      return _wrap_bsr_matvec__SWIG_6(self, args);
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  if (argc == 9) {
+    int _v;
+    {
+      int res = SWIG_AsVal_int(argv[0], NULL);
+      _v = SWIG_CheckState(res);
+    }
+    if (_v) {
+      {
+        int res = SWIG_AsVal_int(argv[1], NULL);
+        _v = SWIG_CheckState(res);
+      }
+      if (_v) {
+        {
+          int res = SWIG_AsVal_int(argv[2], NULL);
+          _v = SWIG_CheckState(res);
+        }
+        if (_v) {
+          {
+            int res = SWIG_AsVal_int(argv[3], NULL);
+            _v = SWIG_CheckState(res);
+          }
+          if (_v) {
+            {
+              _v = (is_array(argv[4]) && PyArray_CanCastSafely(PyArray_TYPE(argv[4]),PyArray_INT)) ? 1 : 0;
+            }
+            if (_v) {
+              {
+                _v = (is_array(argv[5]) && PyArray_CanCastSafely(PyArray_TYPE(argv[5]),PyArray_INT)) ? 1 : 0;
+              }
+              if (_v) {
+                {
+                  _v = (is_array(argv[6]) && PyArray_CanCastSafely(PyArray_TYPE(argv[6]),PyArray_DOUBLE)) ? 1 : 0;
+                }
+                if (_v) {
+                  {
+                    _v = (is_array(argv[7]) && PyArray_CanCastSafely(PyArray_TYPE(argv[7]),PyArray_DOUBLE)) ? 1 : 0;
+                  }
+                  if (_v) {
+                    {
+                      _v = (is_array(argv[8]) && PyArray_CanCastSafely(PyArray_TYPE(argv[8]),PyArray_DOUBLE)) ? 1 : 0;
+                    }
+                    if (_v) {
+                      return _wrap_bsr_matvec__SWIG_7(self, args);
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  if (argc == 9) {
+    int _v;
+    {
+      int res = SWIG_AsVal_int(argv[0], NULL);
+      _v = SWIG_CheckState(res);
+    }
+    if (_v) {
+      {
+        int res = SWIG_AsVal_int(argv[1], NULL);
+        _v = SWIG_CheckState(res);
+      }
+      if (_v) {
+        {
+          int res = SWIG_AsVal_int(argv[2], NULL);
+          _v = SWIG_CheckState(res);
+        }
+        if (_v) {
+          {
+            int res = SWIG_AsVal_int(argv[3], NULL);
+            _v = SWIG_CheckState(res);
+          }
+          if (_v) {
+            {
+              _v = (is_array(argv[4]) && PyArray_CanCastSafely(PyArray_TYPE(argv[4]),PyArray_INT)) ? 1 : 0;
+            }
+            if (_v) {
+              {
+                _v = (is_array(argv[5]) && PyArray_CanCastSafely(PyArray_TYPE(argv[5]),PyArray_INT)) ? 1 : 0;
+              }
+              if (_v) {
+                {
+                  _v = (is_array(argv[6]) && PyArray_CanCastSafely(PyArray_TYPE(argv[6]),PyArray_CFLOAT)) ? 1 : 0;
+                }
+                if (_v) {
+                  {
+                    _v = (is_array(argv[7]) && PyArray_CanCastSafely(PyArray_TYPE(argv[7]),PyArray_CFLOAT)) ? 1 : 0;
+                  }
+                  if (_v) {
+                    {
+                      _v = (is_array(argv[8]) && PyArray_CanCastSafely(PyArray_TYPE(argv[8]),PyArray_CFLOAT)) ? 1 : 0;
+                    }
+                    if (_v) {
+                      return _wrap_bsr_matvec__SWIG_8(self, args);
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  if (argc == 9) {
+    int _v;
+    {
+      int res = SWIG_AsVal_int(argv[0], NULL);
+      _v = SWIG_CheckState(res);
+    }
+    if (_v) {
+      {
+        int res = SWIG_AsVal_int(argv[1], NULL);
+        _v = SWIG_CheckState(res);
+      }
+      if (_v) {
+        {
+          int res = SWIG_AsVal_int(argv[2], NULL);
+          _v = SWIG_CheckState(res);
+        }
+        if (_v) {
+          {
+            int res = SWIG_AsVal_int(argv[3], NULL);
+            _v = SWIG_CheckState(res);
+          }
+          if (_v) {
+            {
+              _v = (is_array(argv[4]) && PyArray_CanCastSafely(PyArray_TYPE(argv[4]),PyArray_INT)) ? 1 : 0;
+            }
+            if (_v) {
+              {
+                _v = (is_array(argv[5]) && PyArray_CanCastSafely(PyArray_TYPE(argv[5]),PyArray_INT)) ? 1 : 0;
+              }
+              if (_v) {
+                {
+                  _v = (is_array(argv[6]) && PyArray_CanCastSafely(PyArray_TYPE(argv[6]),PyArray_CDOUBLE)) ? 1 : 0;
+                }
+                if (_v) {
+                  {
+                    _v = (is_array(argv[7]) && PyArray_CanCastSafely(PyArray_TYPE(argv[7]),PyArray_CDOUBLE)) ? 1 : 0;
+                  }
+                  if (_v) {
+                    {
+                      _v = (is_array(argv[8]) && PyArray_CanCastSafely(PyArray_TYPE(argv[8]),PyArray_CDOUBLE)) ? 1 : 0;
+                    }
+                    if (_v) {
+                      return _wrap_bsr_matvec__SWIG_9(self, args);
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  
+fail:
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'bsr_matvec'.\n  Possible C/C++ prototypes are:\n""    bsr_matvec<(int,signed char)>(int const,int const,int const,int const,int const [],int const [],signed char const [],signed char const [],signed char [])\n""    bsr_matvec<(int,unsigned char)>(int const,int const,int const,int const,int const [],int const [],unsigned char const [],unsigned char const [],unsigned char [])\n""    bsr_matvec<(int,short)>(int const,int const,int const,int const,int const [],int const [],short const [],short const [],short [])\n""    bsr_matvec<(int,int)>(int const,int const,int const,int const,int const [],int const [],int const [],int const [],int [])\n""    bsr_matvec<(int,long long)>(int const,int const,int const,int const,int const [],int const [],long long const [],long long const [],long long [])\n""    bsr_matvec<(int,float)>(int const,int const,int const,int const,int const [],int const [],float const [],float const [],float [])\n""    bsr_matvec<(int,double)>(int const,int const,int const,int const,int const [],int const [],double const [],double const [],double [])\n""    bsr_matvec<(int,npy_cfloat_wrapper)>(int const,int const,int const,int const,int const [],int const [],npy_cfloat_wrapper const [],npy_cfloat_wrapper const [],npy_cfloat_wrapper [])\n""    bsr_matvec<(int,npy_cdouble_wrapper)>(int const,int const,int const,int const,int const [],int const [],npy_cdouble_wrapper const [],npy_cdouble_wrapper const [],npy_cdouble_wrapper [])\n");
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_csr_elmul_csr__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   int arg1 ;
@@ -37905,7 +39623,7 @@
 }
 
 
-SWIGINTERN PyObject *_wrap_sum_csr_duplicates__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_csr_sum_duplicates__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   int arg1 ;
   int arg2 ;
@@ -37925,15 +39643,15 @@
   PyObject * obj3 = 0 ;
   PyObject * obj4 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOOOO:sum_csr_duplicates",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OOOOO:csr_sum_duplicates",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
   ecode1 = SWIG_AsVal_int(obj0, &val1);
   if (!SWIG_IsOK(ecode1)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "sum_csr_duplicates" "', argument " "1"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "csr_sum_duplicates" "', argument " "1"" of type '" "int""'");
   } 
   arg1 = static_cast< int >(val1);
   ecode2 = SWIG_AsVal_int(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "sum_csr_duplicates" "', argument " "2"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "csr_sum_duplicates" "', argument " "2"" of type '" "int""'");
   } 
   arg2 = static_cast< int >(val2);
   {
@@ -37951,7 +39669,7 @@
     if (!temp5  || !require_contiguous(temp5) || !require_native(temp5)) SWIG_fail;
     arg5 = (signed char*) array_data(temp5);
   }
-  sum_csr_duplicates<int,signed char >(arg1,arg2,arg3,arg4,arg5);
+  csr_sum_duplicates<int,signed char >(arg1,arg2,arg3,arg4,arg5);
   resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
@@ -37959,7 +39677,7 @@
 }
 
 
-SWIGINTERN PyObject *_wrap_sum_csr_duplicates__SWIG_2(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_csr_sum_duplicates__SWIG_2(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   int arg1 ;
   int arg2 ;
@@ -37979,15 +39697,15 @@
   PyObject * obj3 = 0 ;
   PyObject * obj4 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOOOO:sum_csr_duplicates",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OOOOO:csr_sum_duplicates",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
   ecode1 = SWIG_AsVal_int(obj0, &val1);
   if (!SWIG_IsOK(ecode1)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "sum_csr_duplicates" "', argument " "1"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "csr_sum_duplicates" "', argument " "1"" of type '" "int""'");
   } 
   arg1 = static_cast< int >(val1);
   ecode2 = SWIG_AsVal_int(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "sum_csr_duplicates" "', argument " "2"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "csr_sum_duplicates" "', argument " "2"" of type '" "int""'");
   } 
   arg2 = static_cast< int >(val2);
   {
@@ -38005,7 +39723,7 @@
     if (!temp5  || !require_contiguous(temp5) || !require_native(temp5)) SWIG_fail;
     arg5 = (unsigned char*) array_data(temp5);
   }
-  sum_csr_duplicates<int,unsigned char >(arg1,arg2,arg3,arg4,arg5);
+  csr_sum_duplicates<int,unsigned char >(arg1,arg2,arg3,arg4,arg5);
   resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
@@ -38013,7 +39731,7 @@
 }
 
 
-SWIGINTERN PyObject *_wrap_sum_csr_duplicates__SWIG_3(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_csr_sum_duplicates__SWIG_3(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   int arg1 ;
   int arg2 ;
@@ -38033,15 +39751,15 @@
   PyObject * obj3 = 0 ;
   PyObject * obj4 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOOOO:sum_csr_duplicates",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OOOOO:csr_sum_duplicates",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
   ecode1 = SWIG_AsVal_int(obj0, &val1);
   if (!SWIG_IsOK(ecode1)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "sum_csr_duplicates" "', argument " "1"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "csr_sum_duplicates" "', argument " "1"" of type '" "int""'");
   } 
   arg1 = static_cast< int >(val1);
   ecode2 = SWIG_AsVal_int(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "sum_csr_duplicates" "', argument " "2"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "csr_sum_duplicates" "', argument " "2"" of type '" "int""'");
   } 
   arg2 = static_cast< int >(val2);
   {
@@ -38059,7 +39777,7 @@
     if (!temp5  || !require_contiguous(temp5) || !require_native(temp5)) SWIG_fail;
     arg5 = (short*) array_data(temp5);
   }
-  sum_csr_duplicates<int,short >(arg1,arg2,arg3,arg4,arg5);
+  csr_sum_duplicates<int,short >(arg1,arg2,arg3,arg4,arg5);
   resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
@@ -38067,7 +39785,7 @@
 }
 
 
-SWIGINTERN PyObject *_wrap_sum_csr_duplicates__SWIG_4(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_csr_sum_duplicates__SWIG_4(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   int arg1 ;
   int arg2 ;
@@ -38087,15 +39805,15 @@
   PyObject * obj3 = 0 ;
   PyObject * obj4 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOOOO:sum_csr_duplicates",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OOOOO:csr_sum_duplicates",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
   ecode1 = SWIG_AsVal_int(obj0, &val1);
   if (!SWIG_IsOK(ecode1)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "sum_csr_duplicates" "', argument " "1"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "csr_sum_duplicates" "', argument " "1"" of type '" "int""'");
   } 
   arg1 = static_cast< int >(val1);
   ecode2 = SWIG_AsVal_int(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "sum_csr_duplicates" "', argument " "2"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "csr_sum_duplicates" "', argument " "2"" of type '" "int""'");
   } 
   arg2 = static_cast< int >(val2);
   {
@@ -38113,7 +39831,7 @@
     if (!temp5  || !require_contiguous(temp5) || !require_native(temp5)) SWIG_fail;
     arg5 = (int*) array_data(temp5);
   }
-  sum_csr_duplicates<int,int >(arg1,arg2,arg3,arg4,arg5);
+  csr_sum_duplicates<int,int >(arg1,arg2,arg3,arg4,arg5);
   resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
@@ -38121,7 +39839,7 @@
 }
 
 
-SWIGINTERN PyObject *_wrap_sum_csr_duplicates__SWIG_5(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_csr_sum_duplicates__SWIG_5(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   int arg1 ;
   int arg2 ;
@@ -38141,15 +39859,15 @@
   PyObject * obj3 = 0 ;
   PyObject * obj4 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOOOO:sum_csr_duplicates",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OOOOO:csr_sum_duplicates",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
   ecode1 = SWIG_AsVal_int(obj0, &val1);
   if (!SWIG_IsOK(ecode1)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "sum_csr_duplicates" "', argument " "1"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "csr_sum_duplicates" "', argument " "1"" of type '" "int""'");
   } 
   arg1 = static_cast< int >(val1);
   ecode2 = SWIG_AsVal_int(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "sum_csr_duplicates" "', argument " "2"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "csr_sum_duplicates" "', argument " "2"" of type '" "int""'");
   } 
   arg2 = static_cast< int >(val2);
   {
@@ -38167,7 +39885,7 @@
     if (!temp5  || !require_contiguous(temp5) || !require_native(temp5)) SWIG_fail;
     arg5 = (long long*) array_data(temp5);
   }
-  sum_csr_duplicates<int,long long >(arg1,arg2,arg3,arg4,arg5);
+  csr_sum_duplicates<int,long long >(arg1,arg2,arg3,arg4,arg5);
   resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
@@ -38175,7 +39893,7 @@
 }
 
 
-SWIGINTERN PyObject *_wrap_sum_csr_duplicates__SWIG_6(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_csr_sum_duplicates__SWIG_6(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   int arg1 ;
   int arg2 ;
@@ -38195,15 +39913,15 @@
   PyObject * obj3 = 0 ;
   PyObject * obj4 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOOOO:sum_csr_duplicates",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OOOOO:csr_sum_duplicates",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
   ecode1 = SWIG_AsVal_int(obj0, &val1);
   if (!SWIG_IsOK(ecode1)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "sum_csr_duplicates" "', argument " "1"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "csr_sum_duplicates" "', argument " "1"" of type '" "int""'");
   } 
   arg1 = static_cast< int >(val1);
   ecode2 = SWIG_AsVal_int(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "sum_csr_duplicates" "', argument " "2"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "csr_sum_duplicates" "', argument " "2"" of type '" "int""'");
   } 
   arg2 = static_cast< int >(val2);
   {
@@ -38221,7 +39939,7 @@
     if (!temp5  || !require_contiguous(temp5) || !require_native(temp5)) SWIG_fail;
     arg5 = (float*) array_data(temp5);
   }
-  sum_csr_duplicates<int,float >(arg1,arg2,arg3,arg4,arg5);
+  csr_sum_duplicates<int,float >(arg1,arg2,arg3,arg4,arg5);
   resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
@@ -38229,7 +39947,7 @@
 }
 
 
-SWIGINTERN PyObject *_wrap_sum_csr_duplicates__SWIG_7(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_csr_sum_duplicates__SWIG_7(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   int arg1 ;
   int arg2 ;
@@ -38249,15 +39967,15 @@
   PyObject * obj3 = 0 ;
   PyObject * obj4 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOOOO:sum_csr_duplicates",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OOOOO:csr_sum_duplicates",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
   ecode1 = SWIG_AsVal_int(obj0, &val1);
   if (!SWIG_IsOK(ecode1)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "sum_csr_duplicates" "', argument " "1"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "csr_sum_duplicates" "', argument " "1"" of type '" "int""'");
   } 
   arg1 = static_cast< int >(val1);
   ecode2 = SWIG_AsVal_int(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "sum_csr_duplicates" "', argument " "2"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "csr_sum_duplicates" "', argument " "2"" of type '" "int""'");
   } 
   arg2 = static_cast< int >(val2);
   {
@@ -38275,7 +39993,7 @@
     if (!temp5  || !require_contiguous(temp5) || !require_native(temp5)) SWIG_fail;
     arg5 = (double*) array_data(temp5);
   }
-  sum_csr_duplicates<int,double >(arg1,arg2,arg3,arg4,arg5);
+  csr_sum_duplicates<int,double >(arg1,arg2,arg3,arg4,arg5);
   resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
@@ -38283,7 +40001,7 @@
 }
 
 
-SWIGINTERN PyObject *_wrap_sum_csr_duplicates__SWIG_8(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_csr_sum_duplicates__SWIG_8(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   int arg1 ;
   int arg2 ;
@@ -38303,15 +40021,15 @@
   PyObject * obj3 = 0 ;
   PyObject * obj4 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOOOO:sum_csr_duplicates",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OOOOO:csr_sum_duplicates",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
   ecode1 = SWIG_AsVal_int(obj0, &val1);
   if (!SWIG_IsOK(ecode1)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "sum_csr_duplicates" "', argument " "1"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "csr_sum_duplicates" "', argument " "1"" of type '" "int""'");
   } 
   arg1 = static_cast< int >(val1);
   ecode2 = SWIG_AsVal_int(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "sum_csr_duplicates" "', argument " "2"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "csr_sum_duplicates" "', argument " "2"" of type '" "int""'");
   } 
   arg2 = static_cast< int >(val2);
   {
@@ -38329,7 +40047,7 @@
     if (!temp5  || !require_contiguous(temp5) || !require_native(temp5)) SWIG_fail;
     arg5 = (npy_cfloat_wrapper*) array_data(temp5);
   }
-  sum_csr_duplicates<int,npy_cfloat_wrapper >(arg1,arg2,arg3,arg4,arg5);
+  csr_sum_duplicates<int,npy_cfloat_wrapper >(arg1,arg2,arg3,arg4,arg5);
   resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
@@ -38337,7 +40055,7 @@
 }
 
 
-SWIGINTERN PyObject *_wrap_sum_csr_duplicates__SWIG_9(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_csr_sum_duplicates__SWIG_9(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   int arg1 ;
   int arg2 ;
@@ -38357,15 +40075,15 @@
   PyObject * obj3 = 0 ;
   PyObject * obj4 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOOOO:sum_csr_duplicates",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OOOOO:csr_sum_duplicates",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
   ecode1 = SWIG_AsVal_int(obj0, &val1);
   if (!SWIG_IsOK(ecode1)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "sum_csr_duplicates" "', argument " "1"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "csr_sum_duplicates" "', argument " "1"" of type '" "int""'");
   } 
   arg1 = static_cast< int >(val1);
   ecode2 = SWIG_AsVal_int(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "sum_csr_duplicates" "', argument " "2"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "csr_sum_duplicates" "', argument " "2"" of type '" "int""'");
   } 
   arg2 = static_cast< int >(val2);
   {
@@ -38383,7 +40101,7 @@
     if (!temp5  || !require_contiguous(temp5) || !require_native(temp5)) SWIG_fail;
     arg5 = (npy_cdouble_wrapper*) array_data(temp5);
   }
-  sum_csr_duplicates<int,npy_cdouble_wrapper >(arg1,arg2,arg3,arg4,arg5);
+  csr_sum_duplicates<int,npy_cdouble_wrapper >(arg1,arg2,arg3,arg4,arg5);
   resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
@@ -38391,7 +40109,7 @@
 }
 
 
-SWIGINTERN PyObject *_wrap_sum_csr_duplicates(PyObject *self, PyObject *args) {
+SWIGINTERN PyObject *_wrap_csr_sum_duplicates(PyObject *self, PyObject *args) {
   int argc;
   PyObject *argv[6];
   int ii;
@@ -38425,7 +40143,7 @@
               _v = (is_array(argv[4]) && PyArray_CanCastSafely(PyArray_TYPE(argv[4]),PyArray_BYTE)) ? 1 : 0;
             }
             if (_v) {
-              return _wrap_sum_csr_duplicates__SWIG_1(self, args);
+              return _wrap_csr_sum_duplicates__SWIG_1(self, args);
             }
           }
         }
@@ -38456,7 +40174,7 @@
               _v = (is_array(argv[4]) && PyArray_CanCastSafely(PyArray_TYPE(argv[4]),PyArray_UBYTE)) ? 1 : 0;
             }
             if (_v) {
-              return _wrap_sum_csr_duplicates__SWIG_2(self, args);
+              return _wrap_csr_sum_duplicates__SWIG_2(self, args);
             }
           }
         }
@@ -38487,7 +40205,7 @@
               _v = (is_array(argv[4]) && PyArray_CanCastSafely(PyArray_TYPE(argv[4]),PyArray_SHORT)) ? 1 : 0;
             }
             if (_v) {
-              return _wrap_sum_csr_duplicates__SWIG_3(self, args);
+              return _wrap_csr_sum_duplicates__SWIG_3(self, args);
             }
           }
         }
@@ -38518,7 +40236,7 @@
               _v = (is_array(argv[4]) && PyArray_CanCastSafely(PyArray_TYPE(argv[4]),PyArray_INT)) ? 1 : 0;
             }
             if (_v) {
-              return _wrap_sum_csr_duplicates__SWIG_4(self, args);
+              return _wrap_csr_sum_duplicates__SWIG_4(self, args);
             }
           }
         }
@@ -38549,7 +40267,7 @@
               _v = (is_array(argv[4]) && PyArray_CanCastSafely(PyArray_TYPE(argv[4]),PyArray_LONGLONG)) ? 1 : 0;
             }
             if (_v) {
-              return _wrap_sum_csr_duplicates__SWIG_5(self, args);
+              return _wrap_csr_sum_duplicates__SWIG_5(self, args);
             }
           }
         }
@@ -38580,7 +40298,7 @@
               _v = (is_array(argv[4]) && PyArray_CanCastSafely(PyArray_TYPE(argv[4]),PyArray_FLOAT)) ? 1 : 0;
             }
             if (_v) {
-              return _wrap_sum_csr_duplicates__SWIG_6(self, args);
+              return _wrap_csr_sum_duplicates__SWIG_6(self, args);
             }
           }
         }
@@ -38611,7 +40329,7 @@
               _v = (is_array(argv[4]) && PyArray_CanCastSafely(PyArray_TYPE(argv[4]),PyArray_DOUBLE)) ? 1 : 0;
             }
             if (_v) {
-              return _wrap_sum_csr_duplicates__SWIG_7(self, args);
+              return _wrap_csr_sum_duplicates__SWIG_7(self, args);
             }
           }
         }
@@ -38642,7 +40360,7 @@
               _v = (is_array(argv[4]) && PyArray_CanCastSafely(PyArray_TYPE(argv[4]),PyArray_CFLOAT)) ? 1 : 0;
             }
             if (_v) {
-              return _wrap_sum_csr_duplicates__SWIG_8(self, args);
+              return _wrap_csr_sum_duplicates__SWIG_8(self, args);
             }
           }
         }
@@ -38673,7 +40391,7 @@
               _v = (is_array(argv[4]) && PyArray_CanCastSafely(PyArray_TYPE(argv[4]),PyArray_CDOUBLE)) ? 1 : 0;
             }
             if (_v) {
-              return _wrap_sum_csr_duplicates__SWIG_9(self, args);
+              return _wrap_csr_sum_duplicates__SWIG_9(self, args);
             }
           }
         }
@@ -38682,12 +40400,12 @@
   }
   
 fail:
-  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'sum_csr_duplicates'.\n  Possible C/C++ prototypes are:\n""    sum_csr_duplicates<(int,signed char)>(int const,int const,int [],int [],signed char [])\n""    sum_csr_duplicates<(int,unsigned char)>(int const,int const,int [],int [],unsigned char [])\n""    sum_csr_duplicates<(int,short)>(int const,int const,int [],int [],short [])\n""    sum_csr_duplicates<(int,int)>(int const,int const,int [],int [],int [])\n""    sum_csr_duplicates<(int,long long)>(int const,int const,int [],int [],long long [])\n""    sum_csr_duplicates<(int,float)>(int const,int const,int [],int [],float [])\n""    sum_csr_duplicates<(int,double)>(int const,int const,int [],int [],double [])\n""    sum_csr_duplicates<(int,npy_cfloat_wrapper)>(int const,int const,int [],int [],npy_cfloat_wrapper [])\n""    sum_csr_duplicates<(int,npy_cdouble_wrapper)>(int const,int const,int [],int [],npy_cdouble_wrapper [])\n");
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'csr_sum_duplicates'.\n  Possible C/C++ prototypes are:\n""    csr_sum_duplicates<(int,signed char)>(int const,int const,int [],int [],signed char [])\n""    csr_sum_duplicates<(int,unsigned char)>(int const,int const,int [],int [],unsigned char [])\n""    csr_sum_duplicates<(int,short)>(int const,int const,int [],int [],short [])\n""    csr_sum_duplicates<(int,int)>(int const,int const,int [],int [],int [])\n""    csr_sum_duplicates<(int,long long)>(int const,int const,int [],int [],long long [])\n""    csr_sum_duplicates<(int,float)>(int const,int const,int [],int [],float [])\n""    csr_sum_duplicates<(int,double)>(int const,int const,int [],int [],double [])\n""    csr_sum_duplicates<(int,npy_cfloat_wrapper)>(int const,int const,int [],int [],npy_cfloat_wrapper [])\n""    csr_sum_duplicates<(int,npy_cdouble_wrapper)>(int const,int const,int [],int [],npy_cdouble_wrapper [])\n");
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_sum_csc_duplicates__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_csc_sum_duplicates__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   int arg1 ;
   int arg2 ;
@@ -38707,15 +40425,15 @@
   PyObject * obj3 = 0 ;
   PyObject * obj4 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOOOO:sum_csc_duplicates",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OOOOO:csc_sum_duplicates",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
   ecode1 = SWIG_AsVal_int(obj0, &val1);
   if (!SWIG_IsOK(ecode1)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "sum_csc_duplicates" "', argument " "1"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "csc_sum_duplicates" "', argument " "1"" of type '" "int""'");
   } 
   arg1 = static_cast< int >(val1);
   ecode2 = SWIG_AsVal_int(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "sum_csc_duplicates" "', argument " "2"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "csc_sum_duplicates" "', argument " "2"" of type '" "int""'");
   } 
   arg2 = static_cast< int >(val2);
   {
@@ -38733,7 +40451,7 @@
     if (!temp5  || !require_contiguous(temp5) || !require_native(temp5)) SWIG_fail;
     arg5 = (signed char*) array_data(temp5);
   }
-  sum_csc_duplicates<int,signed char >(arg1,arg2,arg3,arg4,arg5);
+  csc_sum_duplicates<int,signed char >(arg1,arg2,arg3,arg4,arg5);
   resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
@@ -38741,7 +40459,7 @@
 }
 
 
-SWIGINTERN PyObject *_wrap_sum_csc_duplicates__SWIG_2(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_csc_sum_duplicates__SWIG_2(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   int arg1 ;
   int arg2 ;
@@ -38761,15 +40479,15 @@
   PyObject * obj3 = 0 ;
   PyObject * obj4 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOOOO:sum_csc_duplicates",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OOOOO:csc_sum_duplicates",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
   ecode1 = SWIG_AsVal_int(obj0, &val1);
   if (!SWIG_IsOK(ecode1)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "sum_csc_duplicates" "', argument " "1"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "csc_sum_duplicates" "', argument " "1"" of type '" "int""'");
   } 
   arg1 = static_cast< int >(val1);
   ecode2 = SWIG_AsVal_int(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "sum_csc_duplicates" "', argument " "2"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "csc_sum_duplicates" "', argument " "2"" of type '" "int""'");
   } 
   arg2 = static_cast< int >(val2);
   {
@@ -38787,7 +40505,7 @@
     if (!temp5  || !require_contiguous(temp5) || !require_native(temp5)) SWIG_fail;
     arg5 = (unsigned char*) array_data(temp5);
   }
-  sum_csc_duplicates<int,unsigned char >(arg1,arg2,arg3,arg4,arg5);
+  csc_sum_duplicates<int,unsigned char >(arg1,arg2,arg3,arg4,arg5);
   resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
@@ -38795,7 +40513,7 @@
 }
 
 
-SWIGINTERN PyObject *_wrap_sum_csc_duplicates__SWIG_3(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_csc_sum_duplicates__SWIG_3(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   int arg1 ;
   int arg2 ;
@@ -38815,15 +40533,15 @@
   PyObject * obj3 = 0 ;
   PyObject * obj4 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOOOO:sum_csc_duplicates",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OOOOO:csc_sum_duplicates",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
   ecode1 = SWIG_AsVal_int(obj0, &val1);
   if (!SWIG_IsOK(ecode1)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "sum_csc_duplicates" "', argument " "1"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "csc_sum_duplicates" "', argument " "1"" of type '" "int""'");
   } 
   arg1 = static_cast< int >(val1);
   ecode2 = SWIG_AsVal_int(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "sum_csc_duplicates" "', argument " "2"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "csc_sum_duplicates" "', argument " "2"" of type '" "int""'");
   } 
   arg2 = static_cast< int >(val2);
   {
@@ -38841,7 +40559,7 @@
     if (!temp5  || !require_contiguous(temp5) || !require_native(temp5)) SWIG_fail;
     arg5 = (short*) array_data(temp5);
   }
-  sum_csc_duplicates<int,short >(arg1,arg2,arg3,arg4,arg5);
+  csc_sum_duplicates<int,short >(arg1,arg2,arg3,arg4,arg5);
   resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
@@ -38849,7 +40567,7 @@
 }
 
 
-SWIGINTERN PyObject *_wrap_sum_csc_duplicates__SWIG_4(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_csc_sum_duplicates__SWIG_4(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   int arg1 ;
   int arg2 ;
@@ -38869,15 +40587,15 @@
   PyObject * obj3 = 0 ;
   PyObject * obj4 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOOOO:sum_csc_duplicates",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OOOOO:csc_sum_duplicates",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
   ecode1 = SWIG_AsVal_int(obj0, &val1);
   if (!SWIG_IsOK(ecode1)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "sum_csc_duplicates" "', argument " "1"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "csc_sum_duplicates" "', argument " "1"" of type '" "int""'");
   } 
   arg1 = static_cast< int >(val1);
   ecode2 = SWIG_AsVal_int(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "sum_csc_duplicates" "', argument " "2"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "csc_sum_duplicates" "', argument " "2"" of type '" "int""'");
   } 
   arg2 = static_cast< int >(val2);
   {
@@ -38895,7 +40613,7 @@
     if (!temp5  || !require_contiguous(temp5) || !require_native(temp5)) SWIG_fail;
     arg5 = (int*) array_data(temp5);
   }
-  sum_csc_duplicates<int,int >(arg1,arg2,arg3,arg4,arg5);
+  csc_sum_duplicates<int,int >(arg1,arg2,arg3,arg4,arg5);
   resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
@@ -38903,7 +40621,7 @@
 }
 
 
-SWIGINTERN PyObject *_wrap_sum_csc_duplicates__SWIG_5(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_csc_sum_duplicates__SWIG_5(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   int arg1 ;
   int arg2 ;
@@ -38923,15 +40641,15 @@
   PyObject * obj3 = 0 ;
   PyObject * obj4 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOOOO:sum_csc_duplicates",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OOOOO:csc_sum_duplicates",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
   ecode1 = SWIG_AsVal_int(obj0, &val1);
   if (!SWIG_IsOK(ecode1)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "sum_csc_duplicates" "', argument " "1"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "csc_sum_duplicates" "', argument " "1"" of type '" "int""'");
   } 
   arg1 = static_cast< int >(val1);
   ecode2 = SWIG_AsVal_int(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "sum_csc_duplicates" "', argument " "2"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "csc_sum_duplicates" "', argument " "2"" of type '" "int""'");
   } 
   arg2 = static_cast< int >(val2);
   {
@@ -38949,7 +40667,7 @@
     if (!temp5  || !require_contiguous(temp5) || !require_native(temp5)) SWIG_fail;
     arg5 = (long long*) array_data(temp5);
   }
-  sum_csc_duplicates<int,long long >(arg1,arg2,arg3,arg4,arg5);
+  csc_sum_duplicates<int,long long >(arg1,arg2,arg3,arg4,arg5);
   resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
@@ -38957,7 +40675,7 @@
 }
 
 
-SWIGINTERN PyObject *_wrap_sum_csc_duplicates__SWIG_6(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_csc_sum_duplicates__SWIG_6(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   int arg1 ;
   int arg2 ;
@@ -38977,15 +40695,15 @@
   PyObject * obj3 = 0 ;
   PyObject * obj4 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOOOO:sum_csc_duplicates",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OOOOO:csc_sum_duplicates",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
   ecode1 = SWIG_AsVal_int(obj0, &val1);
   if (!SWIG_IsOK(ecode1)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "sum_csc_duplicates" "', argument " "1"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "csc_sum_duplicates" "', argument " "1"" of type '" "int""'");
   } 
   arg1 = static_cast< int >(val1);
   ecode2 = SWIG_AsVal_int(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "sum_csc_duplicates" "', argument " "2"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "csc_sum_duplicates" "', argument " "2"" of type '" "int""'");
   } 
   arg2 = static_cast< int >(val2);
   {
@@ -39003,7 +40721,7 @@
     if (!temp5  || !require_contiguous(temp5) || !require_native(temp5)) SWIG_fail;
     arg5 = (float*) array_data(temp5);
   }
-  sum_csc_duplicates<int,float >(arg1,arg2,arg3,arg4,arg5);
+  csc_sum_duplicates<int,float >(arg1,arg2,arg3,arg4,arg5);
   resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
@@ -39011,7 +40729,7 @@
 }
 
 
-SWIGINTERN PyObject *_wrap_sum_csc_duplicates__SWIG_7(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_csc_sum_duplicates__SWIG_7(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   int arg1 ;
   int arg2 ;
@@ -39031,15 +40749,15 @@
   PyObject * obj3 = 0 ;
   PyObject * obj4 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOOOO:sum_csc_duplicates",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OOOOO:csc_sum_duplicates",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
   ecode1 = SWIG_AsVal_int(obj0, &val1);
   if (!SWIG_IsOK(ecode1)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "sum_csc_duplicates" "', argument " "1"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "csc_sum_duplicates" "', argument " "1"" of type '" "int""'");
   } 
   arg1 = static_cast< int >(val1);
   ecode2 = SWIG_AsVal_int(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "sum_csc_duplicates" "', argument " "2"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "csc_sum_duplicates" "', argument " "2"" of type '" "int""'");
   } 
   arg2 = static_cast< int >(val2);
   {
@@ -39057,7 +40775,7 @@
     if (!temp5  || !require_contiguous(temp5) || !require_native(temp5)) SWIG_fail;
     arg5 = (double*) array_data(temp5);
   }
-  sum_csc_duplicates<int,double >(arg1,arg2,arg3,arg4,arg5);
+  csc_sum_duplicates<int,double >(arg1,arg2,arg3,arg4,arg5);
   resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
@@ -39065,7 +40783,7 @@
 }
 
 
-SWIGINTERN PyObject *_wrap_sum_csc_duplicates__SWIG_8(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_csc_sum_duplicates__SWIG_8(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   int arg1 ;
   int arg2 ;
@@ -39085,15 +40803,15 @@
   PyObject * obj3 = 0 ;
   PyObject * obj4 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOOOO:sum_csc_duplicates",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OOOOO:csc_sum_duplicates",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
   ecode1 = SWIG_AsVal_int(obj0, &val1);
   if (!SWIG_IsOK(ecode1)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "sum_csc_duplicates" "', argument " "1"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "csc_sum_duplicates" "', argument " "1"" of type '" "int""'");
   } 
   arg1 = static_cast< int >(val1);
   ecode2 = SWIG_AsVal_int(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "sum_csc_duplicates" "', argument " "2"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "csc_sum_duplicates" "', argument " "2"" of type '" "int""'");
   } 
   arg2 = static_cast< int >(val2);
   {
@@ -39111,7 +40829,7 @@
     if (!temp5  || !require_contiguous(temp5) || !require_native(temp5)) SWIG_fail;
     arg5 = (npy_cfloat_wrapper*) array_data(temp5);
   }
-  sum_csc_duplicates<int,npy_cfloat_wrapper >(arg1,arg2,arg3,arg4,arg5);
+  csc_sum_duplicates<int,npy_cfloat_wrapper >(arg1,arg2,arg3,arg4,arg5);
   resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
@@ -39119,7 +40837,7 @@
 }
 
 
-SWIGINTERN PyObject *_wrap_sum_csc_duplicates__SWIG_9(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_csc_sum_duplicates__SWIG_9(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   int arg1 ;
   int arg2 ;
@@ -39139,15 +40857,15 @@
   PyObject * obj3 = 0 ;
   PyObject * obj4 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOOOO:sum_csc_duplicates",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OOOOO:csc_sum_duplicates",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
   ecode1 = SWIG_AsVal_int(obj0, &val1);
   if (!SWIG_IsOK(ecode1)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "sum_csc_duplicates" "', argument " "1"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "csc_sum_duplicates" "', argument " "1"" of type '" "int""'");
   } 
   arg1 = static_cast< int >(val1);
   ecode2 = SWIG_AsVal_int(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "sum_csc_duplicates" "', argument " "2"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "csc_sum_duplicates" "', argument " "2"" of type '" "int""'");
   } 
   arg2 = static_cast< int >(val2);
   {
@@ -39165,7 +40883,7 @@
     if (!temp5  || !require_contiguous(temp5) || !require_native(temp5)) SWIG_fail;
     arg5 = (npy_cdouble_wrapper*) array_data(temp5);
   }
-  sum_csc_duplicates<int,npy_cdouble_wrapper >(arg1,arg2,arg3,arg4,arg5);
+  csc_sum_duplicates<int,npy_cdouble_wrapper >(arg1,arg2,arg3,arg4,arg5);
   resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
@@ -39173,7 +40891,7 @@
 }
 
 
-SWIGINTERN PyObject *_wrap_sum_csc_duplicates(PyObject *self, PyObject *args) {
+SWIGINTERN PyObject *_wrap_csc_sum_duplicates(PyObject *self, PyObject *args) {
   int argc;
   PyObject *argv[6];
   int ii;
@@ -39207,7 +40925,7 @@
               _v = (is_array(argv[4]) && PyArray_CanCastSafely(PyArray_TYPE(argv[4]),PyArray_BYTE)) ? 1 : 0;
             }
             if (_v) {
-              return _wrap_sum_csc_duplicates__SWIG_1(self, args);
+              return _wrap_csc_sum_duplicates__SWIG_1(self, args);
             }
           }
         }
@@ -39238,7 +40956,7 @@
               _v = (is_array(argv[4]) && PyArray_CanCastSafely(PyArray_TYPE(argv[4]),PyArray_UBYTE)) ? 1 : 0;
             }
             if (_v) {
-              return _wrap_sum_csc_duplicates__SWIG_2(self, args);
+              return _wrap_csc_sum_duplicates__SWIG_2(self, args);
             }
           }
         }
@@ -39269,7 +40987,7 @@
               _v = (is_array(argv[4]) && PyArray_CanCastSafely(PyArray_TYPE(argv[4]),PyArray_SHORT)) ? 1 : 0;
             }
             if (_v) {
-              return _wrap_sum_csc_duplicates__SWIG_3(self, args);
+              return _wrap_csc_sum_duplicates__SWIG_3(self, args);
             }
           }
         }
@@ -39300,7 +41018,7 @@
               _v = (is_array(argv[4]) && PyArray_CanCastSafely(PyArray_TYPE(argv[4]),PyArray_INT)) ? 1 : 0;
             }
             if (_v) {
-              return _wrap_sum_csc_duplicates__SWIG_4(self, args);
+              return _wrap_csc_sum_duplicates__SWIG_4(self, args);
             }
           }
         }
@@ -39331,7 +41049,7 @@
               _v = (is_array(argv[4]) && PyArray_CanCastSafely(PyArray_TYPE(argv[4]),PyArray_LONGLONG)) ? 1 : 0;
             }
             if (_v) {
-              return _wrap_sum_csc_duplicates__SWIG_5(self, args);
+              return _wrap_csc_sum_duplicates__SWIG_5(self, args);
             }
           }
         }
@@ -39362,7 +41080,7 @@
               _v = (is_array(argv[4]) && PyArray_CanCastSafely(PyArray_TYPE(argv[4]),PyArray_FLOAT)) ? 1 : 0;
             }
             if (_v) {
-              return _wrap_sum_csc_duplicates__SWIG_6(self, args);
+              return _wrap_csc_sum_duplicates__SWIG_6(self, args);
             }
           }
         }
@@ -39393,7 +41111,7 @@
               _v = (is_array(argv[4]) && PyArray_CanCastSafely(PyArray_TYPE(argv[4]),PyArray_DOUBLE)) ? 1 : 0;
             }
             if (_v) {
-              return _wrap_sum_csc_duplicates__SWIG_7(self, args);
+              return _wrap_csc_sum_duplicates__SWIG_7(self, args);
             }
           }
         }
@@ -39424,7 +41142,7 @@
               _v = (is_array(argv[4]) && PyArray_CanCastSafely(PyArray_TYPE(argv[4]),PyArray_CFLOAT)) ? 1 : 0;
             }
             if (_v) {
-              return _wrap_sum_csc_duplicates__SWIG_8(self, args);
+              return _wrap_csc_sum_duplicates__SWIG_8(self, args);
             }
           }
         }
@@ -39455,7 +41173,7 @@
               _v = (is_array(argv[4]) && PyArray_CanCastSafely(PyArray_TYPE(argv[4]),PyArray_CDOUBLE)) ? 1 : 0;
             }
             if (_v) {
-              return _wrap_sum_csc_duplicates__SWIG_9(self, args);
+              return _wrap_csc_sum_duplicates__SWIG_9(self, args);
             }
           }
         }
@@ -39464,7 +41182,7 @@
   }
   
 fail:
-  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'sum_csc_duplicates'.\n  Possible C/C++ prototypes are:\n""    sum_csc_duplicates<(int,signed char)>(int const,int const,int [],int [],signed char [])\n""    sum_csc_duplicates<(int,unsigned char)>(int const,int const,int [],int [],unsigned char [])\n""    sum_csc_duplicates<(int,short)>(int const,int const,int [],int [],short [])\n""    sum_csc_duplicates<(int,int)>(int const,int const,int [],int [],int [])\n""    sum_csc_duplicates<(int,long long)>(int const,int const,int [],int [],long long [])\n""    sum_csc_duplicates<(int,float)>(int const,int const,int [],int [],float [])\n""    sum_csc_duplicates<(int,double)>(int const,int const,int [],int [],double [])\n""    sum_csc_duplicates<(int,npy_cfloat_wrapper)>(int const,int const,int [],int [],npy_cfloat_wrapper [])\n""    sum_csc_duplicates<(int,npy_cdouble_wrapper)>(int const,int const,int [],int [],npy_cdouble_wrapper [])\n");
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'csc_sum_duplicates'.\n  Possible C/C++ prototypes are:\n""    csc_sum_duplicates<(int,signed char)>(int const,int const,int [],int [],signed char [])\n""    csc_sum_duplicates<(int,unsigned char)>(int const,int const,int [],int [],unsigned char [])\n""    csc_sum_duplicates<(int,short)>(int const,int const,int [],int [],short [])\n""    csc_sum_duplicates<(int,int)>(int const,int const,int [],int [],int [])\n""    csc_sum_duplicates<(int,long long)>(int const,int const,int [],int [],long long [])\n""    csc_sum_duplicates<(int,float)>(int const,int const,int [],int [],float [])\n""    csc_sum_duplicates<(int,double)>(int const,int const,int [],int [],double [])\n""    csc_sum_duplicates<(int,npy_cfloat_wrapper)>(int const,int const,int [],int [],npy_cfloat_wrapper [])\n""    csc_sum_duplicates<(int,npy_cdouble_wrapper)>(int const,int const,int [],int [],npy_cdouble_wrapper [])\n");
   return NULL;
 }
 
@@ -41678,6 +43396,28 @@
 		"csc_matvec(int n_row, int n_col, int Ap, int Ai, npy_cdouble_wrapper Ax, \n"
 		"    npy_cdouble_wrapper Xx, npy_cdouble_wrapper Yx)\n"
 		""},
+	 { (char *)"bsr_matvec", _wrap_bsr_matvec, METH_VARARGS, (char *)"\n"
+		"bsr_matvec(int n_row, int n_col, int R, int C, int Ap, int Aj, \n"
+		"    signed char Ax, signed char Xx, signed char Yx)\n"
+		"bsr_matvec(int n_row, int n_col, int R, int C, int Ap, int Aj, \n"
+		"    unsigned char Ax, unsigned char Xx, unsigned char Yx)\n"
+		"bsr_matvec(int n_row, int n_col, int R, int C, int Ap, int Aj, \n"
+		"    short Ax, short Xx, short Yx)\n"
+		"bsr_matvec(int n_row, int n_col, int R, int C, int Ap, int Aj, \n"
+		"    int Ax, int Xx, int Yx)\n"
+		"bsr_matvec(int n_row, int n_col, int R, int C, int Ap, int Aj, \n"
+		"    long long Ax, long long Xx, long long Yx)\n"
+		"bsr_matvec(int n_row, int n_col, int R, int C, int Ap, int Aj, \n"
+		"    float Ax, float Xx, float Yx)\n"
+		"bsr_matvec(int n_row, int n_col, int R, int C, int Ap, int Aj, \n"
+		"    double Ax, double Xx, double Yx)\n"
+		"bsr_matvec(int n_row, int n_col, int R, int C, int Ap, int Aj, \n"
+		"    npy_cfloat_wrapper Ax, npy_cfloat_wrapper Xx, \n"
+		"    npy_cfloat_wrapper Yx)\n"
+		"bsr_matvec(int n_row, int n_col, int R, int C, int Ap, int Aj, \n"
+		"    npy_cdouble_wrapper Ax, npy_cdouble_wrapper Xx, \n"
+		"    npy_cdouble_wrapper Yx)\n"
+		""},
 	 { (char *)"csr_elmul_csr", _wrap_csr_elmul_csr, METH_VARARGS, (char *)"\n"
 		"csr_elmul_csr(int n_row, int n_col, int Ap, int Aj, signed char Ax, \n"
 		"    int Bp, int Bj, signed char Bx, std::vector<(int)> Cp, \n"
@@ -41948,27 +43688,27 @@
 		"csc_sort_indices(int n_row, int n_col, int Ap, int Ai, npy_cfloat_wrapper Ax)\n"
 		"csc_sort_indices(int n_row, int n_col, int Ap, int Ai, npy_cdouble_wrapper Ax)\n"
 		""},
-	 { (char *)"sum_csr_duplicates", _wrap_sum_csr_duplicates, METH_VARARGS, (char *)"\n"
-		"sum_csr_duplicates(int n_row, int n_col, int Ap, int Aj, signed char Ax)\n"
-		"sum_csr_duplicates(int n_row, int n_col, int Ap, int Aj, unsigned char Ax)\n"
-		"sum_csr_duplicates(int n_row, int n_col, int Ap, int Aj, short Ax)\n"
-		"sum_csr_duplicates(int n_row, int n_col, int Ap, int Aj, int Ax)\n"
-		"sum_csr_duplicates(int n_row, int n_col, int Ap, int Aj, long long Ax)\n"
-		"sum_csr_duplicates(int n_row, int n_col, int Ap, int Aj, float Ax)\n"
-		"sum_csr_duplicates(int n_row, int n_col, int Ap, int Aj, double Ax)\n"
-		"sum_csr_duplicates(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax)\n"
-		"sum_csr_duplicates(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax)\n"
+	 { (char *)"csr_sum_duplicates", _wrap_csr_sum_duplicates, METH_VARARGS, (char *)"\n"
+		"csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, signed char Ax)\n"
+		"csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, unsigned char Ax)\n"
+		"csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, short Ax)\n"
+		"csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, int Ax)\n"
+		"csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, long long Ax)\n"
+		"csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, float Ax)\n"
+		"csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, double Ax)\n"
+		"csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, npy_cfloat_wrapper Ax)\n"
+		"csr_sum_duplicates(int n_row, int n_col, int Ap, int Aj, npy_cdouble_wrapper Ax)\n"
 		""},
-	 { (char *)"sum_csc_duplicates", _wrap_sum_csc_duplicates, METH_VARARGS, (char *)"\n"
-		"sum_csc_duplicates(int n_row, int n_col, int Ap, int Ai, signed char Ax)\n"
-		"sum_csc_duplicates(int n_row, int n_col, int Ap, int Ai, unsigned char Ax)\n"
-		"sum_csc_duplicates(int n_row, int n_col, int Ap, int Ai, short Ax)\n"
-		"sum_csc_duplicates(int n_row, int n_col, int Ap, int Ai, int Ax)\n"
-		"sum_csc_duplicates(int n_row, int n_col, int Ap, int Ai, long long Ax)\n"
-		"sum_csc_duplicates(int n_row, int n_col, int Ap, int Ai, float Ax)\n"
-		"sum_csc_duplicates(int n_row, int n_col, int Ap, int Ai, double Ax)\n"
-		"sum_csc_duplicates(int n_row, int n_col, int Ap, int Ai, npy_cfloat_wrapper Ax)\n"
-		"sum_csc_duplicates(int n_row, int n_col, int Ap, int Ai, npy_cdouble_wrapper Ax)\n"
+	 { (char *)"csc_sum_duplicates", _wrap_csc_sum_duplicates, METH_VARARGS, (char *)"\n"
+		"csc_sum_duplicates(int n_row, int n_col, int Ap, int Ai, signed char Ax)\n"
+		"csc_sum_duplicates(int n_row, int n_col, int Ap, int Ai, unsigned char Ax)\n"
+		"csc_sum_duplicates(int n_row, int n_col, int Ap, int Ai, short Ax)\n"
+		"csc_sum_duplicates(int n_row, int n_col, int Ap, int Ai, int Ax)\n"
+		"csc_sum_duplicates(int n_row, int n_col, int Ap, int Ai, long long Ax)\n"
+		"csc_sum_duplicates(int n_row, int n_col, int Ap, int Ai, float Ax)\n"
+		"csc_sum_duplicates(int n_row, int n_col, int Ap, int Ai, double Ax)\n"
+		"csc_sum_duplicates(int n_row, int n_col, int Ap, int Ai, npy_cfloat_wrapper Ax)\n"
+		"csc_sum_duplicates(int n_row, int n_col, int Ap, int Ai, npy_cdouble_wrapper Ax)\n"
 		""},
 	 { (char *)"get_csr_submatrix", _wrap_get_csr_submatrix, METH_VARARGS, (char *)"\n"
 		"get_csr_submatrix(int n_row, int n_col, int Ap, int Aj, signed char Ax, \n"

Modified: trunk/scipy/sparse/tests/test_base.py
===================================================================
--- trunk/scipy/sparse/tests/test_base.py	2007-12-20 09:16:26 UTC (rev 3690)
+++ trunk/scipy/sparse/tests/test_base.py	2007-12-20 19:22:18 UTC (rev 3691)
@@ -15,7 +15,7 @@
 
 import numpy
 from numpy import arange, zeros, array, dot, ones, matrix, asmatrix, \
-        asarray, vstack, ndarray
+        asarray, vstack, ndarray, kron
 
 import random
 from numpy.testing import *
@@ -30,13 +30,18 @@
 #TODO test spmatrix( [[1,2],[3,4]] ) format
 #TODO check that invalid shape in constructor raises exception
 #TODO check that spmatrix( ... , copy=X ) is respected
+#TODO test repr(spmatrix)
 class _TestCommon:
     """test common functionality shared by all sparse formats"""
 
     def setUp(self):
         self.dat = matrix([[1,0,0,2],[3,0,1,0],[0,2,0,0]],'d')
         self.datsp = self.spmatrix(self.dat)
-    
+   
+    def check_repr(self):
+        """make sure __repr__ works"""
+        repr(self.spmatrix)
+
     def check_empty(self):
         """Test manipulating empty matrices. Fails in SciPy SVN <= r1768
         """
@@ -295,32 +300,37 @@
             assert_equal( result.shape, (4,2) )
             assert_equal( result, dot(a,b) )
 
-    def check_todia(self):
-        a = self.datsp.todia()
-        assert_array_almost_equal(a.todense(), self.dat)
+    def check_conversions(self):
 
-    def check_tocoo(self):
-        a = self.datsp.tocoo()
-        assert_array_almost_equal(a.todense(), self.dat)
+        #TODO add bsr/bsc
+        #for format in ['bsc','bsr','coo','csc','csr','dia','dok','lil']:
+        for format in ['coo','csc','csr','dia','dok','lil']:
+            a = self.datsp.asformat(format)
+            assert_equal(a.format,format)
+            assert_array_almost_equal(a.todense(), self.dat)
+            
+            b = self.spmatrix(self.dat+3j).asformat(format)
+            assert_equal(b.format,format)
+            assert_array_almost_equal(b.todense(), self.dat+3j)
 
-    def check_tolil(self):
-        a = self.datsp.tolil()
-        assert_array_almost_equal(a.todense(), self.dat)
-
-    def check_todok(self):
-        a = self.datsp.todok()
-        assert_array_almost_equal(a.todense(), self.dat)
+            
+    def check_todia(self):
+        #TODO, add and test .todia(maxdiags)
+        pass
     
-    def check_tocsc(self):
-        a = self.datsp.tocsc()
-        assert_array_almost_equal(a.todense(), self.dat)
-        b = complexsp = self.spmatrix(self.dat+3j)
-        c = b.tocsc()
-        assert_array_almost_equal(c.todense(), self.dat+3j)
+#    def check_tocompressedblock(self):
+#        #TODO more extensively test .tobsc() and .tobsr() w/ blocksizes
+#        x = array([[1,0,2,0],[0,0,0,0],[0,0,4,5]])
+#        y = array([[0,1,2],[3,0,5]])
+#        A = kron(x,y)
+#        Asp = self.spmatrix(A)
+#        for format in ['bsc','bsr']:
+#            fn = getattr(Asp, 'to' + format )
+#            
+#            for X in [ 1, 2, 3, 6 ]:
+#                for Y in [ 1, 2, 3, 4, 6, 12]:
+#                    assert_equal( fn(blocksize=(X,Y)).todense(), A)
 
-    def check_tocsr(self):
-        a = self.datsp.tocsr()
-        assert_array_almost_equal(a.todense(), self.dat)
 
     def check_transpose(self):
         a = self.datsp.transpose()
@@ -591,6 +601,8 @@
             caught += 1
         assert caught == 2
 
+
+
 class _TestBothSlicing:
     """Tests vertical and horizontal slicing (e.g. [:,0:2]). Tests for
     individual sparse matrix types that implement this should derive from this
@@ -1210,6 +1222,39 @@
         pass
         #TODO add test
 
+#class TestBSR(_TestCommon, _TestArithmetic, NumpyTestCase):
+#    spmatrix = bsr_matrix
+#
+#    def check_constructor1(self):
+#        indptr  = array([0,2,2,4]) 
+#        indices = array([0,2,2,3])
+#        data    = zeros((4,2,3))
+#
+#        data[0] = array([[ 0,  1,  2],
+#                         [ 3,  0,  5]])
+#        data[1] = array([[ 0,  2,  4],
+#                         [ 6,  0, 10]])
+#        data[2] = array([[ 0,  4,  8],
+#                         [12,  0, 20]])
+#        data[3] = array([[ 0,  5, 10],
+#                         [15,  0, 25]])
+#
+#        A = kron( [[1,0,2,0],[0,0,0,0],[0,0,4,5]], [[0,1,2],[3,0,5]] )
+#        
+#        Asp = bsr_matrix((data,indices,indptr),shape=(6,12))
+#
+#        assert_equal(Asp.todense(),A)
+#        #TODO add infer from shape example
+#        
+#
+#
+#
+#class TestBSC(_TestCommon, _TestArithmetic, NumpyTestCase):
+#    spmatrix = bsc_matrix
+#
+#    def check_constructor1(self):
+#        pass
+#        #TODO add test
                 
 if __name__ == "__main__":
     NumpyTest().run()




More information about the Scipy-svn mailing list