| 1 | ############################################# |
|---|
| 2 | ## Generic *DENSE* matrices over any field |
|---|
| 3 | ############################################# |
|---|
| 4 | |
|---|
| 5 | def _convert_dense_entries_to_list(entries): |
|---|
| 6 | # Create matrix from a list of vectors |
|---|
| 7 | e = [] |
|---|
| 8 | for v in entries: |
|---|
| 9 | e = e+ v.list() |
|---|
| 10 | copy = False |
|---|
| 11 | return e |
|---|
| 12 | |
|---|
| 13 | include "../ext/interrupt.pxi" |
|---|
| 14 | |
|---|
| 15 | cimport matrix_pyx |
|---|
| 16 | import matrix_pyx |
|---|
| 17 | |
|---|
| 18 | |
|---|
| 19 | |
|---|
| 20 | cdef class Matrix_dense(matrix_pyx.Matrix): |
|---|
| 21 | """ |
|---|
| 22 | The \\class{Matrix_dense} class derives from |
|---|
| 23 | \\class{Matrix}, and defines functionality for dense matrices over |
|---|
| 24 | any base ring. Matrices are represented by a list of elements in |
|---|
| 25 | the base ring, and element access operations are implemented in |
|---|
| 26 | this class. |
|---|
| 27 | """ |
|---|
| 28 | def __new__(self, parent, int nrows, int ncols, |
|---|
| 29 | entries = None, |
|---|
| 30 | coerce = True): |
|---|
| 31 | self._nrows = nrows |
|---|
| 32 | self._ncols = ncols |
|---|
| 33 | |
|---|
| 34 | def __init__(self, parent, int nrows, int ncols, |
|---|
| 35 | entries = None, |
|---|
| 36 | coerce = True): |
|---|
| 37 | matrix_pyx.Matrix.__init__(self, parent) |
|---|
| 38 | cdef int i, n |
|---|
| 39 | #self._entries = PyList_New(nrows*ncols) |
|---|
| 40 | self._entries = [None]*(nrows*ncols) |
|---|
| 41 | if entries: |
|---|
| 42 | n = len(entries) |
|---|
| 43 | if coerce: |
|---|
| 44 | R = parent.base_ring() |
|---|
| 45 | for i from 0 <= i < n: |
|---|
| 46 | self._entries[i] = R(entries[i]) |
|---|
| 47 | else: |
|---|
| 48 | for i from 0 <= i < n: |
|---|
| 49 | self._entries[i] = entries[i] |
|---|
| 50 | |
|---|
| 51 | self._row_indices = <int*> PyMem_Malloc(sizeof(int*) * nrows) |
|---|
| 52 | |
|---|
| 53 | n = 0 |
|---|
| 54 | for i from 0 <= i < nrows: |
|---|
| 55 | self._row_indices[i] = n |
|---|
| 56 | n = n + ncols |
|---|
| 57 | |
|---|
| 58 | def __dealloc__(self): |
|---|
| 59 | if self._row_indices != <int*> 0: |
|---|
| 60 | PyMem_Free(self._row_indices) |
|---|
| 61 | |
|---|
| 62 | def __getitem__(self, ij): |
|---|
| 63 | """ |
|---|
| 64 | INPUT: |
|---|
| 65 | A[i, j] -- the i,j of A, and |
|---|
| 66 | A[i] -- the i-th row of A. |
|---|
| 67 | """ |
|---|
| 68 | #self._require_mutable() # todo |
|---|
| 69 | cdef int i, j |
|---|
| 70 | i, j = ij |
|---|
| 71 | if i < 0 or i >= self._nrows: |
|---|
| 72 | raise IndexError |
|---|
| 73 | return self._entries[self._row_indices[i] + j] |
|---|
| 74 | |
|---|
| 75 | def __setitem__(self, ij, value): |
|---|
| 76 | """ |
|---|
| 77 | INPUT: |
|---|
| 78 | A[i, j] = value -- set the (i,j) entry of A |
|---|
| 79 | A[i] = value -- set the ith row of A |
|---|
| 80 | """ |
|---|
| 81 | #self._require_mutable() # todo |
|---|
| 82 | cdef int i, j |
|---|
| 83 | i, j = ij |
|---|
| 84 | if i < 0 or i >= self._nrows: |
|---|
| 85 | raise IndexError |
|---|
| 86 | self._entries[self._row_indices[i] + j] = value |
|---|
| 87 | |
|---|
| 88 | def _multiply(self, Matrix_dense right): |
|---|
| 89 | cdef int i, j, k, m, n, r, nr, nc, snc |
|---|
| 90 | cdef object v |
|---|
| 91 | |
|---|
| 92 | if self._ncols != right._nrows: |
|---|
| 93 | raise IndexError, "Number of columns of self must equal number of rows of other." |
|---|
| 94 | |
|---|
| 95 | cdef Matrix_dense A |
|---|
| 96 | nr = self._nrows |
|---|
| 97 | nc = right._ncols |
|---|
| 98 | snc = self._ncols |
|---|
| 99 | |
|---|
| 100 | R = self.base_ring() |
|---|
| 101 | P = self.matrix_space(nr, nc) |
|---|
| 102 | A = Matrix_dense(P, nr, nc) |
|---|
| 103 | v = A._entries |
|---|
| 104 | zero = R(0) |
|---|
| 105 | r = 0 |
|---|
| 106 | for i from 0 <= i < nr: |
|---|
| 107 | m = self._row_indices[i] |
|---|
| 108 | for j from 0 <= j < nc: |
|---|
| 109 | z = zero |
|---|
| 110 | for k from 0 <= k < snc: |
|---|
| 111 | #z = z + self._entries[m + k] * right._entries[right._row_indices[k]+j] |
|---|
| 112 | |
|---|
| 113 | #z = z + PyList_GET_ITEM(self._entries, m + k)._mul_( |
|---|
| 114 | # PyList_GET_ITEM(right._entries, right._row_indices[k]+j)) |
|---|
| 115 | |
|---|
| 116 | z = z + multiply_items(self._entries, m+k, right._entries, right._row_indices[k]+j) |
|---|
| 117 | |
|---|
| 118 | #z = z + PyNumber_Multiply( PyList_GET_ITEM(self._entries, m + k), |
|---|
| 119 | # PyList_GET_ITEM(right._entries, right._row_indices[k]+j)) |
|---|
| 120 | |
|---|
| 121 | v[r] = z |
|---|
| 122 | r = r + 1 |
|---|
| 123 | return A |
|---|
| 124 | |
|---|
| 125 | def list(self): |
|---|
| 126 | return self._entries |
|---|
| 127 | |
|---|
| 128 | def antitranspose(self): |
|---|
| 129 | raise NotImplementedError |
|---|
| 130 | |
|---|
| 131 | def transpose(self): |
|---|
| 132 | """ |
|---|
| 133 | Returns the transpose of self, without changing self. |
|---|
| 134 | |
|---|
| 135 | EXAMPLES: |
|---|
| 136 | We create a matrix, compute its transpose, and note that the |
|---|
| 137 | original matrix is not changed. |
|---|
| 138 | sage: M = MatrixSpace(QQ, 2) |
|---|
| 139 | sage: A = M([1,2,3,4]) |
|---|
| 140 | sage: B = A.transpose() |
|---|
| 141 | sage: print B |
|---|
| 142 | [1 3] |
|---|
| 143 | [2 4] |
|---|
| 144 | sage: print A |
|---|
| 145 | [1 2] |
|---|
| 146 | [3 4] |
|---|
| 147 | """ |
|---|
| 148 | raise NotImplementedError |
|---|
| 149 | |
|---|
| 150 | |
|---|
| 151 | |
|---|
| 152 | cdef object multiply_items(object v, int i, object w, int j): |
|---|
| 153 | return PyNumber_Multiply( PyList_GET_ITEM(v, i), PyList_GET_ITEM(w, j) ) |
|---|