[Scipy-svn] r3164 - in trunk/Lib/sparse: . sparsetools tests

scipy-svn at scipy.org scipy-svn at scipy.org
Sat Jul 14 22:22:54 EDT 2007


Author: wnbell
Date: 2007-07-14 21:22:48 -0500 (Sat, 14 Jul 2007)
New Revision: 3164

Modified:
   trunk/Lib/sparse/sparse.py
   trunk/Lib/sparse/sparsetools/sparsetools.h
   trunk/Lib/sparse/sparsetools/sparsetools.i
   trunk/Lib/sparse/sparsetools/sparsetools.py
   trunk/Lib/sparse/sparsetools/sparsetools_wrap.cxx
   trunk/Lib/sparse/tests/test_sparse.py
Log:
added sparsetools.sum_csr_duplicates
further refactoring of CSR/CSC
avoided copying indptr and indices when possible (e.g. __abs__ and __neg__)



Modified: trunk/Lib/sparse/sparse.py
===================================================================
--- trunk/Lib/sparse/sparse.py	2007-07-13 09:22:29 UTC (rev 3163)
+++ trunk/Lib/sparse/sparse.py	2007-07-15 02:22:48 UTC (rev 3164)
@@ -190,21 +190,18 @@
         csc = self.tocsc()
         return abs(csc)
 
-    def __add__(self, other):
+    def __add__(self, other):   # self + other
         csc = self.tocsc()
-        return csc + other
+        return csc.__add__(other)
     
     def __radd__(self, other):  # other + self
-        csc = self.tocsc()
-        return csc.__radd__(other)
+        return self.__add__(other)
 
     def __sub__(self, other):   # self - other
-        neg_other = -other
-        return self + neg_other
+        return self.__add__(-other)
 
     def __rsub__(self, other):  # other - self
-        neg_self = -self
-        return other + neg_self
+        return (-self).__add__(other)
 
     def __mul__(self, other):
         csc = self.tocsc()
@@ -246,6 +243,8 @@
             return self._imag()
         elif attr == 'size':
             return self.getnnz()
+        elif attr == 'ftype':
+            return _transtabl.get(self.dtype.char,'')
         else:
             raise AttributeError, attr + " not found"
 
@@ -267,17 +266,11 @@
 
     def _real(self):
         csc = self.tocsc()
-        csc.data = real(csc.data)
-        csc.dtype = csc.data.dtype
-        csc.ftype = _transtabl[csc.dtype.char]
-        return csc
+        return csc._real()
 
     def _imag(self):
         csc = self.tocsc()
-        csc.data = imag(csc.data)
-        csc.dtype = csc.data.dtype
-        csc.ftype = _transtabl[csc.dtype.char]
-        return csc
+        return csc._imag()
 
     def getcol(self, j):
         """Returns a copy of column j of the matrix, as an (m x 1) sparse
@@ -469,13 +462,8 @@
         fd.close()
 
 class _cs_matrix(spmatrix):
-
     def astype(self, t):
-        out = self.copy()
-        out.data = out.data.astype(t)
-        out.dtype = out.data.dtype
-        out.ftype = _transtabl[out.dtype.char]
-        return out
+        return self._with_data(self.data.astype(t))
 
     def __repr__(self):
         format = self.getformat()
@@ -484,11 +472,30 @@
                (self.shape + (self.dtype.type, self.getnnz(), self.nzmax, \
                    _formats[format][1]))
     
+    def _with_data(self,data,copy=False):
+        """
+        Return a matrix with the same sparsity structure as self,
+        but with different data.  By default the structure arrays
+        (i.e. .indptr and .indices) are not copied.
+        """
+        if copy:
+            return self.__class__((data,self.indices.copy(),self.indptr.copy()), \
+                                   dims=self.shape,dtype=data.dtype,check=False)
+        else:
+            return self.__class__((data,self.indices,self.indptr), \
+                                   dims=self.shape,dtype=data.dtype,check=False)
+    
     def __abs__(self):
-        return self.__class__((abs(self.data),self.indices.copy(),self.indptr.copy()), \
-                                dims=self.shape,dtype=self.dtype,check=False)
+        return self._with_data(abs(self.data))
     
-    def __binopt__(self, other, fn, in_shape=None, out_shape=None):
+    def _real(self):
+        return self._with_data(numpy.real(self.data))
+    
+    def _imag(self):
+        return self._with_data(numpy.imag(self.data))
+        
+    
+    def _binopt(self, other, fn, in_shape=None, out_shape=None):
         """apply the binary operation fn to two sparse matrices"""
         other = self._tothis(other)
 
@@ -502,7 +509,7 @@
                                other.indptr, other.indices, other.data)
         return self.__class__((data, ind, indptr), dims=out_shape, check=False)
             
-    def __addsub__(self, other, fn):
+    def __addsub(self, other, fn):
         # First check if argument is a scalar
         if isscalarlike(other):
             # Now we would add this scalar to every element.
@@ -511,32 +518,31 @@
         elif isspmatrix(other):
             if (other.shape != self.shape):
                 raise ValueError, "inconsistent shapes"
-            return self.__binopt__(other,fn)
+            return self._binopt(other,fn)
         elif isdense(other):
             # Convert this matrix to a dense matrix and add them
             return other + self.todense()
         else:
-            raise TypeError, "unsupported type for sparse matrix arithmetic"
+            raise NotImplemented
         
     def __add__(self,other,fn):
-        return self.__addsub__(other,fn)
+        return self.__addsub(other,fn)
    
     def __sub__(self,other,fn):
-        return self.__addsub__(other,fn)
+        return self.__addsub(other,fn)
     
     def __mul__(self, other): # self * other 
         """ Scalar, vector, or matrix multiplication
         """
         if isscalarlike(other):
-            return self.__class__((self.data * other, self.indices.copy(), self.indptr.copy()), \
-                                    dims=self.shape, check=False)
+            return self._with_data(self.data * other)
         else:
             return self.dot(other)
 
 
     def __rmul__(self, other): # other * self 
         if isscalarlike(other):
-            return self * other  # use __mul__
+            return self.__mul__(other)
         else:
             # Don't use asarray unless we have to
             try:
@@ -547,11 +553,8 @@
 
 
     def __neg__(self):
-        new = self.copy()
-        new.data *= -1
-        return new
+        return self._with_data(-self.data)
 
-
     def __truediv__(self,other,fn):
         if isscalarlike(other):
             return self * (1./other)
@@ -559,9 +562,9 @@
             other = self._tothis(other)
             if (other.shape != self.shape):
                 raise ValueError, "inconsistent shapes"
-            return self.__binopt__(other,fn)
+            return self._binopt(other,fn)
         else:
-            raise TypeError, "unsupported type for sparse matrix power"
+            raise NotImplemented
 
 
     def __pow__(self, other, fn):
@@ -569,12 +572,11 @@
         case return the matrix power.)
         """
         if isscalarlike(other):
