# HG changeset patch
# User Martin Albrecht <martinralbrecht@googlemail.com>
# Date 1326300377 -3600
# Node ID 62b283ab0192cdaf62719e332ec700528aaadece
# Parent ba3a0fe5a10da1f31070c6e80128530bc8440173
#12841: adapted to new M4RIE version
diff --git a/sage/libs/m4rie.pxd b/sage/libs/m4rie.pxd
|
a
|
b
|
|
| 18 | 18 | |
| 19 | 19 | void gf2e_free(gf2e *ff) |
| 20 | 20 | |
| 21 | | #cdef extern from "m4rie/gf2e_matrix.h": |
| | 21 | #cdef extern from "m4rie/mzed.h": |
| 22 | 22 | ctypedef struct mzed_t: |
| 23 | 23 | mzd_t *x |
| 24 | 24 | gf2e *finite_field |
| … |
… |
|
| 87 | 87 | |
| 88 | 88 | void mzed_print(const_mzed_t *M) |
| 89 | 89 | |
| 90 | | mzed_t *mzed_invert_travolta(mzed_t *A, mzed_t *B) |
| | 90 | mzed_t *mzed_invert_newton_john(mzed_t *A, mzed_t *B) |
| 91 | 91 | |
| 92 | 92 | # TODO: not implemented yet in m4rie |
| 93 | 93 | double mzed_density(mzed_t *A, int res) |
| … |
… |
|
| 95 | 95 | # TODO: not implemented yet in m4rie |
| 96 | 96 | double _mzed_density(mzed_t *A, int res, size_t r, size_t c) |
| 97 | 97 | |
| 98 | | #cdef extern from "m4rie/travolta.h": |
| 99 | | size_t mzed_echelonize_travolta(mzed_t *, size_t) |
| | 98 | #cdef extern from "m4rie/newton_john.h": |
| | 99 | size_t mzed_echelonize_newton_john(mzed_t *, size_t) |
| 100 | 100 | |
| 101 | | mzed_t *mzed_mul_travolta(mzed_t *, mzed_t *, mzed_t *) |
| | 101 | mzed_t *mzed_mul_newton_john(mzed_t *, mzed_t *, mzed_t *) |
| 102 | 102 | |
| 103 | 103 | #cdef extern from "m4rie/echelonform.h": |
| 104 | 104 | size_t mzed_echelonize(mzed_t *, size_t) |
| … |
… |
|
| 110 | 110 | |
| 111 | 111 | size_t _mzed_strassen_cutoff(mzed_t *C, mzed_t *A, mzed_t *B) |
| 112 | 112 | |
| 113 | | #cdef extern from "m4rie/bitslice.h": |
| | 113 | #cdef extern from "m4rie/mzd_slice.h": |
| 114 | 114 | |
| 115 | 115 | int __M4RIE_MAX_KARATSUBA_DEGREE |
| 116 | 116 | |
diff --git a/sage/matrix/matrix_mod2e_dense.pxd b/sage/matrix/matrix_mod2e_dense.pxd
|
a
|
b
|
|
| 12 | 12 | cdef object _one |
| 13 | 13 | cdef object _zero |
| 14 | 14 | |
| 15 | | cpdef Matrix_mod2e_dense _multiply_travolta(Matrix_mod2e_dense self, Matrix_mod2e_dense right) |
| | 15 | cpdef Matrix_mod2e_dense _multiply_newton_john(Matrix_mod2e_dense self, Matrix_mod2e_dense right) |
| 16 | 16 | cpdef Matrix_mod2e_dense _multiply_karatsuba(Matrix_mod2e_dense self, Matrix_mod2e_dense right) |
| 17 | 17 | cpdef Matrix_mod2e_dense _multiply_strassen(Matrix_mod2e_dense self, Matrix_mod2e_dense right, cutoff=*) |
diff --git a/sage/matrix/matrix_mod2e_dense.pyx b/sage/matrix/matrix_mod2e_dense.pyx
|
a
|
b
|
|
| 12 | 12 | represented as ``[0xxx|0xxx|0xxx|0xxx|...]``. This representation is |
| 13 | 13 | wrapped as :class:`Matrix_mod2e_dense` in Sage. |
| 14 | 14 | |
| 15 | | Multiplication and elimination both use "Travolta" tables. These |
| | 15 | Multiplication and elimination both use "Newton-John" tables. These |
| 16 | 16 | tables are simply all possible multiples of a given row in a matrix |
| 17 | 17 | such that a scale+add operation is reduced to a table lookup + |
| 18 | | add. On top of Travolta multiplication M4RIE implements |
| | 18 | add. On top of Newton-John multiplication M4RIE implements |
| 19 | 19 | asymptotically fast Strassen-Winograd multiplication. Elimination |
| 20 | 20 | uses simple Gaussian elimination which requires `O(n^3)` additions |
| 21 | 21 | but only `O(n^2 * 2^e)` multiplications. |
| … |
… |
|
| 430 | 430 | sage: K.<a> = GF(2^3) |
| 431 | 431 | sage: A = random_matrix(K, 51, 50) |
| 432 | 432 | sage: B = random_matrix(K, 50, 52) |
| 433 | | sage: A*B == A._multiply_travolta(B) # indirect doctest |
| | 433 | sage: A*B == A._multiply_newton_john(B) # indirect doctest |
| 434 | 434 | True |
| 435 | 435 | |
| 436 | 436 | sage: K.<a> = GF(2^5) |
| 437 | 437 | sage: A = random_matrix(K, 10, 50) |
| 438 | 438 | sage: B = random_matrix(K, 50, 12) |
| 439 | | sage: A*B == A._multiply_travolta(B) |
| | 439 | sage: A*B == A._multiply_newton_john(B) |
| 440 | 440 | True |
| 441 | 441 | |
| 442 | 442 | sage: K.<a> = GF(2^7) |
| … |
… |
|
| 458 | 458 | _sig_off |
| 459 | 459 | return ans |
| 460 | 460 | |
| 461 | | cpdef Matrix_mod2e_dense _multiply_travolta(Matrix_mod2e_dense self, Matrix_mod2e_dense right): |
| | 461 | cpdef Matrix_mod2e_dense _multiply_newton_john(Matrix_mod2e_dense self, Matrix_mod2e_dense right): |
| 462 | 462 | """ |
| 463 | | Return A*B using Travolta tables. |
| | 463 | Return A*B using Newton-John tables. |
| 464 | 464 | |
| 465 | 465 | We can write classical cubic multiplication (``C=A*B``) as:: |
| 466 | 466 | |
| … |
… |
|
| 474 | 474 | ``e * B[j]`` is computed more than once for any ``e`` in the finite |
| 475 | 475 | field. Instead, we compute all possible |
| 476 | 476 | multiples of ``B[j]`` and re-use this data in the inner loop. |
| 477 | | This is what is called a "Travolta" table in M4RIE. |
| | 477 | This is what is called a "Newton-John" table in M4RIE. |
| 478 | 478 | |
| 479 | 479 | INPUT: |
| 480 | 480 | |
| … |
… |
|
| 485 | 485 | sage: K.<a> = GF(2^2) |
| 486 | 486 | sage: A = random_matrix(K, 50, 50) |
| 487 | 487 | sage: B = random_matrix(K, 50, 50) |
| 488 | | sage: A._multiply_travolta(B) == A._multiply_classical(B) # indirect doctest |
| | 488 | sage: A._multiply_newton_john(B) == A._multiply_classical(B) # indirect doctest |
| 489 | 489 | True |
| 490 | 490 | |
| 491 | 491 | sage: K.<a> = GF(2^4) |
| 492 | 492 | sage: A = random_matrix(K, 50, 50) |
| 493 | 493 | sage: B = random_matrix(K, 50, 50) |
| 494 | | sage: A._multiply_travolta(B) == A._multiply_classical(B) |
| | 494 | sage: A._multiply_newton_john(B) == A._multiply_classical(B) |
| 495 | 495 | True |
| 496 | 496 | |
| 497 | 497 | sage: K.<a> = GF(2^8) |
| 498 | 498 | sage: A = random_matrix(K, 50, 50) |
| 499 | 499 | sage: B = random_matrix(K, 50, 50) |
| 500 | | sage: A._multiply_travolta(B) == A._multiply_classical(B) |
| | 500 | sage: A._multiply_newton_john(B) == A._multiply_classical(B) |
| 501 | 501 | True |
| 502 | 502 | |
| 503 | 503 | sage: K.<a> = GF(2^10) |
| 504 | 504 | sage: A = random_matrix(K, 50, 50) |
| 505 | 505 | sage: B = random_matrix(K, 50, 50) |
| 506 | | sage: A._multiply_travolta(B) == A._multiply_classical(B) |
| | 506 | sage: A._multiply_newton_john(B) == A._multiply_classical(B) |
| 507 | 507 | True |
| 508 | 508 | """ |
| 509 | 509 | if self._ncols != right._nrows: |
| … |
… |
|
| 516 | 516 | return ans |
| 517 | 517 | |
| 518 | 518 | _sig_on |
| 519 | | ans._entries = mzed_mul_travolta(ans._entries, self._entries, (<Matrix_mod2e_dense>right)._entries) |
| | 519 | ans._entries = mzed_mul_newton_john(ans._entries, self._entries, (<Matrix_mod2e_dense>right)._entries) |
| 520 | 520 | _sig_off |
| 521 | 521 | return ans |
| 522 | 522 | |
| … |
… |
|
| 550 | 550 | |
| 551 | 551 | TESTS:: |
| 552 | 552 | |
| 553 | | sage: K.<a> = GF(2^5) |
| | 553 | sage: K.<a> = GF(2^10) |
| 554 | 554 | sage: A = random_matrix(K, 50, 50) |
| 555 | 555 | sage: B = random_matrix(K, 50, 50) |
| 556 | 556 | sage: A._multiply_karatsuba(B) == A._multiply_classical(B) |
| 557 | 557 | Traceback (most recent call last): |
| 558 | 558 | ... |
| 559 | | NotImplementedError: Karatsuba multiplication is only implemented for matrices over GF(2^e) with e <= 4. |
| | 559 | NotImplementedError: Karatsuba multiplication is only implemented for matrices over GF(2^e) with e <= 8. |
| 560 | 560 | """ |
| 561 | 561 | if self._ncols != right._nrows: |
| 562 | 562 | raise ArithmeticError("left ncols must match right nrows") |
| … |
… |
|
| 577 | 577 | |
| 578 | 578 | cpdef Matrix_mod2e_dense _multiply_strassen(Matrix_mod2e_dense self, Matrix_mod2e_dense right, cutoff=0): |
| 579 | 579 | """ |
| 580 | | Winograd-Strassen matrix multiplication with Travolta |
| | 580 | Winograd-Strassen matrix multiplication with Newton-John |
| 581 | 581 | multiplication as base case. |
| 582 | 582 | |
| 583 | 583 | INPUT: |
| 584 | 584 | |
| 585 | 585 | - ``right`` - a matrix |
| 586 | 586 | - ``cutoff`` - row or column dimension to switch over to |
| 587 | | Travolta multiplication (default: 64) |
| | 587 | Newton-John multiplication (default: 64) |
| 588 | 588 | |
| 589 | 589 | EXAMPLES:: |
| 590 | 590 | |
| … |
… |
|
| 877 | 877 | |
| 878 | 878 | - ``algorithm`` - one of the following |
| 879 | 879 | - ``heuristic`` - let M4RIE decide (default) |
| 880 | | - ``travolta`` - use travolta table based algorithm |
| | 880 | - ``newton_john`` - use newton_john table based algorithm |
| 881 | 881 | - ``ple`` - use PLE decomposition |
| 882 | 882 | - ``naive`` - use naive cubic Gaussian elimination (M4RIE implementation) |
| 883 | 883 | - ``builtin`` - use naive cubic Gaussian elimination (Sage implementation) |
| … |
… |
|
| 904 | 904 | sage: MS = MatrixSpace(K,m,n) |
| 905 | 905 | sage: A = random_matrix(K, 3, 5) |
| 906 | 906 | |
| 907 | | sage: copy(A).echelon_form('travolta') |
| | 907 | sage: copy(A).echelon_form('newton_john') |
| 908 | 908 | [ 1 0 0 a^2 a^2 + 1] |
| 909 | 909 | [ 0 1 0 a^2 1] |
| 910 | 910 | [ 0 0 1 a^2 + a + 1 a + 1] |
| … |
… |
|
| 940 | 940 | r = mzed_echelonize_naive(self._entries, full) |
| 941 | 941 | _sig_off |
| 942 | 942 | |
| 943 | | elif algorithm == 'travolta': |
| | 943 | elif algorithm == 'newton_john': |
| 944 | 944 | _sig_on |
| 945 | | r = mzed_echelonize_travolta(self._entries, full) |
| | 945 | r = mzed_echelonize_newton_john(self._entries, full) |
| 946 | 946 | _sig_off |
| 947 | 947 | |
| 948 | 948 | elif algorithm == 'ple': |
| … |
… |
|
| 1014 | 1014 | A = Matrix_mod2e_dense.__new__(Matrix_mod2e_dense, self._parent, 0, 0, 0) |
| 1015 | 1015 | |
| 1016 | 1016 | if self._nrows and self._nrows == self._ncols: |
| 1017 | | mzed_invert_travolta(A._entries, self._entries) |
| | 1017 | mzed_invert_newton_john(A._entries, self._entries) |
| 1018 | 1018 | |
| 1019 | 1019 | return A |
| 1020 | 1020 | |