Skip to content

Commit

Permalink
Trac #22970: use flint fmpq_mat for rational dense matrices
Browse files Browse the repository at this point in the history
The flint library has a builtin type for rational matrices:
`fmpq_mat_t`. This ticket proposes to replace the current array of
`mpq_t` wrapped by `Matrix_rational_dense` in favor of `fmpq_mat_t`.

(See also the related #22924 and #22872)

URL: https://trac.sagemath.org/22970
Reported by: vdelecroix
Ticket author(s): Vincent Delecroix
Reviewer(s): Marc Masdeu
  • Loading branch information
Release Manager authored and vbraun committed May 30, 2017
2 parents 3d23385 + cb0dae1 commit 0db4ada
Show file tree
Hide file tree
Showing 23 changed files with 1,667 additions and 1,160 deletions.
29 changes: 17 additions & 12 deletions src/sage/algebras/quatalg/quaternion_algebra_cython.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ from .quaternion_algebra_element cimport QuaternionAlgebraElement_rational_field
from sage.libs.gmp.mpz cimport mpz_t, mpz_lcm, mpz_init, mpz_set, mpz_clear, mpz_init_set, mpz_mul, mpz_fdiv_q, mpz_cmp_si
from sage.libs.gmp.mpq cimport mpq_set_num, mpq_set_den, mpq_canonicalize

from sage.libs.flint.fmpz cimport fmpz_set_mpz
from sage.libs.flint.fmpq cimport fmpq_canonicalise
from sage.libs.flint.fmpq_mat cimport fmpq_mat_entry_num, fmpq_mat_entry_den, fmpq_mat_entry

def integral_matrix_and_denom_from_rational_quaternions(v, reverse=False):
r"""
Given a list of rational quaternions, return matrix `A` over `\ZZ`
Expand Down Expand Up @@ -142,27 +146,28 @@ def rational_matrix_from_rational_quaternions(v, reverse=False):
if reverse:
for i in range(n):
x = v[i]
mpq_set_num(A._matrix[n-i-1][3], x.x)
mpq_set_num(A._matrix[n-i-1][2], x.y)
mpq_set_num(A._matrix[n-i-1][1], x.z)
mpq_set_num(A._matrix[n-i-1][0], x.w)
fmpz_set_mpz(fmpq_mat_entry_num(A._matrix, n-i-1, 3), x.x)
fmpz_set_mpz(fmpq_mat_entry_num(A._matrix, n-i-1, 2), x.y)
fmpz_set_mpz(fmpq_mat_entry_num(A._matrix, n-i-1, 1), x.z)
fmpz_set_mpz(fmpq_mat_entry_num(A._matrix, n-i-1, 0), x.w)

if mpz_cmp_si(x.d,1):
for j in range(4):
mpq_set_den(A._matrix[n-i-1][j], x.d)
mpq_canonicalize(A._matrix[n-i-1][j])
fmpz_set_mpz(fmpq_mat_entry_den(A._matrix, n-i-1, j), x.d)
fmpq_canonicalise(fmpq_mat_entry(A._matrix, n-i-1, j))
else:
for i in range(n):
x = v[i]
mpq_set_num(A._matrix[i][0], x.x)
mpq_set_num(A._matrix[i][1], x.y)
mpq_set_num(A._matrix[i][2], x.z)
mpq_set_num(A._matrix[i][3], x.w)
fmpz_set_mpz(fmpq_mat_entry_num(A._matrix, i, 0), x.x)
fmpz_set_mpz(fmpq_mat_entry_num(A._matrix, i, 1), x.y)
fmpz_set_mpz(fmpq_mat_entry_num(A._matrix, i, 2), x.z)
fmpz_set_mpz(fmpq_mat_entry_num(A._matrix, i, 3), x.w)

if mpz_cmp_si(x.d,1):
for j in range(4):
mpq_set_den(A._matrix[i][j], x.d)
mpq_canonicalize(A._matrix[i][j])
fmpz_set_mpz(fmpq_mat_entry_den(A._matrix, i, j), x.d)
fmpq_canonicalise(fmpq_mat_entry(A._matrix, i, j))

return A

def rational_quaternions_from_integral_matrix_and_denom(A, Matrix_integer_dense H, Integer d, reverse=False):
Expand Down
79 changes: 66 additions & 13 deletions src/sage/libs/flint/fmpq.pxd
Original file line number Diff line number Diff line change
@@ -1,21 +1,74 @@
# distutils: libraries = flint

from libc.stdio cimport FILE
from sage.libs.gmp.types cimport mpq_t
from sage.libs.flint.types cimport fmpq_t
from sage.libs.flint.types cimport fmpz_t, fmpq_t, flint_rand_t, mp_bitcnt_t, fmpz
from sage.libs.mpfr cimport mpfr_t, mpfr_rnd_t

cdef extern from "flint/fmpq.h":
# Memory management
fmpz * fmpq_numref(fmpq_t)
fmpz * fmpq_denref(fmpq_t)
void fmpq_init(fmpq_t)
void fmpq_clear(fmpq_t)

# Conversion
void fmpq_set_mpq(fmpq_t, const mpq_t)
void fmpq_get_mpq(mpq_t, const fmpq_t)

# Comparison
int fmpq_is_zero(const fmpq_t res)
int fmpq_is_one(const fmpq_t res)
int fmpq_equal(const fmpq_t x, const fmpq_t y)
int fmpq_sgn(const fmpq_t)
void fmpq_one(fmpq_t)
void fmpq_zero(fmpq_t)
bint fmpq_is_zero(fmpq_t)
bint fmpq_is_one(fmpq_t)
int fmpq_sgn(const fmpq_t x)
void fmpq_set(fmpq_t dest, const fmpq_t src)
void fmpq_swap(fmpq_t op1, fmpq_t op2)
void fmpq_neg(fmpq_t dest, const fmpq_t src)
void fmpq_abs(fmpq_t dest, const fmpq_t src)
int fmpq_cmp(const fmpq_t x, const fmpq_t y)

void fmpq_canonicalise(fmpq_t res)
int fmpq_is_canonical(const fmpq_t x)
void fmpq_set_si(fmpq_t res, long p, unsigned long q)
void fmpq_set_fmpz_frac(fmpq_t res, const fmpz_t p, const fmpz_t q)
void fmpq_set_mpq(fmpq_t dest, const mpq_t src)
void fmpq_get_mpq(mpq_t dest, const fmpq_t src)
int fmpq_get_mpfr(mpfr_t r, const fmpq_t x, mpfr_rnd_t rnd)
void flint_mpq_init_set_readonly(mpq_t z, const fmpq_t f)
void flint_mpq_clear_readonly(mpq_t z)
void fmpq_init_set_readonly(fmpq_t f, const mpq_t z)
void fmpq_clear_readonly(fmpq_t f)
char * fmpq_get_str(char * str, int b, const fmpq_t x)
void fmpq_fprint(FILE * file, const fmpq_t x)
void fmpq_print(const fmpq_t x)
void fmpq_randtest(fmpq_t res, flint_rand_t state, mp_bitcnt_t bits)
void fmpq_randtest_not_zero(fmpq_t res, flint_rand_t state, mp_bitcnt_t bits)
void fmpq_randbits(fmpq_t res, flint_rand_t state, mp_bitcnt_t bits)
void fmpq_add(fmpq_t res, const fmpq_t op1, const fmpq_t op2)
void fmpq_add_si(fmpq_t res, const fmpq_t op1, long c)
void fmpq_add_fmpz(fmpq_t res, const fmpq_t op1, const fmpz_t c)
void fmpq_sub(fmpq_t res, const fmpq_t op1, const fmpq_t op2)
void fmpq_sub_si(fmpq_t res, const fmpq_t op1, long c)
void fmpq_sub_fmpz(fmpq_t res, const fmpq_t op1, const fmpz_t c)
void fmpq_mul(fmpq_t res, const fmpq_t op1, const fmpq_t op2)
void fmpq_mul_fmpz(fmpq_t res, const fmpq_t op, const fmpz_t x)
void fmpq_pow_si(fmpq_t rop, const fmpq_t op, long e)
void fmpq_addmul(fmpq_t res, const fmpq_t op1, const fmpq_t op2)
void fmpq_submul(fmpq_t res, const fmpq_t op1, const fmpq_t op2)
void fmpq_inv(fmpq_t dest, const fmpq_t src)
void fmpq_div(fmpq_t res, const fmpq_t op1, const fmpq_t op2)
void fmpq_div_fmpz(fmpq_t res, const fmpq_t op, const fmpz_t x)
void fmpq_mul_2exp(fmpq_t res, const fmpq_t x, mp_bitcnt_t exp)
void fmpq_div_2exp(fmpq_t res, const fmpq_t x, mp_bitcnt_t exp)
int fmpq_mod_fmpz(fmpz_t res, const fmpq_t x, const fmpz_t mod)
void fmpq_gcd(fmpq_t res, const fmpq_t op1, const fmpq_t op2)
int fmpq_reconstruct_fmpz(fmpq_t res, const fmpz_t a, const fmpz_t m)
int fmpq_reconstruct_fmpz_2(fmpq_t res, const fmpz_t a, const fmpz_t m, const fmpz_t N, const fmpz_t D)
mp_bitcnt_t fmpq_height_bits(const fmpq_t x)
void fmpq_height(fmpz_t height, const fmpq_t x)
void fmpq_next_calkin_wilf(fmpq_t res, const fmpq_t x)
void fmpq_next_signed_calkin_wilf(fmpq_t res, const fmpq_t x)
void fmpq_next_minimal(fmpq_t res, const fmpq_t x)
void fmpq_next_signed_minimal(fmpq_t res, const fmpq_t x)
long fmpq_get_cfrac(fmpz * c, fmpq_t rem, const fmpq_t x, long n)
void fmpq_set_cfrac(fmpq_t x, const fmpz * c, long n)
long fmpq_cfrac_bound(const fmpq_t x)
void fmpq_dedekind_sum_naive(fmpq_t s, const fmpz_t h, const fmpz_t k)
void fmpq_dedekind_sum_coprime_large(fmpq_t s, const fmpz_t h, const fmpz_t k)
double fmpq_dedekind_sum_coprime_d(double h, double k)
void fmpq_dedekind_sum_coprime(fmpq_t s, const fmpz_t h, const fmpz_t k)
void fmpq_dedekind_sum(fmpq_t s, const fmpz_t h, const fmpz_t k)
void fmpq_harmonic_ui(fmpq_t x, unsigned long n)
62 changes: 62 additions & 0 deletions src/sage/libs/flint/fmpq_mat.pxd
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# distutils: libraries = flint

from sage.libs.flint.types cimport fmpz_t, fmpz, fmpq_t, fmpq, fmpz_mat_t, fmpq_mat_t, flint_rand_t, mp_bitcnt_t

cdef extern from "flint/fmpq_mat.h":
fmpq * fmpq_mat_entry(const fmpq_mat_t mat, long i, long j)
fmpz * fmpq_mat_entry_num(const fmpq_mat_t mat, long i, long j)
fmpz * fmpq_mat_entry_den(const fmpq_mat_t mat, long i, long j)
long fmpq_mat_nrows(const fmpq_mat_t mat)
long fmpq_mat_ncols(const fmpq_mat_t mat)
void fmpq_mat_init(fmpq_mat_t mat, long rows, long cols)
void fmpq_mat_clear(fmpq_mat_t mat)
void fmpq_mat_swap(fmpq_mat_t mat1, fmpq_mat_t mat2)
void fmpq_mat_window_init(fmpq_mat_t window, const fmpq_mat_t mat, long r1, long c1, long r2, long c2)
void fmpq_mat_window_clear(fmpq_mat_t window)
void fmpq_mat_concat_horizontal(fmpq_mat_t res, const fmpq_mat_t mat1, const fmpq_mat_t mat2)
void fmpq_mat_concat_vertical(fmpq_mat_t res, const fmpq_mat_t mat1, const fmpq_mat_t mat2)
void fmpq_mat_print(const fmpq_mat_t mat)
void fmpq_mat_randbits(fmpq_mat_t mat, flint_rand_t state, mp_bitcnt_t bits)
void fmpq_mat_randtest(fmpq_mat_t mat, flint_rand_t state, mp_bitcnt_t bits)
void fmpq_mat_hilbert_matrix(fmpq_mat_t mat)
void fmpq_mat_set(fmpq_mat_t dest, const fmpq_mat_t src)
void fmpq_mat_zero(fmpq_mat_t mat)
void fmpq_mat_one(fmpq_mat_t mat)
void fmpq_mat_transpose(fmpq_mat_t rop, const fmpq_mat_t op)
void fmpq_mat_add(fmpq_mat_t mat, const fmpq_mat_t mat1, const fmpq_mat_t mat2)
void fmpq_mat_sub(fmpq_mat_t mat, const fmpq_mat_t mat1, const fmpq_mat_t mat2)
void fmpq_mat_neg(fmpq_mat_t rop, const fmpq_mat_t op)
void fmpq_mat_scalar_mul_fmpz(fmpq_mat_t rop, const fmpq_mat_t op, const fmpz_t x)
void fmpq_mat_scalar_div_fmpz(fmpq_mat_t rop, const fmpq_mat_t op, const fmpz_t x)
bint fmpq_mat_equal(const fmpq_mat_t mat1, const fmpq_mat_t mat2)
bint fmpq_mat_is_integral(const fmpq_mat_t mat)
bint fmpq_mat_is_zero(const fmpq_mat_t mat)
bint fmpq_mat_is_empty(const fmpq_mat_t mat)
bint fmpq_mat_is_square(const fmpq_mat_t mat)
int fmpq_mat_get_fmpz_mat(fmpz_mat_t dest, const fmpq_mat_t mat)
void fmpq_mat_get_fmpz_mat_entrywise(fmpz_mat_t num, fmpz_mat_t den, const fmpq_mat_t mat)
void fmpq_mat_get_fmpz_mat_matwise(fmpz_mat_t num, fmpz_t den, const fmpq_mat_t mat)
void fmpq_mat_get_fmpz_mat_rowwise(fmpz_mat_t num, fmpz * den, const fmpq_mat_t mat)
void fmpq_mat_get_fmpz_mat_colwise(fmpz_mat_t num, fmpz * den, const fmpq_mat_t mat)
void fmpq_mat_get_fmpz_mat_rowwise_2(fmpz_mat_t num, fmpz_mat_t num2, fmpz * den, const fmpq_mat_t mat, const fmpq_mat_t mat2)
void fmpq_mat_get_fmpz_mat_mod_fmpz(fmpz_mat_t dest, const fmpq_mat_t mat, const fmpz_t mod)
void fmpq_mat_set_fmpz_mat(fmpq_mat_t dest, const fmpz_mat_t src)
void fmpq_mat_set_fmpz_mat_div_fmpz(fmpq_mat_t X, const fmpz_mat_t Xmod, const fmpz_t div)
int fmpq_mat_set_fmpz_mat_mod_fmpz(fmpq_mat_t X, const fmpz_mat_t Xmod, const fmpz_t mod)
void fmpq_mat_mul_direct(fmpq_mat_t C, const fmpq_mat_t A, const fmpq_mat_t B)
void fmpq_mat_mul_cleared(fmpq_mat_t C, const fmpq_mat_t A, const fmpq_mat_t B)
void fmpq_mat_mul(fmpq_mat_t C, const fmpq_mat_t A, const fmpq_mat_t B)
void fmpq_mat_mul_fmpz_mat(fmpq_mat_t C, const fmpq_mat_t A, const fmpz_mat_t B)
void fmpq_mat_mul_r_fmpz_mat(fmpq_mat_t C, const fmpz_mat_t A, const fmpq_mat_t B)
void fmpq_mat_trace(fmpq_t trace, const fmpq_mat_t mat)
void fmpq_mat_det(fmpq_t det, const fmpq_mat_t mat)
int fmpq_mat_solve_fraction_free(fmpq_mat_t X, const fmpq_mat_t A, const fmpq_mat_t B)
int fmpq_mat_solve_dixon(fmpq_mat_t X, const fmpq_mat_t A, const fmpq_mat_t B)
int fmpq_mat_solve_fmpz_mat(fmpq_mat_t X, const fmpz_mat_t A, const fmpz_mat_t B)
int fmpq_mat_inv(fmpq_mat_t B, const fmpq_mat_t A)
int fmpq_mat_pivot(long * perm, fmpq_mat_t mat, long r, long c)
long fmpq_mat_rref_classical(fmpq_mat_t B, const fmpq_mat_t A)
long fmpq_mat_rref_fraction_free(fmpq_mat_t B, const fmpq_mat_t A)
long fmpq_mat_rref(fmpq_mat_t B, const fmpq_mat_t A)
void fmpq_mat_gso(fmpq_mat_t B, const fmpq_mat_t A)

4 changes: 4 additions & 0 deletions src/sage/libs/flint/fmpz.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -184,3 +184,7 @@ cdef extern from "flint/fmpz.h":
void fmpz_bin_uiui(fmpz_t, ulong, ulong)
void fmpz_rfac_ui(fmpz_t, fmpz_t, ulong)
void fmpz_rfac_uiui(fmpz_t, ulong, ulong)

# Random Generators
void fmpz_randbits(fmpz_t f, flint_rand_t state, mp_bitcnt_t bits)
void fmpz_randm(fmpz_t f, flint_rand_t state, const fmpz_t m)
7 changes: 7 additions & 0 deletions src/sage/libs/flint/types.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,19 @@ cdef extern from "flint/fmpz.h":

ctypedef fmpz_preinvn_struct[1] fmpz_preinvn_t


cdef extern from "flint/fmpz_mat.h":
ctypedef struct fmpz_mat_struct:
pass

ctypedef fmpz_mat_struct fmpz_mat_t[1]

cdef extern from "flint/fmpq_mat.h":
ctypedef struct fmpq_mat_struct:
pass

ctypedef fmpq_mat_struct fmpq_mat_t[1]

cdef extern from "flint/fmpz_mod_poly.h":
ctypedef struct fmpz_mod_poly_struct:
pass
Expand Down
15 changes: 15 additions & 0 deletions src/sage/libs/gmp/randomize.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,23 @@ cdef inline void mpq_randomize_entry(mpq_t x, mpz_t num_bound, mpz_t den_bound):
mpz_mul_si(mpq_numref(x), mpq_numref(x), -1)
mpq_canonicalize(x)

cdef inline void mpq_randomize_entry_nonzero(mpq_t x, mpz_t num_bound, mpz_t den_bound):
mpq_randomize_entry(x, num_bound, den_bound)
while mpq_sgn(x) == 0:
mpq_randomize_entry(x, num_bound, den_bound)

cdef inline void mpq_randomize_entry_as_int(mpq_t x, mpz_t bound):
cdef randstate rstate = current_randstate()
mpz_urandomm(mpq_numref(x), rstate.gmp_state, bound)
mpz_set_si(mpq_denref(x), 1)
if rstate.c_random() % 2:
mpz_mul_si(mpq_numref(x), mpq_numref(x), -1)

cdef inline void mpq_randomize_entry_as_int_nonzero(mpq_t x, mpz_t bound):
mpq_randomize_entry_as_int(x, bound)
while mpq_sgn(x) == 0:
mpq_randomize_entry_as_int(x, bound)

cdef inline void mpq_randomize_entry_recip_uniform(mpq_t x):
cdef randstate rstate = current_randstate()
# Numerator is selected the same way as ZZ.random_element();
Expand All @@ -39,3 +49,8 @@ cdef inline void mpq_randomize_entry_recip_uniform(mpq_t x):
if den == 0: den = 1
mpz_set_si(mpq_denref(x), SAGE_RAND_MAX / den)
mpq_canonicalize(x)

cdef inline void mpq_randomize_entry_recip_uniform_nonzero(mpq_t x):
mpq_randomize_entry_recip_uniform_nonzero(x)
while mpq_sgn(x) == 0:
mpq_randomize_entry_recip_uniform_nonzero(x)
13 changes: 9 additions & 4 deletions src/sage/libs/pari/convert_flint.pxd
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
from cypari2.types cimport GEN
from cypari2.gen cimport Gen
from sage.libs.flint.types cimport fmpz_t, fmpz_mat_t
from sage.libs.flint.types cimport fmpz_t, fmpz_mat_t, fmpq_t, fmpq_mat_t

cdef GEN _new_GEN_from_fmpz_t(fmpz_t value)
cdef GEN _new_GEN_from_fmpz_mat_t(fmpz_mat_t B, Py_ssize_t nr, Py_ssize_t nc)
cdef GEN _new_GEN_from_fmpz_mat_t_rotate90(fmpz_mat_t B, Py_ssize_t nr, Py_ssize_t nc)
cdef Gen integer_matrix(fmpz_mat_t B, Py_ssize_t nr, Py_ssize_t nc, bint permute_for_hnf)
cdef GEN _new_GEN_from_fmpz_mat_t(fmpz_mat_t B)
cdef GEN _new_GEN_from_fmpz_mat_t_rotate90(fmpz_mat_t B)
cdef Gen integer_matrix(fmpz_mat_t B, bint rotate)

cdef GEN _new_GEN_from_fmpq_t(fmpq_t value)
cdef GEN _new_GEN_from_fmpq_mat_t(fmpq_mat_t B)
cdef GEN _new_GEN_from_fmpq_mat_t_rotate90(fmpq_mat_t B)
cdef Gen rational_matrix(fmpq_mat_t B, bint rotate)
Loading

0 comments on commit 0db4ada

Please sign in to comment.