-            return self.__class__((self.data ** other, self.indices.copy(), self.indptr.copy()), \
-                                    dims=self.shape, check=False)
+            return self._with_data(self.data**other)
         elif isspmatrix(other):
-            return self.__binopt__(other,fn)
+            return self._binopt(other,fn)
         else:
-            raise TypeError, "unsupported type for sparse matrix power"
+            raise NotImplemented
 
 
     def _matmat(self, other, fn):
@@ -584,7 +586,7 @@
             if (K1 != K2):
                 raise ValueError, "shape mismatch error"
             other = self._tothis(other)
-            return self.__binopt__(other,fn,in_shape=(M,N),out_shape=(M,N))
+            return self._binopt(other,fn,in_shape=(M,N),out_shape=(M,N))
         elif isdense(other):
             # This is SLOW!  We need a more efficient implementation
             # of sparse * dense matrix multiplication!
@@ -643,10 +645,8 @@
 
 
     def copy(self):
-        return self.__class__((self.data.copy(),self.indices.copy(),self.indptr.copy()), \
-                              self.shape, dtype=self.dtype, check=False)
-
-
+        return self._with_data(self.data.copy(),copy=True)
+    
     def _get_slice(self, i, start, stop, stride, dims):
         """Returns a view of the elements [i, myslice.start:myslice.stop].
         """
@@ -674,7 +674,7 @@
         
 
     def conj(self, copy=False):
