@@ -19,6 +19,8 @@ from cysparse.sparse.csr_mat_matrices.csr_mat_@index@_@type@ cimport MakeCSRSpar
1919from cysparse.sparse.csc_mat_matrices.csc_mat_@index@_@type@ cimport MakeCSCSparseMatrix_@index@_@type@
2020
2121from cysparse.sparse.sparse_utils.generic.generate_indices_@index@ cimport create_c_array_indices_from_python_object_@index@
22+ from cysparse.sparse.sparse_utils.generic.find_@index@_@index@ cimport find_linear_@index@_@index@
23+
2224from cysparse.sparse.sparse_utils.generic.print_@type@ cimport element_to_string_@type@, conjugated_element_to_string_@type@, empty_to_string_@type@
2325
2426########################################################################################################################
@@ -367,25 +369,90 @@ cdef class LLSparseMatrix_@index@_@type@(MutableSparseMatrix_@index@_@type@):
367369 Args:
368370 B: List or :program:`NumPy` array with indices of the rows to be deleted.
369371 """
370- # TODO: to be written...
372+ # TODO: this code is duplicated from 'delete_rows_with_mask': maybe we should merge both codes?
373+ # TODO: this code is very slow... maybe optimize one day? In particular the main loop combined with linear search
374+ # for non existing elements is particularly poor design.
375+
376+ if self.__is_symmetric:
377+ raise NotImplementedError('This method is not allowed for symmetric matrices')
378+
379+ cdef:
380+ @index@ nrow
381+ @index@ * row_indices
382+
383+ row_indices = create_c_array_indices_from_python_object_@index@(self.__nrow, <PyObject *> B, &nrow)
384+
385+ # Delete the rows to be cancelled by rearranging the row
386+ # array. After having done so, newdim is the new matrix dim.
387+ cdef:
388+ @index@ row, act
389+ @index@ newm = 0
390+ @index@ newnnz = self.__nnz
391+
392+ for row from 0<= row < self.__nrow:
393+
394+ if find_linear_@index@_@index@(row, row_indices, 0, nrow) == nrow: # This row has to be kept
395+ self.root[newm] = self.root[row] # Shift row to the left
396+ newm += 1
397+ else: # row left out; update free list
398+ act = self.root[row]
399+ if act != -1:
400+ newnnz -= 1
401+ while self.link[act] != -1: # Walk to the end of the list
402+ act = self.link[act]
403+ newnnz -= 1
404+
405+ self.link[act] = self.free # Attach end of row to free list
406+ self.free = self.root[row] # Start free list where row began
407+
408+
409+ # Set the new values
410+ self.__nrow = newm
411+ self.__nnz = newnnz
412+
413+ PyMem_Free(row_indices)
414+
415+ def delete_row(self, @index@ row):
416+ """
417+ Delete one row in place.
418+
419+ Args:
420+ row: Number of the row to delete.
421+
422+ Note:
423+ **Don't** call this method repeatly to delete several rows. See ...
424+ """
425+ # Deleting one or several rows takes the same amount of time.
371426
372- raise NotImplementedError('Not yet implemented')
427+ if not (0<= row < self.__nrow):
428+ raise IndexError('Wrong row number (%d)' % row)
373429
374- #cdef :
375- # Py_ssize_t B_list_length, i_list
430+ if self.__is_symmetric :
431+ raise NotImplementedError('This method is not allowed for symmetric matrices')
376432
377- #if PyList_Check(<PyObject *>B):
378- # B_list_length = PyList_Size(<PyObject *>B)
433+ cdef:
434+ @index@ act, i
435+ @index@ newnnz = self.__nnz
436+
437+ # deal with the row to be deleted
438+ act = self.root[row]
379439
380- # for i_list from 0 <= i_list < B_list_length:
381- # pass
440+ if act != -1:
441+ newnnz -= 1
442+ while self.link[act] != -1: # Walk to the end of the list
443+ act = self.link[act]
444+ newnnz -= 1
382445
446+ self.link[act] = self.free # Attach end of row to free list
447+ self.free = self.root[row] # Start free list where row began
383448
449+ # Shift remaining rows to the left
450+ for i from row <= i < self.__nrow - 1:
451+ self.root[i] = self.root[i+1]
384452
385- #elif cnp.PyArray_Check(B):
386- # pass
387- #else:
388- # raise NotImplementedError('Argument must be a list or a NumPy array with indices of rows to delete')
453+ # Set the new values
454+ self.__nrow = self.__nrow - 1
455+ self.__nnz = newnnz
389456
390457 def delete_rows_with_mask(self, cnp.ndarray[dtype=cnp.npy_int8, ndim=1] maskArray):
391458 """
@@ -422,18 +489,18 @@ cdef class LLSparseMatrix_@index@_@type@(MutableSparseMatrix_@index@_@type@):
422489 for row from 0<= row < self.__nrow:
423490
424491 if maskArray_data[row * maskArray_stride]: # This row has to be kept
425- self.root[newm] = self.root[row]
492+ self.root[newm] = self.root[row] # Shift row to the left
426493 newm += 1
427- else: # row let out; update free list
494+ else: # row left out; update free list
428495 act = self.root[row]
429496 if act != -1:
430497 newnnz -= 1
431- while self.link[act] != -1: # Walk to the end of the list
498+ while self.link[act] != -1: # Walk to the end of the list
432499 act = self.link[act]
433500 newnnz -= 1
434501
435- self.link[act] = self.free # Attach end of row to free list
436- self.free = self.root[row] # Start free list where row began
502+ self.link[act] = self.free # Attach end of row to free list
503+ self.free = self.root[row] # Start free list where row began
437504
438505
439506 # Set the new values
0 commit comments