Attachment 'm4rie_for_sage.patch'

Download

   1 # HG changeset patch
   2 # User Martin Albrecht <[email protected]>
   3 # Date 1279639189 -3600
   4 # Node ID cc88353e2acb2bdbe05178a09647ccb8d524f340
   5 # Parent  96e2020790df6a5f4d413e65b111f0ec6e73fc2a
   6 Matrices over GF(2^n)
   7 
   8 diff -r 96e2020790df -r cc88353e2acb module_list.py
   9 --- a/module_list.py	Mon Jun 28 23:27:14 2010 +0100
  10 +++ b/module_list.py	Tue Jul 20 16:19:49 2010 +0100
  11 @@ -785,6 +785,12 @@
  12                libraries = ['gmp','m4ri', 'gd', 'png12', 'z'],
  13                depends = [SAGE_ROOT + "/local/include/png.h", SAGE_ROOT + "/local/include/m4ri/m4ri.h"]),
  14  
  15 +    Extension('sage.matrix.matrix_mod2e_dense',
  16 +              sources = ['sage/matrix/matrix_mod2e_dense.pyx'],
  17 +              libraries = ['m4rie', 'm4ri', 'givaro', 'ntl', 'gmpxx', 'gmp', 'm', 'stdc++'],
  18 +              depends = [SAGE_ROOT + "/local/include/m4rie/m4rie.h"],
  19 +              language="c++"),
  20 +
  21      Extension('sage.matrix.matrix_modn_dense',
  22                sources = ['sage/matrix/matrix_modn_dense.pyx'],
  23                libraries = ['gmp']),
  24 diff -r 96e2020790df -r cc88353e2acb sage/libs/m4rie.pxd
  25 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
  26 +++ b/sage/libs/m4rie.pxd	Tue Jul 20 16:19:49 2010 +0100
  27 @@ -0,0 +1,110 @@
  28 +##############################################################################
  29 +#       Copyright (C) 2010 Martin Albrecht <[email protected]>
  30 +#  Distributed under the terms of the GNU General Public License (GPL)
  31 +#  The full text of the GPL is available at:
  32 +#                  http://www.gnu.org/licenses/
  33 +##############################################################################
  34 +
  35 +from sage.libs.m4ri cimport mzd_t, m4ri_word
  36 +
  37 +
  38 +
  39 +cdef extern from "m4rie/m4rie.h":
  40 +    ctypedef struct gf2e:
  41 +        m4ri_word **mul
  42 +        m4ri_word *inv
  43 +        size_t degree
  44 +
  45 +    void gf2e_free(gf2e *ff)
  46 +
  47 +#cdef extern from "m4rie/gf2e_matrix.h":
  48 +    ctypedef struct mzed_t:
  49 +        mzd_t *x
  50 +        gf2e *finite_field
  51 +        int nrows
  52 +        int ncols
  53 +        int w
  54 +
  55 +    ctypedef int const_int "const int"
  56 +    ctypedef size_t const_size_t "const size_t"
  57 +    ctypedef mzed_t const_mzed_t "const mzed_t"
  58 +
  59 +    mzed_t *mzed_init(gf2e *, size_t m, size_t n)
  60 +
  61 +    void mzed_free(mzed_t *)
  62 +
  63 +    int mzed_read_elem(const_mzed_t *M, const_size_t row, const_size_t col)
  64 +
  65 +    void mzed_write_elem(mzed_t *, const_size_t row, const_size_t col, const_int elem)
  66 +
  67 +    mzed_t *mzed_copy(mzed_t *o, const_mzed_t *i)
  68 +
  69 +    int mzed_cmp(mzed_t *l, mzed_t *r)
  70 +
  71 +    mzed_t *mzed_randomize(mzed_t *)
  72 +
  73 +    mzed_t *mzed_add(mzed_t *, mzed_t *, mzed_t *)
  74 +
  75 +    size_t mzed_echelonize_naive(mzed_t *, size_t)
  76 +
  77 +    void mzed_add_elem(mzed_t *a, const_size_t row, const_size_t col, const_int elem)
  78 +
  79 +    void mzed_add_multiple_of_row(mzed_t *A, size_t ar, mzed_t *B, size_t br, m4ri_word *X, size_t start_col)
  80 +
  81 +    void mzed_rescale_row(mzed_t *A, size_t r, size_t c, m4ri_word *X)
  82 +
  83 +    void mzed_row_swap(mzed_t *M, const_size_t rowa, const_size_t rowb)
  84 +
  85 +    void mzed_copy_row(mzed_t* B, size_t i, const_mzed_t* A, size_t j)
  86 +
  87 +    void mzed_col_swap(mzed_t *M, const_size_t cola, const_size_t colb)
  88 +
  89 +    void mzed_row_add(mzed_t *M, const_size_t sourcerow, const_size_t destrow)
  90 +
  91 +    size_t mzed_first_zero_row(mzed_t *A)
  92 +
  93 +    int mzed_is_zero(mzed_t *A)
  94 +
  95 +    void mzed_row_clear_offset(mzed_t *M, const_size_t row, const_size_t coloffset)
  96 +
  97 +    mzed_t *mzed_concat(mzed_t *C, const_mzed_t *A, const_mzed_t *B)
  98 +
  99 +    mzed_t *mzed_stack(mzed_t *C, const_mzed_t *A, const_mzed_t *B)
 100 +
 101 +    mzed_t *mzed_submatrix(mzed_t *S, const_mzed_t *M, size_t lowr, size_t lowc, size_t highr, size_t highc)
 102 +
 103 +    mzed_t *mzed_mul_naive(mzed_t *C, const_mzed_t *A, const_mzed_t *B, const_int clear)
 104 +
 105 +    # TODO: not implemented yet in m4rie
 106 +    mzed_t *mzed_transpose(mzed_t *DST, const_mzed_t *A )
 107 +
 108 +    void mzed_print(const_mzed_t *M)
 109 + 
 110 +    mzed_t *mzed_invert_travolta(mzed_t *A, mzed_t *B)
 111 +
 112 +    # TODO: not implemented yet in m4rie
 113 +    double mzed_density(mzed_t *A, int res)
 114 +
 115 +    # TODO: not implemented yet in m4rie
 116 +    double _mzed_density(mzed_t *A, int res, size_t r, size_t c)
 117 +
 118 +
 119 +#cdef extern from "m4rie/travolta.h":
 120 +    size_t mzed_echelonize_travolta(mzed_t *, size_t)
 121 +
 122 +    mzed_t *mzed_mul_travolta(mzed_t *, mzed_t *, mzed_t *)
 123 +
 124 +#cdef extern from "m4rie/echelonform.h":
 125 +    size_t mzed_echelonize(mzed_t *, size_t)
 126 +
 127 +cdef extern from "m4rie/finite_field_givaro.h":
 128 +    ctypedef struct M4RIE__FiniteField "M4RIE::FiniteField":
 129 +        int (* pol2log)(int r)
 130 +        int (* log2pol)(int r)
 131 +        
 132 +    gf2e *gf2e_init_givgfq(M4RIE__FiniteField *givgfq)
 133 +
 134 +    int mzed_read_elem_log(const_mzed_t *a, const_size_t row, const_size_t col, M4RIE__FiniteField *ff)
 135 +    void mzed_write_elem_log(mzed_t *a, const_size_t row, const_size_t col, const_int elem, M4RIE__FiniteField *ff)
 136 +    void mzed_add_elem_log(mzed_t *a, const_size_t row, const_size_t col, const_int elem, M4RIE__FiniteField *ff)
 137 +        
 138 diff -r 96e2020790df -r cc88353e2acb sage/libs/ntl/ntl_mat_GF2E.pyx
 139 --- a/sage/libs/ntl/ntl_mat_GF2E.pyx	Mon Jun 28 23:27:14 2010 +0100
 140 +++ b/sage/libs/ntl/ntl_mat_GF2E.pyx	Tue Jul 20 16:19:49 2010 +0100
 141 @@ -619,3 +619,11 @@
 142          mat_GF2E_kernel(X.x, self.x)
 143          _sig_off
 144          return X
 145 +
 146 +    def randomize(self):
 147 +        cdef long i,j
 148 +        cdef GF2E_c tmp
 149 +        for i in xrange(self.x.NumRows()):
 150 +            for j in xrange(self.x.NumCols()):
 151 +                tmp = GF2E_random()
 152 +                mat_GF2E_setitem(&self.x, i, j, &tmp)
 153 diff -r 96e2020790df -r cc88353e2acb sage/matrix/matrix_mod2_dense.pyx
 154 --- a/sage/matrix/matrix_mod2_dense.pyx	Mon Jun 28 23:27:14 2010 +0100
 155 +++ b/sage/matrix/matrix_mod2_dense.pyx	Tue Jul 20 16:19:49 2010 +0100
 156 @@ -1127,7 +1127,7 @@
 157              self._echelon_in_place_classical()
 158          else:
 159              raise ValueError, "no algorithm '%s'"%algorithm
 160 -
 161 + 
 162      def _pivots(self):
 163          r"""
 164          Returns the pivot columns of \code{self} if \code{self} is in
 165 diff -r 96e2020790df -r cc88353e2acb sage/matrix/matrix_mod2e_dense.pxd
 166 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
 167 +++ b/sage/matrix/matrix_mod2e_dense.pxd	Tue Jul 20 16:19:49 2010 +0100
 168 @@ -0,0 +1,15 @@
 169 +# choose: dense or sparse
 170 +
 171 +from sage.rings.finite_rings.element_givaro cimport GivaroGfq, Cache_givaro
 172 +
 173 +from sage.libs.m4rie cimport mzed_t
 174 +
 175 +cimport matrix_dense 
 176 +
 177 +cdef class Matrix_mod2e_dense(matrix_dense.Matrix_dense):
 178 +    cdef mzed_t *_entries
 179 +    cdef Cache_givaro cc
 180 +    cdef object _one
 181 +    cdef object _zero
 182 +
 183 +
 184 diff -r 96e2020790df -r cc88353e2acb sage/matrix/matrix_mod2e_dense.pyx
 185 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
 186 +++ b/sage/matrix/matrix_mod2e_dense.pyx	Tue Jul 20 16:19:49 2010 +0100
 187 @@ -0,0 +1,951 @@
 188 +"""
 189 +Dense matrices over GF(2^e) for 2 <= e <= 10 using the M4RIe library.
 190 +
 191 +m x n matrices over GF(2^e) are internally represented as m x (en)
 192 +matrices over GF(2) which allows to reuse much of the existing
 193 +machinery of M4RI.
 194 +
 195 +EXAMPLE::
 196 +
 197 +    sage: K.<a> = GF(2^8)
 198 +    sage: A = random_matrix(K, 3,4)
 199 +    sage: A
 200 +    [                  a^3 + a^2 + 1         a^7 + a^5 + a^4 + a + 1                       a^7 + a^3                   a^6 + a^4 + a]
 201 +    [      a^5 + a^4 + a^3 + a^2 + 1 a^7 + a^6 + a^5 + a^4 + a^3 + a             a^5 + a^4 + a^3 + a             a^6 + a^4 + a^2 + 1]
 202 +    [  a^6 + a^5 + a^4 + a^2 + a + 1   a^7 + a^5 + a^3 + a^2 + a + 1       a^7 + a^6 + a^3 + a^2 + a             a^7 + a^5 + a^3 + a]
 203 +
 204 +    sage: A.echelon_form()
 205 +    [                        1                         0                         0       a^7 + a^6 + a^2 + a]
 206 +    [                        0                         1                         0     a^6 + a^4 + a^3 + a^2]
 207 +    [                        0                         0                         1 a^6 + a^4 + a^3 + a^2 + a]
 208 +
 209 +AUTHOR: 
 210 + * Martin Albrecht <[email protected]>
 211 +
 212 +TESTS::
 213 +
 214 +    sage: sage: TestSuite(sage.matrix.matrix_mod2e_dense.Matrix_mod2e_dense).run(verbose=True)
 215 +    running ._test_pickling() . . . pass
 216 +"""
 217 +
 218 +include "../ext/interrupt.pxi"
 219 +include "../ext/cdefs.pxi"
 220 +include '../ext/stdsage.pxi'
 221 +include '../ext/random.pxi'
 222 +
 223 +cimport matrix_dense
 224 +from sage.structure.element cimport Matrix, Vector
 225 +from sage.structure.element cimport ModuleElement, Element
 226 +
 227 +#from sage.misc.functional import log
 228 +#from sage.misc.misc import verbose, get_verbose, cputime
 229 +
 230 +from sage.rings.all import FiniteField as GF
 231 +from sage.rings.finite_rings.element_givaro cimport FiniteField_givaroElement, GivRandom, GivRandomSeeded
 232 +from sage.misc.randstate cimport randstate, current_randstate
 233 +
 234 +from sage.matrix.matrix_mod2_dense cimport Matrix_mod2_dense
 235 +
 236 +from sage.libs.m4ri cimport m4ri_word, mzd_copy
 237 +from sage.libs.m4rie cimport *
 238 +from sage.libs.m4rie cimport mzed_t, M4RIE__FiniteField
 239 +
 240 +
 241 +
 242 +# we must keep a copy of the internal finite field representation
 243 +# around to avoid re-creating it over and over again. Furthermore,
 244 +# M4RIE assumes pointer equivalence of identical fields.
 245 +
 246 +_givaro_cache = {}
 247 +
 248 +cdef class M4RIE_finite_field:
 249 +    """
 250 +    A thin wrapper around the M4RIE finite field class such that we
 251 +    can put it in a hash table. This class isn't meant for public
 252 +    consumption.
 253 +    """
 254 +    cdef gf2e *ff
 255 +
 256 +    def __cinit__(self):
 257 +        """
 258 +        EXAMPLE::
 259 +
 260 +            sage: from sage.matrix.matrix_mod2e_dense import M4RIE_finite_field
 261 +            sage: K = M4RIE_finite_field(); K
 262 +            <sage.matrix.matrix_mod2e_dense.M4RIE_finite_field object at 0x...>
 263 +        """
 264 +        pass
 265 +
 266 +    def __dealloc__(self):
 267 +        """
 268 +        EXAMPLE::
 269 +
 270 +            sage: from sage.matrix.matrix_mod2e_dense import M4RIE_finite_field
 271 +            sage: K = M4RIE_finite_field()
 272 +            sage: del K
 273 +        """
 274 +        if self.ff:
 275 +            gf2e_free(self.ff)
 276 +
 277 +cdef class Matrix_mod2e_dense(matrix_dense.Matrix_dense):   # dense or sparse
 278 +    ########################################################################
 279 +    # LEVEL 1 functionality
 280 +    ########################################################################
 281 +    def __cinit__(self, parent, entries, copy, coerce, alloc=True):
 282 +        """
 283 +        Create new matrix over `GF(2^k)` for 2<=k<=10.
 284 +
 285 +        EXAMPLES::
 286 +
 287 +            sage: K.<a> = GF(2^4)
 288 +            sage: A = Matrix(K, 3, 4); A
 289 +            [0 0 0 0]
 290 +            [0 0 0 0]
 291 +            [0 0 0 0]
 292 +
 293 +            sage: A.randomize(); A 
 294 +            [      a^2 + 1 a^3 + a^2 + a   a^3 + a + 1         a + 1]
 295 +            [        a + 1         a + 1       a^3 + a     a^3 + a^2]
 296 +            [a^3 + a^2 + a             a             1   a^3 + a + 1]
 297 +
 298 +            sage: K.<a> = GF(2^3)
 299 +            sage: A = Matrix(K,3,4); A
 300 +            [0 0 0 0]
 301 +            [0 0 0 0]
 302 +            [0 0 0 0]
 303 +
 304 +            sage: A.randomize(); A
 305 +            [a^2 + 1       0   a + 1       0]
 306 +            [      a       a   a + 1       a]
 307 +            [      1     a^2 a^2 + a       0]
 308 +        """
 309 +        matrix_dense.Matrix_dense.__init__(self, parent)
 310 +
 311 +        cdef M4RIE_finite_field FF
 312 +
 313 +        R = parent.base_ring()
 314 +
 315 +        self.cc = <Cache_givaro>R._cache
 316 +        
 317 +        if alloc and self._nrows and self._ncols:
 318 +            if self.cc in _givaro_cache:
 319 +                self._entries = mzed_init((<M4RIE_finite_field>_givaro_cache[self.cc]).ff, self._nrows, self._ncols)
 320 +            else:
 321 +                FF = PY_NEW(M4RIE_finite_field)
 322 +                FF.ff = gf2e_init_givgfq(<M4RIE__FiniteField*>self.cc.objectptr)
 323 +                self._entries = mzed_init(FF.ff, self._nrows, self._ncols)
 324 +                _givaro_cache[self.cc] = FF
 325 +
 326 +        # cache elements
 327 +        self._zero = self._base_ring(0)
 328 +        self._one = self._base_ring(1)
 329 +
 330 +    def __dealloc__(self):
 331 +        """
 332 +        TESTS::
 333 +        
 334 +            sage: K.<a> = GF(2^4)
 335 +            sage: A = Matrix(K, 1000, 1000)
 336 +            sage: del A
 337 +            sage: A = Matrix(K, 1000, 1000)
 338 +            sage: del A
 339 +        """
 340 +        if self._entries:
 341 +            mzed_free(self._entries)
 342 +            self._entries = NULL
 343 +
 344 +    def __init__(self, parent, entries, copy, coerce):
 345 +        """
 346 +        EXAMPLE::
 347 +        
 348 +            sage: K.<a> = GF(2^4)
 349 +            sage: l = [K.random_element() for _ in range(3*4)]; l
 350 +            [a^2 + 1, a^3 + 1, 0, 0, a, a^3 + a + 1, a + 1, a + 1, a^2, a^3 + a + 1, a^3 + a, a^3 + a]
 351 +
 352 +            sage: A = Matrix(K, 3, 4, l); A
 353 +            [    a^2 + 1     a^3 + 1           0           0]
 354 +            [          a a^3 + a + 1       a + 1       a + 1]
 355 +            [        a^2 a^3 + a + 1     a^3 + a     a^3 + a]
 356 +
 357 +            sage: A.list()
 358 +            [a^2 + 1, a^3 + 1, 0, 0, a, a^3 + a + 1, a + 1, a + 1, a^2, a^3 + a + 1, a^3 + a, a^3 + a]
 359 +
 360 +            sage: l[0], A[0,0]
 361 +            (a^2 + 1, a^2 + 1)
 362 +
 363 +            sage: A = Matrix(K, 3, 3, a); A
 364 +            [a 0 0]
 365 +            [0 a 0]
 366 +            [0 0 a]
 367 +        """
 368 +        cdef int i,j
 369 +        cdef FiniteField_givaroElement e
 370 +
 371 +        if entries is None:
 372 +            return
 373 +
 374 +        R = self.base_ring()
 375 +        
 376 +        # scalar ?  
 377 +        if not isinstance(entries, list):
 378 +            if entries != 0:
 379 +                if self.nrows() != self.ncols():
 380 +                    raise TypeError("self must be a  square matrices for scalar assignment")
 381 +                for i in range(self.nrows()):
 382 +                    self.set_unsafe(i,i, R(entries))
 383 +            return 
 384 +
 385 +        # all entries are given as a long list
 386 +        if len(entries) != self._nrows * self._ncols:
 387 +            raise IndexError("The vector of entries has the wrong length.")
 388 +        
 389 +        k = 0
 390 +
 391 +        for i from 0 <= i < self._nrows:
 392 +            if PyErr_CheckSignals(): raise KeyboardInterrupt
 393 +            for j from 0 <= j < self._ncols:
 394 +                e = R(entries[k])
 395 +                
 396 +                mzed_write_elem_log(self._entries,i,j, e.element, <M4RIE__FiniteField*>self.cc.objectptr)
 397 +                k = k + 1
 398 +            
 399 +    cdef set_unsafe(self, Py_ssize_t i, Py_ssize_t j, value):
 400 +        """
 401 +        EXAMPLE::
 402 +        
 403 +            sage: K.<a> = GF(2^4)
 404 +            sage: A = Matrix(K,3,4,[K.random_element() for _ in range(3*4)]); A
 405 +            [    a^2 + 1     a^3 + 1           0           0]
 406 +            [          a a^3 + a + 1       a + 1       a + 1]
 407 +            [        a^2 a^3 + a + 1     a^3 + a     a^3 + a]
 408 +
 409 +            sage: A[0,0] = a
 410 +            sage: A
 411 +            [          a     a^3 + 1           0           0]
 412 +            [          a a^3 + a + 1       a + 1       a + 1]
 413 +            [        a^2 a^3 + a + 1     a^3 + a     a^3 + a]
 414 +        """
 415 +        mzed_write_elem_log(self._entries, i, j, (<FiniteField_givaroElement>value).element, <M4RIE__FiniteField*>self.cc.objectptr)
 416 +
 417 +    cdef get_unsafe(self, Py_ssize_t i, Py_ssize_t j):
 418 +        """
 419 +        EXAMPLE::
 420 +        
 421 +            sage: K.<a> = GF(2^4)
 422 +            sage: A = random_matrix(K,3,4)
 423 +            sage: A[2,3]
 424 +            a^3 + a + 1
 425 +            sage: K.<a> = GF(2^3)
 426 +            sage: m,n  = 3, 4
 427 +            sage: A = random_matrix(K,3,4); A
 428 +            [a^2 + 1       0   a + 1       0]
 429 +            [      a       a   a + 1       a]
 430 +            [      1     a^2 a^2 + a       0]
 431 +        """
 432 +        cdef int r = mzed_read_elem_log(self._entries, i, j, <M4RIE__FiniteField*>self.cc.objectptr)
 433 +        return self.cc._new_c(r)
 434 +
 435 +
 436 +    cpdef ModuleElement _add_(self, ModuleElement right):
 437 +        """
 438 +        EXAMPLE::
 439 +        
 440 +            sage: K.<a> = GF(2^4)
 441 +            sage: A = random_matrix(K,3,4); A
 442 +            [      a^2 + 1 a^3 + a^2 + a   a^3 + a + 1         a + 1]
 443 +            [        a + 1         a + 1       a^3 + a     a^3 + a^2]
 444 +            [a^3 + a^2 + a             a             1   a^3 + a + 1]
 445 +            
 446 +            sage: B = random_matrix(K,3,4); B
 447 +            [          a^3 + 1                 0               a^3                 0]
 448 +            [          a^3 + a                 a     a^3 + a^2 + a           a^3 + a]
 449 +            [      a^3 + a + 1               a^2 a^3 + a^2 + a + 1           a^2 + 1]
 450 +
 451 +            sage: C = A + B; C # indirect doctest
 452 +            [    a^3 + a^2 a^3 + a^2 + a         a + 1         a + 1]
 453 +            [      a^3 + 1             1           a^2       a^2 + a]
 454 +            [      a^2 + 1       a^2 + a a^3 + a^2 + a a^3 + a^2 + a]
 455 +        """
 456 +        cdef Matrix_mod2e_dense A
 457 +        A = Matrix_mod2e_dense.__new__(Matrix_mod2e_dense, self._parent, 0, 0, 0, alloc=False)
 458 +        if self._nrows == 0 or self._ncols == 0:
 459 +            return A
 460 +        A._entries = mzed_add(NULL, self._entries, (<Matrix_mod2e_dense>right)._entries)
 461 +
 462 +        return A
 463 +
 464 +    cpdef ModuleElement _sub_(self, ModuleElement right):
 465 +        """
 466 +        EXAMPLE::
 467 +        
 468 +            sage: from sage.matrix.matrix_mod2e_dense import Matrix_mod2e_dense
 469 +            sage: K.<a> = GF(2^4)
 470 +            sage: m,n  = 3, 4
 471 +            sage: MS = MatrixSpace(K,m,n)
 472 +            sage: A = random_matrix(K,3,4); A
 473 +            [      a^2 + 1 a^3 + a^2 + a   a^3 + a + 1         a + 1]
 474 +            [        a + 1         a + 1       a^3 + a     a^3 + a^2]
 475 +            [a^3 + a^2 + a             a             1   a^3 + a + 1]
 476 +
 477 +            sage: B = random_matrix(K,3,4); B
 478 +            [          a^3 + 1                 0               a^3                 0]
 479 +            [          a^3 + a                 a     a^3 + a^2 + a           a^3 + a]
 480 +            [      a^3 + a + 1               a^2 a^3 + a^2 + a + 1           a^2 + 1]
 481 +
 482 +            sage: C = A - B; C  # indirect doctest
 483 +            [    a^3 + a^2 a^3 + a^2 + a         a + 1         a + 1]
 484 +            [      a^3 + 1             1           a^2       a^2 + a]
 485 +            [      a^2 + 1       a^2 + a a^3 + a^2 + a a^3 + a^2 + a]
 486 +        """
 487 +        return self._add_(right)
 488 +
 489 +    cdef Matrix _matrix_times_matrix_(self, Matrix right):
 490 +        """
 491 +        Matrix multiplication.
 492 +
 493 +        EXAMPLES::
 494 +
 495 +            sage: K.<a> = GF(2^2)
 496 +            sage: A = random_matrix(K, 50, 50)
 497 +            sage: B = random_matrix(K, 50, 50)
 498 +            sage: A*B == A._multiply_classical(B)
 499 +            True
 500 +
 501 +            sage: K.<a> = GF(2^4)
 502 +            sage: A = random_matrix(K, 50, 50)
 503 +            sage: B = random_matrix(K, 50, 50)
 504 +            sage: A*B == A._multiply_classical(B)
 505 +            True
 506 +
 507 +            sage: K.<a> = GF(2^8)
 508 +            sage: A = random_matrix(K, 50, 50)
 509 +            sage: B = random_matrix(K, 50, 50)
 510 +            sage: A*B == A._multiply_classical(B)
 511 +            True
 512 +
 513 +            sage: K.<a> = GF(2^10)
 514 +            sage: A = random_matrix(K, 50, 50)
 515 +            sage: B = random_matrix(K, 50, 50)
 516 +            sage: A*B == A._multiply_classical(B)
 517 +            True
 518 +        """
 519 +        if self._ncols != right._nrows:
 520 +            raise ArithmeticError("left ncols must match right nrows")
 521 +
 522 +        cdef Matrix_mod2e_dense ans
 523 +        
 524 +        ans = self.new_matrix(nrows = self.nrows(), ncols = right.ncols())
 525 +        if self._nrows == 0 or self._ncols == 0 or right._ncols == 0:
 526 +            return ans
 527 +        ans._entries = mzed_mul_travolta(ans._entries, self._entries, (<Matrix_mod2e_dense>right)._entries)
 528 +        return ans
 529 +
 530 +    def __neg__(self):
 531 +        """
 532 +        EXAMPLE::
 533 +        
 534 +            sage: K.<a> = GF(2^4)
 535 +            sage: A = random_matrix(K, 3, 4); A
 536 +            [      a^2 + 1 a^3 + a^2 + a   a^3 + a + 1         a + 1]
 537 +            [        a + 1         a + 1       a^3 + a     a^3 + a^2]
 538 +            [a^3 + a^2 + a             a             1   a^3 + a + 1]
 539 +
 540 +            sage: -A
 541 +            [      a^2 + 1 a^3 + a^2 + a   a^3 + a + 1         a + 1]
 542 +            [        a + 1         a + 1       a^3 + a     a^3 + a^2]
 543 +            [a^3 + a^2 + a             a             1   a^3 + a + 1]
 544 +        """
 545 +        return self.__copy__()
 546 +
 547 +    def __richcmp__(Matrix self, right, int op):  # always need for mysterious reasons.
 548 +        """
 549 +        EXAMPLE::
 550 +        
 551 +            sage: K.<a> = GF(2^4)
 552 +            sage: A = random_matrix(K,3,4)
 553 +            sage: B = copy(A)
 554 +            sage: A == B
 555 +            True
 556 +            sage: A[0,0] = a
 557 +            sage: A == B
 558 +            False
 559 +        """
 560 +        return self._richcmp(right, op)
 561 +
 562 +    cdef int _cmp_c_impl(self, Element right) except -2:
 563 +        if self._nrows == 0 or self._ncols == 0:
 564 +            return 0
 565 +        return mzed_cmp(self._entries, (<Matrix_mod2e_dense>right)._entries)
 566 +
 567 +    def __copy__(self):
 568 +        """
 569 +        EXAMPLE::
 570 +        
 571 +            sage: K.<a> = GF(2^4)
 572 +            sage: m,n  = 3, 4
 573 +            sage: A = random_matrix(K,3,4); A
 574 +            [      a^2 + 1 a^3 + a^2 + a   a^3 + a + 1         a + 1]
 575 +            [        a + 1         a + 1       a^3 + a     a^3 + a^2]
 576 +            [a^3 + a^2 + a             a             1   a^3 + a + 1]
 577 +
 578 +            sage: A2 = copy(A); A2
 579 +            [      a^2 + 1 a^3 + a^2 + a   a^3 + a + 1         a + 1]
 580 +            [        a + 1         a + 1       a^3 + a     a^3 + a^2]
 581 +            [a^3 + a^2 + a             a             1   a^3 + a + 1]
 582 +
 583 +            sage: A[0,0] = 1
 584 +            sage: A2[0,0]
 585 +            a^2 + 1
 586 +        """
 587 +        cdef Matrix_mod2e_dense A
 588 +        A = Matrix_mod2e_dense.__new__(Matrix_mod2e_dense, self._parent, 0, 0, 0)
 589 +        
 590 +        if self._nrows and self._ncols:
 591 +            mzed_copy(A._entries, <const_mzed_t *>self._entries)
 592 +
 593 +        return A
 594 +        
 595 +    def _list(self):
 596 +        """
 597 +        EXAMPLE::
 598 +        
 599 +            sage: K.<a> = GF(2^4)
 600 +            sage: m,n  = 3, 4
 601 +            sage: A = random_matrix(K,3,4); A
 602 +            [      a^2 + 1 a^3 + a^2 + a   a^3 + a + 1         a + 1]
 603 +            [        a + 1         a + 1       a^3 + a     a^3 + a^2]
 604 +            [a^3 + a^2 + a             a             1   a^3 + a + 1]
 605 +
 606 +            sage: A.list() # indirect doctest
 607 +            [a^2 + 1, a^3 + a^2 + a, a^3 + a + 1, a + 1, a + 1, a + 1, a^3 + a, a^3 + a^2, a^3 + a^2 + a, a, 1, a^3 + a + 1]
 608 +        """
 609 +        cdef int i,j
 610 +        l = []
 611 +        for i from 0 <= i < self._nrows:
 612 +            for j from 0 <= j < self._ncols:
 613 +                l.append(self.get_unsafe(i,j))
 614 +        return l
 615 +
 616 +    def randomize(self, density=1, nonzero=False):
 617 +        """
 618 +        EXAMPLE::
 619 +        
 620 +            sage: K.<a> = GF(2^4)
 621 +            sage: A = Matrix(K,3,3)
 622 +
 623 +            sage: A.randomize(); A
 624 +            [      a^2 + 1 a^3 + a^2 + a   a^3 + a + 1]
 625 +            [        a + 1         a + 1         a + 1]
 626 +            [      a^3 + a     a^3 + a^2 a^3 + a^2 + a]
 627 +        """
 628 +        cdef Py_ssize_t i,j
 629 +        cdef int seed = current_randstate().c_random()
 630 +        cdef GivRandom generator = GivRandomSeeded(seed)
 631 +        cdef int res
 632 +                
 633 +        if self._ncols == 0 or self._nrows == 0:
 634 +            return
 635 +
 636 +        if density !=1:
 637 +            raise NotImplementedError
 638 +        for i in range(self._nrows):
 639 +            for j in range(self._ncols):
 640 +                res = self.cc.objectptr.random(generator,res)
 641 +                mzed_write_elem_log(self._entries, i, j, res, <M4RIE__FiniteField*>self.cc.objectptr)
 642 +        
 643 +
 644 +    def echelonize(self, algorithm='heuristic', reduced=True, **kwds):
 645 +        """
 646 +        EXAMPLE::
 647 +        
 648 +            sage: K.<a> = GF(2^4)
 649 +            sage: m,n  = 3, 5
 650 +            sage: A = random_matrix(K, 3, 5); A
 651 +            [      a^2 + 1 a^3 + a^2 + a   a^3 + a + 1         a + 1         a + 1]
 652 +            [        a + 1       a^3 + a     a^3 + a^2 a^3 + a^2 + a             a]
 653 +            [            1   a^3 + a + 1     a^3 + a^2 a^3 + a^2 + 1           a^2]
 654 +
 655 +            sage: A.echelonize(); A
 656 +            [            1             0             0             a             a]
 657 +            [            0             1             0   a^2 + a + 1             a]
 658 +            [            0             0             1             a a^3 + a^2 + 1]
 659 +
 660 +            sage: K.<a> = GF(2^3)
 661 +            sage: m,n  = 3, 5
 662 +            sage: MS = MatrixSpace(K,m,n)
 663 +            sage: A = random_matrix(K, 3, 5)
 664 +
 665 +            sage: copy(A).echelon_form('travolta')
 666 +            [          1           0           0         a^2     a^2 + 1]
 667 +            [          0           1           0         a^2           1]
 668 +            [          0           0           1 a^2 + a + 1       a + 1]
 669 +            
 670 +            sage: copy(A).echelon_form('naive');
 671 +            [          1           0           0         a^2     a^2 + 1]
 672 +            [          0           1           0         a^2           1]
 673 +            [          0           0           1 a^2 + a + 1       a + 1]
 674 +
 675 +            sage: copy(A).echelon_form('builtin');
 676 +            [          1           0           0         a^2     a^2 + 1]
 677 +            [          0           1           0         a^2           1]
 678 +            [          0           0           1 a^2 + a + 1       a + 1]
 679 +        """
 680 +        if self._nrows == 0 or self._ncols == 0:
 681 +            self.cache('in_echelon_form',True)
 682 +            self.cache('rank', 0)
 683 +            self.cache('pivots', [])
 684 +            return self
 685 +        cdef int k, n, full
 686 +
 687 +        full = int(reduced)
 688 +
 689 +        x = self.fetch('in_echelon_form')
 690 +        if not x is None: return  # already known to be in echelon form
 691 +
 692 +        if algorithm == 'naive':
 693 +            self.check_mutability()
 694 +            self.clear_cache()        
 695 +
 696 +            _sig_on
 697 +            r =  mzed_echelonize_naive(self._entries, full)
 698 +            _sig_off
 699 +            
 700 +            self.cache('in_echelon_form',True)
 701 +            self.cache('rank', r)
 702 +            self.cache('pivots', self._pivots())
 703 +
 704 +        elif algorithm == 'travolta':
 705 +            self.check_mutability()
 706 +            self.clear_cache()        
 707 +
 708 +            _sig_on
 709 +            r =  mzed_echelonize_travolta(self._entries, full)
 710 +            _sig_off
 711 +            
 712 +            self.cache('in_echelon_form',True)
 713 +            self.cache('rank', r)
 714 +            self.cache('pivots', self._pivots())
 715 +
 716 +        elif algorithm == 'heuristic':
 717 +            self.check_mutability()
 718 +            self.clear_cache()        
 719 +
 720 +            _sig_on
 721 +            r =  mzed_echelonize(self._entries, full)
 722 +            _sig_off
 723 +            
 724 +            self.cache('in_echelon_form',True)
 725 +            self.cache('rank', r)
 726 +            self.cache('pivots', self._pivots())
 727 +
 728 +        elif algorithm == 'builtin':
 729 +            self._echelon_in_place_classical()
 730 +        else:
 731 +            raise ValueError, "no algorithm '%s'"%algorithm
 732 +
 733 +    def _pivots(self):
 734 +        """
 735 +        EXAMPLE::
 736 +
 737 +            sage: K.<a> = GF(2^8)
 738 +            sage: A = random_matrix(K, 15, 15)
 739 +            sage: A.pivots() # indirect doctest
 740 +             [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
 741 +        """
 742 +        if not self.fetch('in_echelon_form'):
 743 +            raise ValueError("self must be in reduced row echelon form first.")
 744 +        pivots = []
 745 +        cdef Py_ssize_t i, j, nc
 746 +        nc = self._ncols
 747 +        i = 0
 748 +        while i < self._nrows: 
 749 +            for j from i <= j < nc:
 750 +                if self.get_unsafe(i,j):
 751 +                    pivots.append(j)
 752 +                    i += 1
 753 +                    break
 754 +            if j == nc:
 755 +                break
 756 +        return pivots
 757 +
 758 +    def __invert__(self):
 759 +        """
 760 +        EXAMPLE::
 761 +
 762 +            sage: K.<a> = GF(2^3)
 763 +            sage: A = random_matrix(K,3,3); A
 764 +            [      0   a + 1       1]
 765 +            [a^2 + a a^2 + a a^2 + a]
 766 +            [      a a^2 + 1   a + 1]
 767 +
 768 +            sage: B = ~A; B
 769 +            [        a^2           0     a^2 + 1]
 770 +            [a^2 + a + 1         a^2 a^2 + a + 1]
 771 +            [      a + 1 a^2 + a + 1           a]
 772 +            
 773 +            sage: A*B
 774 +            [1 0 0]
 775 +            [0 1 0]
 776 +            [0 0 1]
 777 +        """
 778 +        cdef Matrix_mod2e_dense A
 779 +        A = Matrix_mod2e_dense.__new__(Matrix_mod2e_dense, self._parent, 0, 0, 0)
 780 +        
 781 +        if self._nrows and self._nrows == self._ncols:
 782 +            mzed_invert_travolta(A._entries, self._entries)
 783 +
 784 +        return A
 785 +        
 786 +    cdef rescale_row_c(self, Py_ssize_t row, multiple, Py_ssize_t start_col):
 787 +        """
 788 +        EXAMPLE::
 789 +
 790 +            sage: K.<a> = GF(2^3)
 791 +            sage: A = random_matrix(K,3,3); A
 792 +            [      0   a + 1       1]
 793 +            [a^2 + a a^2 + a a^2 + a]
 794 +            [      a a^2 + 1   a + 1]
 795 +
 796 +            sage: A.rescale_row(0, a , 0); A
 797 +            [      0 a^2 + a       a]
 798 +            [a^2 + a a^2 + a a^2 + a]
 799 +            [      a a^2 + 1   a + 1]
 800 +
 801 +            sage: A.rescale_row(0,0,0); A
 802 +            [      0       0       0]
 803 +            [a^2 + a a^2 + a a^2 + a]
 804 +            [      a a^2 + 1   a + 1]
 805 +        """        
 806 +        cdef m4ri_word x = <m4ri_word>(<M4RIE__FiniteField*>self.cc.objectptr).log2pol((<FiniteField_givaroElement>multiple).element)
 807 +        cdef m4ri_word *X = self._entries.finite_field.mul[x]
 808 +        mzed_rescale_row(self._entries, row, start_col, X) 
 809 +
 810 +
 811 +    cdef add_multiple_of_row_c(self,  Py_ssize_t row_to, Py_ssize_t row_from, multiple, Py_ssize_t start_col):
 812 +        """
 813 +        EXAMPLE::
 814 +
 815 +            sage: K.<a> = GF(2^3)
 816 +            sage: A = random_matrix(K,3,3); A
 817 +            [      0   a + 1       1]
 818 +            [a^2 + a a^2 + a a^2 + a]
 819 +            [      a a^2 + 1   a + 1]
 820 +
 821 +            sage: A.add_multiple_of_row(0,1,a,0); A
 822 +            [a^2 + a + 1         a^2     a^2 + a]
 823 +            [    a^2 + a     a^2 + a     a^2 + a]
 824 +            [          a     a^2 + 1       a + 1]
 825 +        """
 826 +        
 827 +        cdef m4ri_word x = <m4ri_word>(<M4RIE__FiniteField*>self.cc.objectptr).log2pol((<FiniteField_givaroElement>multiple).element)
 828 +        cdef m4ri_word *X = self._entries.finite_field.mul[x]
 829 +        mzed_add_multiple_of_row(self._entries, row_to, self._entries, row_from, X, start_col)
 830 +
 831 +
 832 +    cdef swap_rows_c(self, Py_ssize_t row1, Py_ssize_t row2):
 833 +        """
 834 +        EXAMPLE::
 835 +
 836 +            sage: K.<a> = GF(2^3)
 837 +            sage: A = random_matrix(K,3,3)
 838 +            sage: A
 839 +            [      0   a + 1       1]
 840 +            [a^2 + a a^2 + a a^2 + a]
 841 +            [      a a^2 + 1   a + 1]
 842 +
 843 +            sage: A.swap_rows(0,1); A
 844 +            [a^2 + a a^2 + a a^2 + a]
 845 +            [      0   a + 1       1]
 846 +            [      a a^2 + 1   a + 1]
 847 +
 848 +        """
 849 +        mzed_row_swap(self._entries, row1, row2)
 850 +
 851 +    cdef swap_columns_c(self, Py_ssize_t col1, Py_ssize_t col2):
 852 +        """
 853 +        EXAMPLE::
 854 +
 855 +            sage: K.<a> = GF(2^3)
 856 +            sage: A = random_matrix(K,3,3)
 857 +            sage: A
 858 +            [      0   a + 1       1]
 859 +            [a^2 + a a^2 + a a^2 + a]
 860 +            [      a a^2 + 1   a + 1]
 861 +
 862 +            sage: A.swap_columns(0,1); A
 863 +            [  a + 1       0       1]
 864 +            [a^2 + a a^2 + a a^2 + a]
 865 +            [a^2 + 1       a   a + 1]
 866 +
 867 +            sage: A = random_matrix(K,4,16)
 868 +
 869 +            sage: B = copy(A)
 870 +            sage: B.swap_columns(0,1)
 871 +            sage: B.swap_columns(0,1)
 872 +            sage: A == B
 873 +            True
 874 +
 875 +            sage: A.swap_columns(0,15)
 876 +            sage: A.column(0) == B.column(15)
 877 +            True
 878 +            sage: A.swap_columns(14,15)
 879 +            sage: A.column(14) == B.column(0)
 880 +            True
 881 +        """
 882 +        mzed_col_swap(self._entries, col1, col2)
 883 +
 884 +    def augment(self, Matrix_mod2e_dense right):
 885 +        """
 886 +        Augments ``self`` with ``right``.
 887 +
 888 +        EXAMPLE::
 889 +
 890 +            sage: K.<a> = GF(2^4)
 891 +            sage: MS = MatrixSpace(K,3,3)
 892 +            sage: A = random_matrix(K,3,3)
 893 +            sage: B = A.augment(MS(1)); B
 894 +            [      a^2 + 1 a^3 + a^2 + a   a^3 + a + 1             1             0             0]
 895 +            [        a + 1         a + 1         a + 1             0             1             0]
 896 +            [      a^3 + a     a^3 + a^2 a^3 + a^2 + a             0             0             1]
 897 +
 898 +            sage: B.echelonize(); B
 899 +            [            1             0             0 a^3 + a^2 + 1 a^3 + a^2 + 1       a^2 + a]
 900 +            [            0             1             0       a^3 + 1       a^2 + 1       a^2 + 1]
 901 +            [            0             0             1           a^2       a^2 + a         a + 1]
 902 +
 903 +            sage: C = B.matrix_from_columns([3,4,5]); C
 904 +            [a^3 + a^2 + 1 a^3 + a^2 + 1       a^2 + a]
 905 +            [      a^3 + 1       a^2 + 1       a^2 + 1]
 906 +            [          a^2       a^2 + a         a + 1]
 907 +
 908 +            sage: C == ~A
 909 +            True
 910 +
 911 +            sage: C*A == MS(1)
 912 +            True
 913 +
 914 +        TESTS::
 915 +
 916 +            sage: K.<a> = GF(2^4)
 917 +            sage: A = random_matrix(K,2,3)
 918 +            sage: B = random_matrix(K,2,0)
 919 +            sage: A.augment(B)
 920 +            [a^3 + 1       0     a^3]
 921 +            [      0 a^3 + a       a]
 922 +
 923 +            sage: B.augment(A)
 924 +            [a^3 + 1       0     a^3]
 925 +            [      0 a^3 + a       a]
 926 +
 927 +            sage: M = Matrix(K, 0, 0, 0)
 928 +            sage: N = Matrix(K, 0, 19, 0)
 929 +            sage: W = M.augment(N)
 930 +            sage: W.ncols()
 931 +            19
 932 +
 933 +            sage: M = Matrix(K, 0, 1, 0)
 934 +            sage: N = Matrix(K, 0, 1, 0)
 935 +            sage: M.augment(N)
 936 +            []
 937 +        """
 938 +        cdef Matrix_mod2e_dense A
 939 +
 940 +        if self._nrows != right._nrows:
 941 +            raise TypeError, "Both numbers of rows must match."
 942 +
 943 +        if self._ncols == 0:
 944 +            return right.__copy__()
 945 +        if right._ncols == 0:
 946 +            return self.__copy__()
 947 +
 948 +        A = self.new_matrix(ncols = self._ncols + right._ncols)
 949 +        if self._nrows == 0:
 950 +            return A
 951 +        A._entries = mzed_concat(A._entries, self._entries, right._entries)
 952 +        return A
 953 +
 954 +    def stack(self, Matrix_mod2e_dense other):
 955 +        """
 956 +        Stack ``self`` on top of ``other``.
 957 +
 958 +        EXAMPLE::
 959 +
 960 +            sage: K.<a> = GF(2^4)
 961 +            sage: A = random_matrix(K,2,2); A
 962 +            [      a^2 + 1 a^3 + a^2 + a]
 963 +            [  a^3 + a + 1         a + 1]
 964 +            
 965 +            sage: B = random_matrix(K,2,2); B
 966 +            [a^3 + 1       0]
 967 +            [    a^3       0]
 968 +
 969 +            sage: A.stack(B)
 970 +            [      a^2 + 1 a^3 + a^2 + a]
 971 +            [  a^3 + a + 1         a + 1]
 972 +            [      a^3 + 1             0]
 973 +            [          a^3             0]
 974 +
 975 +            sage: B.stack(A)
 976 +            [      a^3 + 1             0]
 977 +            [          a^3             0]
 978 +            [      a^2 + 1 a^3 + a^2 + a]
 979 +            [  a^3 + a + 1         a + 1]
 980 +
 981 +        TESTS::
 982 +
 983 +            sage: A = random_matrix(K,0,3)
 984 +            sage: B = random_matrix(K,3,3)
 985 +            sage: A.stack(B)
 986 +            [            0 a^3 + a^2 + a       a^2 + 1]
 987 +            [    a^3 + a^2       a^2 + 1           a^2]
 988 +            [    a^3 + a^2             a a^3 + a^2 + 1]
 989 +
 990 +            sage: B.stack(A)
 991 +            [            0 a^3 + a^2 + a       a^2 + 1]
 992 +            [    a^3 + a^2       a^2 + 1           a^2]
 993 +            [    a^3 + a^2             a a^3 + a^2 + 1]
 994 +
 995 +            sage: M = Matrix(K, 0, 0, 0)
 996 +            sage: N = Matrix(K, 19, 0, 0)
 997 +            sage: W = M.stack(N)
 998 +            sage: W.nrows()
 999 +            19
1000 +            sage: M = Matrix(K, 1, 0, 0)
1001 +            sage: N = Matrix(K, 1, 0, 0)
1002 +            sage: M.stack(N)
1003 +            []
1004 +        """
1005 +        if self._ncols != other._ncols:
1006 +            raise TypeError, "Both numbers of columns must match."
1007 +
1008 +        if self._nrows == 0:
1009 +            return other.__copy__()
1010 +        if other._nrows == 0:
1011 +            return self.__copy__()
1012 +
1013 +        cdef Matrix_mod2e_dense A
1014 +        A = self.new_matrix(nrows = self._nrows + other._nrows)
1015 +        if self._ncols == 0:
1016 +            return A
1017 +        A._entries = mzed_stack(A._entries, self._entries, other._entries)
1018 +        return A
1019 +
1020 +    def submatrix(self, lowr, lowc, nrows , ncols):
1021 +        """
1022 +        Return submatrix from the index lowr,lowc (inclusive) with
1023 +        dimension nrows x ncols.
1024 +
1025 +        INPUT:
1026 + 
1027 +        - ``lowr`` -- index of start row
1028 +        - ``lowc`` -- index of start column
1029 +        - ``nrows`` -- number of rows of submatrix
1030 +        - ``ncols`` -- number of columns of submatrix
1031 +        
1032 +        EXAMPLES::
1033 +
1034 +             sage: K.<a> = GF(2^10)
1035 +             sage: A = random_matrix(K,200,200)
1036 +             sage: A[0:2,0:2] == A.submatrix(0,0,2,2)
1037 +             True
1038 +             sage: A[0:100,0:100] == A.submatrix(0,0,100,100)
1039 +             True
1040 +             sage: A == A.submatrix(0,0,200,200)
1041 +             True
1042 +
1043 +             sage: A[1:3,1:3] == A.submatrix(1,1,2,2)
1044 +             True
1045 +             sage: A[1:100,1:100] == A.submatrix(1,1,99,99)
1046 +             True
1047 +             sage: A[1:200,1:200] == A.submatrix(1,1,199,199)
1048 +             True
1049 +        """
1050 +        cdef int highr = lowr + nrows
1051 +        cdef int highc = lowc + ncols
1052 +
1053 +        if nrows <= 0 or ncols <= 0:
1054 +            raise TypeError("Expected nrows, ncols to be > 0, but got %d,%d instead."%(nrows, ncols))
1055 +  
1056 +        if highc > self._entries.ncols:
1057 +            raise TypeError("Expected highc <= self.ncols(), but got %d > %d instead."%(highc, self._entries.ncols))
1058 +
1059 +        if highr > self._entries.nrows:
1060 +            raise TypeError("Expected highr <= self.nrows(), but got %d > %d instead."%(highr, self._entries.nrows))
1061 +
1062 +        if lowr < 0:
1063 +            raise TypeError("Expected lowr >= 0, but got %d instead."%lowr)
1064 +
1065 +        if lowc < 0:
1066 +            raise TypeError("Expected lowc >= 0, but got %d instead."%lowc)
1067 +
1068 +        cdef Matrix_mod2e_dense A = self.new_matrix(nrows = nrows, ncols = ncols)
1069 +        if self._ncols == 0 or self._nrows == 0:
1070 +            return A
1071 +        A._entries = mzed_submatrix(A._entries, self._entries, lowr, lowc, highr, highc)
1072 +        return A
1073 +
1074 +    def rank(self):
1075 +        """
1076 +        Return the rank of this matrix.
1077 +
1078 +        EXAMPLE::
1079 +
1080 +            sage: K.<a> = GF(2^4)
1081 +            sage: A = random_matrix(K, 1000, 1000)
1082 +            sage: A.rank()
1083 +            1000
1084 +
1085 +            sage: A = matrix(K, 10, 0)
1086 +            sage: A.rank()
1087 +            0
1088 +        """
1089 +        x = self.fetch('rank')
1090 +        if not x is None: 
1091 +            return x
1092 +        if self._nrows == 0 or self._ncols == 0:
1093 +            return 0
1094 +        cdef mzed_t *A = mzed_copy(NULL, self._entries)
1095 +
1096 +        cdef size_t r = mzed_echelonize(A, 0)
1097 +        mzed_free(A)
1098 +        self.cache('rank', r)
1099 +        return r
1100 +
1101 +    def __reduce__(self):
1102 +        """
1103 +        EXAMPLE::
1104 +            sage: K.<a> = GF(2^8)
1105 +            sage: A = random_matrix(K,70,70)
1106 +            sage: f, s= A.__reduce__()
1107 +            sage: from sage.matrix.matrix_mod2e_dense import unpickle_matrix_mod2e_dense_v0
1108 +            sage: f == unpickle_matrix_mod2e_dense_v0
1109 +            True
1110 +            sage: f(*s) == A
1111 +            True
1112 +        """
1113 +        from sage.matrix.matrix_space import MatrixSpace
1114 +
1115 +        cdef Matrix_mod2_dense A
1116 +        MS = MatrixSpace(GF(2), self._entries.x.nrows, self._entries.x.ncols)
1117 +        A = Matrix_mod2_dense.__new__(Matrix_mod2_dense, MS, 0, 0, 0, alloc = False)
1118 +        A._entries = mzd_copy( NULL, self._entries.x)
1119 +        return unpickle_matrix_mod2e_dense_v0, (A, self.base_ring(), self.nrows(), self.ncols())
1120 +
1121 +def unpickle_matrix_mod2e_dense_v0(Matrix_mod2_dense a, base_ring, nrows, ncols):
1122 +    """
1123 +    EXAMPLE::
1124 +        sage: K.<a> = GF(2^2)
1125 +        sage: A = random_matrix(K,10,10)
1126 +        sage: f, s= A.__reduce__()
1127 +        sage: from sage.matrix.matrix_mod2e_dense import unpickle_matrix_mod2e_dense_v0
1128 +        sage: f == unpickle_matrix_mod2e_dense_v0
1129 +        True
1130 +        sage: f(*s) == A
1131 +        True
1132 +    """
1133 +    from sage.matrix.matrix_space import MatrixSpace
1134 +
1135 +    MS = MatrixSpace(base_ring, nrows, ncols)
1136 +    cdef Matrix_mod2e_dense A  = Matrix_mod2e_dense.__new__(Matrix_mod2e_dense, MS, 0, 0, 0)
1137 +    mzd_copy(A._entries.x, a._entries)
1138 +    return A
1139 diff -r 96e2020790df -r cc88353e2acb sage/matrix/matrix_space.py
1140 --- a/sage/matrix/matrix_space.py	Mon Jun 28 23:27:14 2010 +0100
1141 +++ b/sage/matrix/matrix_space.py	Tue Jul 20 16:19:49 2010 +0100
1142 @@ -38,7 +38,7 @@
1143  import matrix_modn_sparse
1144  
1145  import matrix_mod2_dense
1146 -#import matrix_mod2_sparse
1147 +import matrix_mod2e_dense
1148  
1149  import matrix_integer_dense
1150  import matrix_integer_sparse
1151 @@ -851,6 +851,8 @@
1152                  if R.order() == 2:
1153                      return matrix_mod2_dense.Matrix_mod2_dense
1154                  return matrix_modn_dense.Matrix_modn_dense
1155 +            elif sage.rings.finite_rings.all.is_FiniteField(R) and R.characteristic() == 2 and R.order() <= 1024:
1156 +                return matrix_mod2e_dense.Matrix_mod2e_dense
1157              elif sage.rings.polynomial.multi_polynomial_ring_generic.is_MPolynomialRing(R) and R.base_ring().is_field():
1158                  return matrix_mpolynomial_dense.Matrix_mpolynomial_dense
1159              #elif isinstance(R, sage.rings.padics.padic_ring_capped_relative.pAdicRingCappedRelative):
1160 diff -r 96e2020790df -r cc88353e2acb sage/rings/finite_rings/element_givaro.pxd
1161 --- a/sage/rings/finite_rings/element_givaro.pxd	Mon Jun 28 23:27:14 2010 +0100
1162 +++ b/sage/rings/finite_rings/element_givaro.pxd	Tue Jul 20 16:19:49 2010 +0100
1163 @@ -78,6 +78,7 @@
1164      cpdef int characteristic(self)
1165      cpdef FiniteField_givaroElement gen(self)
1166      cpdef FiniteField_givaroElement element_from_data(self, e)
1167 +    cdef FiniteField_givaroElement _new_c(self, int value)
1168  
1169  cdef class FiniteField_givaro_iterator:
1170      cdef int iterator
1171 diff -r 96e2020790df -r cc88353e2acb sage/rings/finite_rings/element_givaro.pyx
1172 --- a/sage/rings/finite_rings/element_givaro.pyx	Mon Jun 28 23:27:14 2010 +0100
1173 +++ b/sage/rings/finite_rings/element_givaro.pyx	Tue Jul 20 16:19:49 2010 +0100
1174 @@ -771,6 +771,9 @@
1175              rep = 'int'
1176          return unpickle_Cache_givaro, (self.parent, p, k, self.parent.polynomial(), rep, self._has_array)
1177  
1178 +    cdef FiniteField_givaroElement _new_c(self, int value):
1179 +        return make_FiniteField_givaroElement(self, value)
1180 +
1181  
1182  def unpickle_Cache_givaro(parent, p, k, modulus, rep, cache):
1183      """

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.

You are not allowed to attach a file to this page.