-        return self.__class__((self.data.conj(),self.indices,self.indptr),self.shape,copy=copy,check=False)
+        return self._with_data(self.data.conj(),copy=copy)
 
     def _ensure_sorted_indices(self, shape0, shape1, inplace=False):
         """Return a copy of this matrix where the row indices are sorted
@@ -876,9 +876,6 @@
             self.data = 1.0 * self.data
             self.dtype = self.data.dtype
 
-        self.ftype = _transtabl[self.dtype.char]
-
-
     def __getattr__(self, attr):
         if attr == 'rowind':
             warnings.warn("rowind attribute no longer in use. Use .indices instead",
@@ -890,16 +887,10 @@
     
     def __add__(self, other):
         return _cs_matrix.__add__(self, other, csc_plus_csc)
-   
-    def __radd__(self,other):
-        return self.__add__(other)
     
     def __sub__(self, other):
         return _cs_matrix.__sub__(self, other, csc_minus_csc)
 
-    def __rsub__(self,other):
-        return self.__sub__(other)
-
     def __truediv__(self,other):
         return _cs_matrix.__truediv__(self,other, csc_eldiv_csc)
     
@@ -1226,8 +1217,6 @@
             self.data = self.data + 0.0
             self.dtype = self.data.dtype
 
-        self.ftype = _transtabl[self.dtype.char]
-
     def __getattr__(self, attr):
         if attr == 'colind':
             warnings.warn("colind attribute no longer in use. Use .indices instead",
@@ -1239,15 +1228,9 @@
     def __add__(self, other):
         return _cs_matrix.__add__(self, other, csr_plus_csr)
    
-    def __radd__(self,other):
-        return self.__add__(other)
-    
     def __sub__(self, other):
         return _cs_matrix.__sub__(self, other, csr_minus_csr)
     
-    def __rsub__(self,other):
-        return self.__sub__(other)
-
     def __truediv__(self,other):
         return _cs_matrix.__truediv__(self,other, csr_eldiv_csr)
 
@@ -2088,7 +2071,6 @@
         # some functions pass floats
         self.shape = tuple([int(x) for x in self.shape])
         self.nnz = nnz
-        self.ftype = _transtabl.get(self.dtype.char,'')
 
     def _normalize(self, rowfirst=False):
         if rowfirst:

Modified: trunk/Lib/sparse/sparsetools/sparsetools.h
===================================================================
--- trunk/Lib/sparse/sparsetools/sparsetools.h	2007-07-13 09:22:29 UTC (rev 3163)
+++ trunk/Lib/sparse/sparsetools/sparsetools.h	2007-07-15 02:22:48 UTC (rev 3164)
@@ -10,6 +10,8 @@
  *    Nathan Bell
  *
  * Revisions:
+ *    07/14/2007 - added sum_csr_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
  *
@@ -414,7 +416,73 @@
 
 
 
+/*
+ * Sum together duplicate column entries in each row of CSR matrix A
+ *
+ *   
+ * Input Arguments:
+ *   I    n_row       - number of rows in A (and B)
+ *   I    n_col       - number of columns in A (and B)
+ *   I    Ap[n_row+1] - row pointer
+ *   I    Aj[nnz(A)]  - column indices
+ *   T    Ax[nnz(A)]  - nonzeros
+ *   
+ * Note:
+ *   Ap,Aj, and Ax will be modified *inplace*
+ *
+ */
+template <class I, class T>
+void sum_csr_duplicates(const I n_row,
+                        const I n_col, 
+                              I Ap[], 
+                              I Aj[], 
+                              T Ax[])
+{
+  const T zero = ZERO<T>();
 
+  std::vector<I>  next(n_col,-1);
+  std::vector<T>  sums(n_col,zero);
+
+  I NNZ = 0;
+
+  I row_start = 0;
+  I row_end   = 0;
+  
+  for(I i = 0; i < n_row; i++){
+    I head = -2;
+    
+    row_start = row_end; //Ap[i] may have been changed
+    row_end   = Ap[i+1]; //Ap[i+1] is safe
+    
+    for(I jj = row_start; jj < row_end; jj++){
+      I j = Aj[jj];
+
+      sums[j] += Ax[jj];
+      
+      if(next[j] == -1){
+	    next[j] = head;                        
+	    head    = j;
+      }
+    }
+
+    while(head != -2){
+        I curr = head; //current column
+        head   = next[curr];
+
+        Aj[NNZ] = curr;
+        Ax[NNZ] = sums[curr];
+
+        next[curr] = -1;
+        sums[curr] = zero;
+
+        NNZ++;
+    }
+    Ap[i+1] = NNZ;
+  }
+}
+
+
+
 /*
  * Compute B = A for COO matrix A, CSR matrix B
  *
@@ -453,10 +521,10 @@
               std::vector<I>* Bj,
               std::vector<T>* Bx)
 {
-  std::vector<I> tempBp(n_row+1,0);
-  std::vector<I> tempBj(NNZ);
-  std::vector<T> tempBx(NNZ);
-
+  Bp->resize(n_row+1,0);
+  Bj->resize(NNZ);
+  Bx->resize(NNZ);
+  
   std::vector<I> nnz_per_row(n_row,0); //temp array
 
   //compute nnz per row, then compute Bp
@@ -464,33 +532,30 @@
     nnz_per_row[Ai[i]]++;
   }
   for(I i = 0, cumsum = 0; i < n_row; i++){
-    tempBp[i]      = cumsum;
+    (*Bp)[i]          = cumsum;
     cumsum        += nnz_per_row[i];
     nnz_per_row[i] = 0; //reset count
   }
-  tempBp[n_row] = NNZ;
+  (*Bp)[n_row] = NNZ;
 
 
   //write Aj,Ax Io tempBj,tempBx
   for(I i = 0; i < NNZ; i++){
     I row = Ai[i];
-    I n   = tempBp[row] + nnz_per_row[row];
+    I n   = (*Bp)[row] + nnz_per_row[row];
 
-    tempBj[n] = Aj[i];
-    tempBx[n] = Ax[i];
+    (*Bj)[n] = Aj[i];
+    (*Bx)[n] = Ax[i];
 
     nnz_per_row[row]++;
   }
   //now tempBp,tempBj,tempBx form a CSR representation (with duplicates)
 
+  sum_csr_duplicates(n_row,n_col,&(*Bp)[0],&(*Bj)[0],&(*Bx)[0]);
 
-  //use (tempB + 0) to sum duplicates
-  std::vector<I> Xp(n_row+1,0); //row pointer for an empty matrix
-
-  csr_plus_csr<I,T>(n_row,n_col,
-                    &tempBp[0],&tempBj[0],&tempBx[0],
-                    &Xp[0],NULL,NULL,
-                    Bp,Bj,Bx);    	   
+  //trim unused space at the end
+  Bj->resize(Bp->back());
+  Bx->resize(Bp->back());
 }
 	    
 
@@ -869,6 +934,13 @@
 
 
 
+template <class I, class T>
+void sum_csc_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); }
 
 
 template<class I, class T>

Modified: trunk/Lib/sparse/sparsetools/sparsetools.i
===================================================================
--- trunk/Lib/sparse/sparsetools/sparsetools.i	2007-07-13 09:22:29 UTC (rev 3163)
+++ trunk/Lib/sparse/sparsetools/sparsetools.i	2007-07-15 02:22:48 UTC (rev 3164)
@@ -136,6 +136,7 @@
 
 %define I_INPLACE_ARRAY1( ctype )
 %apply ctype * INPLACE_ARRAY {
+  ctype Ap [ ],
   ctype Aj [ ]
 };
 %enddef
@@ -237,3 +238,10 @@
 INSTANTIATE_ALL(sort_csr_indices)
 INSTANTIATE_ALL(sort_csc_indices)
 
+/*
+ * Sum duplicate CSR/CSC entries.
+ */
+INSTANTIATE_ALL(sum_csr_duplicates)
+INSTANTIATE_ALL(sum_csc_duplicates)
+
+

Modified: trunk/Lib/sparse/sparsetools/sparsetools.py
===================================================================
--- trunk/Lib/sparse/sparsetools/sparsetools.py	2007-07-13 09:22:29 UTC (rev 3163)
+++ trunk/Lib/sparse/sparsetools/sparsetools.py	2007-07-15 02:22:48 UTC (rev 3164)
@@ -511,3 +511,25 @@
     """
   return _sparsetools.sort_csc_indices(*args)
 
+def sum_csr_duplicates(*args):
+  """
+    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 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 Ax)
+    sum_csr_duplicates(int n_row, int n_col, int Ap, int Aj, npy_cdouble Ax)
+    """
+  return _sparsetools.sum_csr_duplicates(*args)
+
+def sum_csc_duplicates(*args):
+  """
+    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 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 Ax)
+    sum_csc_duplicates(int n_row, int n_col, int Ap, int Ai, npy_cdouble Ax)
+    """
+  return _sparsetools.sum_csc_duplicates(*args)
+

Modified: trunk/Lib/sparse/sparsetools/sparsetools_wrap.cxx
===================================================================
--- trunk/Lib/sparse/sparsetools/sparsetools_wrap.cxx	2007-07-13 09:22:29 UTC (rev 3163)
+++ trunk/Lib/sparse/sparsetools/sparsetools_wrap.cxx	2007-07-15 02:22:48 UTC (rev 3164)
@@ -27765,6 +27765,1068 @@
 }
 
 
