# source:sage/matrix/matrix_space.py@3271:d86a714eab75

Revision 3271:d86a714eab75, 24.0 KB checked in by William Stein <wstein@…>, 6 years ago (diff)

Sparse matrices over the integers; also fixed a bug that prevented sparse matrices over ZZ and QQ from pickling.

Line
1r"""
2Matrix Spaces.
3
4You can create any space $\text{Mat}_{n\times m}(R)$ of either dense
5or sparse matrices with given number of rows and columns over any
6commutative or noncommutative ring.
7
8EXAMPLES:
9    sage: MS = MatrixSpace(QQ,6,6,sparse=True); MS
10    Full MatrixSpace of 6 by 6 sparse matrices over Rational Field
11    sage: MS.base_ring()
12    Rational Field
13    sage: MS = MatrixSpace(ZZ,3,5,sparse=False); MS
14    Full MatrixSpace of 3 by 5 dense matrices over Integer Ring
15"""
16
17# System imports
18import random
19import weakref
20
21# SAGE matrix imports
22import matrix
23import matrix_generic_dense
24import matrix_generic_sparse
25
26import matrix_modn_dense
27import matrix_modn_sparse
28
29import matrix_integer_dense
30import matrix_integer_sparse
31
32import matrix_rational_dense
33import matrix_rational_sparse
34
35## import matrix_cyclo_dense
36## import matrix_cyclo_sparse
37
38
39# IMPORTANT - these two guys get imported below only later
40# since they currently force numpy to import, which takes
41# a *long* time.
42#import matrix_real_double_dense
43#import matrix_complex_double_dense
44
45import sage.groups.matrix_gps.matrix_group_element
46
47
48# SAGE imports
49import sage.structure.parent_gens as parent_gens
50import sage.rings.ring as ring
51import sage.rings.rational_field as rational_field
52import sage.rings.integer_ring as integer_ring
53import sage.rings.integer as integer
54import sage.rings.field as field
55import sage.rings.finite_field as finite_field
56import sage.rings.principal_ideal_domain as principal_ideal_domain
57import sage.rings.integral_domain as integral_domain
58import sage.rings.number_field.all
59import sage.rings.integer_mod_ring
60import sage.misc.latex as latex
61#import sage.rings.real_double as real_double
62from sage.misc.misc import xsrange
63
64import sage.modules.free_module_element
65import sage.modules.free_module
66
67from sage.structure.sequence import Sequence
68
69def is_MatrixSpace(x):
70    """
71    returns true if self is an instance of MatrixSpace
72    returns false if self is not an instance of MatrixSpace
73
74    EXAMPLES:
75        sage: MS = MatrixSpace(QQ,2)
76        sage: A = MS.random_element()
77        sage: is_MatrixSpace(MS)
78        True
79        sage: is_MatrixSpace(A)
80        False
81        sage: is_MatrixSpace(5)
82        False
83    """
84
85    return isinstance(x, MatrixSpace_generic)
86
87_cache = {}
88def MatrixSpace(base_ring, nrows, ncols=None, sparse=False):
89    """
90    Create with the command
91
92          MatrixSpace(base_ring , nrows [, ncols] [, sparse])
93
94    The default value of the optional argument sparse is False.
95    The default value of the optional argument ncols is nrows.
96
97    INPUT:
98         base_ring -- a ring
99         nrows -- int, the number of rows
100         ncols -- (default nrows) int, the number of columns
101         sparse -- (default false) whether or not matrices are given
102                   a sparse representation
103    OUTPUT:
104        The unique space of all nrows x ncols matrices over base_ring.
105
106    EXAMPLES:
107        sage: MS = MatrixSpace(RationalField(),2)
108        sage: MS.base_ring()
109        Rational Field
110        sage: MS.dimension()
111        4
112        sage: MS.dims()
113        (2, 2)
114        sage: B = MS.basis()
115        sage: B
116        [
117        [1 0]
118        [0 0],
119        [0 1]
120        [0 0],
121        [0 0]
122        [1 0],
123        [0 0]
124        [0 1]
125        ]
126        sage: B[0]
127        [1 0]
128        [0 0]
129        sage: B[1]
130        [0 1]
131        [0 0]
132        sage: B[2]
133        [0 0]
134        [1 0]
135        sage: B[3]
136        [0 0]
137        [0 1]
138        sage: A = MS.matrix([1,2,3,4])
139        sage: A
140        [1 2]
141        [3 4]
142        sage: MS2 = MatrixSpace(RationalField(),2,3)
143        sage: B = MS2.matrix([1,2,3,4,5,6])
144        sage: A*B
145        [ 9 12 15]
146        [19 26 33]
147
148        sage: M = MatrixSpace(ZZ, 10)
149        sage: M
150        Full MatrixSpace of 10 by 10 dense matrices over Integer Ring
152        True
153
154    """
155    if ncols is None: ncols = nrows
156    nrows = int(nrows); ncols = int(ncols); sparse=bool(sparse)
157    key = (base_ring, nrows, ncols, sparse)
158    if _cache.has_key(key):
159        M = _cache[key]()
160        if not M is None: return M
161
162    if not sage.rings.ring.is_Ring(base_ring):
163        raise TypeError, "base_ring (=%s) must be a ring"%base_ring
164
165    M = MatrixSpace_generic(base_ring, nrows, ncols, sparse)
166
167    _cache[key] = weakref.ref(M)
168    return M
169
170
171
172class MatrixSpace_generic(parent_gens.ParentWithGens):
173    """
174    The space of all nrows x ncols matrices over base_ring.
175
176    EXAMPLES:
177        sage: MatrixSpace(ZZ,10,5)
178        Full MatrixSpace of 10 by 5 dense matrices over Integer Ring
179        sage: MatrixSpace(ZZ,10,2^33)
180        Traceback (most recent call last):                                   # 32-bit
181        ...                                                                  # 32-bit
182        ValueError: number of rows and columns must be less than 2^32 (on a 32-bit computer -- use a 64-bit computer for bigger matrices)    # 32-bit
183        Full MatrixSpace of 10 by 8589934592 dense matrices over Integer Ring   # 64-bit
184    """
185    def __init__(self,  base_ring,
186                        nrows,
187                        ncols=None,
188                        sparse=False):
189        parent_gens.ParentWithGens.__init__(self, base_ring)
190        if not isinstance(base_ring, ring.Ring):
191            raise TypeError, "base_ring must be a ring"
192        if ncols == None: ncols = nrows
193        nrows = int(nrows)
194        ncols = int(ncols)
195        if nrows < 0:
196            raise ArithmeticError, "nrows must be nonnegative"
197        if ncols < 0:
198            raise ArithmeticError, "ncols must be nonnegative"
199
200        if sage.misc.misc.is_64bit():
201            if nrows >= 2**64 or ncols >= 2**64:
202                raise ValueError, "number of rows and columns must be less than 2^64"
203        else:
204            if nrows >= 2**32 or ncols >= 2**32:
205                raise ValueError, "number of rows and columns must be less than 2^32 (on a 32-bit computer -- use a 64-bit computer for bigger matrices)"
206
207        self.__nrows = nrows
208        self.__is_sparse = sparse
209        if ncols == None:
210            self.__ncols = nrows
211        else:
212            self.__ncols = ncols
213        self.__matrix_class = self._get_matrix_class()
214
215    def __reduce__(self):
216        """
217        EXAMPLES:
218            sage: A = Mat(ZZ,5,7,sparse=True)
219            sage: A
220            Full MatrixSpace of 5 by 7 sparse matrices over Integer Ring
222            True
223        """
224        return MatrixSpace, (self.base_ring(), self.__nrows, self.__ncols, self.__is_sparse)
225
226    def __call__(self, entries=0, coerce=True, copy=True):
227        """
228        EXAMPLES:
229            sage: k = GF(7); G = MatrixGroup([matrix(k,2,[1,1,0,1]), matrix(k,2,[1,0,0,2])])
230            sage: g = G.0
231            sage: MatrixSpace(k,2)(g)
232            [1 1]
233            [0 1]
234        """
235        if entries == 0 and hasattr(self, '__zero_matrix'):
236            return self.zero_matrix()
237
238        if isinstance(entries, list) and len(entries) > 0 and \
239           sage.modules.free_module_element.is_FreeModuleElement(entries[0]):
240            if self.__is_sparse:
241                e = {}
242                zero = self.base_ring()(0)
243                for i in xrange(len(entries)):
244                    for j, x in entries[i].iteritems():
245                        if x != zero:
246                            e[(i,j)] = x
247                entries = e
248            else:
249                entries = sum([v.list() for v in entries],[])
250        if not self.__is_sparse and isinstance(entries, dict):
251            entries = dict_to_list(entries, self.__nrows, self.__ncols)
252            coerce = True
253            copy = False
254        elif self.__is_sparse and isinstance(entries, (list, tuple)):
255            entries = list_to_dict(entries, self.__nrows, self.__ncols)
256            coerce = True
257            copy = False
258        elif sage.groups.matrix_gps.matrix_group_element.is_MatrixGroupElement(entries):
259            return self(entries.matrix(), copy=False)
260        return self.matrix(entries, copy=copy, coerce=coerce)
261
262    def change_ring(self, R):
263        """
264        Return matrix space over R with otherwise same parameters as self.
265
266        INPUT:
267            R -- ring
268
269        OUTPUT:
270            a matrix space
271
272        EXAMPLES:
273            sage: Mat(QQ,3,5).change_ring(GF(7))
274            Full MatrixSpace of 3 by 5 dense matrices over Finite Field of size 7
275        """
276        try:
277            return self.__change_ring[R]
278        except AttributeError:
279            self.__change_ring = {}
280        except KeyError:
281            pass
282        M = MatrixSpace(R, self.__nrows, self.__ncols, self.__is_sparse)
283        self.__change_ring[R] = M
284        return M
285
286    def base_extend(self, R):
287        """
288        Return base extension of this matrix space to R.
289
290
291        INPUT:
292            R -- ring
293
294        OUTPUT:
295            a matrix space
296
297        EXAMPLES:
298            sage: Mat(ZZ,3,5).base_extend(QQ)
299            Full MatrixSpace of 3 by 5 dense matrices over Rational Field
300            sage: Mat(QQ,3,5).base_extend(GF(7))
301            Traceback (most recent call last):
302            ...
303            TypeError: no base extension defined
304        """
305        if R.has_coerce_map_from(self.base_ring()):
306            return self.change_ring(R)
307        raise TypeError, "no base extension defined"
308
309    def _coerce_impl(self, x):
310        """
311        EXAMPLES:
312            sage: MS1 = MatrixSpace(QQ,3)
313            sage: MS2 = MatrixSpace(ZZ,4,5,true)
314            sage: A = MS1(range(9))
315            sage: D = MS2(range(20))
316            sage: MS1._coerce_(A)
317            [0 1 2]
318            [3 4 5]
319            [6 7 8]
320            sage: MS2._coerce_(D)
321            [ 0  1  2  3  4]
322            [ 5  6  7  8  9]
323            [10 11 12 13 14]
324            [15 16 17 18 19]
325        """
326        if isinstance(x, matrix.Matrix):
327            if self.is_sparse() and x.is_dense():
328                raise TypeError, "cannot coerce dense matrix into sparse space for arithmetic"
329            if x.nrows() == self.nrows() and x.ncols() == self.ncols():
330                if self.base_ring().has_coerce_map_from(x.base_ring()):
331                    return self(x)
332                raise TypeError, "no canonical coercion"
333        return self._coerce_try(x, self.base_ring())
334
335    def __cmp__(self, other):
336        """
337        Compare this matrix space with other.  Sparse and dense matrix
338        spaces with otherwise the same parameters are considered
339        equal.
340
341        If other is not a matrix space, return something arbitrary but
342        deterministic.  Otherwise, compare based on base ring, then on
343        number of rows and columns.
344
345        EXAMPLES:
346            sage: Mat(ZZ,1000) == Mat(QQ,1000)
347            False
348            sage: Mat(ZZ,10) == Mat(ZZ,10)
349            True
350            sage: Mat(ZZ,10, sparse=False) == Mat(ZZ,10, sparse=True)
351            True
352        """
353        if isinstance(other, MatrixSpace_generic):
354            return cmp((self.base_ring(), self.__nrows, self.__ncols),
355                       (other.base_ring(), other.__nrows, other.__ncols))
356        return cmp(type(self), type(other))
357
358    def _repr_(self):
359        """
360        Returns the string representation of a MatrixSpace
361
362        EXAMPLES:
363            sage: MS = MatrixSpace(ZZ,2,4,true)
364            sage: repr(MS)
365            'Full MatrixSpace of 2 by 4 sparse matrices over Integer Ring'
366            sage: MS
367            Full MatrixSpace of 2 by 4 sparse matrices over Integer Ring
368        """
369        if self.is_sparse():
370            s = "sparse"
371        else:
372            s = "dense"
373        return "Full MatrixSpace of %s by %s %s matrices over %s"%(
374                    self.__nrows, self.__ncols, s, self.base_ring())
375
376    def _latex_(self):
377        r"""
378        Returns the latex representation of a MatrixSpace
379
380        EXAMPLES:
381            sage: MS3 = MatrixSpace(QQ,6,6,true)
382            sage: latex(MS3)
383            \mbox{\rm Mat}_{6\times 6}(\mathbf{Q})
384        """
385        return "\\mbox{\\rm Mat}_{%s\\times %s}(%s)"%(self.nrows(), self.ncols(),
386                                                      latex.latex(self.base_ring()))
387
388    def _get_matrix_class(self):
389        """
390        Returns the class of self
391
392        EXAMPLES:
393            sage: MS1 = MatrixSpace(QQ,4)
394            sage: MS2 = MatrixSpace(ZZ,4,5,true)
395            sage: MS1._get_matrix_class()
396            <type 'sage.matrix.matrix_rational_dense.Matrix_rational_dense'>
397            sage: MS2._get_matrix_class()
398            <type 'sage.matrix.matrix_integer_sparse.Matrix_integer_sparse'>
399        """
400        R = self.base_ring()
401        if self.is_dense():
402            if sage.rings.integer_ring.is_IntegerRing(R):
403                return matrix_integer_dense.Matrix_integer_dense
404            elif sage.rings.rational_field.is_RationalField(R):
405                return matrix_rational_dense.Matrix_rational_dense
406            elif R==sage.rings.real_double.RDF:
407                import matrix_real_double_dense
408                return matrix_real_double_dense.Matrix_real_double_dense
409            elif R==sage.rings.complex_double.CDF:
410                import matrix_complex_double_dense
411                return matrix_complex_double_dense.Matrix_complex_double_dense
412            elif sage.rings.integer_mod_ring.is_IntegerModRing(R) and R.order() < matrix_modn_dense.MAX_MODULUS:
413                return matrix_modn_dense.Matrix_modn_dense
414            # the default
415            return matrix_generic_dense.Matrix_generic_dense
416
417        else:
418            if sage.rings.integer_mod_ring.is_IntegerModRing(R) and R.order() < matrix_modn_sparse.MAX_MODULUS:
419                return matrix_modn_sparse.Matrix_modn_sparse
420            # the default
421            elif sage.rings.rational_field.is_RationalField(R):
422                return matrix_rational_sparse.Matrix_rational_sparse
423            elif sage.rings.integer_ring.is_IntegerRing(R):
424                return matrix_integer_sparse.Matrix_integer_sparse
425            return matrix_generic_sparse.Matrix_generic_sparse
426
427
428    def basis(self):
429        """
430        Returns a basis for this matrix space.
431
432        WARNING: This will of course compute every generator of this
433        matrix space.  So for large matrices, this could take a long
434        time, waste a massive amount of memory (for dense matrices),
435        and is likely not very useful.  Don't use this on large matrix
436        spaces.
437
438        EXAMPLES:
439            sage: Mat(ZZ,2,2).basis()
440            [
441            [1 0]
442            [0 0],
443            [0 1]
444            [0 0],
445            [0 0]
446            [1 0],
447            [0 0]
448            [0 1]
449            ]
450        """
451        v = [self.zero_matrix() for _ in range(self.dimension())]
452        one = self.base_ring()(1)
453        i = 0
454        for r in range(self.__nrows):
455            for c in range(self.__ncols):
456                v[i][r,c] = one
457                v[i].set_immutable()
458                i += 1
459        return Sequence(v, universe=self, check=False, immutable=True, cr=True)
460
461    def dimension(self):
462        """
463        Returns (m rows) * (n cols) of self as Integer
464
465        EXAMPLES:
466            sage: MS = MatrixSpace(ZZ,4,6)
467            sage: u = MS.dimension()
468            sage: u - 24 == 0
469            True
470        """
471        return self.__nrows * self.__ncols
472
473    def dims(self):
474        """
475        Returns (m row, n col) representation of self dimension
476
477        EXAMPLES:
478            sage: MS = MatrixSpace(ZZ,4,6)
479            sage: MS.dims()
480            (4, 6)
481        """
482        return (self.__nrows, self.__ncols)
483
484    def identity_matrix(self):
485        """
486        Create an identity matrix in self.  (Must be a space of square matrices).
487
488        EXAMPLES:
489            sage: MS1 = MatrixSpace(ZZ,4)
490            sage: MS2 = MatrixSpace(QQ,3,4)
491            sage: I = MS1.identity_matrix()
492            sage: I
493            [1 0 0 0]
494            [0 1 0 0]
495            [0 0 1 0]
496            [0 0 0 1]
497            sage: Er = MS2.identity_matrix()
498            Traceback (most recent call last):
499            ...
500            TypeError: self must be a space of square matrices
501        """
502        if self.__nrows != self.__ncols:
503            raise TypeError, "self must be a space of square matrices"
504        A = self(0)
505        for i in xrange(self.__nrows):
506            A[i,i] = 1
507        return A
508
509    def is_dense(self):
510        """
511        Returns True if matrices in self are dense and False otherwise.
512
513        EXAMPLES:
514            sage: Mat(RDF,2,3).is_sparse()
515            False
516            sage: Mat(RR,123456,22,sparse=True).is_sparse()
517            True
518        """
519        return not self.__is_sparse
520
521    def is_sparse(self):
522        """
523        Returns True if matrices in self are sparse and False otherwise.
524
525        EXAMPLES:
526            sage: Mat(GF(2011),10000).is_sparse()
527            False
528            sage: Mat(GF(2011),10000,sparse=True).is_sparse()
529            True
530        """
531        return self.__is_sparse
532
533    def gen(self, n):
534        """
535        Return the n-th generator of this matrix space.
536
537        This doesn't compute all basis matrices, so it is reasonably intelligent.
538
539        EXAMPLES:
540            sage: M = Mat(GF(7),10000,5); M.ngens()
541            50000
542            sage: a = M.10
543            sage: a[:4]
544            [0 0 0 0 0]
545            [0 0 0 0 0]
546            [1 0 0 0 0]
547            [0 0 0 0 0]
548        """
549        if hasattr(self, '__basis'):
550            return self.__basis[n]
551        r = n // self.__ncols
552        c = n - (r * self.__ncols)
553        z = self.zero_matrix()
554        z[r,c] = 1
555        return z
556
557    def zero_matrix(self):
558        """
559        Return the zero matrix.
560        """
561        try:
562            z = self.__zero_matrix
563        except AttributeError:
564            z = self(0)
565            self.__zero_matrix = z
566        return z.__copy__()
567
568    def ngens(self):
569        """
570        Return the number of generators of this matrix space, which is the number
571        of entries in the matrices in this space.
572
573        EXAMPLES:
574            sage: M = Mat(GF(7),100,200); M.ngens()
575            20000
576        """
577        return self.dimension()
578
579    def matrix(self, x=0, coerce=True, copy=True):
580        """
581        Create a matrix in self.  The entries can be specified either
582        as a single list of length nrows*ncols, or as a list of
583        lists.
584
585        EXAMPLES:
586            sage: M = MatrixSpace(ZZ, 2)
587            sage: M.matrix([[1,0],[0,-1]])
588            [ 1  0]
589            [ 0 -1]
590            sage: M.matrix([1,0,0,-1])
591            [ 1  0]
592            [ 0 -1]
593        """
594        if isinstance(x, (xrange,xsrange)):
595            x = list(x)
596        elif isinstance(x, (int, integer.Integer)) and x==1:
597            return self.identity_matrix()
598        if matrix.is_Matrix(x):
599            if x.parent() is self:
600                if x.is_immutable():
601                    return x
602                else:
603                    return x.copy()
604            x = x.list()
605        if isinstance(x, list) and len(x) > 0:
606            if isinstance(x[0], list):
607                x = sum(x,[])
608            elif hasattr(x[0], "is_vector"): # TODO: is this the best way to test that?
609                e = []
610                for v in x:
611                    e = e + v.list()
612                copy = False # deep copy?
613                x = e
614            elif isinstance(x[0], tuple):
615                x = list(sum(x,()))
616        return self.__matrix_class(self, entries=x, copy=copy, coerce=coerce)
617
618    def matrix_space(self, nrows=None, ncols=None, sparse=False):
619        """
620        Return the matrix space with given number of rows, columns and
621        sparcity over the same base ring as self, and defaults the
622        same as self.
623
624        EXAMPLES:
625            sage: M = Mat(GF(7),100,200)
626            sage: M.matrix_space(5000)
627            Full MatrixSpace of 5000 by 200 dense matrices over Finite Field of size 7
628            sage: M.matrix_space(ncols=5000)
629            Full MatrixSpace of 100 by 5000 dense matrices over Finite Field of size 7
630            sage: M.matrix_space(sparse=True)
631            Full MatrixSpace of 100 by 200 sparse matrices over Finite Field of size 7
632        """
633        if nrows is None:
634            nrows = self.__nrows
635        if ncols is None:
636            ncols = self.__ncols
637        return MatrixSpace(self.base_ring(), nrows, ncols,
638                        sparse=sparse)
639
640    def ncols(self):
641        """
642        Return the number of columns of matrices in this space.
643
644        EXAMPLES:
645            sage: M = Mat(ZZ['x'],200000,500000,sparse=True)
646            sage: M.ncols()
647            500000
648        """
649        return self.__ncols
650
651    def nrows(self):
652        """
653        Return the number of rows of matrices in this space.
654
655        EXAMPLES:
656            sage: M = Mat(ZZ,200000,500000)
657            sage: M.nrows()
658            200000
659        """
660        return self.__nrows
661
662    def row_space(self):
663        """
664        Return the module spanned by all rows of matrices in this matrix space.
665        This is a free module of rank the number of rows.  It will be sparse
666        or dense as this matrix space is sparse or dense.
667
668        EXAMPLES:
669            sage: M = Mat(ZZ,20,5,sparse=False); M.row_space()
670            Ambient free module of rank 5 over the principal ideal domain Integer Ring
671        """
672        try:
673            return self.__row_space
674        except AttributeError:
675            self.__row_space = sage.modules.free_module.FreeModule(self.base_ring(),
676                                                self.ncols(), sparse=self.is_sparse())
677            return self.__row_space
678
679    def column_space(self):
680        """
681        Return the module spanned by all columns of matrices in this matrix space.
682        This is a free module of rank the number of columns.  It will be sparse
683        or dense as this matrix space is sparse or dense.
684
685        EXAMPLES:
686            sage: M = Mat(GF(9,'a'),20,5,sparse=True); M.column_space()
687            Sparse vector space of dimension 20 over Finite Field in a of size 3^2
688        """
689        try:
690            return self.__column_space
691        except AttributeError:
692            self.__column_space = sage.modules.free_module.FreeModule(self.base_ring(), self.nrows(),
693                                                                   sparse=self.is_sparse())
694            return self.__column_space
695
696    def random_element(self, density=1, *args, **kwds):
697        """
698        INPUT:
699            density -- integer (default: 1) rough measure of the proportion of nonzero
700                       entries in the random matrix
701            *args, **kwds -- rest of parameters may be passed to the random_element function
702                   of the base ring. ("may be", since this function calls the randomize
703                   function on the zero matrix, which need not call the random_element function
704                   of the base ring at all in general.)
705
706        EXAMPLES:
707            sage: Mat(ZZ,2,5).random_element()                # random output
708            [-1 -1  0 -2  0]
709            [ 0 -1  2 -1 -1]
710            sage: Mat(QQ,2,5).random_element(density=0.5)        # random output
711            [-1/2    0 -1/2  1/2    0]
712            [   0    0   -1    0    0]
713            sage: Mat(QQ,3,sparse=True).random_element()      # random output
714            [  1   2   1]
715            [  0   1  -3]
716            [1/2  -1   0]
717            sage: Mat(GF(9,'a'),3,sparse=True).random_element()   # random output
718            [      a   a + 1       0]
719            [    2*a 2*a + 1   a + 2]
720            [      1       0       1]
721        """
722        Z = self.zero_matrix()
723        Z.randomize(density, *args, **kwds)
724        return Z
725
726_random = 1
727
728def dict_to_list(entries, nrows, ncols):
729    v = [0]*(nrows*ncols)
730    for ij, y in entries:
731        i,j = ij
732        v[i*ncols + j] = y
733    return v
734
735def list_to_dict(entries, nrows, ncols):
736    d = {}
737    if ncols == 0 or nrows == 0:
738        return d
739    for i in range(len(entries)):
740        x = entries[i]
741        if x != 0:
742            col = i % ncols
743            row = i // ncols
744            d[(row,col)] = x
745    return d
746
747
Note: See TracBrowser for help on using the repository browser.