+SWIGINTERN PyObject *_wrap_sum_csr_duplicates__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  int arg1 ;
+  int arg2 ;
+  int *arg3 ;
+  int *arg4 ;
+  int *arg5 ;
+  int val1 ;
+  int ecode1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyArrayObject *temp3 = NULL ;
+  PyArrayObject *temp4 = NULL ;
+  void *argp5 = 0 ;
+  int res5 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOOOO:sum_csr_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""'");
+  } 
+  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""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  {
+    temp3 = obj_to_array_no_conversion(obj2,PyArray_INT);
+    if (!temp3  || !require_contiguous(temp3)) SWIG_fail;
+    arg3 = (int*) temp3->data;
+  }
+  {
+    temp4 = obj_to_array_no_conversion(obj3,PyArray_INT);
+    if (!temp4  || !require_contiguous(temp4)) SWIG_fail;
+    arg4 = (int*) temp4->data;
+  }
+  res5 = SWIG_ConvertPtr(obj4, &argp5,SWIGTYPE_p_int, 0 |  0 );
+  if (!SWIG_IsOK(res5)) {
+    SWIG_exception_fail(SWIG_ArgError(res5), "in method '" "sum_csr_duplicates" "', argument " "5"" of type '" "int []""'"); 
+  } 
+  arg5 = reinterpret_cast< int * >(argp5);
+  sum_csr_duplicates<int,int >(arg1,arg2,arg3,arg4,arg5);
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_sum_csr_duplicates__SWIG_2(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  int arg1 ;
+  int arg2 ;
+  int *arg3 ;
+  int *arg4 ;
+  long *arg5 ;
+  int val1 ;
+  int ecode1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyArrayObject *temp3 = NULL ;
+  PyArrayObject *temp4 = NULL ;
+  PyArrayObject *temp5 = NULL ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOOOO:sum_csr_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""'");
+  } 
+  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""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  {
+    temp3 = obj_to_array_no_conversion(obj2,PyArray_INT);
+    if (!temp3  || !require_contiguous(temp3)) SWIG_fail;
+    arg3 = (int*) temp3->data;
+  }
+  {
+    temp4 = obj_to_array_no_conversion(obj3,PyArray_INT);
+    if (!temp4  || !require_contiguous(temp4)) SWIG_fail;
+    arg4 = (int*) temp4->data;
+  }
+  {
+    temp5 = obj_to_array_no_conversion(obj4,PyArray_LONG);
+    if (!temp5  || !require_contiguous(temp5)) SWIG_fail;
+    arg5 = (long*) temp5->data;
+  }
+  sum_csr_duplicates<int,long >(arg1,arg2,arg3,arg4,arg5);
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_sum_csr_duplicates__SWIG_3(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  int arg1 ;
+  int arg2 ;
+  int *arg3 ;
+  int *arg4 ;
+  float *arg5 ;
+  int val1 ;
+  int ecode1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyArrayObject *temp3 = NULL ;
+  PyArrayObject *temp4 = NULL ;
+  PyArrayObject *temp5 = NULL ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOOOO:sum_csr_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""'");
+  } 
+  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""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  {
+    temp3 = obj_to_array_no_conversion(obj2,PyArray_INT);
+    if (!temp3  || !require_contiguous(temp3)) SWIG_fail;
+    arg3 = (int*) temp3->data;
+  }
+  {
+    temp4 = obj_to_array_no_conversion(obj3,PyArray_INT);
+    if (!temp4  || !require_contiguous(temp4)) SWIG_fail;
+    arg4 = (int*) temp4->data;
+  }
+  {
+    temp5 = obj_to_array_no_conversion(obj4,PyArray_FLOAT);
+    if (!temp5  || !require_contiguous(temp5)) SWIG_fail;
+    arg5 = (float*) temp5->data;
+  }
+  sum_csr_duplicates<int,float >(arg1,arg2,arg3,arg4,arg5);
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_sum_csr_duplicates__SWIG_4(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  int arg1 ;
+  int arg2 ;
+  int *arg3 ;
+  int *arg4 ;
+  double *arg5 ;
+  int val1 ;
+  int ecode1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyArrayObject *temp3 = NULL ;
+  PyArrayObject *temp4 = NULL ;
+  PyArrayObject *temp5 = NULL ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOOOO:sum_csr_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""'");
+  } 
+  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""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  {
+    temp3 = obj_to_array_no_conversion(obj2,PyArray_INT);
+    if (!temp3  || !require_contiguous(temp3)) SWIG_fail;
+    arg3 = (int*) temp3->data;
+  }
+  {
+    temp4 = obj_to_array_no_conversion(obj3,PyArray_INT);
+    if (!temp4  || !require_contiguous(temp4)) SWIG_fail;
+    arg4 = (int*) temp4->data;
+  }
+  {
+    temp5 = obj_to_array_no_conversion(obj4,PyArray_DOUBLE);
+    if (!temp5  || !require_contiguous(temp5)) SWIG_fail;
+    arg5 = (double*) temp5->data;
+  }
+  sum_csr_duplicates<int,double >(arg1,arg2,arg3,arg4,arg5);
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_sum_csr_duplicates__SWIG_5(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  int arg1 ;
+  int arg2 ;
+  int *arg3 ;
+  int *arg4 ;
+  npy_cfloat *arg5 ;
+  int val1 ;
+  int ecode1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyArrayObject *temp3 = NULL ;
+  PyArrayObject *temp4 = NULL ;
+  PyArrayObject *temp5 = NULL ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOOOO:sum_csr_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""'");
+  } 
+  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""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  {
+    temp3 = obj_to_array_no_conversion(obj2,PyArray_INT);
+    if (!temp3  || !require_contiguous(temp3)) SWIG_fail;
+    arg3 = (int*) temp3->data;
+  }
+  {
+    temp4 = obj_to_array_no_conversion(obj3,PyArray_INT);
+    if (!temp4  || !require_contiguous(temp4)) SWIG_fail;
+    arg4 = (int*) temp4->data;
+  }
+  {
+    temp5 = obj_to_array_no_conversion(obj4,PyArray_CFLOAT);
+    if (!temp5  || !require_contiguous(temp5)) SWIG_fail;
+    arg5 = (npy_cfloat*) temp5->data;
+  }
+  sum_csr_duplicates<int,npy_cfloat >(arg1,arg2,arg3,arg4,arg5);
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_sum_csr_duplicates__SWIG_6(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  int arg1 ;
+  int arg2 ;
+  int *arg3 ;
+  int *arg4 ;
+  npy_cdouble *arg5 ;
+  int val1 ;
+  int ecode1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyArrayObject *temp3 = NULL ;
+  PyArrayObject *temp4 = NULL ;
+  PyArrayObject *temp5 = NULL ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOOOO:sum_csr_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""'");
+  } 
+  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""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  {
+    temp3 = obj_to_array_no_conversion(obj2,PyArray_INT);
+    if (!temp3  || !require_contiguous(temp3)) SWIG_fail;
+    arg3 = (int*) temp3->data;
+  }
+  {
+    temp4 = obj_to_array_no_conversion(obj3,PyArray_INT);
+    if (!temp4  || !require_contiguous(temp4)) SWIG_fail;
+    arg4 = (int*) temp4->data;
+  }
+  {
+    temp5 = obj_to_array_no_conversion(obj4,PyArray_CDOUBLE);
+    if (!temp5  || !require_contiguous(temp5)) SWIG_fail;
+    arg5 = (npy_cdouble*) temp5->data;
+  }
+  sum_csr_duplicates<int,npy_cdouble >(arg1,arg2,arg3,arg4,arg5);
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_sum_csr_duplicates(PyObject *self, PyObject *args) {
+  int argc;
+  PyObject *argv[6];
+  int ii;
+  
+  if (!PyTuple_Check(args)) SWIG_fail;
+  argc = PyObject_Length(args);
+  for (ii = 0; (ii < argc) && (ii < 5); ii++) {
+    argv[ii] = PyTuple_GET_ITEM(args,ii);
+  }
+  if (argc == 5) {
+    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) {
+        {
+          _v = (is_array(argv[2]) && PyArray_CanCastSafely(PyArray_TYPE(argv[2]),PyArray_INT)) ? 1 : 0;
+        }
+        if (_v) {
+          {
+            _v = (is_array(argv[3]) && PyArray_CanCastSafely(PyArray_TYPE(argv[3]),PyArray_INT)) ? 1 : 0;
+          }
+          if (_v) {
+            {
+              _v = (is_array(argv[4]) && PyArray_CanCastSafely(PyArray_TYPE(argv[4]),PyArray_INT)) ? 1 : 0;
+            }
+            if (_v) {
+              return _wrap_sum_csr_duplicates__SWIG_1(self, args);
+            }
+          }
+        }
+      }
+    }
+  }
+  if (argc == 5) {
+    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) {
+        {
+          _v = (is_array(argv[2]) && PyArray_CanCastSafely(PyArray_TYPE(argv[2]),PyArray_INT)) ? 1 : 0;
+        }
+        if (_v) {
+          {
+            _v = (is_array(argv[3]) && PyArray_CanCastSafely(PyArray_TYPE(argv[3]),PyArray_INT)) ? 1 : 0;
+          }
+          if (_v) {
+            {
+              _v = (is_array(argv[4]) && PyArray_CanCastSafely(PyArray_TYPE(argv[4]),PyArray_LONG)) ? 1 : 0;
+            }
+            if (_v) {
+              return _wrap_sum_csr_duplicates__SWIG_2(self, args);
+            }
+          }
+        }
+      }
+    }
+  }
+  if (argc == 5) {
+    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) {
+        {
+          _v = (is_array(argv[2]) && PyArray_CanCastSafely(PyArray_TYPE(argv[2]),PyArray_INT)) ? 1 : 0;
+        }
+        if (_v) {
+          {
+            _v = (is_array(argv[3]) && PyArray_CanCastSafely(PyArray_TYPE(argv[3]),PyArray_INT)) ? 1 : 0;
+          }
+          if (_v) {
+            {
+              _v = (is_array(argv[4]) && PyArray_CanCastSafely(PyArray_TYPE(argv[4]),PyArray_FLOAT)) ? 1 : 0;
+            }
+            if (_v) {
+              return _wrap_sum_csr_duplicates__SWIG_3(self, args);
+            }
+          }
+        }
+      }
+    }
+  }
+  if (argc == 5) {
+    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) {
+        {
+          _v = (is_array(argv[2]) && PyArray_CanCastSafely(PyArray_TYPE(argv[2]),PyArray_INT)) ? 1 : 0;
+        }
+        if (_v) {
+          {
+            _v = (is_array(argv[3]) && PyArray_CanCastSafely(PyArray_TYPE(argv[3]),PyArray_INT)) ? 1 : 0;
+          }
+          if (_v) {
+            {
+              _v = (is_array(argv[4]) && PyArray_CanCastSafely(PyArray_TYPE(argv[4]),PyArray_DOUBLE)) ? 1 : 0;
+            }
+            if (_v) {
+              return _wrap_sum_csr_duplicates__SWIG_4(self, args);
+            }
+          }
+        }
+      }
+    }
+  }
+  if (argc == 5) {
+    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) {
+        {
+          _v = (is_array(argv[2]) && PyArray_CanCastSafely(PyArray_TYPE(argv[2]),PyArray_INT)) ? 1 : 0;
+        }
+        if (_v) {
+          {
+            _v = (is_array(argv[3]) && PyArray_CanCastSafely(PyArray_TYPE(argv[3]),PyArray_INT)) ? 1 : 0;
+          }
+          if (_v) {
+            {
+              _v = (is_array(argv[4]) && PyArray_CanCastSafely(PyArray_TYPE(argv[4]),PyArray_CFLOAT)) ? 1 : 0;
+            }
+            if (_v) {
+              return _wrap_sum_csr_duplicates__SWIG_5(self, args);
+            }
+          }
+        }
+      }
+    }
+  }
+  if (argc == 5) {
+    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) {
+        {
+          _v = (is_array(argv[2]) && PyArray_CanCastSafely(PyArray_TYPE(argv[2]),PyArray_INT)) ? 1 : 0;
+        }
+        if (_v) {
+          {
+            _v = (is_array(argv[3]) && PyArray_CanCastSafely(PyArray_TYPE(argv[3]),PyArray_INT)) ? 1 : 0;
+          }
+          if (_v) {
+            {
+              _v = (is_array(argv[4]) && PyArray_CanCastSafely(PyArray_TYPE(argv[4]),PyArray_CDOUBLE)) ? 1 : 0;
+            }
+            if (_v) {
+              return _wrap_sum_csr_duplicates__SWIG_6(self, args);
+            }
+          }
+        }
+      }
+    }
+  }
+  
+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,int)>(int const,int const,int [],int [],int [])\n    sum_csr_duplicates<(int,long)>(int const,int const,int [],int [],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)>(int const,int const,int [],int [],npy_cfloat [])\n    sum_csr_duplicates<(int,npy_cdouble)>(int const,int const,int [],int [],npy_cdouble [])\n");
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_sum_csc_duplicates__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  int arg1 ;
+  int arg2 ;
+  int *arg3 ;
+  int *arg4 ;
+  int *arg5 ;
+  int val1 ;
+  int ecode1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyArrayObject *temp3 = NULL ;
+  void *argp4 = 0 ;
+  int res4 = 0 ;
+  void *argp5 = 0 ;
+  int res5 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOOOO:sum_csc_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""'");
+  } 
+  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""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  {
+    temp3 = obj_to_array_no_conversion(obj2,PyArray_INT);
+    if (!temp3  || !require_contiguous(temp3)) SWIG_fail;
+    arg3 = (int*) temp3->data;
+  }
+  res4 = SWIG_ConvertPtr(obj3, &argp4,SWIGTYPE_p_int, 0 |  0 );
+  if (!SWIG_IsOK(res4)) {
+    SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "sum_csc_duplicates" "', argument " "4"" of type '" "int []""'"); 
+  } 
+  arg4 = reinterpret_cast< int * >(argp4);
+  res5 = SWIG_ConvertPtr(obj4, &argp5,SWIGTYPE_p_int, 0 |  0 );
+  if (!SWIG_IsOK(res5)) {
+    SWIG_exception_fail(SWIG_ArgError(res5), "in method '" "sum_csc_duplicates" "', argument " "5"" of type '" "int []""'"); 
+  } 
+  arg5 = reinterpret_cast< int * >(argp5);
+  sum_csc_duplicates<int,int >(arg1,arg2,arg3,arg4,arg5);
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_sum_csc_duplicates__SWIG_2(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  int arg1 ;
+  int arg2 ;
+  int *arg3 ;
+  int *arg4 ;
+  long *arg5 ;
+  int val1 ;
+  int ecode1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyArrayObject *temp3 = NULL ;
+  void *argp4 = 0 ;
+  int res4 = 0 ;
+  PyArrayObject *temp5 = NULL ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOOOO:sum_csc_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""'");
+  } 
+  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""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  {
+    temp3 = obj_to_array_no_conversion(obj2,PyArray_INT);
+    if (!temp3  || !require_contiguous(temp3)) SWIG_fail;
+    arg3 = (int*) temp3->data;
+  }
+  res4 = SWIG_ConvertPtr(obj3, &argp4,SWIGTYPE_p_int, 0 |  0 );
+  if (!SWIG_IsOK(res4)) {
+    SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "sum_csc_duplicates" "', argument " "4"" of type '" "int []""'"); 
+  } 
+  arg4 = reinterpret_cast< int * >(argp4);
+  {
+    temp5 = obj_to_array_no_conversion(obj4,PyArray_LONG);
+    if (!temp5  || !require_contiguous(temp5)) SWIG_fail;
+    arg5 = (long*) temp5->data;
+  }
+  sum_csc_duplicates<int,long >(arg1,arg2,arg3,arg4,arg5);
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_sum_csc_duplicates__SWIG_3(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  int arg1 ;
+  int arg2 ;
+  int *arg3 ;
+  int *arg4 ;
+  float *arg5 ;
+  int val1 ;
+  int ecode1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyArrayObject *temp3 = NULL ;
+  void *argp4 = 0 ;
+  int res4 = 0 ;
+  PyArrayObject *temp5 = NULL ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOOOO:sum_csc_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""'");
+  } 
+  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""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  {
+    temp3 = obj_to_array_no_conversion(obj2,PyArray_INT);
+    if (!temp3  || !require_contiguous(temp3)) SWIG_fail;
+    arg3 = (int*) temp3->data;
+  }
+  res4 = SWIG_ConvertPtr(obj3, &argp4,SWIGTYPE_p_int, 0 |  0 );
+  if (!SWIG_IsOK(res4)) {
+    SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "sum_csc_duplicates" "', argument " "4"" of type '" "int []""'"); 
+  } 
+  arg4 = reinterpret_cast< int * >(argp4);
+  {
+    temp5 = obj_to_array_no_conversion(obj4,PyArray_FLOAT);
+    if (!temp5  || !require_contiguous(temp5)) SWIG_fail;
+    arg5 = (float*) temp5->data;
+  }
+  sum_csc_duplicates<int,float >(arg1,arg2,arg3,arg4,arg5);
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_sum_csc_duplicates__SWIG_4(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  int arg1 ;
+  int arg2 ;
+  int *arg3 ;
+  int *arg4 ;
+  double *arg5 ;
+  int val1 ;
+  int ecode1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyArrayObject *temp3 = NULL ;
+  void *argp4 = 0 ;
+  int res4 = 0 ;
+  PyArrayObject *temp5 = NULL ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOOOO:sum_csc_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""'");
+  } 
+  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""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  {
+    temp3 = obj_to_array_no_conversion(obj2,PyArray_INT);
+    if (!temp3  || !require_contiguous(temp3)) SWIG_fail;
+    arg3 = (int*) temp3->data;
+  }
+  res4 = SWIG_ConvertPtr(obj3, &argp4,SWIGTYPE_p_int, 0 |  0 );
+  if (!SWIG_IsOK(res4)) {
+    SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "sum_csc_duplicates" "', argument " "4"" of type '" "int []""'"); 
+  } 
+  arg4 = reinterpret_cast< int * >(argp4);
+  {
+    temp5 = obj_to_array_no_conversion(obj4,PyArray_DOUBLE);
+    if (!temp5  || !require_contiguous(temp5)) SWIG_fail;
+    arg5 = (double*) temp5->data;
+  }
+  sum_csc_duplicates<int,double >(arg1,arg2,arg3,arg4,arg5);
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_sum_csc_duplicates__SWIG_5(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  int arg1 ;
+  int arg2 ;
+  int *arg3 ;
+  int *arg4 ;
+  npy_cfloat *arg5 ;
+  int val1 ;
+  int ecode1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyArrayObject *temp3 = NULL ;
+  void *argp4 = 0 ;
+  int res4 = 0 ;
+  PyArrayObject *temp5 = NULL ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOOOO:sum_csc_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""'");
+  } 
+  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""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  {
+    temp3 = obj_to_array_no_conversion(obj2,PyArray_INT);
+    if (!temp3  || !require_contiguous(temp3)) SWIG_fail;
+    arg3 = (int*) temp3->data;
+  }
+  res4 = SWIG_ConvertPtr(obj3, &argp4,SWIGTYPE_p_int, 0 |  0 );
+  if (!SWIG_IsOK(res4)) {
+    SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "sum_csc_duplicates" "', argument " "4"" of type '" "int []""'"); 
+  } 
+  arg4 = reinterpret_cast< int * >(argp4);
+  {
+    temp5 = obj_to_array_no_conversion(obj4,PyArray_CFLOAT);
+    if (!temp5  || !require_contiguous(temp5)) SWIG_fail;
+    arg5 = (npy_cfloat*) temp5->data;
+  }
+  sum_csc_duplicates<int,npy_cfloat >(arg1,arg2,arg3,arg4,arg5);
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_sum_csc_duplicates__SWIG_6(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  int arg1 ;
+  int arg2 ;
+  int *arg3 ;
+  int *arg4 ;
+  npy_cdouble *arg5 ;
+  int val1 ;
+  int ecode1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyArrayObject *temp3 = NULL ;
+  void *argp4 = 0 ;
+  int res4 = 0 ;
+  PyArrayObject *temp5 = NULL ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOOOO:sum_csc_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""'");
+  } 
+  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""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  {
+    temp3 = obj_to_array_no_conversion(obj2,PyArray_INT);
+    if (!temp3  || !require_contiguous(temp3)) SWIG_fail;
+    arg3 = (int*) temp3->data;
+  }
+  res4 = SWIG_ConvertPtr(obj3, &argp4,SWIGTYPE_p_int, 0 |  0 );
+  if (!SWIG_IsOK(res4)) {
+    SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "sum_csc_duplicates" "', argument " "4"" of type '" "int []""'"); 
+  } 
+  arg4 = reinterpret_cast< int * >(argp4);
+  {
+    temp5 = obj_to_array_no_conversion(obj4,PyArray_CDOUBLE);
+    if (!temp5  || !require_contiguous(temp5)) SWIG_fail;
+    arg5 = (npy_cdouble*) temp5->data;
+  }
+  sum_csc_duplicates<int,npy_cdouble >(arg1,arg2,arg3,arg4,arg5);
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_sum_csc_duplicates(PyObject *self, PyObject *args) {
+  int argc;
+  PyObject *argv[6];
+  int ii;
+  
+  if (!PyTuple_Check(args)) SWIG_fail;
+  argc = PyObject_Length(args);
+  for (ii = 0; (ii < argc) && (ii < 5); ii++) {
+    argv[ii] = PyTuple_GET_ITEM(args,ii);
+  }
+  if (argc == 5) {
+    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) {
+        {
+          _v = (is_array(argv[2]) && PyArray_CanCastSafely(PyArray_TYPE(argv[2]),PyArray_INT)) ? 1 : 0;
+        }
+        if (_v) {
+          {
+            _v = (is_array(argv[3]) && PyArray_CanCastSafely(PyArray_TYPE(argv[3]),PyArray_INT)) ? 1 : 0;
+          }
+          if (_v) {
+            {
+              _v = (is_array(argv[4]) && PyArray_CanCastSafely(PyArray_TYPE(argv[4]),PyArray_INT)) ? 1 : 0;
+            }
+            if (_v) {
+              return _wrap_sum_csc_duplicates__SWIG_1(self, args);
+            }
+          }
+        }
+      }
+    }
+  }
+  if (argc == 5) {
+    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) {
+        {
+          _v = (is_array(argv[2]) && PyArray_CanCastSafely(PyArray_TYPE(argv[2]),PyArray_INT)) ? 1 : 0;
+        }
+        if (_v) {
+          {
+            _v = (is_array(argv[3]) && PyArray_CanCastSafely(PyArray_TYPE(argv[3]),PyArray_INT)) ? 1 : 0;
+          }
+          if (_v) {
+            {
+              _v = (is_array(argv[4]) && PyArray_CanCastSafely(PyArray_TYPE(argv[4]),PyArray_LONG)) ? 1 : 0;
+            }
+            if (_v) {
+              return _wrap_sum_csc_duplicates__SWIG_2(self, args);
+            }
+          }
+        }
+      }
+    }
+  }
+  if (argc == 5) {
+    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) {
+        {
+          _v = (is_array(argv[2]) && PyArray_CanCastSafely(PyArray_TYPE(argv[2]),PyArray_INT)) ? 1 : 0;
+        }
+        if (_v) {
+          {
+            _v = (is_array(argv[3]) && PyArray_CanCastSafely(PyArray_TYPE(argv[3]),PyArray_INT)) ? 1 : 0;
+          }
+          if (_v) {
+            {
+              _v = (is_array(argv[4]) && PyArray_CanCastSafely(PyArray_TYPE(argv[4]),PyArray_FLOAT)) ? 1 : 0;
+            }
+            if (_v) {
+              return _wrap_sum_csc_duplicates__SWIG_3(self, args);
+            }
+          }
+        }
+      }
+    }
+  }
+  if (argc == 5) {
+    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) {
+        {
+          _v = (is_array(argv[2]) && PyArray_CanCastSafely(PyArray_TYPE(argv[2]),PyArray_INT)) ? 1 : 0;
+        }
+        if (_v) {
+          {
+            _v = (is_array(argv[3]) && PyArray_CanCastSafely(PyArray_TYPE(argv[3]),PyArray_INT)) ? 1 : 0;
+          }
+          if (_v) {
+            {
+              _v = (is_array(argv[4]) && PyArray_CanCastSafely(PyArray_TYPE(argv[4]),PyArray_DOUBLE)) ? 1 : 0;
+            }
+            if (_v) {
+              return _wrap_sum_csc_duplicates__SWIG_4(self, args);
+            }
+          }
+        }
+      }
+    }
+  }
+  if (argc == 5) {
+    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) {
+        {
+          _v = (is_array(argv[2]) && PyArray_CanCastSafely(PyArray_TYPE(argv[2]),PyArray_INT)) ? 1 : 0;
+        }
+        if (_v) {
+          {
+            _v = (is_array(argv[3]) && PyArray_CanCastSafely(PyArray_TYPE(argv[3]),PyArray_INT)) ? 1 : 0;
+          }
+          if (_v) {
+            {
+              _v = (is_array(argv[4]) && PyArray_CanCastSafely(PyArray_TYPE(argv[4]),PyArray_CFLOAT)) ? 1 : 0;
+            }
+            if (_v) {
+              return _wrap_sum_csc_duplicates__SWIG_5(self, args);
+            }
+          }
+        }
+      }
+    }
+  }
+  if (argc == 5) {
+    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) {
+        {
+          _v = (is_array(argv[2]) && PyArray_CanCastSafely(PyArray_TYPE(argv[2]),PyArray_INT)) ? 1 : 0;
+        }
+        if (_v) {
+          {
+            _v = (is_array(argv[3]) && PyArray_CanCastSafely(PyArray_TYPE(argv[3]),PyArray_INT)) ? 1 : 0;
+          }
+          if (_v) {
+            {
+              _v = (is_array(argv[4]) && PyArray_CanCastSafely(PyArray_TYPE(argv[4]),PyArray_CDOUBLE)) ? 1 : 0;
+            }
+            if (_v) {
+              return _wrap_sum_csc_duplicates__SWIG_6(self, args);
+            }
+          }
+        }
+      }
+    }
+  }
+  
+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,int)>(int const,int const,int [],int [],int [])\n    sum_csc_duplicates<(int,long)>(int const,int const,int [],int [],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)>(int const,int const,int [],int [],npy_cfloat [])\n    sum_csc_duplicates<(int,npy_cdouble)>(int const,int const,int [],int [],npy_cdouble [])\n");
+  return NULL;
+}
+
+
 static PyMethodDef SwigMethods[] = {
 	 { (char *)"csrtocsc", _wrap_csrtocsc, METH_VARARGS, (char *)"\n"
 		"csrtocsc(int n_row, int n_col, int Ap, int Aj, int Ax, std::vector<(int)> Bp, \n"
@@ -28158,6 +29220,22 @@
 		"sort_csc_indices(int n_row, int n_col, int Ap, int Ai, npy_cfloat Ax)\n"
 		"sort_csc_indices(int n_row, int n_col, int Ap, int Ai, npy_cdouble 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, int Ax)\n"
+		"sum_csr_duplicates(int n_row, int n_col, int Ap, int Aj, 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 Ax)\n"
+		"sum_csr_duplicates(int n_row, int n_col, int Ap, int Aj, npy_cdouble 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, int Ax)\n"
+		"sum_csc_duplicates(int n_row, int n_col, int Ap, int Ai, 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 Ax)\n"
+		"sum_csc_duplicates(int n_row, int n_col, int Ap, int Ai, npy_cdouble Ax)\n"
+		""},
 	 { NULL, NULL, 0, NULL }
 };
 

Modified: trunk/Lib/sparse/tests/test_sparse.py
===================================================================
--- trunk/Lib/sparse/tests/test_sparse.py	2007-07-13 09:22:29 UTC (rev 3163)
+++ trunk/Lib/sparse/tests/test_sparse.py	2007-07-15 02:22:48 UTC (rev 3164)
@@ -107,13 +107,27 @@
         c = a + b
         assert_array_equal(c.todense(),[[2,0,2,4],[6,0,2,0],[0,4,0,0]])
     
+    def check_radd(self):
+        a = self.datsp
+        b = self.datsp.copy()
+        b[0,2] = 2.0
+        c = a.todense() + b
+        assert_array_equal(c,[[2,0,2,4],[6,0,2,0],[0,4,0,0]])
+    
     def check_sub(self):
         assert_array_equal((self.datsp - self.datsp).todense(),[[0,0,0,0],[0,0,0,0],[0,0,0,0]])
 
         A = self.spmatrix(matrix([[1,0,0,4],[-1,0,0,0],[0,8,0,-5]],'d'))
         assert_array_equal((self.datsp - A).todense(),self.dat - A.todense())
         assert_array_equal((A - self.datsp).todense(),A.todense() - self.dat)
+    
+    def check_rsub(self):
+        assert_array_equal((self.dat - self.datsp),[[0,0,0,0],[0,0,0,0],[0,0,0,0]])
 
+        A = self.spmatrix(matrix([[1,0,0,4],[-1,0,0,0],[0,8,0,-5]],'d'))
+        assert_array_equal((self.dat - A),self.dat - A.todense())
+        assert_array_equal((A.todense() - self.datsp),A.todense() - self.dat)
+
     def check_elmul(self):
         a = self.datsp
         b = self.datsp.copy()




More information about the Scipy-svn mailing list